root/source3/lib/substitute.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. free_local_machine_name
  2. set_local_machine_name
  3. get_local_machine_name
  4. set_remote_machine_name
  5. get_remote_machine_name
  6. sub_set_smb_name
  7. get_smb_user_name
  8. set_current_user_info
  9. get_current_username
  10. realloc_expand_env_var
  11. longvar_domainsid
  12. get_longvar_val
  13. realloc_expand_longvar
  14. automount_path
  15. automount_server
  16. standard_sub_basic
  17. talloc_sub_basic
  18. alloc_sub_basic
  19. talloc_sub_specified
  20. alloc_sub_advanced
  21. talloc_sub_advanced
  22. standard_sub_advanced
  23. standard_sub_conn

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    string substitution functions
   4    Copyright (C) Andrew Tridgell 1992-2000
   5    Copyright (C) Gerald Carter   2006
   6    
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11    
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16    
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 
  22 #include "includes.h"
  23 
  24 userdom_struct current_user_info;
  25 fstring remote_proto="UNKNOWN";
  26 
  27 /**
  28  * Set the 'local' machine name
  29  * @param local_name the name we are being called
  30  * @param if this is the 'final' name for us, not be be changed again
  31  */
  32 
  33 static char *local_machine;
  34 
  35 void free_local_machine_name(void)
     /* [<][>][^][v][top][bottom][index][help] */
  36 {
  37         SAFE_FREE(local_machine);
  38 }
  39 
  40 bool set_local_machine_name(const char *local_name, bool perm)
     /* [<][>][^][v][top][bottom][index][help] */
  41 {
  42         static bool already_perm = false;
  43         char *tmp_local_machine = NULL;
  44         char addr[INET6_ADDRSTRLEN];
  45         size_t len;
  46 
  47         tmp_local_machine = SMB_STRDUP(local_name);
  48         if (!tmp_local_machine) {
  49                 return false;
  50         }
  51         trim_char(tmp_local_machine,' ',' ');
  52 
  53         /*
  54          * Windows NT/2k uses "*SMBSERVER" and XP uses "*SMBSERV"
  55          * arrggg!!!
  56          */
  57 
  58         if (strequal(tmp_local_machine, "*SMBSERVER") ||
  59                         strequal(tmp_local_machine, "*SMBSERV") )  {
  60                 SAFE_FREE(local_machine);
  61                 local_machine = SMB_STRDUP(client_socket_addr(get_client_fd(),
  62                                         addr, sizeof(addr)) );
  63                 SAFE_FREE(tmp_local_machine);
  64                 return local_machine ? true : false;
  65         }
  66 
  67         if (already_perm) {
  68                 return true;
  69         }
  70 
  71         SAFE_FREE(local_machine);
  72         len = strlen(tmp_local_machine);
  73         local_machine = SMB_CALLOC_ARRAY(char, len+1);
  74         if (!local_machine) {
  75                 SAFE_FREE(tmp_local_machine);
  76                 return false;
  77         }
  78         /* alpha_strcpy includes the space for the terminating nul. */
  79         alpha_strcpy(local_machine,tmp_local_machine,
  80                         SAFE_NETBIOS_CHARS,len+1);
  81         strlower_m(local_machine);
  82         SAFE_FREE(tmp_local_machine);
  83 
  84         already_perm = perm;
  85 
  86         return true;
  87 }
  88 
  89 const char *get_local_machine_name(void)
     /* [<][>][^][v][top][bottom][index][help] */
  90 {
  91         if (!local_machine || !*local_machine) {
  92                 return global_myname();
  93         }
  94 
  95         return local_machine;
  96 }
  97 
  98 /**
  99  * Set the 'remote' machine name
 100  * @param remote_name the name our client wants to be called by
 101  * @param if this is the 'final' name for them, not be be changed again
 102  */
 103 
 104 static char *remote_machine;
 105 
 106 bool set_remote_machine_name(const char *remote_name, bool perm)
     /* [<][>][^][v][top][bottom][index][help] */
 107 {
 108         static bool already_perm = False;
 109         char *tmp_remote_machine;
 110         size_t len;
 111 
 112         if (already_perm) {
 113                 return true;
 114         }
 115 
 116         tmp_remote_machine = SMB_STRDUP(remote_name);
 117         if (!tmp_remote_machine) {
 118                 return false;
 119         }
 120         trim_char(tmp_remote_machine,' ',' ');
 121 
 122         SAFE_FREE(remote_machine);
 123         len = strlen(tmp_remote_machine);
 124         remote_machine = SMB_CALLOC_ARRAY(char, len+1);
 125         if (!remote_machine) {
 126                 SAFE_FREE(tmp_remote_machine);
 127                 return false;
 128         }
 129 
 130         /* alpha_strcpy includes the space for the terminating nul. */
 131         alpha_strcpy(remote_machine,tmp_remote_machine,
 132                         SAFE_NETBIOS_CHARS,len+1);
 133         strlower_m(remote_machine);
 134         SAFE_FREE(tmp_remote_machine);
 135 
 136         already_perm = perm;
 137 
 138         return true;
 139 }
 140 
 141 const char *get_remote_machine_name(void)
     /* [<][>][^][v][top][bottom][index][help] */
 142 {
 143         return remote_machine ? remote_machine : "";
 144 }
 145 
 146 /*******************************************************************
 147  Setup the string used by %U substitution.
 148 ********************************************************************/
 149 
 150 static char *smb_user_name;
 151 
 152 void sub_set_smb_name(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 153 {
 154         char *tmp;
 155         size_t len;
 156         bool is_machine_account = false;
 157 
 158         /* don't let anonymous logins override the name */
 159         if (!name || !*name) {
 160                 return;
 161         }
 162 
 163         tmp = SMB_STRDUP(name);
 164         if (!tmp) {
 165                 return;
 166         }
 167         trim_char(tmp, ' ', ' ');
 168         strlower_m(tmp);
 169 
 170         len = strlen(tmp);
 171 
 172         if (len == 0) {
 173                 SAFE_FREE(tmp);
 174                 return;
 175         }
 176 
 177         /* long story but here goes....we have to allow usernames
 178            ending in '$' as they are valid machine account names.
 179            So check for a machine account and re-add the '$'
 180            at the end after the call to alpha_strcpy().   --jerry  */
 181 
 182         if (tmp[len-1] == '$') {
 183                 is_machine_account = True;
 184         }
 185 
 186         SAFE_FREE(smb_user_name);
 187         smb_user_name = SMB_CALLOC_ARRAY(char, len+1);
 188         if (!smb_user_name) {
 189                 SAFE_FREE(tmp);
 190                 return;
 191         }
 192 
 193         /* alpha_strcpy includes the space for the terminating nul. */
 194         alpha_strcpy(smb_user_name, tmp,
 195                         SAFE_NETBIOS_CHARS,
 196                         len+1);
 197 
 198         SAFE_FREE(tmp);
 199 
 200         if (is_machine_account) {
 201                 len = strlen(smb_user_name);
 202                 smb_user_name[len-1] = '$';
 203         }
 204 }
 205 
 206 static const char *get_smb_user_name(void)
     /* [<][>][^][v][top][bottom][index][help] */
 207 {
 208         return smb_user_name ? smb_user_name : "";
 209 }
 210 
 211 /*******************************************************************
 212  Setup the strings used by substitutions. Called per packet. Ensure
 213  %U name is set correctly also.
 214 
 215  smb_name must be sanitized by alpha_strcpy
 216 ********************************************************************/
 217 
 218 void set_current_user_info(const char *smb_name, const char *unix_name,
     /* [<][>][^][v][top][bottom][index][help] */
 219                            const char *domain)
 220 {
 221         fstrcpy(current_user_info.smb_name, smb_name);
 222         fstrcpy(current_user_info.unix_name, unix_name);
 223         fstrcpy(current_user_info.domain, domain);
 224 
 225         /* The following is safe as current_user_info.smb_name
 226          * has already been sanitised in register_existing_vuid. */
 227 
 228         sub_set_smb_name(current_user_info.smb_name);
 229 }
 230 
 231 /*******************************************************************
 232  Return the current active user name.
 233 *******************************************************************/
 234 
 235 const char *get_current_username(void)
     /* [<][>][^][v][top][bottom][index][help] */
 236 {
 237         if (current_user_info.smb_name[0] == '\0' ) {
 238                 return get_smb_user_name();
 239         }
 240 
 241         return current_user_info.smb_name;
 242 }
 243 
 244 /*******************************************************************
 245  Given a pointer to a %$(NAME) in p and the whole string in str
 246  expand it as an environment variable.
 247  Return a new allocated and expanded string.
 248  Based on code by Branko Cibej <branko.cibej@hermes.si>
 249  When this is called p points at the '%' character.
 250  May substitute multiple occurrencies of the same env var.
 251 ********************************************************************/
 252 
 253 static char * realloc_expand_env_var(char *str, char *p)
     /* [<][>][^][v][top][bottom][index][help] */
 254 {
 255         char *envname;
 256         char *envval;
 257         char *q, *r;
 258         int copylen;
 259 
 260         if (p[0] != '%' || p[1] != '$' || p[2] != '(') {
 261                 return str;
 262         }
 263 
 264         /*
 265          * Look for the terminating ')'.
 266          */
 267 
 268         if ((q = strchr_m(p,')')) == NULL) {
 269                 DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
 270                 return str;
 271         }
 272 
 273         /*
 274          * Extract the name from within the %$(NAME) string.
 275          */
 276 
 277         r = p + 3;
 278         copylen = q - r;
 279         
 280         /* reserve space for use later add %$() chars */
 281         if ( (envname = (char *)SMB_MALLOC(copylen + 1 + 4)) == NULL ) {
 282                 return NULL;
 283         }
 284         
 285         strncpy(envname,r,copylen);
 286         envname[copylen] = '\0';
 287 
 288         if ((envval = getenv(envname)) == NULL) {
 289                 DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
 290                 SAFE_FREE(envname);
 291                 return str;
 292         }
 293 
 294         /*
 295          * Copy the full %$(NAME) into envname so it
 296          * can be replaced.
 297          */
 298 
 299         copylen = q + 1 - p;
 300         strncpy(envname,p,copylen);
 301         envname[copylen] = '\0';
 302         r = realloc_string_sub(str, envname, envval);
 303         SAFE_FREE(envname);
 304                 
 305         return r;
 306 }
 307 
 308 /*******************************************************************
 309 *******************************************************************/
 310 
 311 static char *longvar_domainsid( void )
     /* [<][>][^][v][top][bottom][index][help] */
 312 {
 313         DOM_SID sid;
 314         fstring tmp;
 315         char *sid_string;
 316         
 317         if ( !secrets_fetch_domain_sid( lp_workgroup(), &sid ) ) {
 318                 return NULL;
 319         }
 320         
 321         sid_string = SMB_STRDUP( sid_to_fstring( tmp, &sid ) );
 322         
 323         if ( !sid_string ) {
 324                 DEBUG(0,("longvar_domainsid: failed to dup SID string!\n"));
 325         }
 326         
 327         return sid_string;
 328 }
 329 
 330 /*******************************************************************
 331 *******************************************************************/
 332 
 333 struct api_longvar {
 334         const char *name;
 335         char* (*fn)( void );
 336 };
 337 
 338 static struct api_longvar longvar_table[] = {
 339         { "DomainSID",          longvar_domainsid },
 340         { NULL,                 NULL }
 341 };
 342 
 343 static char *get_longvar_val( const char *varname )
     /* [<][>][^][v][top][bottom][index][help] */
 344 {
 345         int i;
 346         
 347         DEBUG(7,("get_longvar_val: expanding variable [%s]\n", varname));
 348         
 349         for ( i=0; longvar_table[i].name; i++ ) {
 350                 if ( strequal( longvar_table[i].name, varname ) ) {
 351                         return longvar_table[i].fn();
 352                 }
 353         }
 354         
 355         return NULL;
 356 }
 357 
 358 /*******************************************************************
 359  Expand the long smb.conf variable names given a pointer to a %(NAME).
 360  Return the number of characters by which the pointer should be advanced.
 361  When this is called p points at the '%' character.
 362 ********************************************************************/
 363 
 364 static char *realloc_expand_longvar(char *str, char *p)
     /* [<][>][^][v][top][bottom][index][help] */
 365 {
 366         fstring varname;
 367         char *value;
 368         char *q, *r;
 369         int copylen;
 370 
 371         if ( p[0] != '%' || p[1] != '(' ) {
 372                 return str;
 373         }
 374 
 375         /* Look for the terminating ')'.*/
 376 
 377         if ((q = strchr_m(p,')')) == NULL) {
 378                 DEBUG(0,("realloc_expand_longvar: Unterminated environment variable [%s]\n", p));
 379                 return str;
 380         }
 381 
 382         /* Extract the name from within the %(NAME) string.*/
 383 
 384         r = p+2;
 385         copylen = MIN( (q-r), (sizeof(varname)-1) );
 386         strncpy(varname, r, copylen);
 387         varname[copylen] = '\0';
 388 
 389         if ((value = get_longvar_val(varname)) == NULL) {
 390                 DEBUG(0,("realloc_expand_longvar: Variable [%s] not set.  Skipping\n", varname));
 391                 return str;
 392         }
 393 
 394         /* Copy the full %(NAME) into envname so it can be replaced.*/
 395 
 396         copylen = MIN( (q+1-p),(sizeof(varname)-1) );
 397         strncpy( varname, p, copylen );
 398         varname[copylen] = '\0';
 399         r = realloc_string_sub(str, varname, value);
 400         SAFE_FREE( value );
 401 
 402         /* skip over the %(varname) */
 403 
 404         return r;
 405 }
 406 
 407 /*******************************************************************
 408  Patch from jkf@soton.ac.uk
 409  Added this to implement %p (NIS auto-map version of %H)
 410 *******************************************************************/
 411 
 412 static const char *automount_path(const char *user_name)
     /* [<][>][^][v][top][bottom][index][help] */
 413 {
 414         TALLOC_CTX *ctx = talloc_tos();
 415         const char *server_path;
 416 
 417         /* use the passwd entry as the default */
 418         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
 419 
 420         server_path = talloc_strdup(ctx, get_user_home_dir(ctx, user_name));
 421         if (!server_path) {
 422                 return "";
 423         }
 424 
 425 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
 426 
 427         if (lp_nis_home_map()) {
 428                 const char *home_path_start;
 429                 char *automount_value = automount_lookup(ctx, user_name);
 430 
 431                 if(automount_value && strlen(automount_value) > 0) {
 432                         home_path_start = strchr_m(automount_value,':');
 433                         if (home_path_start != NULL) {
 434                                 DEBUG(5, ("NIS lookup succeeded. "
 435                                         "Home path is: %s\n",
 436                                         home_path_start ?
 437                                                 (home_path_start+1):""));
 438                                 server_path = talloc_strdup(ctx,
 439                                                         home_path_start+1);
 440                                 if (!server_path) {
 441                                         server_path = "";
 442                                 }
 443                         }
 444                 } else {
 445                         /* NIS key lookup failed: default to
 446                          * user home directory from password file */
 447                         DEBUG(5, ("NIS lookup failed. Using Home path from "
 448                         "passwd file. Home path is: %s\n", server_path ));
 449                 }
 450         }
 451 #endif
 452 
 453         DEBUG(4,("Home server path: %s\n", server_path));
 454         return server_path;
 455 }
 456 
 457 /*******************************************************************
 458  Patch from jkf@soton.ac.uk
 459  This is Luke's original function with the NIS lookup code
 460  moved out to a separate function.
 461 *******************************************************************/
 462 
 463 static const char *automount_server(const char *user_name)
     /* [<][>][^][v][top][bottom][index][help] */
 464 {
 465         TALLOC_CTX *ctx = talloc_tos();
 466         const char *server_name;
 467         const char *local_machine_name = get_local_machine_name();
 468 
 469         /* use the local machine name as the default */
 470         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
 471         if (local_machine_name && *local_machine_name) {
 472                 server_name = talloc_strdup(ctx, local_machine_name);
 473         } else {
 474                 server_name = talloc_strdup(ctx, global_myname());
 475         }
 476 
 477         if (!server_name) {
 478                 return "";
 479         }
 480 
 481 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
 482         if (lp_nis_home_map()) {
 483                 char *p;
 484                 char *srv;
 485                 char *automount_value = automount_lookup(ctx, user_name);
 486                 if (!automount_value) {
 487                         return "";
 488                 }
 489                 srv = talloc_strdup(ctx, automount_value);
 490                 if (!srv) {
 491                         return "";
 492                 }
 493                 p = strchr_m(srv, ':');
 494                 if (!p) {
 495                         return "";
 496                 }
 497                 *p = '\0';
 498                 server_name = srv;
 499                 DEBUG(5, ("NIS lookup succeeded.  Home server %s\n",
 500                                         server_name));
 501         }
 502 #endif
 503 
 504         DEBUG(4,("Home server: %s\n", server_name));
 505         return server_name;
 506 }
 507 
 508 /****************************************************************************
 509  Do some standard substitutions in a string.
 510  len is the length in bytes of the space allowed in string str. If zero means
 511  don't allow expansions.
 512 ****************************************************************************/
 513 
 514 void standard_sub_basic(const char *smb_name, const char *domain_name,
     /* [<][>][^][v][top][bottom][index][help] */
 515                         char *str, size_t len)
 516 {
 517         char *s;
 518         
 519         if ( (s = alloc_sub_basic( smb_name, domain_name, str )) != NULL ) {
 520                 strncpy( str, s, len );
 521         }
 522         
 523         SAFE_FREE( s );
 524         
 525 }
 526 
 527 /****************************************************************************
 528  Do some standard substitutions in a string.
 529  This function will return an allocated string that have to be freed.
 530 ****************************************************************************/
 531 
 532 char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name,
     /* [<][>][^][v][top][bottom][index][help] */
 533                        const char *domain_name, const char *str)
 534 {
 535         char *a, *t;
 536         
 537         if ( (a = alloc_sub_basic(smb_name, domain_name, str)) == NULL ) {
 538                 return NULL;
 539         }
 540         t = talloc_strdup(mem_ctx, a);
 541         SAFE_FREE(a);
 542         return t;
 543 }
 544 
 545 /****************************************************************************
 546 ****************************************************************************/
 547 
 548 char *alloc_sub_basic(const char *smb_name, const char *domain_name,
     /* [<][>][^][v][top][bottom][index][help] */
 549                       const char *str)
 550 {
 551         char *b, *p, *s, *r, *a_string;
 552         fstring pidstr, vnnstr;
 553         char addr[INET6_ADDRSTRLEN];
 554         const char *local_machine_name = get_local_machine_name();
 555         TALLOC_CTX *tmp_ctx = NULL;
 556 
 557         /* workaround to prevent a crash while looking at bug #687 */
 558         
 559         if (!str) {
 560                 DEBUG(0,("alloc_sub_basic: NULL source string!  This should not happen\n"));
 561                 return NULL;
 562         }
 563         
 564         a_string = SMB_STRDUP(str);
 565         if (a_string == NULL) {
 566                 DEBUG(0, ("alloc_sub_basic: Out of memory!\n"));
 567                 return NULL;
 568         }
 569 
 570         tmp_ctx = talloc_stackframe();
 571 
 572         for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
 573 
 574                 r = NULL;
 575                 b = a_string;
 576 
 577                 switch (*(p+1)) {
 578                 case 'U' : 
 579                         r = strdup_lower(smb_name);
 580                         if (r == NULL) {
 581                                 goto error;
 582                         }
 583                         a_string = realloc_string_sub(a_string, "%U", r);
 584                         break;
 585                 case 'G' : {
 586                         struct passwd *pass;
 587                         r = SMB_STRDUP(smb_name);
 588                         if (r == NULL) {
 589                                 goto error;
 590                         }
 591                         pass = Get_Pwnam_alloc(tmp_ctx, r);
 592                         if (pass != NULL) {
 593                                 a_string = realloc_string_sub(
 594                                         a_string, "%G",
 595                                         gidtoname(pass->pw_gid));
 596                         }
 597                         TALLOC_FREE(pass);
 598                         break;
 599                 }
 600                 case 'D' :
 601                         r = strdup_upper(domain_name);
 602                         if (r == NULL) {
 603                                 goto error;
 604                         }
 605                         a_string = realloc_string_sub(a_string, "%D", r);
 606                         break;
 607                 case 'I' : {
 608                         int offset = 0;
 609                         client_addr(get_client_fd(), addr, sizeof(addr));
 610                         if (strnequal(addr,"::ffff:",7)) {
 611                                 offset = 7;
 612                         }
 613                         a_string = realloc_string_sub(a_string, "%I",
 614                                                       addr + offset);
 615                         break;
 616                 }
 617                 case 'i': 
 618                         a_string = realloc_string_sub( a_string, "%i",
 619                                         client_socket_addr(get_client_fd(), addr, sizeof(addr)) );
 620                         break;
 621                 case 'L' : 
 622                         if ( StrnCaseCmp(p, "%LOGONSERVER%", strlen("%LOGONSERVER%")) == 0 ) {
 623                                 break;
 624                         }
 625                         if (local_machine_name && *local_machine_name) {
 626                                 a_string = realloc_string_sub(a_string, "%L", local_machine_name); 
 627                         } else {
 628                                 a_string = realloc_string_sub(a_string, "%L", global_myname()); 
 629                         }
 630                         break;
 631                 case 'N':
 632                         a_string = realloc_string_sub(a_string, "%N", automount_server(smb_name));
 633                         break;
 634                 case 'M' :
 635                         a_string = realloc_string_sub(a_string, "%M", client_name(get_client_fd()));
 636                         break;
 637                 case 'R' :
 638                         a_string = realloc_string_sub(a_string, "%R", remote_proto);
 639                         break;
 640                 case 'T' :
 641                         a_string = realloc_string_sub(a_string, "%T", current_timestring(tmp_ctx, False));
 642                         break;
 643                 case 'a' :
 644                         a_string = realloc_string_sub(a_string, "%a",
 645                                         get_remote_arch_str());
 646                         break;
 647                 case 'd' :
 648                         slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid());
 649                         a_string = realloc_string_sub(a_string, "%d", pidstr);
 650                         break;
 651                 case 'h' :
 652                         a_string = realloc_string_sub(a_string, "%h", myhostname());
 653                         break;
 654                 case 'm' :
 655                         a_string = realloc_string_sub(a_string, "%m",
 656                                                       remote_machine
 657                                                       ? remote_machine
 658                                                       : "");
 659                         break;
 660                 case 'v' :
 661                         a_string = realloc_string_sub(a_string, "%v", samba_version_string());
 662                         break;
 663                 case 'w' :
 664                         a_string = realloc_string_sub(a_string, "%w", lp_winbind_separator());
 665                         break;
 666                 case '$' :
 667                         a_string = realloc_expand_env_var(a_string, p); /* Expand environment variables */
 668                         break;
 669                 case '(':
 670                         a_string = realloc_expand_longvar( a_string, p );
 671                         break;
 672                 case 'V' :
 673                         slprintf(vnnstr,sizeof(vnnstr)-1, "%u", get_my_vnn());
 674                         a_string = realloc_string_sub(a_string, "%V", vnnstr);
 675                         break;
 676                 default: 
 677                         break;
 678                 }
 679 
 680                 p++;
 681                 SAFE_FREE(r);
 682 
 683                 if (a_string == NULL) {
 684                         goto done;
 685                 }
 686         }
 687 
 688         goto done;
 689 
 690 error:
 691         SAFE_FREE(a_string);
 692 
 693 done:
 694         TALLOC_FREE(tmp_ctx);
 695         return a_string;
 696 }
 697 
 698 /****************************************************************************
 699  Do some specific substitutions in a string.
 700  This function will return an allocated string that have to be freed.
 701 ****************************************************************************/
 702 
 703 char *talloc_sub_specified(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 704                         const char *input_string,
 705                         const char *username,
 706                         const char *domain,
 707                         uid_t uid,
 708                         gid_t gid)
 709 {
 710         char *a_string;
 711         char *ret_string = NULL;
 712         char *b, *p, *s;
 713         TALLOC_CTX *tmp_ctx;
 714 
 715         if (!(tmp_ctx = talloc_new(mem_ctx))) {
 716                 DEBUG(0, ("talloc_new failed\n"));
 717                 return NULL;
 718         }
 719 
 720         a_string = talloc_strdup(tmp_ctx, input_string);
 721         if (a_string == NULL) {
 722                 DEBUG(0, ("talloc_sub_specified: Out of memory!\n"));
 723                 goto done;
 724         }
 725         
 726         for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
 727                 
 728                 b = a_string;
 729                 
 730                 switch (*(p+1)) {
 731                 case 'U' : 
 732                         a_string = talloc_string_sub(
 733                                 tmp_ctx, a_string, "%U", username);
 734                         break;
 735                 case 'u' : 
 736                         a_string = talloc_string_sub(
 737                                 tmp_ctx, a_string, "%u", username);
 738                         break;
 739                 case 'G' :
 740                         if (gid != -1) {
 741                                 a_string = talloc_string_sub(
 742                                         tmp_ctx, a_string, "%G",
 743                                         gidtoname(gid));
 744                         } else {
 745                                 a_string = talloc_string_sub(
 746                                         tmp_ctx, a_string,
 747                                         "%G", "NO_GROUP");
 748                         }
 749                         break;
 750                 case 'g' :
 751                         if (gid != -1) {
 752                                 a_string = talloc_string_sub(
 753                                         tmp_ctx, a_string, "%g",
 754                                         gidtoname(gid));
 755                         } else {
 756                                 a_string = talloc_string_sub(
 757                                         tmp_ctx, a_string, "%g", "NO_GROUP");
 758                         }
 759                         break;
 760                 case 'D' :
 761                         a_string = talloc_string_sub(tmp_ctx, a_string,
 762                                                      "%D", domain);
 763                         break;
 764                 case 'N' : 
 765                         a_string = talloc_string_sub(
 766                                 tmp_ctx, a_string, "%N",
 767                                 automount_server(username)); 
 768                         break;
 769                 default: 
 770                         break;
 771                 }
 772 
 773                 p++;
 774                 if (a_string == NULL) {
 775                         goto done;
 776                 }
 777         }
 778 
 779         /* Watch out, using "mem_ctx" here, so all intermediate stuff goes
 780          * away with the TALLOC_FREE(tmp_ctx) further down. */
 781 
 782         ret_string = talloc_sub_basic(mem_ctx, username, domain, a_string);
 783 
 784  done:
 785         TALLOC_FREE(tmp_ctx);
 786         return ret_string;
 787 }
 788 
 789 /****************************************************************************
 790 ****************************************************************************/
 791 
 792 static char *alloc_sub_advanced(const char *servicename, const char *user, 
     /* [<][>][^][v][top][bottom][index][help] */
 793                          const char *connectpath, gid_t gid, 
 794                          const char *smb_name, const char *domain_name,
 795                          const char *str)
 796 {
 797         char *a_string, *ret_string;
 798         char *b, *p, *s;
 799 
 800         a_string = SMB_STRDUP(str);
 801         if (a_string == NULL) {
 802                 DEBUG(0, ("alloc_sub_advanced: Out of memory!\n"));
 803                 return NULL;
 804         }
 805         
 806         for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
 807                 
 808                 b = a_string;
 809                 
 810                 switch (*(p+1)) {
 811                 case 'N' :
 812                         a_string = realloc_string_sub(a_string, "%N", automount_server(user));
 813                         break;
 814                 case 'H': {
 815                         char *h;
 816                         if ((h = get_user_home_dir(talloc_tos(), user)))
 817                                 a_string = realloc_string_sub(a_string, "%H", h);
 818                         TALLOC_FREE(h);
 819                         break;
 820                 }
 821                 case 'P': 
 822                         a_string = realloc_string_sub(a_string, "%P", connectpath); 
 823                         break;
 824                 case 'S': 
 825                         a_string = realloc_string_sub(a_string, "%S", servicename);
 826                         break;
 827                 case 'g': 
 828                         a_string = realloc_string_sub(a_string, "%g", gidtoname(gid)); 
 829                         break;
 830                 case 'u': 
 831                         a_string = realloc_string_sub(a_string, "%u", user); 
 832                         break;
 833                         
 834                         /* Patch from jkf@soton.ac.uk Left the %N (NIS
 835                          * server name) in standard_sub_basic as it is
 836                          * a feature for logon servers, hence uses the
 837                          * username.  The %p (NIS server path) code is
 838                          * here as it is used instead of the default
 839                          * "path =" string in [homes] and so needs the
 840                          * service name, not the username.  */
 841                 case 'p': 
 842                         a_string = realloc_string_sub(a_string, "%p",
 843                                                       automount_path(servicename)); 
 844                         break;
 845                         
 846                 default: 
 847                         break;
 848                 }
 849 
 850                 p++;
 851                 if (a_string == NULL) {
 852                         return NULL;
 853                 }
 854         }
 855 
 856         ret_string = alloc_sub_basic(smb_name, domain_name, a_string);
 857         SAFE_FREE(a_string);
 858         return ret_string;
 859 }
 860 
 861 /*
 862  * This obviously is inefficient and needs to be merged into
 863  * alloc_sub_advanced...
 864  */
 865 
 866 char *talloc_sub_advanced(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 867                           const char *servicename, const char *user,
 868                           const char *connectpath, gid_t gid,
 869                           const char *smb_name, const char *domain_name,
 870                           const char *str)
 871 {
 872         char *a, *t;
 873 
 874         if (!(a = alloc_sub_advanced(servicename, user, connectpath, gid,
 875                                      smb_name, domain_name, str))) {
 876                 return NULL;
 877         }
 878         t = talloc_strdup(mem_ctx, a);
 879         SAFE_FREE(a);
 880         return t;
 881 }
 882 
 883 
 884 void standard_sub_advanced(const char *servicename, const char *user,
     /* [<][>][^][v][top][bottom][index][help] */
 885                            const char *connectpath, gid_t gid,
 886                            const char *smb_name, const char *domain_name,
 887                            char *str, size_t len)
 888 {
 889         char *s;
 890 
 891         s = alloc_sub_advanced(servicename, user, connectpath,
 892                                gid, smb_name, domain_name, str);
 893 
 894         if ( s ) {
 895                 strncpy( str, s, len );
 896                 SAFE_FREE( s );
 897         }
 898 }
 899 
 900 /****************************************************************************
 901  Do some standard substitutions in a string.
 902 ****************************************************************************/
 903 
 904 char *standard_sub_conn(TALLOC_CTX *ctx, connection_struct *conn, const char *str)
     /* [<][>][^][v][top][bottom][index][help] */
 905 {
 906         return talloc_sub_advanced(ctx,
 907                                 lp_servicename(SNUM(conn)),
 908                                 conn->server_info->unix_name,
 909                                 conn->connectpath,
 910                                 conn->server_info->utok.gid,
 911                                 get_smb_user_name(),
 912                                 "",
 913                                 str);
 914 }

/* [<][>][^][v][top][bottom][index][help] */