From 4d6b6eb94a3bb53ab47d458a4071ba805281c6a1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 31 Jan 2001 05:14:31 +0000 Subject: lib/system.c: Fix for pw caching. srv_samr.c: Fix for pw caching. smbd/nttrans.c: Fix to allow trans create to set ACL on open. Jeremy. (This used to be commit c4f810a7588a2faf41f4222dc77678c53ab1dec0) --- source3/include/proto.h | 3 + source3/include/rpc_secdes.h | 2 + source3/lib/system.c | 49 +++++++++++---- source3/rpc_server/srv_samr.c | 12 ++-- source3/smbd/nttrans.c | 139 ++++++++++++++++++++++++++++-------------- 5 files changed, 141 insertions(+), 64 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index ffd6a8bfe5..b452d1c9f1 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -649,6 +649,9 @@ void sys_srandom(unsigned int seed); int groups_max(void); int sys_getgroups(int setlen, gid_t *gidset); int sys_setgroups(int setlen, gid_t *gidset); +void sys_setpwent(void); +struct passwd *sys_getpwent(void); +void sys_endpwent(void); struct passwd *sys_getpwnam(const char *name); struct passwd *sys_getpwuid(uid_t uid); int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf); diff --git a/source3/include/rpc_secdes.h b/source3/include/rpc_secdes.h index ab8a24d2d6..d32ab3f3e7 100644 --- a/source3/include/rpc_secdes.h +++ b/source3/include/rpc_secdes.h @@ -73,6 +73,8 @@ #define DACL_SECURITY_INFORMATION 0x00000004 #define SACL_SECURITY_INFORMATION 0x00000008 +#define ALL_SECURITY_INFORMATION (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|\ + DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION) #ifndef _SEC_ACCESS /* SEC_ACCESS */ diff --git a/source3/lib/system.c b/source3/lib/system.c index a2b9a7dbf7..48a8a3f687 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -611,20 +611,47 @@ static struct passwd *setup_pwret(struct passwd *pass) getpw[nam|uid]() call. Patch by "Richard Bollinger" */ +/* + * This next static pointer is used to cache the results + * from the real getpwXX calls. It is never returned to + * the caller, only the output from calling setup_pwret with + * this is returned. JRA. + */ + static struct passwd *sv_pw_ret; /* implicitly initialized to NULL */ static int num_lookups; /* Counter so we don't always use cache. */ #ifndef PW_RET_CACHE_MAX_LOOKUPS #define PW_RET_CACHE_MAX_LOOKUPS 100 #endif +/************************************************************************** + Wrappers for setpwent(), getpwent() and endpwent() +****************************************************************************/ + +void sys_setpwent(void) +{ + sv_pw_ret = NULL; + setpwent(); +} + +struct passwd *sys_getpwent(void) +{ + sv_pw_ret = getpwent(); + return setup_pwret(sv_pw_ret); +} + +void sys_endpwent(void) +{ + sv_pw_ret = NULL; + endpwent(); +} + /************************************************************************** Wrapper for getpwnam(). Always returns a static that can be modified. ****************************************************************************/ struct passwd *sys_getpwnam(const char *name) { - struct passwd *pw_ret; - if (!name || !name[0]) return NULL; @@ -634,17 +661,17 @@ struct passwd *sys_getpwnam(const char *name) DEBUG(2,("getpwnam(%s) avoided - using cached results\n",name)); num_lookups++; num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS); - return sv_pw_ret; + return setup_pwret(sv_pw_ret); } /* no cache hit--use old lookup instead */ DEBUG(2,("getpwnam(%s) called\n",name)); - if (!(pw_ret = getpwnam(name))) - return NULL; num_lookups = 1; - return (sv_pw_ret = setup_pwret(pw_ret)); + sv_pw_ret = getpwnam(name); + + return setup_pwret(sv_pw_ret); } /************************************************************************** @@ -653,23 +680,21 @@ struct passwd *sys_getpwnam(const char *name) struct passwd *sys_getpwuid(uid_t uid) { - struct passwd *pw_ret; - if (num_lookups && sv_pw_ret && (uid == sv_pw_ret->pw_uid)) { DEBUG(2,("getpwuid(%d) avoided - using cached results\n",uid)); num_lookups++; num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS); - return sv_pw_ret; + return setup_pwret(sv_pw_ret); } DEBUG(2,("getpwuid(%d) called\n",uid)); - if (!(pw_ret = getpwuid(uid))) - return NULL; num_lookups = 1; - return (sv_pw_ret = setup_pwret(pw_ret)); + sv_pw_ret = getpwuid(uid); + + return setup_pwret(sv_pw_ret); } /************************************************************************** diff --git a/source3/rpc_server/srv_samr.c b/source3/rpc_server/srv_samr.c index 30a0350f67..857581a471 100644 --- a/source3/rpc_server/srv_samr.c +++ b/source3/rpc_server/srv_samr.c @@ -217,7 +217,7 @@ static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf, if (pw_buf == NULL) return False; if (current_idx == 0) { - setpwent(); + sys_setpwent(); } /* These two cases are inefficient, but should be called very rarely */ @@ -230,7 +230,7 @@ static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf, char *unmap_name; if(!orig_done) { - if ((pwd = getpwent()) == NULL) break; + if ((pwd = sys_getpwent()) == NULL) break; current_idx++; orig_done = True; } @@ -248,8 +248,8 @@ static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf, } } else if (start_idx < current_idx) { /* We are already too far; start over and advance to start_idx */ - endpwent(); - setpwent(); + sys_endpwent(); + sys_setpwent(); current_idx = 0; mapped_idx = 0; orig_done = False; @@ -257,7 +257,7 @@ static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf, char *unmap_name; if(!orig_done) { - if ((pwd = getpwent()) == NULL) break; + if ((pwd = sys_getpwent()) == NULL) break; current_idx++; orig_done = True; } @@ -284,7 +284,7 @@ static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf, /* This does the original UNIX user itself */ if(!orig_done) { - if ((pwd = getpwent()) == NULL) break; + if ((pwd = sys_getpwent()) == NULL) break; /* Don't enumerate winbind users as they are not local */ diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3aaaa9aebb..19f5859abb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1057,6 +1057,77 @@ static int do_nt_transact_create_pipe( connection_struct *conn, return -1; } +/**************************************************************************** + Internal fn to set security descriptors. +****************************************************************************/ + +static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint security_info_sent, int *pdef_class,uint32 *pdef_code) +{ + prs_struct pd; + SEC_DESC *psd = NULL; + TALLOC_CTX *mem_ctx; + BOOL ret; + + if (sd_len == 0) { + *pdef_class = ERRDOS; + *pdef_code = ERRbadaccess; + return False; + } + + /* + * Init the parse struct we will unmarshall from. + */ + + if ((mem_ctx = talloc_init()) == NULL) { + DEBUG(0,("set_sd: talloc_init failed.\n")); + *pdef_class = ERRDOS; + *pdef_code = ERRnomem; + return False; + } + + prs_init(&pd, 0, 4, mem_ctx, UNMARSHALL); + + /* + * Setup the prs_struct to point at the memory we just + * allocated. + */ + + prs_give_memory( &pd, data, sd_len, False); + + /* + * Finally, unmarshall from the data buffer. + */ + + if(!sec_io_desc( "sd data", &psd, &pd, 1)) { + free_sec_desc(&psd); + DEBUG(0,("set_sd: Error in unmarshalling security descriptor.\n")); + /* + * Return access denied for want of a better error message.. + */ + talloc_destroy(mem_ctx); + *pdef_class = ERRDOS; + *pdef_code = ERRnomem; + return False; + } + + ret = set_nt_acl( fsp, security_info_sent, psd); + + if (!ret) { + free_sec_desc(&psd); + talloc_destroy(mem_ctx); + *pdef_class = ERRDOS; + *pdef_code = ERRnoaccess; + return False; + } + + free_sec_desc(&psd); + talloc_destroy(mem_ctx); + + *pdef_class = 0; + *pdef_code = 0; + return True; +} + /**************************************************************************** Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ @@ -1068,6 +1139,7 @@ static int call_nt_transact_create(connection_struct *conn, { pstring fname; char *params = *ppparams; + char *data = *ppdata; int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); /* Breakout the oplock request bits so we can set the reply bits separately. */ @@ -1088,10 +1160,13 @@ static int call_nt_transact_create(connection_struct *conn, uint32 create_disposition; uint32 create_options; uint32 fname_len; + uint32 sd_len; uint16 root_dir_fid; int smb_ofun; int smb_open_mode; int smb_attr; + int error_class; + uint32 error_code; DEBUG(5,("call_nt_transact_create\n")); @@ -1122,6 +1197,7 @@ static int call_nt_transact_create(connection_struct *conn, share_access = IVAL(params,24); create_disposition = IVAL(params,28); create_options = IVAL(params,32); + sd_len = IVAL(params,36); fname_len = MIN(((uint32)IVAL(params,44)),((uint32)sizeof(fname)-1)); root_dir_fid = (uint16)IVAL(params,4); smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK); @@ -1336,6 +1412,16 @@ static int call_nt_transact_create(connection_struct *conn, smb_action |= EXTENDED_OPLOCK_GRANTED; } + /* + * Now try and apply the desired SD. + */ + + if (!set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION, &error_class, &error_code)) { + close_file(fsp,False); + restore_case_semantics(file_attributes); + return(ERROR(error_class, error_code)); + } + restore_case_semantics(file_attributes); /* Realloc the size of parameters and data we will return */ @@ -1621,13 +1707,11 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, uint32 total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); char *params= *ppparams; char *data = *ppdata; - prs_struct pd; - SEC_DESC *psd = NULL; uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); files_struct *fsp = NULL; uint32 security_info_sent = 0; - TALLOC_CTX *mem_ctx; - BOOL ret; + int error_class; + uint32 error_code; if(!lp_nt_acl_support()) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1643,49 +1727,9 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name, (unsigned int)security_info_sent )); - /* - * Init the parse struct we will unmarshall from. - */ - - if ((mem_ctx = talloc_init()) == NULL) { - DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); - return(ERROR(ERRDOS,ERRnomem)); - } - - prs_init(&pd, 0, 4, mem_ctx, UNMARSHALL); - - /* - * Setup the prs_struct to point at the memory we just - * allocated. - */ - - prs_give_memory( &pd, data, total_data_count, False); - - /* - * Finally, unmarshall from the data buffer. - */ - - if(!sec_io_desc( "sd data", &psd, &pd, 1)) { - free_sec_desc(&psd); - DEBUG(0,("call_nt_transact_set_security_desc: Error in unmarshalling \ -security descriptor.\n")); - /* - * Return access denied for want of a better error message.. - */ - talloc_destroy(mem_ctx); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - ret = set_nt_acl( fsp, security_info_sent, psd); + if (!set_sd( fsp, data, total_data_count, security_info_sent, &error_class, &error_code)) + return (ERROR(error_class, error_code)); - if (!ret) { - free_sec_desc(&psd); - talloc_destroy(mem_ctx); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - free_sec_desc(&psd); - talloc_destroy(mem_ctx); send_nt_replies(inbuf, outbuf, bufsize, 0, NULL, 0, NULL, 0); return -1; } @@ -1774,6 +1818,9 @@ due to being in oplock break state.\n" )); if ((total_parameter_count && !params) || (total_data_count && !data) || (setup_count && !setup)) { + safe_free(setup); + safe_free(params); + safe_free(data); DEBUG(0,("reply_nttrans : Out of memory\n")); END_PROFILE(SMBnttrans); return(ERROR(ERRDOS,ERRnomem)); -- cgit