X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source%2Flib%2Fsubstitute.c;h=57df02f7216f7b7a7141104ecaaf6f30368e5b77;hb=5c6c8e1fe93;hp=767ca0c071add46bd3a52d9a22a40f74333328c8;hpb=29b4b9a2b5a0347d227b1a30e3f34bf40afa6de4;p=samba.git diff --git a/source/lib/substitute.c b/source/lib/substitute.c index 767ca0c071a..57df02f7216 100644 --- a/source/lib/substitute.c +++ b/source/lib/substitute.c @@ -2,10 +2,11 @@ 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 - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,40 +15,75 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" +extern struct current_user current_user; + fstring local_machine=""; fstring remote_arch="UNKNOWN"; userdom_struct current_user_info; fstring remote_proto="UNKNOWN"; -extern pstring global_myname; -static fstring remote_machine=""; +static fstring remote_machine; +static fstring smb_user_name; +/** + * Set the 'local' machine name + * @param local_name the name we are being called + * @param if this is the 'final' name for us, not be be changed again + */ -void set_local_machine_name(const char* local_name) +void set_local_machine_name(const char* local_name, BOOL perm) { + static BOOL already_perm = False; fstring tmp_local_machine; fstrcpy(tmp_local_machine,local_name); - trim_string(tmp_local_machine," "," "); - strlower(tmp_local_machine); + trim_char(tmp_local_machine,' ',' '); + + /* + * Windows NT/2k uses "*SMBSERVER" and XP uses "*SMBSERV" + * arrggg!!! + */ + + if ( strequal(tmp_local_machine, "*SMBSERVER") || strequal(tmp_local_machine, "*SMBSERV") ) { + fstrcpy( local_machine, client_socket_addr() ); + return; + } + + if (already_perm) + return; + + already_perm = perm; + alpha_strcpy(local_machine,tmp_local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1); + strlower_m(local_machine); } -void set_remote_machine_name(const char* remote_name) +/** + * Set the 'remote' machine name + * @param remote_name the name our client wants to be called by + * @param if this is the 'final' name for them, not be be changed again + */ + +void set_remote_machine_name(const char* remote_name, BOOL perm) { + static BOOL already_perm = False; fstring tmp_remote_machine; + if (already_perm) + return; + + already_perm = perm; + fstrcpy(tmp_remote_machine,remote_name); - trim_string(tmp_remote_machine," "," "); - strlower(tmp_remote_machine); + trim_char(tmp_remote_machine,' ',' '); alpha_strcpy(remote_machine,tmp_remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1); + strlower_m(remote_machine); } const char* get_remote_machine_name(void) @@ -57,62 +93,76 @@ const char* get_remote_machine_name(void) const char* get_local_machine_name(void) { + if (!*local_machine) { + return global_myname(); + } + return local_machine; } /******************************************************************* - Given a pointer to a %$(NAME) expand it as an environment variable. - Return the number of characters by which the pointer should be advanced. - Based on code by Branko Cibej - When this is called p points at the '%' character. + Setup the string used by %U substitution. ********************************************************************/ -static size_t expand_env_var(char *p, int len) +void sub_set_smb_name(const char *name) { - fstring envname; - char *envval; - char *q, *r; - int copylen; + fstring tmp; + int len; + BOOL is_machine_account = False; - if (p[1] != '$') - return 1; + /* don't let anonymous logins override the name */ + if (! *name) + return; - if (p[2] != '(') - return 2; - /* - * Look for the terminating ')'. - */ + fstrcpy( tmp, name ); + trim_char( tmp, ' ', ' ' ); + strlower_m( tmp ); - if ((q = strchr_m(p,')')) == NULL) { - DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p)); - return 2; - } + len = strlen( tmp ); - /* - * Extract the name from within the %$(NAME) string. - */ + if ( len == 0 ) + return; - r = p+3; - copylen = MIN((q-r),(sizeof(envname)-1)); - strncpy(envname,r,copylen); - envname[copylen] = '\0'; + /* long story but here goes....we have to allow usernames + ending in '$' as they are valid machine account names. + So check for a machine account and re-add the '$' + at the end after the call to alpha_strcpy(). --jerry */ + + if ( tmp[len-1] == '$' ) + is_machine_account = True; + + alpha_strcpy( smb_user_name, tmp, SAFE_NETBIOS_CHARS, sizeof(smb_user_name)-1 ); - if ((envval = getenv(envname)) == NULL) { - DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname)); - return 2; + if ( is_machine_account ) { + len = strlen( smb_user_name ); + smb_user_name[len-1] = '$'; } +} - /* - * Copy the full %$(NAME) into envname so it - * can be replaced. - */ +/******************************************************************* + Setup the strings used by substitutions. Called per packet. Ensure + %U name is set correctly also. +********************************************************************/ - copylen = MIN((q+1-p),(sizeof(envname)-1)); - strncpy(envname,p,copylen); - envname[copylen] = '\0'; - string_sub(p,envname,envval,len); - return 0; /* Allow the environment contents to be parsed. */ +void set_current_user_info(const userdom_struct *pcui) +{ + current_user_info = *pcui; + /* The following is safe as current_user_info.smb_name + * has already been sanitised in register_existing_vuid. */ + fstrcpy(smb_user_name, current_user_info.smb_name); +} + +/******************************************************************* + return the current active user name +*******************************************************************/ + +const char* get_current_username( void ) +{ + if ( current_user_info.smb_name[0] == '\0' ) + return smb_user_name; + + return current_user_info.smb_name; } /******************************************************************* @@ -124,7 +174,6 @@ static size_t expand_env_var(char *p, int len) May substitute multiple occurrencies of the same env var. ********************************************************************/ - static char * realloc_expand_env_var(char *str, char *p) { char *envname; @@ -132,8 +181,9 @@ static char * realloc_expand_env_var(char *str, char *p) char *q, *r; int copylen; - if (p[0] != '%' || p[1] != '$' || p[2] != '(') + if (p[0] != '%' || p[1] != '$' || p[2] != '(') { return str; + } /* * Look for the terminating ')'. @@ -150,8 +200,12 @@ static char * realloc_expand_env_var(char *str, char *p) r = p + 3; copylen = q - r; - envname = (char *)malloc(copylen + 1 + 4); /* reserve space for use later add %$() chars */ - if (envname == NULL) return NULL; + + /* 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'; @@ -171,7 +225,105 @@ static char * realloc_expand_env_var(char *str, char *p) envname[copylen] = '\0'; r = realloc_string_sub(str, envname, envval); SAFE_FREE(envname); - if (r == NULL) return NULL; + + return r; +} + +/******************************************************************* +*******************************************************************/ + +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 ); +}; + +static 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. +********************************************************************/ + +static char *realloc_expand_longvar(char *str, char *p) +{ + fstring varname; + char *value; + char *q, *r; + int copylen; + + if ( p[0] != '%' || p[1] != '(' ) { + return str; + } + + /* Look for the terminating ')'.*/ + + if ((q = strchr_m(p,')')) == NULL) { + DEBUG(0,("realloc_expand_longvar: Unterminated environment variable [%s]\n", p)); + return str; + } + + /* Extract the name from within the %(NAME) string.*/ + + r = p+2; + copylen = MIN( (q-r), (sizeof(varname)-1) ); + strncpy(varname, r, copylen); + varname[copylen] = '\0'; + + 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.*/ + + 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; } @@ -182,7 +334,7 @@ static char * realloc_expand_env_var(char *str, char *p) static char *automount_path(const char *user_name) { - static pstring server_path; + pstring server_path; /* use the passwd entry as the default */ /* this will be the default if WITH_AUTOMOUNT is not used or fails */ @@ -192,8 +344,8 @@ static char *automount_path(const char *user_name) #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT)) if (lp_nis_home_map()) { - char *home_path_start; - char *automount_value = automount_lookup(user_name); + const char *home_path_start; + const char *automount_value = automount_lookup(user_name); if(strlen(automount_value) > 0) { home_path_start = strchr_m(automount_value,':'); @@ -211,7 +363,7 @@ static char *automount_path(const char *user_name) DEBUG(4,("Home server path: %s\n", server_path)); - return server_path; + return talloc_strdup(talloc_tos(), server_path); } /******************************************************************* @@ -222,7 +374,7 @@ static char *automount_path(const char *user_name) static const char *automount_server(const char *user_name) { - static pstring server_name; + pstring server_name; const char *local_machine_name = get_local_machine_name(); /* use the local machine name as the default */ @@ -230,7 +382,7 @@ static const char *automount_server(const char *user_name) if (local_machine_name && *local_machine_name) pstrcpy(server_name, local_machine_name); else - pstrcpy(server_name, global_myname); + pstrcpy(server_name, global_myname()); #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT)) @@ -248,7 +400,7 @@ static const char *automount_server(const char *user_name) DEBUG(4,("Home server: %s\n", server_name)); - return server_name; + return talloc_strdup(talloc_tos(), server_name); } /**************************************************************************** @@ -257,142 +409,17 @@ 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, const char *domain_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(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(tmp_str); - string_sub(p,"%D", tmp_str,l); - break; - case 'I' : - string_sub(p,"%I", client_addr(),l); - break; - case 'L' : - if (local_machine_name && *local_machine_name) - string_sub(p,"%L", local_machine_name,l); - else - string_sub(p,"%L", global_myname,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", VERSION,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, domain_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': - 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': - 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); } /**************************************************************************** @@ -400,101 +427,143 @@ static void standard_sub_advanced(int snum, const char *user, This function will return an allocated string that have to be freed. ****************************************************************************/ -char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *str) +char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, + const char *domain_name, const char *str) { char *a, *t; - a = alloc_sub_basic(smb_name, str); - if (!a) return NULL; + + if ( (a = alloc_sub_basic(smb_name, domain_name, str)) == NULL ) { + return NULL; + } t = talloc_strdup(mem_ctx, a); SAFE_FREE(a); return t; } -char *alloc_sub_basic(const char *smb_name, const char *str) +/**************************************************************************** +****************************************************************************/ + +char *alloc_sub_basic(const char *smb_name, const char *domain_name, + const char *str) { - char *b, *p, *s, *t, *r, *a_string; - fstring pidstr; + char *b, *p, *s, *r, *a_string; + fstring pidstr, vnnstr; struct passwd *pass; const char *local_machine_name = get_local_machine_name(); - a_string = strdup(str); + /* workaround to prevent a crash while looking at bug #687 */ + + if (!str) { + DEBUG(0,("alloc_sub_basic: NULL source string! This should not happen\n")); + return NULL; + } + + a_string = SMB_STRDUP(str); if (a_string == NULL) { - DEBUG(0, ("alloc_sub_specified: Out of memory!\n")); + DEBUG(0, ("alloc_sub_basic: Out of memory!\n")); return NULL; } for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) { r = NULL; - b = t = a_string; + b = a_string; switch (*(p+1)) { case 'U' : r = strdup_lower(smb_name); - if (r == NULL) goto error; - t = realloc_string_sub(t, "%U", r); + if (r == NULL) { + goto error; + } + a_string = realloc_string_sub(a_string, "%U", r); break; case 'G' : - r = strdup(smb_name); - if (r == NULL) goto error; + r = SMB_STRDUP(smb_name); + if (r == NULL) { + goto error; + } if ((pass = Get_Pwnam(r))!=NULL) { - t = realloc_string_sub(t, "%G", gidtoname(pass->pw_gid)); + a_string = realloc_string_sub(a_string, "%G", gidtoname(pass->pw_gid)); } break; case 'D' : - r = strdup_upper(current_user_info.domain); - if (r == NULL) goto error; - t = realloc_string_sub(t, "%D", r); + r = strdup_upper(domain_name); + if (r == NULL) { + goto error; + } + a_string = realloc_string_sub(a_string, "%D", r); break; case 'I' : - t = realloc_string_sub(t, "%I", client_addr()); + 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 (local_machine_name && *local_machine_name) - t = realloc_string_sub(t, "%L", local_machine_name); - else - t = realloc_string_sub(t, "%L", global_myname); + 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 { + a_string = realloc_string_sub(a_string, "%L", global_myname()); + } + break; + case 'N': + a_string = realloc_string_sub(a_string, "%N", automount_server(smb_name)); break; case 'M' : - t = realloc_string_sub(t, "%M", client_name()); + a_string = realloc_string_sub(a_string, "%M", client_name()); break; case 'R' : - t = realloc_string_sub(t, "%R", remote_proto); + a_string = realloc_string_sub(a_string, "%R", remote_proto); break; case 'T' : - t = realloc_string_sub(t, "%T", timestring(False)); + a_string = realloc_string_sub(a_string, "%T", current_timestring(False)); break; case 'a' : - t = realloc_string_sub(t, "%a", remote_arch); + a_string = realloc_string_sub(a_string, "%a", remote_arch); break; case 'd' : slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid()); - t = realloc_string_sub(t, "%d", pidstr); + a_string = realloc_string_sub(a_string, "%d", pidstr); break; case 'h' : - t = realloc_string_sub(t, "%h", myhostname()); + a_string = realloc_string_sub(a_string, "%h", myhostname()); break; case 'm' : - t = realloc_string_sub(t, "%m", remote_machine); + a_string = realloc_string_sub(a_string, "%m", remote_machine); break; case 'v' : - t = realloc_string_sub(t, "%v", VERSION); + a_string = realloc_string_sub(a_string, "%v", SAMBA_VERSION_STRING); + break; + case 'w' : + a_string = realloc_string_sub(a_string, "%w", lp_winbind_separator()); break; case '$' : - t = realloc_expand_env_var(t, p); /* Expand environment variables */ + a_string = realloc_expand_env_var(a_string, p); /* Expand environment variables */ + break; + case '(': + a_string = realloc_expand_longvar( a_string, p ); + break; + case 'V' : + slprintf(vnnstr,sizeof(vnnstr)-1, "%u", get_my_vnn()); + a_string = realloc_string_sub(a_string, "%V", vnnstr); break; - default: break; } p++; SAFE_FREE(r); - if (t == NULL) goto error; - a_string = t; + + if ( !a_string ) { + return NULL; + } } return a_string; + error: SAFE_FREE(a_string); return NULL; @@ -512,129 +581,125 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx, uid_t uid, gid_t gid) { - char *a, *t; - a = alloc_sub_specified(input_string, username, domain, uid, gid); - if (!a) return NULL; - t = talloc_strdup(mem_ctx, a); - SAFE_FREE(a); - return t; -} + char *a_string; + char *ret_string = NULL; + char *b, *p, *s; + TALLOC_CTX *tmp_ctx; -char *alloc_sub_specified(const char *input_string, - const char *username, - const char *domain, - uid_t uid, - gid_t gid) -{ - char *a_string, *ret_string; - char *b, *p, *s, *t; + if (!(tmp_ctx = talloc_new(mem_ctx))) { + DEBUG(0, ("talloc_new failed\n")); + return NULL; + } - a_string = strdup(input_string); + a_string = talloc_strdup(tmp_ctx, input_string); if (a_string == NULL) { - DEBUG(0, ("alloc_sub_specified: Out of memory!\n")); - return NULL; + DEBUG(0, ("talloc_sub_specified: Out of memory!\n")); + goto done; } for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) { - b = t = a_string; + b = a_string; switch (*(p+1)) { case 'U' : - t = realloc_string_sub(t, "%U", username); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%U", username); break; case 'u' : - t = realloc_string_sub(t, "%u", username); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%u", username); break; case 'G' : if (gid != -1) { - t = realloc_string_sub(t, "%G", gidtoname(gid)); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%G", + gidtoname(gid)); } else { - t = realloc_string_sub(t, "%G", "NO_GROUP"); + a_string = talloc_string_sub( + tmp_ctx, a_string, + "%G", "NO_GROUP"); } break; case 'g' : if (gid != -1) { - t = realloc_string_sub(t, "%g", gidtoname(gid)); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%g", + gidtoname(gid)); } else { - t = realloc_string_sub(t, "%g", "NO_GROUP"); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%g", "NO_GROUP"); } break; case 'D' : - t = realloc_string_sub(t, "%D", domain); + a_string = talloc_string_sub(tmp_ctx, a_string, + "%D", domain); break; case 'N' : - t = realloc_string_sub(t, "%N", automount_server(username)); + a_string = talloc_string_sub( + tmp_ctx, a_string, "%N", + automount_server(username)); break; default: break; } p++; - if (t == NULL) { - SAFE_FREE(a_string); - return NULL; + if (a_string == NULL) { + goto done; } - a_string = t; } - ret_string = alloc_sub_basic(username, a_string); - SAFE_FREE(a_string); + /* Watch out, using "mem_ctx" here, so all intermediate stuff goes + * away with the TALLOC_FREE(tmp_ctx) further down. */ + + ret_string = talloc_sub_basic(mem_ctx, username, domain, a_string); + + done: + TALLOC_FREE(tmp_ctx); return ret_string; } -char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, - int snum, - const char *user, - const char *connectpath, - gid_t gid, - const char *smb_name, - char *str) -{ - char *a, *t; - a = alloc_sub_advanced(snum, user, connectpath, gid, smb_name, str); - if (!a) return NULL; - t = talloc_strdup(mem_ctx, a); - SAFE_FREE(a); - return t; -} +/**************************************************************************** +****************************************************************************/ -char *alloc_sub_advanced(int snum, const char *user, - const char *connectpath, gid_t gid, - const char *smb_name, char *str) +static char *alloc_sub_advanced(const char *servicename, const char *user, + const char *connectpath, gid_t gid, + const char *smb_name, const char *domain_name, + const char *str) { char *a_string, *ret_string; - char *b, *p, *s, *t, *h; + char *b, *p, *s, *h; - a_string = strdup(str); + a_string = SMB_STRDUP(str); if (a_string == NULL) { - DEBUG(0, ("alloc_sub_specified: Out of memory!\n")); + DEBUG(0, ("alloc_sub_advanced: Out of memory!\n")); return NULL; } for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) { - b = t = a_string; + b = a_string; switch (*(p+1)) { case 'N' : - t = realloc_string_sub(t, "%N", automount_server(user)); + a_string = realloc_string_sub(a_string, "%N", automount_server(user)); break; case 'H': if ((h = get_user_home_dir(user))) - t = realloc_string_sub(t, "%H", h); + a_string = realloc_string_sub(a_string, "%H", h); break; case 'P': - t = realloc_string_sub(t, "%P", connectpath); + a_string = realloc_string_sub(a_string, "%P", connectpath); break; case 'S': - t = realloc_string_sub(t, "%S", lp_servicename(snum)); + a_string = realloc_string_sub(a_string, "%S", servicename); break; case 'g': - t = realloc_string_sub(t, "%g", gidtoname(gid)); + a_string = realloc_string_sub(a_string, "%g", gidtoname(gid)); break; case 'u': - t = realloc_string_sub(t, "%u", user); + a_string = realloc_string_sub(a_string, "%u", user); break; /* Patch from jkf@soton.ac.uk Left the %N (NIS @@ -645,7 +710,8 @@ char *alloc_sub_advanced(int snum, const char *user, * "path =" string in [homes] and so needs the * service name, not the username. */ case 'p': - t = realloc_string_sub(t, "%p", automount_path(lp_servicename(snum))); + a_string = realloc_string_sub(a_string, "%p", + automount_path(servicename)); break; default: @@ -653,58 +719,69 @@ char *alloc_sub_advanced(int snum, const char *user, } p++; - if (t == NULL) { - SAFE_FREE(a_string); + if (a_string == NULL) { return NULL; } - a_string = t; } - ret_string = alloc_sub_basic(smb_name, a_string); + ret_string = alloc_sub_basic(smb_name, domain_name, a_string); SAFE_FREE(a_string); return ret_string; } -/**************************************************************************** - Do some standard substitutions in a string. -****************************************************************************/ +/* + * This obviously is inefficient and needs to be merged into + * alloc_sub_advanced... + */ -void standard_sub_conn(connection_struct *conn, char *str, size_t len) +char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, + const char *servicename, const char *user, + const char *connectpath, gid_t gid, + const char *smb_name, const char *domain_name, + const char *str) { - standard_sub_advanced(SNUM(conn), conn->user, conn->connectpath, - conn->gid, current_user_info.smb_name, str, len); -} + char *a, *t; -char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, char *str) -{ - return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user, - conn->connectpath, conn->gid, - current_user_info.smb_name, str); + if (!(a = alloc_sub_advanced(servicename, user, connectpath, gid, + smb_name, domain_name, str))) { + return NULL; + } + t = talloc_strdup(mem_ctx, a); + SAFE_FREE(a); + return t; } -char *alloc_sub_conn(connection_struct *conn, char *str) + +void standard_sub_advanced(const char *servicename, const char *user, + const char *connectpath, gid_t gid, + const char *smb_name, const char *domain_name, + char *str, size_t len) { - return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath, - conn->gid, current_user_info.smb_name, str); + char *s; + + s = alloc_sub_advanced(servicename, user, connectpath, + gid, smb_name, domain_name, str); + + if ( s ) { + strncpy( str, s, len ); + SAFE_FREE( s ); + } } /**************************************************************************** - Like standard_sub but by snum. -****************************************************************************/ + * Do some standard substitutions in a string. + * ****************************************************************************/ -void standard_sub_snum(int snum, char *str, size_t len) +void standard_sub_conn(connection_struct *conn, char *str, size_t len) { - extern struct current_user current_user; - static uid_t cached_uid = -1; - static fstring cached_user; - /* calling uidtoname() on every substitute would be too expensive, so - we cache the result here as nearly every call is for the same uid */ - - if (cached_uid != current_user.uid) { - fstrcpy(cached_user, uidtoname(current_user.uid)); - cached_uid = current_user.uid; - } + char *s; + + s = alloc_sub_advanced(lp_servicename(SNUM(conn)), conn->user, conn->connectpath, + conn->gid, smb_user_name, "", str); - standard_sub_advanced(snum, cached_user, "", -1, - current_user_info.smb_name, str, len); + if ( s ) { + strncpy( str, s, len ); + SAFE_FREE( s ); + } } +