From owner-p4-projects@FreeBSD.ORG Fri Mar 17 15:52:17 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 8B7CF16A420; Fri, 17 Mar 2006 15:52:17 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1EB4F16A400 for ; Fri, 17 Mar 2006 15:52:17 +0000 (UTC) (envelope-from soc-bushman@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id C876F43D45 for ; Fri, 17 Mar 2006 15:52:16 +0000 (GMT) (envelope-from soc-bushman@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id k2HFqGkf081709 for ; Fri, 17 Mar 2006 15:52:16 GMT (envelope-from soc-bushman@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id k2HFqGp5081706 for perforce@freebsd.org; Fri, 17 Mar 2006 15:52:16 GMT (envelope-from soc-bushman@freebsd.org) Date: Fri, 17 Mar 2006 15:52:16 GMT Message-Id: <200603171552.k2HFqGp5081706@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to soc-bushman@freebsd.org using -f From: soc-bushman To: Perforce Change Reviews Cc: Subject: PERFORCE change 93450 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 17 Mar 2006 15:52:17 -0000 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 #include #include +#include #include #include #include @@ -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 #include #include +#include #include #include #include @@ -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);