Date: Fri, 17 Mar 2006 15:52:16 GMT From: soc-bushman <soc-bushman@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 93450 for review Message-ID: <200603171552.k2HFqGp5081706@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=93450 Change 93450 by soc-bushman@soc-bushman_stinger on 2006/03/17 15:51:16 the euid/egid checking policy was updated Affected files ... .. //depot/projects/soc2005/nsswitch_cached/src/lib/libc/net/nsdispatch.c#15 edit .. //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/mp_rs_query.c#2 edit .. //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/mp_rs_query.h#2 edit .. //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/mp_ws_query.c#2 edit .. //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/mp_ws_query.h#2 edit .. //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/query.c#2 edit .. //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/query.h#2 edit Differences ... ==== //depot/projects/soc2005/nsswitch_cached/src/lib/libc/net/nsdispatch.c#15 (text+ko) ==== @@ -644,10 +644,10 @@ #ifdef NS_CACHING if ((strcmp(srclist[i].name, NSSRC_CACHE) == 0) && (nss_cache_cycle_prevention_func == NULL)) { -#ifndef NS_NO_STRICT_EID_CHECKING +#ifdef NS_STRICT_LIBC_EID_CHECKING if (issetugid() != 0) continue; -#endif /* NS_NO_STRICT_EID_CHECKING */ +#endif cache_flag = 1; memset(&cache_data, 0, sizeof(nss_cache_data)); ==== //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/mp_rs_query.c#2 (text+ko) ==== @@ -30,6 +30,7 @@ #include <sys/types.h> #include <sys/event.h> #include <assert.h> +#include <errno.h> #include <stdlib.h> #include <string.h> #include <stdio.h> @@ -38,6 +39,7 @@ #include "config.h" #include "debug.h" #include "log.h" +#include "query.h" #include "mp_rs_query.h" #include "mp_ws_query.h" #include "singletons.h" @@ -174,27 +176,35 @@ qstate->config_entry = configuration_find_entry( s_configuration, c_mp_rs_request->entry); if (qstate->config_entry == NULL) { + c_mp_rs_response->error_code = ENOENT; + LOG_ERR_2("read_session_request", "can't find configuration entry '%s'." " aborting request", c_mp_rs_request->entry); - TRACE_OUT(on_write_request_process); - return (-1); + goto fin; } if (qstate->config_entry->enabled == 0) { + c_mp_rs_response->error_code = EACCES; + LOG_ERR_2("read_session_request", "configuration entry '%s' is disabled", c_mp_rs_request->entry); - TRACE_OUT(on_read_request_process); - return (-1); + goto fin; } if (qstate->config_entry->perform_actual_lookups != 0) dec_cache_entry_name = strdup( qstate->config_entry->mp_cache_params.entry_name); - else + else { + if (check_query_eids(qstate) != 0) { + c_mp_rs_response->error_code = EPERM; + goto fin; + } + asprintf(&dec_cache_entry_name, "%s%s", qstate->eid_str, qstate->config_entry->mp_cache_params.entry_name); + } assert(dec_cache_entry_name != NULL); @@ -301,6 +311,7 @@ } else c_mp_rs_response->error_code = -1; +fin: qstate->process_func = on_mp_read_session_response_write1; qstate->kevent_watermark = sizeof(int); qstate->kevent_filter = EVFILT_WRITE; ==== //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/mp_rs_query.h#2 (text+ko) ==== @@ -28,8 +28,6 @@ #ifndef __CACHED_MP_RS_QUERY_H__ #define __CACHED_MP_RS_QUERY_H__ -#include "query.h" - extern int on_mp_read_session_request_read1(struct query_state *); #endif ==== //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/mp_ws_query.c#2 (text+ko) ==== @@ -30,6 +30,7 @@ #include <sys/types.h> #include <sys/event.h> #include <assert.h> +#include <errno.h> #include <stdlib.h> #include <string.h> #include <stdio.h> @@ -38,6 +39,7 @@ #include "config.h" #include "debug.h" #include "log.h" +#include "query.h" #include "mp_ws_query.h" #include "singletons.h" @@ -173,28 +175,35 @@ qstate->config_entry = configuration_find_entry( s_configuration, c_mp_ws_request->entry); if (qstate->config_entry == NULL) { + c_mp_ws_response->error_code = ENOENT; + LOG_ERR_2("write_session_request", "can't find configuration entry '%s'. " "aborting request", c_mp_ws_request->entry); - TRACE_OUT(on_write_request_process); - return (-1); + goto fin; } if (qstate->config_entry->enabled == 0) { + c_mp_ws_response->error_code = EACCES; + LOG_ERR_2("write_session_request", "configuration entry '%s' is disabled", c_mp_ws_request->entry); - TRACE_OUT(on_read_request_process); - return (-1); + goto fin; } if (qstate->config_entry->perform_actual_lookups != 0) { + c_mp_ws_response->error_code = EOPNOTSUPP; + LOG_ERR_2("write_session_request", "entry '%s' performs lookups by itself: " "can't write to it", c_mp_ws_request->entry); - TRACE_OUT(on_write_request_process); - return (-1); - } + goto fin; + } else + if (check_query_eids(qstate) != 0) { + c_mp_ws_response->error_code = EPERM; + goto fin; + } /* * All multipart entries are separated by their name decorations. @@ -233,9 +242,11 @@ } configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); +fin: qstate->process_func = on_mp_write_session_response_write1; qstate->kevent_watermark = sizeof(int); qstate->kevent_filter = EVFILT_WRITE; + TRACE_OUT(on_mp_write_session_request_process); return (0); } ==== //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/mp_ws_query.h#2 (text+ko) ==== @@ -28,8 +28,6 @@ #ifndef __CACHED_MP_WS_QUERY_H__ #define __CACHED_MP_WS_QUERY_H__ -#include "query.h" - extern int on_mp_write_session_request_read1(struct query_state *); extern cache_entry register_new_mp_cache_entry(struct query_state *, const char *); ==== //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/query.c#2 (text+ko) ==== @@ -46,7 +46,7 @@ static const char negative_data[1] = { 0 }; extern void get_time_func(struct timeval *); - + static void clear_config_entry(struct configuration_entry *); static void clear_config_entry_part(struct configuration_entry *, const char *, size_t); @@ -73,7 +73,6 @@ static int on_write_request_process(struct query_state *); static int on_write_response_write1(struct query_state *); - /* * Clears the specified configuration entry (clears the cache for positive and * and negative entries) and also for all multipart entries. @@ -191,14 +190,21 @@ * This check is probably a bit redundant - per-user cache is always separated * by the euid/egid pair */ -#ifndef NO_STRICT_EID_CHECKING - if ((qstate->uid != qstate->euid) || - (qstate->gid != qstate->egid)) { + if (check_query_eids(qstate) != 0) { +#ifdef NS_STRICT_CACHED_EID_CHECKING TRACE_OUT(on_query_startup); return (-1); +#else + if ((elem_type != CET_READ_REQUEST) && + (elem_type != CET_MP_READ_SESSION_REQUEST) && + (elem_type != CET_WRITE_REQUEST) && + (elem_type != CET_MP_WRITE_SESSION_REQUEST)) { + TRACE_OUT(on_query_startup); + return (-1); + } +#endif } -#endif - + switch (elem_type) { case CET_WRITE_REQUEST: qstate->process_func = on_write_request_read1; @@ -400,27 +406,30 @@ s_configuration, write_request->entry); if (qstate->config_entry == NULL) { + write_response->error_code = ENOENT; + LOG_ERR_2("write_request", "can't find configuration" " entry '%s'. aborting request", write_request->entry); - TRACE_OUT(on_write_request_process); - return (-1); + goto fin; } if (qstate->config_entry->enabled == 0) { + write_response->error_code = EACCES; + LOG_ERR_2("write_request", "configuration entry '%s' is disabled", write_request->entry); - TRACE_OUT(on_write_request_process); - return (-1); + goto fin; } if (qstate->config_entry->perform_actual_lookups != 0) { + write_response->error_code = EOPNOTSUPP; + LOG_ERR_2("write_request", "entry '%s' performs lookups by itself: " "can't write to it", write_request->entry); - TRACE_OUT(on_write_request_process); - return (-1); - } + goto fin; + } configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, @@ -445,9 +454,11 @@ } else write_response->error_code = -1; +fin: qstate->kevent_filter = EVFILT_WRITE; qstate->kevent_watermark = sizeof(int); qstate->process_func = on_write_response_write1; + TRACE_OUT(on_write_request_process); return (0); } @@ -468,28 +479,35 @@ s_configuration, write_request->entry); if (qstate->config_entry == NULL) { + write_response->error_code = ENOENT; + LOG_ERR_2("negative_write_request", "can't find configuration" " entry '%s'. aborting request", write_request->entry); - TRACE_OUT(on_negative_write_request_process); - return (-1); + goto fin; } if (qstate->config_entry->enabled == 0) { + write_response->error_code = EACCES; + LOG_ERR_2("negative_write_request", "configuration entry '%s' is disabled", write_request->entry); - TRACE_OUT(on_negative_write_request_process); - return (-1); + goto fin; } if (qstate->config_entry->perform_actual_lookups != 0) { + write_response->error_code = EOPNOTSUPP; + LOG_ERR_2("negative_write_request", "entry '%s' performs lookups by itself: " "can't write to it", write_request->entry); - TRACE_OUT(on_negative_write_request_process); - return (-1); - } + goto fin; + } else + if (check_query_eids(qstate) != 0) { + write_response->error_code = EPERM; + goto fin; + } configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, @@ -513,9 +531,11 @@ } else write_response->error_code = -1; +fin: qstate->kevent_filter = EVFILT_WRITE; qstate->kevent_watermark = sizeof(int); qstate->process_func = on_write_response_write1; + TRACE_OUT(on_negative_write_request_process); return (0); } @@ -541,6 +561,7 @@ qstate->kevent_watermark = sizeof(int); qstate->kevent_filter = EVFILT_READ; qstate->process_func = on_rw_mapper; + TRACE_OUT(on_write_response_write1); return (0); } @@ -650,19 +671,21 @@ qstate->config_entry = configuration_find_entry( s_configuration, read_request->entry); if (qstate->config_entry == NULL) { + read_response->error_code = ENOENT; + LOG_ERR_2("read_request", "can't find configuration " "entry '%s'. aborting request", read_request->entry); - TRACE_OUT(on_read_request_process); - return (-1); + goto fin; } if (qstate->config_entry->enabled == 0) { + read_response->error_code = EACCES; + LOG_ERR_2("read_request", "configuration entry '%s' is disabled", read_request->entry); - TRACE_OUT(on_read_request_process); - return (-1); + goto fin; } /* @@ -671,6 +694,12 @@ */ if (qstate->config_entry->perform_actual_lookups != 0) memset(read_request->cache_key, 0, qstate->eid_str_length); + else + if (check_query_eids(qstate) != 0) { + /* if the lookup is not self-performing, we check for clients euid/egid */ + read_response->error_code = EPERM; + goto fin; + } configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, @@ -776,6 +805,7 @@ } else read_response->error_code = -1; +fin: qstate->kevent_filter = EVFILT_WRITE; if (read_response->error_code == 0) qstate->kevent_watermark = sizeof(int) + sizeof(size_t); @@ -1051,6 +1081,17 @@ } /* + * Checks if the client's euid and egid do not differ from its uid and gid. + * Returns 0 on success. + */ +int +check_query_eids(struct query_state *qstate) +{ + + return ((qstate->uid != qstate->euid) || (qstate->gid != qstate->egid) ? -1 : 0); +} + +/* * Uses the qstate fields to process an "alternate" read - when the buffer is * too large to be received during one socket read operation */ ==== //depot/projects/soc2005/nsswitch_cached/src/usr.sbin/cached/query.h#2 (text+ko) ==== @@ -93,6 +93,8 @@ int use_alternate_io; }; +extern int check_query_eids(struct query_state *); + extern ssize_t query_io_buffer_read(struct query_state *, void *, size_t); extern ssize_t query_io_buffer_write(struct query_state *, const void *, size_t);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200603171552.k2HFqGp5081706>