2 Unix SMB/CIFS implementation.
3 string substitution functions
4 Copyright (C) Andrew Tridgell 1992-2000
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern struct current_user current_user
;
26 fstring local_machine
="";
27 fstring remote_arch
="UNKNOWN";
28 userdom_struct current_user_info
;
29 fstring remote_proto
="UNKNOWN";
31 static fstring remote_machine
;
32 static fstring smb_user_name
;
35 * Set the 'local' machine name
36 * @param local_name the name we are being called
37 * @param if this is the 'final' name for us, not be be changed again
40 void set_local_machine_name(const char* local_name
, BOOL perm
)
42 static BOOL already_perm
= False
;
43 fstring tmp_local_machine
;
45 fstrcpy(tmp_local_machine
,local_name
);
46 trim_char(tmp_local_machine
,' ',' ');
49 * Windows NT/2k uses "*SMBSERVER" and XP uses "*SMBSERV"
53 if ( strequal(tmp_local_machine
, "*SMBSERVER") || strequal(tmp_local_machine
, "*SMBSERV") ) {
54 fstrcpy( local_machine
, client_socket_addr() );
63 alpha_strcpy(local_machine
,tmp_local_machine
,SAFE_NETBIOS_CHARS
,sizeof(local_machine
)-1);
64 strlower_m(local_machine
);
68 * Set the 'remote' machine name
69 * @param remote_name the name our client wants to be called by
70 * @param if this is the 'final' name for them, not be be changed again
73 void set_remote_machine_name(const char* remote_name
, BOOL perm
)
75 static BOOL already_perm
= False
;
76 fstring tmp_remote_machine
;
83 fstrcpy(tmp_remote_machine
,remote_name
);
84 trim_char(tmp_remote_machine
,' ',' ');
85 alpha_strcpy(remote_machine
,tmp_remote_machine
,SAFE_NETBIOS_CHARS
,sizeof(remote_machine
)-1);
86 strlower_m(remote_machine
);
89 const char* get_remote_machine_name(void)
91 return remote_machine
;
94 const char* get_local_machine_name(void)
96 if (!*local_machine
) {
97 return global_myname();
100 return local_machine
;
103 /*******************************************************************
104 Setup the string used by %U substitution.
105 ********************************************************************/
107 void sub_set_smb_name(const char *name
)
111 BOOL is_machine_account
= False
;
113 /* don't let anonymous logins override the name */
118 fstrcpy( tmp
, name
);
119 trim_char( tmp
, ' ', ' ' );
127 /* long story but here goes....we have to allow usernames
128 ending in '$' as they are valid machine account names.
129 So check for a machine account and re-add the '$'
130 at the end after the call to alpha_strcpy(). --jerry */
132 if ( tmp
[len
-1] == '$' )
133 is_machine_account
= True
;
135 alpha_strcpy( smb_user_name
, tmp
, SAFE_NETBIOS_CHARS
, sizeof(smb_user_name
)-1 );
137 if ( is_machine_account
) {
138 len
= strlen( smb_user_name
);
139 smb_user_name
[len
-1] = '$';
143 char* sub_get_smb_name( void )
145 return smb_user_name
;
148 /*******************************************************************
149 Setup the strings used by substitutions. Called per packet. Ensure
150 %U name is set correctly also.
151 ********************************************************************/
153 void set_current_user_info(const userdom_struct
*pcui
)
155 current_user_info
= *pcui
;
156 /* The following is safe as current_user_info.smb_name
157 * has already been sanitised in register_vuid. */
158 fstrcpy(smb_user_name
, current_user_info
.smb_name
);
161 /*******************************************************************
162 return the current active user name
163 *******************************************************************/
165 const char* get_current_username( void )
167 if ( current_user_info
.smb_name
[0] == '\0' )
168 return smb_user_name
;
170 return current_user_info
.smb_name
;
173 /*******************************************************************
174 Given a pointer to a %$(NAME) expand it as an environment variable.
175 Return the number of characters by which the pointer should be advanced.
176 Based on code by Branko Cibej <branko.cibej@hermes.si>
177 When this is called p points at the '%' character.
178 ********************************************************************/
180 static size_t expand_env_var(char *p
, int len
)
194 * Look for the terminating ')'.
197 if ((q
= strchr_m(p
,')')) == NULL
) {
198 DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p
));
203 * Extract the name from within the %$(NAME) string.
207 copylen
= MIN((q
-r
),(sizeof(envname
)-1));
208 strncpy(envname
,r
,copylen
);
209 envname
[copylen
] = '\0';
211 if ((envval
= getenv(envname
)) == NULL
) {
212 DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname
));
217 * Copy the full %$(NAME) into envname so it
221 copylen
= MIN((q
+1-p
),(sizeof(envname
)-1));
222 strncpy(envname
,p
,copylen
);
223 envname
[copylen
] = '\0';
224 string_sub(p
,envname
,envval
,len
);
225 return 0; /* Allow the environment contents to be parsed. */
228 /*******************************************************************
229 Given a pointer to a %$(NAME) in p and the whole string in str
230 expand it as an environment variable.
231 Return a new allocated and expanded string.
232 Based on code by Branko Cibej <branko.cibej@hermes.si>
233 When this is called p points at the '%' character.
234 May substitute multiple occurrencies of the same env var.
235 ********************************************************************/
238 static char * realloc_expand_env_var(char *str
, char *p
)
245 if (p
[0] != '%' || p
[1] != '$' || p
[2] != '(')
249 * Look for the terminating ')'.
252 if ((q
= strchr_m(p
,')')) == NULL
) {
253 DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p
));
258 * Extract the name from within the %$(NAME) string.
263 envname
= (char *)SMB_MALLOC(copylen
+ 1 + 4); /* reserve space for use later add %$() chars */
264 if (envname
== NULL
) return NULL
;
265 strncpy(envname
,r
,copylen
);
266 envname
[copylen
] = '\0';
268 if ((envval
= getenv(envname
)) == NULL
) {
269 DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname
));
275 * Copy the full %$(NAME) into envname so it
280 strncpy(envname
,p
,copylen
);
281 envname
[copylen
] = '\0';
282 r
= realloc_string_sub(str
, envname
, envval
);
284 if (r
== NULL
) return NULL
;
288 /*******************************************************************
289 Patch from jkf@soton.ac.uk
290 Added this to implement %p (NIS auto-map version of %H)
291 *******************************************************************/
293 static char *automount_path(const char *user_name
)
295 static pstring server_path
;
297 /* use the passwd entry as the default */
298 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
300 pstrcpy(server_path
, get_user_home_dir(user_name
));
302 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
304 if (lp_nis_home_map()) {
305 const char *home_path_start
;
306 const char *automount_value
= automount_lookup(user_name
);
308 if(strlen(automount_value
) > 0) {
309 home_path_start
= strchr_m(automount_value
,':');
310 if (home_path_start
!= NULL
) {
311 DEBUG(5, ("NIS lookup succeeded. Home path is: %s\n",
312 home_path_start
?(home_path_start
+1):""));
313 pstrcpy(server_path
, home_path_start
+1);
316 /* NIS key lookup failed: default to user home directory from password file */
317 DEBUG(5, ("NIS lookup failed. Using Home path from passwd file. Home path is: %s\n", server_path
));
322 DEBUG(4,("Home server path: %s\n", server_path
));
327 /*******************************************************************
328 Patch from jkf@soton.ac.uk
329 This is Luke's original function with the NIS lookup code
330 moved out to a separate function.
331 *******************************************************************/
333 static const char *automount_server(const char *user_name
)
335 static pstring server_name
;
336 const char *local_machine_name
= get_local_machine_name();
338 /* use the local machine name as the default */
339 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
340 if (local_machine_name
&& *local_machine_name
)
341 pstrcpy(server_name
, local_machine_name
);
343 pstrcpy(server_name
, global_myname());
345 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
347 if (lp_nis_home_map()) {
349 char *automount_value
= automount_lookup(user_name
);
350 home_server_len
= strcspn(automount_value
,":");
351 DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len
));
352 if (home_server_len
> sizeof(pstring
))
353 home_server_len
= sizeof(pstring
);
354 strncpy(server_name
, automount_value
, home_server_len
);
355 server_name
[home_server_len
] = '\0';
359 DEBUG(4,("Home server: %s\n", server_name
));
364 /****************************************************************************
365 Do some standard substitutions in a string.
366 len is the length in bytes of the space allowed in string str. If zero means
367 don't allow expansions.
368 ****************************************************************************/
370 void standard_sub_basic(const char *smb_name
, char *str
,size_t len
)
375 const char *local_machine_name
= get_local_machine_name();
377 for (s
=str
; (p
=strchr_m(s
, '%'));s
=p
) {
380 int l
= (int)len
- (int)(p
-str
);
387 fstrcpy(tmp_str
, smb_name
);
389 string_sub(p
,"%U",tmp_str
,l
);
392 fstrcpy(tmp_str
, smb_name
);
393 if ((pass
= Get_Pwnam(tmp_str
))!=NULL
) {
394 string_sub(p
,"%G",gidtoname(pass
->pw_gid
),l
);
400 fstrcpy(tmp_str
, current_user_info
.domain
);
402 string_sub(p
,"%D", tmp_str
,l
);
405 string_sub(p
,"%I", client_addr(),l
);
408 string_sub(p
,"%i", client_socket_addr(),l
);
411 if (!StrnCaseCmp(p
, "%LOGONSERVER%", strlen("%LOGONSERVER%"))) {
416 if (local_machine_name
&& *local_machine_name
) {
417 string_sub_once(p
, "%L", local_machine_name
, l
);
421 pstrcpy(temp_name
, global_myname());
422 strlower_m(temp_name
);
423 string_sub_once(p
, "%L", temp_name
, l
);
427 string_sub(p
,"%M", client_name(),l
);
430 string_sub(p
,"%R", remote_proto
,l
);
433 string_sub(p
,"%T", timestring(False
),l
);
436 string_sub(p
,"%a", remote_arch
,l
);
439 slprintf(pidstr
,sizeof(pidstr
)-1, "%d",(int)sys_getpid());
440 string_sub(p
,"%d", pidstr
,l
);
443 string_sub(p
,"%h", myhostname(),l
);
446 string_sub(p
,"%m", get_remote_machine_name(),l
);
449 string_sub(p
,"%v", SAMBA_VERSION_STRING
,l
);
452 string_sub(p
,"%w", lp_winbind_separator(),l
);
455 p
+= expand_env_var(p
,l
);
456 break; /* Expand environment variables */
459 break; /* don't run off the end of the string */
467 static void standard_sub_advanced(int snum
, const char *user
,
468 const char *connectpath
, gid_t gid
,
469 const char *smb_name
, char *str
, size_t len
)
473 for (s
=str
; (p
=strchr_m(s
, '%'));s
=p
) {
474 int l
= (int)len
- (int)(p
-str
);
481 string_sub(p
,"%N", automount_server(user
),l
);
484 if ((home
= get_user_home_dir(user
)))
485 string_sub(p
,"%H",home
, l
);
490 string_sub(p
,"%P", connectpath
, l
);
494 string_sub(p
,"%S", lp_servicename(snum
), l
);
497 string_sub(p
,"%g", gidtoname(gid
), l
);
500 string_sub(p
,"%u", user
, l
);
503 /* Patch from jkf@soton.ac.uk Left the %N (NIS
504 * server name) in standard_sub_basic as it is
505 * a feature for logon servers, hence uses the
506 * username. The %p (NIS server path) code is
507 * here as it is used instead of the default
508 * "path =" string in [homes] and so needs the
509 * service name, not the username. */
512 string_sub(p
,"%p", automount_path(lp_servicename(snum
)), l
);
516 break; /* don't run off the end of the string */
523 standard_sub_basic(smb_name
, str
, len
);
526 /****************************************************************************
527 Do some standard substitutions in a string.
528 This function will return an allocated string that have to be freed.
529 ****************************************************************************/
531 char *talloc_sub_basic(TALLOC_CTX
*mem_ctx
, const char *smb_name
, const char *str
)
534 a
= alloc_sub_basic(smb_name
, str
);
536 t
= talloc_strdup(mem_ctx
, a
);
541 char *alloc_sub_basic(const char *smb_name
, const char *str
)
543 char *b
, *p
, *s
, *t
, *r
, *a_string
;
546 const char *local_machine_name
= get_local_machine_name();
548 /* workaround to prevent a crash while lookinf at bug #687 */
551 DEBUG(0,("alloc_sub_basic: NULL source string! This should not happen\n"));
555 a_string
= SMB_STRDUP(str
);
556 if (a_string
== NULL
) {
557 DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
561 for (b
= s
= a_string
; (p
= strchr_m(s
, '%')); s
= a_string
+ (p
- b
)) {
568 r
= strdup_lower(smb_name
);
569 if (r
== NULL
) goto error
;
570 t
= realloc_string_sub(t
, "%U", r
);
573 r
= SMB_STRDUP(smb_name
);
574 if (r
== NULL
) goto error
;
575 if ((pass
= Get_Pwnam(r
))!=NULL
) {
576 t
= realloc_string_sub(t
, "%G", gidtoname(pass
->pw_gid
));
580 r
= strdup_upper(current_user_info
.domain
);
581 if (r
== NULL
) goto error
;
582 t
= realloc_string_sub(t
, "%D", r
);
585 t
= realloc_string_sub(t
, "%I", client_addr());
588 if (local_machine_name
&& *local_machine_name
)
589 t
= realloc_string_sub(t
, "%L", local_machine_name
);
591 t
= realloc_string_sub(t
, "%L", global_myname());
594 t
= realloc_string_sub(t
, "%N", automount_server(smb_name
));
597 t
= realloc_string_sub(t
, "%M", client_name());
600 t
= realloc_string_sub(t
, "%R", remote_proto
);
603 t
= realloc_string_sub(t
, "%T", timestring(False
));
606 t
= realloc_string_sub(t
, "%a", remote_arch
);
609 slprintf(pidstr
,sizeof(pidstr
)-1, "%d",(int)sys_getpid());
610 t
= realloc_string_sub(t
, "%d", pidstr
);
613 t
= realloc_string_sub(t
, "%h", myhostname());
616 t
= realloc_string_sub(t
, "%m", remote_machine
);
619 t
= realloc_string_sub(t
, "%v", SAMBA_VERSION_STRING
);
622 t
= realloc_string_sub(t
, "%w", lp_winbind_separator());
625 t
= realloc_expand_env_var(t
, p
); /* Expand environment variables */
634 if (t
== NULL
) goto error
;
644 /****************************************************************************
645 Do some specific substitutions in a string.
646 This function will return an allocated string that have to be freed.
647 ****************************************************************************/
649 char *talloc_sub_specified(TALLOC_CTX
*mem_ctx
,
650 const char *input_string
,
651 const char *username
,
657 a
= alloc_sub_specified(input_string
, username
, domain
, uid
, gid
);
659 t
= talloc_strdup(mem_ctx
, a
);
664 char *alloc_sub_specified(const char *input_string
,
665 const char *username
,
670 char *a_string
, *ret_string
;
673 a_string
= SMB_STRDUP(input_string
);
674 if (a_string
== NULL
) {
675 DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
679 for (b
= s
= a_string
; (p
= strchr_m(s
, '%')); s
= a_string
+ (p
- b
)) {
685 t
= realloc_string_sub(t
, "%U", username
);
688 t
= realloc_string_sub(t
, "%u", username
);
692 t
= realloc_string_sub(t
, "%G", gidtoname(gid
));
694 t
= realloc_string_sub(t
, "%G", "NO_GROUP");
699 t
= realloc_string_sub(t
, "%g", gidtoname(gid
));
701 t
= realloc_string_sub(t
, "%g", "NO_GROUP");
705 t
= realloc_string_sub(t
, "%D", domain
);
708 t
= realloc_string_sub(t
, "%N", automount_server(username
));
722 ret_string
= alloc_sub_basic(username
, a_string
);
727 char *talloc_sub_advanced(TALLOC_CTX
*mem_ctx
,
730 const char *connectpath
,
732 const char *smb_name
,
736 a
= alloc_sub_advanced(snum
, user
, connectpath
, gid
, smb_name
, str
);
738 t
= talloc_strdup(mem_ctx
, a
);
743 char *alloc_sub_advanced(int snum
, const char *user
,
744 const char *connectpath
, gid_t gid
,
745 const char *smb_name
, const char *str
)
747 char *a_string
, *ret_string
;
748 char *b
, *p
, *s
, *t
, *h
;
750 a_string
= SMB_STRDUP(str
);
751 if (a_string
== NULL
) {
752 DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
756 for (b
= s
= a_string
; (p
= strchr_m(s
, '%')); s
= a_string
+ (p
- b
)) {
762 t
= realloc_string_sub(t
, "%N", automount_server(user
));
765 if ((h
= get_user_home_dir(user
)))
766 t
= realloc_string_sub(t
, "%H", h
);
769 t
= realloc_string_sub(t
, "%P", connectpath
);
772 t
= realloc_string_sub(t
, "%S", lp_servicename(snum
));
775 t
= realloc_string_sub(t
, "%g", gidtoname(gid
));
778 t
= realloc_string_sub(t
, "%u", user
);
781 /* Patch from jkf@soton.ac.uk Left the %N (NIS
782 * server name) in standard_sub_basic as it is
783 * a feature for logon servers, hence uses the
784 * username. The %p (NIS server path) code is
785 * here as it is used instead of the default
786 * "path =" string in [homes] and so needs the
787 * service name, not the username. */
789 t
= realloc_string_sub(t
, "%p", automount_path(lp_servicename(snum
)));
804 ret_string
= alloc_sub_basic(smb_name
, a_string
);
809 /****************************************************************************
810 Do some standard substitutions in a string.
811 ****************************************************************************/
813 void standard_sub_conn(connection_struct
*conn
, char *str
, size_t len
)
815 standard_sub_advanced(SNUM(conn
), conn
->user
, conn
->connectpath
,
816 conn
->gid
, smb_user_name
, str
, len
);
819 char *talloc_sub_conn(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, const char *str
)
821 return talloc_sub_advanced(mem_ctx
, SNUM(conn
), conn
->user
,
822 conn
->connectpath
, conn
->gid
,
826 char *alloc_sub_conn(connection_struct
*conn
, const char *str
)
828 return alloc_sub_advanced(SNUM(conn
), conn
->user
, conn
->connectpath
,
829 conn
->gid
, smb_user_name
, str
);
832 /****************************************************************************
833 Like standard_sub but by snum.
834 ****************************************************************************/
836 void standard_sub_snum(int snum
, char *str
, size_t len
)
838 static uid_t cached_uid
= -1;
839 static fstring cached_user
;
840 /* calling uidtoname() on every substitute would be too expensive, so
841 we cache the result here as nearly every call is for the same uid */
843 if (cached_uid
!= current_user
.ut
.uid
) {
844 fstrcpy(cached_user
, uidtoname(current_user
.ut
.uid
));
845 cached_uid
= current_user
.ut
.uid
;
848 standard_sub_advanced(snum
, cached_user
, "", current_user
.ut
.gid
,
849 smb_user_name
, str
, len
);