r14075: * add support for long variable names in smb.conf in the form of %(....)
authorGerald Carter <jerry@samba.org>
Thu, 9 Mar 2006 15:51:55 +0000 (15:51 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:11:09 +0000 (11:11 -0500)
* 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())

source/Makefile.in
source/lib/substitute.c
source/smbd/share_access.c

index d5346cf4f92a59f4fd4d44e95b32b67a1a8620b4..f31e5fb3aa46c05ae4723eacbc280e17d6227711 100644 (file)
@@ -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) \
index 23b204d02460101326bf7d213403a753e66c5cf1..bfe7dc814caf66d009a667f2f76e5fde65f45aae 100644 (file)
@@ -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 <branko.cibej@hermes.si>
  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 <branko.cibej@hermes.si>
+*******************************************************************/
+
+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 );
+       }
 }
index a429937f8d5e19ca36388553e0beec2484139e65..df5f445587fbf3809be588bcb089fc53c657269f 100644 (file)
@@ -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;
                }