From 9f18298beee5c6abf2cffc9e1d36da2795f4e9d6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 9 Mar 2006 15:51:55 +0000 Subject: r14075: * add support for long variable names in smb.conf in the form of %(....) * add support for %(DomainSID) * replace standard_sub_XXX() functions with wrappers around their alloc_sub_XXX() counterparts * add support for using SIDs in read list, et. al. (anything that is checked by nt_token_contains_name_in_list()) (This used to be commit 71d960250d2c6d01096a03e98884d3f9c395baa0) --- source3/Makefile.in | 3 +- source3/lib/substitute.c | 365 +++++++++++++++++++------------------------- source3/smbd/share_access.c | 13 +- 3 files changed, 166 insertions(+), 215 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index d5346cf4f9..f31e5fb3aa 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -635,7 +635,8 @@ EVTLOGADM_OBJ0 = utils/eventlogadm.o EVTLOGADM_OBJ = $(EVTLOGADM_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ) \ $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(DOSERR_OBJ) \ - registry/reg_eventlog.o rpc_server/srv_eventlog_lib.o registry/reg_util.o \ + $(SECRETS_OBJ) \ + registry/reg_eventlog.o rpc_server/srv_eventlog_lib.o registry/reg_util.o \ registry/reg_db.o TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index 23b204d024..bfe7dc814c 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. string substitution functions Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Gerald Carter 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -171,24 +172,24 @@ const char* get_current_username( void ) } /******************************************************************* - Given a pointer to a %$(NAME) expand it as an environment variable. - Return the number of characters by which the pointer should be advanced. + Given a pointer to a %$(NAME) in p and the whole string in str + expand it as an environment variable. + Return a new allocated and expanded string. Based on code by Branko Cibej When this is called p points at the '%' character. + May substitute multiple occurrencies of the same env var. ********************************************************************/ -static size_t expand_env_var(char *p, int len) +static char * realloc_expand_env_var(char *str, char *p) { - fstring envname; + char *envname; char *envval; char *q, *r; int copylen; - if (p[1] != '$') - return 1; - - if (p[2] != '(') - return 2; + if (p[0] != '%' || p[1] != '$' || p[2] != '(') { + return str; + } /* * Look for the terminating ')'. @@ -196,21 +197,28 @@ static size_t expand_env_var(char *p, int len) if ((q = strchr_m(p,')')) == NULL) { DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p)); - return 2; + return str; } /* * Extract the name from within the %$(NAME) string. */ - r = p+3; - copylen = MIN((q-r),(sizeof(envname)-1)); + r = p + 3; + copylen = q - r; + + /* reserve space for use later add %$() chars */ + if ( (envname = (char *)SMB_MALLOC(copylen + 1 + 4)) == NULL ) { + return NULL; + } + strncpy(envname,r,copylen); envname[copylen] = '\0'; if ((envval = getenv(envname)) == NULL) { DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname)); - return 2; + SAFE_FREE(envname); + return str; } /* @@ -218,70 +226,110 @@ static size_t expand_env_var(char *p, int len) * can be replaced. */ - copylen = MIN((q+1-p),(sizeof(envname)-1)); + copylen = q + 1 - p; strncpy(envname,p,copylen); envname[copylen] = '\0'; - string_sub(p,envname,envval,len); - return 0; /* Allow the environment contents to be parsed. */ + r = realloc_string_sub(str, envname, envval); + SAFE_FREE(envname); + + return r; } /******************************************************************* - Given a pointer to a %$(NAME) in p and the whole string in str - expand it as an environment variable. - Return a new allocated and expanded string. - Based on code by Branko Cibej +*******************************************************************/ + +static char *longvar_domainsid( void ) +{ + DOM_SID sid; + char *sid_string; + + if ( !secrets_fetch_domain_sid( lp_workgroup(), &sid ) ) { + return NULL; + } + + sid_string = SMB_STRDUP( sid_string_static( &sid ) ); + + if ( !sid_string ) { + DEBUG(0,("longvar_domainsid: failed to dup SID string!\n")); + } + + return sid_string; +} + +/******************************************************************* +*******************************************************************/ + +struct api_longvar { + const char *name; + char* (*fn)( void ); +}; + +struct api_longvar longvar_table[] = { + { "DomainSID", longvar_domainsid }, + { NULL, NULL } +}; + +static char *get_longvar_val( const char *varname ) +{ + int i; + + DEBUG(7,("get_longvar_val: expanding variable [%s]\n", varname)); + + for ( i=0; longvar_table[i].name; i++ ) { + if ( strequal( longvar_table[i].name, varname ) ) { + return longvar_table[i].fn(); + } + } + + return NULL; +} + +/******************************************************************* + Expand the long smb.conf variable names given a pointer to a %(NAME). + Return the number of characters by which the pointer should be advanced. When this is called p points at the '%' character. - May substitute multiple occurrencies of the same env var. ********************************************************************/ - -static char * realloc_expand_env_var(char *str, char *p) +static char *realloc_expand_longvar(char *str, char *p) { - char *envname; - char *envval; + fstring varname; + char *value; char *q, *r; int copylen; - if (p[0] != '%' || p[1] != '$' || p[2] != '(') + if ( p[0] != '%' || p[1] != '(' ) { return str; + } - /* - * Look for the terminating ')'. - */ + /* Look for the terminating ')'.*/ if ((q = strchr_m(p,')')) == NULL) { - DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p)); + DEBUG(0,("realloc_expand_longvar: Unterminated environment variable [%s]\n", p)); return str; } - /* - * Extract the name from within the %$(NAME) string. - */ + /* Extract the name from within the %(NAME) string.*/ - r = p + 3; - copylen = q - r; - envname = (char *)SMB_MALLOC(copylen + 1 + 4); /* reserve space for use later add %$() chars */ - if (envname == NULL) return NULL; - strncpy(envname,r,copylen); - envname[copylen] = '\0'; + r = p+2; + copylen = MIN( (q-r), (sizeof(varname)-1) ); + strncpy(varname, r, copylen); + varname[copylen] = '\0'; - if ((envval = getenv(envname)) == NULL) { - DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname)); - SAFE_FREE(envname); + if ((value = get_longvar_val(varname)) == NULL) { + DEBUG(0,("realloc_expand_longvar: Variable [%s] not set. Skipping\n", varname)); return str; } - /* - * Copy the full %$(NAME) into envname so it - * can be replaced. - */ + /* Copy the full %(NAME) into envname so it can be replaced.*/ - copylen = q + 1 - p; - strncpy(envname,p,copylen); - envname[copylen] = '\0'; - r = realloc_string_sub(str, envname, envval); - SAFE_FREE(envname); - if (r == NULL) return NULL; + copylen = MIN( (q+1-p),(sizeof(varname)-1) ); + strncpy( varname, p, copylen ); + varname[copylen] = '\0'; + r = realloc_string_sub(str, varname, value); + SAFE_FREE( value ); + + /* skip over the %(varname) */ + return r; } @@ -367,160 +415,16 @@ static const char *automount_server(const char *user_name) don't allow expansions. ****************************************************************************/ -void standard_sub_basic(const char *smb_name, char *str,size_t len) +void standard_sub_basic(const char *smb_name, char *str, size_t len) { - char *p, *s; - fstring pidstr; - struct passwd *pass; - const char *local_machine_name = get_local_machine_name(); - - for (s=str; (p=strchr_m(s, '%'));s=p) { - fstring tmp_str; - - int l = (int)len - (int)(p-str); - - if (l < 0) - l = 0; - - switch (*(p+1)) { - case 'U' : - fstrcpy(tmp_str, smb_name); - strlower_m(tmp_str); - string_sub(p,"%U",tmp_str,l); - break; - case 'G' : - fstrcpy(tmp_str, smb_name); - if ((pass = Get_Pwnam(tmp_str))!=NULL) { - string_sub(p,"%G",gidtoname(pass->pw_gid),l); - } else { - p += 2; - } - break; - case 'D' : - fstrcpy(tmp_str, current_user_info.domain); - strupper_m(tmp_str); - string_sub(p,"%D", tmp_str,l); - break; - case 'I' : - string_sub(p,"%I", client_addr(),l); - break; - case 'i' : - string_sub(p,"%i", client_socket_addr(),l); - break; - case 'L' : - if (!StrnCaseCmp(p, "%LOGONSERVER%", strlen("%LOGONSERVER%"))) { - p++; - break; - } - - if (local_machine_name && *local_machine_name) { - string_sub_once(p, "%L", local_machine_name, l); - } else { - pstring temp_name; - - pstrcpy(temp_name, global_myname()); - strlower_m(temp_name); - string_sub_once(p, "%L", temp_name, l); - } - break; - case 'M' : - string_sub(p,"%M", client_name(),l); - break; - case 'R' : - string_sub(p,"%R", remote_proto,l); - break; - case 'T' : - string_sub(p,"%T", timestring(False),l); - break; - case 'a' : - string_sub(p,"%a", remote_arch,l); - break; - case 'd' : - slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid()); - string_sub(p,"%d", pidstr,l); - break; - case 'h' : - string_sub(p,"%h", myhostname(),l); - break; - case 'm' : - string_sub(p,"%m", get_remote_machine_name(),l); - break; - case 'v' : - string_sub(p,"%v", SAMBA_VERSION_STRING,l); - break; - case 'w' : - string_sub(p,"%w", lp_winbind_separator(),l); - break; - case '$' : - p += expand_env_var(p,l); - break; /* Expand environment variables */ - case '\0': - p++; - break; /* don't run off the end of the string */ - - default: p+=2; - break; - } + char *s; + + if ( (s = alloc_sub_basic( smb_name, str )) != NULL ) { + strncpy( str, s, len ); } -} - -static void standard_sub_advanced(int snum, const char *user, - const char *connectpath, gid_t gid, - const char *smb_name, char *str, size_t len) -{ - char *p, *s, *home; - - for (s=str; (p=strchr_m(s, '%'));s=p) { - int l = (int)len - (int)(p-str); - if (l < 0) - l = 0; + SAFE_FREE( s ); - switch (*(p+1)) { - case 'N' : - string_sub(p,"%N", automount_server(user),l); - break; - case 'H': - if ((home = get_user_home_dir(user))) - string_sub(p,"%H",home, l); - else - p += 2; - break; - case 'P': - string_sub(p,"%P", connectpath, l); - break; - case 'S': - if ( snum != -1 ) - string_sub(p,"%S", lp_servicename(snum), l); - break; - case 'g': - string_sub(p,"%g", gidtoname(gid), l); - break; - case 'u': - string_sub(p,"%u", user, l); - break; - - /* Patch from jkf@soton.ac.uk Left the %N (NIS - * server name) in standard_sub_basic as it is - * a feature for logon servers, hence uses the - * username. The %p (NIS server path) code is - * here as it is used instead of the default - * "path =" string in [homes] and so needs the - * service name, not the username. */ - case 'p': - if ( snum != -1 ) - string_sub(p,"%p", automount_path(lp_servicename(snum)), l); - break; - case '\0': - p++; - break; /* don't run off the end of the string */ - - default: p+=2; - break; - } - } - - standard_sub_basic(smb_name, str, len); } /**************************************************************************** @@ -531,8 +435,8 @@ static void standard_sub_advanced(int snum, const char *user, char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *str) { char *a, *t; - a = alloc_sub_basic(smb_name, str); - if (!a) { + + if ( (a = alloc_sub_basic(smb_name, str)) == NULL ) { return NULL; } t = talloc_strdup(mem_ctx, a); @@ -540,6 +444,9 @@ char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *st return t; } +/**************************************************************************** +****************************************************************************/ + char *alloc_sub_basic(const char *smb_name, const char *str) { char *b, *p, *s, *r, *a_string; @@ -592,7 +499,13 @@ char *alloc_sub_basic(const char *smb_name, const char *str) case 'I' : a_string = realloc_string_sub(a_string, "%I", client_addr()); break; + case 'i': + a_string = realloc_string_sub( a_string, "%i", client_socket_addr() ); + break; case 'L' : + if ( StrnCaseCmp(p, "%LOGONSERVER%", strlen("%LOGONSERVER%")) == 0 ) { + break; + } if (local_machine_name && *local_machine_name) { a_string = realloc_string_sub(a_string, "%L", local_machine_name); } else { @@ -633,14 +546,17 @@ char *alloc_sub_basic(const char *smb_name, const char *str) case '$' : a_string = realloc_expand_env_var(a_string, p); /* Expand environment variables */ break; - + case '(': + a_string = realloc_expand_longvar( a_string, p ); + break; default: break; } p++; SAFE_FREE(r); - if (a_string == NULL) { + + if ( !a_string ) { return NULL; } } @@ -674,6 +590,9 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx, return t; } +/**************************************************************************** +****************************************************************************/ + char *alloc_sub_specified(const char *input_string, const char *username, const char *domain, @@ -735,6 +654,9 @@ char *alloc_sub_specified(const char *input_string, return ret_string; } +/**************************************************************************** +****************************************************************************/ + char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, int snum, const char *user, @@ -753,6 +675,9 @@ char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, return t; } +/**************************************************************************** +****************************************************************************/ + char *alloc_sub_advanced(int snum, const char *user, const char *connectpath, gid_t gid, const char *smb_name, const char *str) @@ -823,10 +748,20 @@ char *alloc_sub_advanced(int snum, const char *user, void standard_sub_conn(connection_struct *conn, char *str, size_t len) { - standard_sub_advanced(SNUM(conn), conn->user, conn->connectpath, - conn->gid, smb_user_name, str, len); + char *s; + + s = alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath, + conn->gid, smb_user_name, str); + + if ( s ) { + strncpy( str, s, len ); + SAFE_FREE( s ); + } } +/**************************************************************************** +****************************************************************************/ + char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *str) { return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user, @@ -834,6 +769,9 @@ char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char * smb_user_name, str); } +/**************************************************************************** +****************************************************************************/ + char *alloc_sub_conn(connection_struct *conn, const char *str) { return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath, @@ -848,6 +786,8 @@ void standard_sub_snum(int snum, char *str, size_t len) { static uid_t cached_uid = -1; static fstring cached_user; + char *s; + /* calling uidtoname() on every substitute would be too expensive, so we cache the result here as nearly every call is for the same uid */ @@ -856,6 +796,11 @@ void standard_sub_snum(int snum, char *str, size_t len) cached_uid = current_user.ut.uid; } - standard_sub_advanced(snum, cached_user, "", current_user.ut.gid, - smb_user_name, str, len); + s = alloc_sub_advanced(snum, cached_user, "", current_user.ut.gid, + smb_user_name, str); + + if ( s ) { + strncpy( str, s, len ); + SAFE_FREE( s ); + } } diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c index a429937f8d..df5f445587 100644 --- a/source3/smbd/share_access.c +++ b/source3/smbd/share_access.c @@ -85,6 +85,13 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx, * result that might be interpreted in a wrong way. */ smb_panic("substitutions failed\n"); } + + /* check to see is we already have a SID */ + + if ( string_to_sid( &sid, name ) ) { + DEBUG(5,("token_contains_name: Checking for SID [%s] in token\n", name)); + return nt_token_check_sid( &sid, token ); + } if (!do_group_checks(&name, &prefix)) { if (!lookup_name(mem_ctx, name, LOOKUP_NAME_ALL, @@ -153,14 +160,12 @@ BOOL token_contains_name_in_list(const char *username, return False; } - mem_ctx = talloc_new(NULL); - if (mem_ctx == NULL) { + if ( (mem_ctx = talloc_new(NULL)) == NULL ) { smb_panic("talloc_new failed\n"); } while (*list != NULL) { - if (token_contains_name(mem_ctx, username, sharename, - token, *list)) { + if (token_contains_name(mem_ctx, username, sharename,token, *list)) { TALLOC_FREE(mem_ctx); return True; } -- cgit