2 Unix SMB/CIFS implementation.
3 string substitution functions
4 Copyright (C) Andrew Tridgell 1992-2000
5 Copyright (C) Gerald Carter 2006
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.
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.
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/>.
23 #include "system/passwd.h"
26 #include "lib/util/string_wrappers.h"
28 /* Max DNS name is 253 + '\0' */
29 #define MACHINE_NAME_SIZE 254
31 static char local_machine
[MACHINE_NAME_SIZE
];
32 static char remote_machine
[MACHINE_NAME_SIZE
];
34 userdom_struct current_user_info
;
35 fstring remote_proto
="UNKNOWN";
38 * Set the 'local' machine name
39 * @param local_name the name we are being called
40 * @param if this is the 'final' name for us, not be be changed again
42 bool set_local_machine_name(const char *local_name
, bool perm
)
44 static bool already_perm
= false;
45 char tmp
[MACHINE_NAME_SIZE
];
51 strlcpy(tmp
, local_name
, sizeof(tmp
));
52 trim_char(tmp
, ' ', ' ');
54 alpha_strcpy(local_machine
,
57 sizeof(local_machine
) - 1);
58 if (!strlower_m(local_machine
)) {
67 const char *get_local_machine_name(void)
69 if (local_machine
[0] == '\0') {
70 return lp_netbios_name();
77 * Set the 'remote' machine name
79 * @param remote_name the name our client wants to be called by
80 * @param if this is the 'final' name for them, not be be changed again
82 bool set_remote_machine_name(const char *remote_name
, bool perm
)
84 static bool already_perm
= False
;
85 char tmp
[MACHINE_NAME_SIZE
];
91 strlcpy(tmp
, remote_name
, sizeof(tmp
));
92 trim_char(tmp
, ' ', ' ');
94 alpha_strcpy(remote_machine
,
97 sizeof(remote_machine
) - 1);
98 if (!strlower_m(remote_machine
)) {
107 const char *get_remote_machine_name(void)
109 return remote_machine
;
112 static char sub_peeraddr
[INET6_ADDRSTRLEN
];
113 static const char *sub_peername
= NULL
;
114 static char sub_sockaddr
[INET6_ADDRSTRLEN
];
116 void sub_set_socket_ids(const char *peeraddr
, const char *peername
,
117 const char *sockaddr
)
119 const char *addr
= peeraddr
;
121 if (strnequal(addr
, "::ffff:", 7)) {
124 strlcpy(sub_peeraddr
, addr
, sizeof(sub_peeraddr
));
126 if (sub_peername
!= NULL
&&
127 sub_peername
!= sub_peeraddr
) {
128 talloc_free(discard_const_p(char,sub_peername
));
131 sub_peername
= talloc_strdup(NULL
, peername
);
132 if (sub_peername
== NULL
) {
133 sub_peername
= sub_peeraddr
;
137 * Shouldn't we do the ::ffff: cancellation here as well? The
138 * original code in talloc_sub_basic() did not do it, so I'm
139 * leaving it out here as well for compatibility.
141 strlcpy(sub_sockaddr
, sockaddr
, sizeof(sub_sockaddr
));
144 /*******************************************************************
145 Setup the strings used by substitutions. Called per packet. Ensure
146 %U name is set correctly also.
148 smb_name must be sanitized by alpha_strcpy
149 ********************************************************************/
151 void set_current_user_info(const char *smb_name
, const char *unix_name
,
154 static const void *last_smb_name
;
155 static const void *last_unix_name
;
156 static const void *last_domain
;
158 if (likely(last_smb_name
== smb_name
&&
159 last_unix_name
== unix_name
&&
160 last_domain
== domain
))
165 fstrcpy(current_user_info
.smb_name
, smb_name
);
166 fstrcpy(current_user_info
.unix_name
, unix_name
);
167 fstrcpy(current_user_info
.domain
, domain
);
169 last_smb_name
= smb_name
;
170 last_unix_name
= unix_name
;
171 last_domain
= domain
;
174 /*******************************************************************
175 Return the current active user name.
176 *******************************************************************/
178 const char *get_current_username(void)
180 return current_user_info
.smb_name
;
183 /*******************************************************************
184 Given a pointer to a %$(NAME) in p and the whole string in str
185 expand it as an environment variable.
186 str must be a talloced string.
187 Return a new allocated and expanded string.
188 Based on code by Branko Cibej <branko.cibej@hermes.si>
189 When this is called p points at the '%' character.
190 May substitute multiple occurrencies of the same env var.
191 ********************************************************************/
193 static char *realloc_expand_env_var(char *str
, char *p
)
200 if (p
[0] != '%' || p
[1] != '$' || p
[2] != '(') {
205 * Look for the terminating ')'.
208 if ((q
= strchr_m(p
,')')) == NULL
) {
209 DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p
));
214 * Extract the name from within the %$(NAME) string.
220 /* reserve space for use later add %$() chars */
221 if ( (envname
= talloc_array(talloc_tos(), char, copylen
+ 1 + 4)) == NULL
) {
225 strncpy(envname
,r
,copylen
);
226 envname
[copylen
] = '\0';
228 if ((envval
= getenv(envname
)) == NULL
) {
229 DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname
));
230 TALLOC_FREE(envname
);
235 * Copy the full %$(NAME) into envname so it
240 strncpy(envname
,p
,copylen
);
241 envname
[copylen
] = '\0';
242 r
= realloc_string_sub(str
, envname
, envval
);
243 TALLOC_FREE(envname
);
248 /*******************************************************************
249 Patch from jkf@soton.ac.uk
250 Added this to implement %p (NIS auto-map version of %H)
251 *******************************************************************/
253 static const char *automount_path(const char *user_name
)
255 TALLOC_CTX
*ctx
= talloc_tos();
256 const char *server_path
;
258 /* use the passwd entry as the default */
259 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
261 server_path
= talloc_strdup(ctx
, get_user_home_dir(ctx
, user_name
));
266 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
268 if (lp_nis_homedir()) {
269 const char *home_path_start
;
270 char *automount_value
= automount_lookup(ctx
, user_name
);
272 if(automount_value
&& strlen(automount_value
) > 0) {
273 home_path_start
= strchr_m(automount_value
,':');
274 if (home_path_start
!= NULL
) {
275 DEBUG(5, ("NIS lookup succeeded. "
276 "Home path is: %s\n",
278 (home_path_start
+1):""));
279 server_path
= talloc_strdup(ctx
,
286 /* NIS key lookup failed: default to
287 * user home directory from password file */
288 DEBUG(5, ("NIS lookup failed. Using Home path from "
289 "passwd file. Home path is: %s\n", server_path
));
294 DEBUG(4,("Home server path: %s\n", server_path
));
298 /*******************************************************************
299 Patch from jkf@soton.ac.uk
300 This is Luke's original function with the NIS lookup code
301 moved out to a separate function.
302 *******************************************************************/
304 static const char *automount_server(const char *user_name
)
306 TALLOC_CTX
*ctx
= talloc_tos();
307 const char *server_name
;
308 const char *local_machine_name
= get_local_machine_name();
310 /* use the local machine name as the default */
311 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
312 if (local_machine_name
&& *local_machine_name
) {
313 server_name
= talloc_strdup(ctx
, local_machine_name
);
315 server_name
= talloc_strdup(ctx
, lp_netbios_name());
322 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
323 if (lp_nis_homedir()) {
326 char *automount_value
= automount_lookup(ctx
, user_name
);
327 if (!automount_value
) {
330 srv
= talloc_strdup(ctx
, automount_value
);
334 p
= strchr_m(srv
, ':');
340 DEBUG(5, ("NIS lookup succeeded. Home server %s\n",
345 DEBUG(4,("Home server: %s\n", server_name
));
349 /****************************************************************************
350 Do some standard substitutions in a string.
351 len is the length in bytes of the space allowed in string str. If zero means
352 don't allow expansions.
353 ****************************************************************************/
355 void standard_sub_basic(const char *smb_name
, const char *domain_name
,
356 char *str
, size_t len
)
360 if ( (s
= talloc_sub_basic(talloc_tos(), smb_name
, domain_name
, str
)) != NULL
) {
361 strncpy( str
, s
, len
);
368 * Limit addresses to hexalpha charactes and underscore, safe for path
369 * components for Windows clients.
371 static void make_address_pathsafe(char *addr
)
373 while(addr
&& *addr
) {
374 if(!isxdigit(*addr
)) {
381 /****************************************************************************
382 Do some standard substitutions in a string.
383 This function will return a talloced string that has to be freed.
384 ****************************************************************************/
386 char *talloc_sub_basic(TALLOC_CTX
*mem_ctx
,
387 const char *smb_name
,
388 const char *domain_name
,
391 char *b
, *p
, *s
, *r
, *a_string
;
392 fstring pidstr
, vnnstr
;
393 const char *local_machine_name
= get_local_machine_name();
394 TALLOC_CTX
*tmp_ctx
= NULL
;
396 /* workaround to prevent a crash while looking at bug #687 */
399 DEBUG(0,("talloc_sub_basic: NULL source string! This should not happen\n"));
403 a_string
= talloc_strdup(mem_ctx
, str
);
404 if (a_string
== NULL
) {
405 DEBUG(0, ("talloc_sub_basic: Out of memory!\n"));
409 tmp_ctx
= talloc_stackframe();
411 for (s
= a_string
; (p
= strchr_m(s
, '%')); s
= a_string
+ (p
- b
)) {
418 r
= strlower_talloc(tmp_ctx
, smb_name
);
422 a_string
= realloc_string_sub(a_string
, "%U", r
);
426 bool is_domain_name
= false;
427 const char *sep
= lp_winbind_separator();
429 if (domain_name
!= NULL
&& domain_name
[0] != '\0' &&
430 (lp_security() == SEC_ADS
||
431 lp_security() == SEC_DOMAIN
)) {
432 r
= talloc_asprintf(tmp_ctx
,
437 is_domain_name
= true;
439 r
= talloc_strdup(tmp_ctx
, smb_name
);
445 pass
= Get_Pwnam_alloc(tmp_ctx
, r
);
449 group_name
= gidtoname(pass
->pw_gid
);
450 if (is_domain_name
) {
452 group_sep
= strchr_m(group_name
, *sep
);
453 if (group_sep
!= NULL
) {
454 group_name
= group_sep
+ 1;
457 a_string
= realloc_string_sub(a_string
,
465 r
= strupper_talloc(tmp_ctx
, domain_name
);
469 a_string
= realloc_string_sub(a_string
, "%D", r
);
472 a_string
= realloc_string_sub(
474 sub_peeraddr
[0] ? sub_peeraddr
: "0.0.0.0");
478 r
= talloc_strdup(tmp_ctx
,
479 sub_peeraddr
[0] ? sub_peeraddr
: "0.0.0.0");
480 make_address_pathsafe(r
);
481 a_string
= realloc_string_sub(a_string
, "%J", r
);
485 a_string
= realloc_string_sub(
487 sub_sockaddr
[0] ? sub_sockaddr
: "0.0.0.0");
490 r
= talloc_strdup(tmp_ctx
,
491 sub_sockaddr
[0] ? sub_sockaddr
: "0.0.0.0");
492 make_address_pathsafe(r
);
493 a_string
= realloc_string_sub(a_string
, "%j", r
);
497 if ( strncasecmp_m(p
, "%LOGONSERVER%", strlen("%LOGONSERVER%")) == 0 ) {
500 if (local_machine_name
&& *local_machine_name
) {
501 a_string
= realloc_string_sub(a_string
, "%L", local_machine_name
);
503 a_string
= realloc_string_sub(a_string
, "%L", lp_netbios_name());
507 a_string
= realloc_string_sub(a_string
, "%N", automount_server(smb_name
));
510 a_string
= realloc_string_sub(a_string
, "%M",
511 sub_peername
? sub_peername
: "");
514 a_string
= realloc_string_sub(a_string
, "%R", remote_proto
);
517 a_string
= realloc_string_sub(a_string
, "%T", current_timestring(tmp_ctx
, False
));
520 a_string
= realloc_string_sub(a_string
, "%t",
521 current_minimal_timestring(tmp_ctx
, False
));
524 a_string
= realloc_string_sub(a_string
, "%a",
525 get_remote_arch_str());
528 slprintf(pidstr
,sizeof(pidstr
)-1, "%d",(int)getpid());
529 a_string
= realloc_string_sub(a_string
, "%d", pidstr
);
532 a_string
= realloc_string_sub(a_string
, "%h", myhostname());
535 a_string
= realloc_string_sub(a_string
, "%m",
539 a_string
= realloc_string_sub(a_string
, "%v", samba_version_string());
542 a_string
= realloc_string_sub(a_string
, "%w", lp_winbind_separator());
545 a_string
= realloc_expand_env_var(a_string
, p
); /* Expand environment variables */
548 slprintf(vnnstr
,sizeof(vnnstr
)-1, "%u", get_my_vnn());
549 a_string
= realloc_string_sub(a_string
, "%V", vnnstr
);
558 if (a_string
== NULL
) {
566 TALLOC_FREE(a_string
);
569 TALLOC_FREE(tmp_ctx
);
573 /****************************************************************************
574 Do some specific substitutions in a string.
575 This function will return an allocated string that have to be freed.
576 ****************************************************************************/
578 char *talloc_sub_specified(TALLOC_CTX
*mem_ctx
,
579 const char *input_string
,
580 const char *username
,
587 char *ret_string
= NULL
;
591 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
592 DEBUG(0, ("talloc_new failed\n"));
596 a_string
= talloc_strdup(tmp_ctx
, input_string
);
597 if (a_string
== NULL
) {
598 DEBUG(0, ("talloc_sub_specified: Out of memory!\n"));
602 for (s
= a_string
; (p
= strchr_m(s
, '%')); s
= a_string
+ (p
- b
)) {
608 a_string
= talloc_string_sub(
609 tmp_ctx
, a_string
, "%U", username
);
612 a_string
= talloc_string_sub(
613 tmp_ctx
, a_string
, "%u", username
);
619 if (grpname
!= NULL
) {
622 name
= gidtoname(gid
);
625 a_string
= talloc_string_sub(tmp_ctx
,
630 a_string
= talloc_string_sub(
639 if (grpname
!= NULL
) {
642 name
= gidtoname(gid
);
645 a_string
= talloc_string_sub(tmp_ctx
,
650 a_string
= talloc_string_sub(
651 tmp_ctx
, a_string
, "%g", "NO_GROUP");
655 a_string
= talloc_string_sub(tmp_ctx
, a_string
,
659 a_string
= talloc_string_sub(
660 tmp_ctx
, a_string
, "%N",
661 automount_server(username
));
668 if (a_string
== NULL
) {
673 /* Watch out, using "mem_ctx" here, so all intermediate stuff goes
674 * away with the TALLOC_FREE(tmp_ctx) further down. */
676 ret_string
= talloc_sub_basic(mem_ctx
, username
, domain
, a_string
);
679 TALLOC_FREE(tmp_ctx
);
683 /****************************************************************************
684 ****************************************************************************/
686 char *talloc_sub_advanced(TALLOC_CTX
*ctx
,
687 const char *servicename
,
689 const char *connectpath
,
696 a_string
= talloc_strdup(talloc_tos(), str
);
697 if (a_string
== NULL
) {
698 DEBUG(0, ("talloc_sub_advanced_only: Out of memory!\n"));
702 for (s
= a_string
; (p
= strchr_m(s
, '%')); s
= a_string
+ (p
- b
)) {
708 a_string
= realloc_string_sub(a_string
, "%N", automount_server(user
));
712 if ((h
= get_user_home_dir(talloc_tos(), user
)))
713 a_string
= realloc_string_sub(a_string
, "%H", h
);
718 a_string
= realloc_string_sub(a_string
, "%P", connectpath
);
721 a_string
= realloc_string_sub(a_string
, "%S", servicename
);
724 a_string
= realloc_string_sub(a_string
, "%g", gidtoname(gid
));
727 a_string
= realloc_string_sub(a_string
, "%u", user
);
730 /* Patch from jkf@soton.ac.uk Left the %N (NIS
731 * server name) in standard_sub_basic as it is
732 * a feature for logon servers, hence uses the
733 * username. The %p (NIS server path) code is
734 * here as it is used instead of the default
735 * "path =" string in [homes] and so needs the
736 * service name, not the username. */
738 a_string
= realloc_string_sub(a_string
, "%p",
739 automount_path(servicename
));
747 if (a_string
== NULL
) {
755 char *talloc_sub_full(TALLOC_CTX
*ctx
,
756 const char *servicename
,
758 const char *connectpath
,
760 const char *smb_name
,
761 const char *domain_name
,
764 char *a_string
, *ret_string
;
766 a_string
= talloc_sub_advanced(ctx
, servicename
, user
, connectpath
,
768 if (a_string
== NULL
) {
772 ret_string
= talloc_sub_basic(ctx
, smb_name
, domain_name
, a_string
);
773 TALLOC_FREE(a_string
);