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 "substitute.h"
24 #include "system/passwd.h"
27 #include "lib/util/string_wrappers.h"
29 /* Max DNS name is 253 + '\0' */
30 #define MACHINE_NAME_SIZE 254
32 static char local_machine
[MACHINE_NAME_SIZE
];
33 static char remote_machine
[MACHINE_NAME_SIZE
];
35 userdom_struct current_user_info
;
36 fstring remote_proto
="UNKNOWN";
39 * Set the 'local' machine name
40 * @param local_name the name we are being called
41 * @param if this is the 'final' name for us, not be be changed again
43 bool set_local_machine_name(const char *local_name
, bool perm
)
45 static bool already_perm
= false;
46 char tmp
[MACHINE_NAME_SIZE
];
52 strlcpy(tmp
, local_name
, sizeof(tmp
));
53 trim_char(tmp
, ' ', ' ');
55 alpha_strcpy(local_machine
,
58 sizeof(local_machine
) - 1);
59 if (!strlower_m(local_machine
)) {
68 const char *get_local_machine_name(void)
70 if (local_machine
[0] == '\0') {
71 return lp_netbios_name();
78 * Set the 'remote' machine name
80 * @param remote_name the name our client wants to be called by
81 * @param if this is the 'final' name for them, not be be changed again
83 bool set_remote_machine_name(const char *remote_name
, bool perm
)
85 static bool already_perm
= False
;
86 char tmp
[MACHINE_NAME_SIZE
];
92 strlcpy(tmp
, remote_name
, sizeof(tmp
));
93 trim_char(tmp
, ' ', ' ');
95 alpha_strcpy(remote_machine
,
98 sizeof(remote_machine
) - 1);
99 if (!strlower_m(remote_machine
)) {
108 const char *get_remote_machine_name(void)
110 return remote_machine
;
113 static char sub_peeraddr
[INET6_ADDRSTRLEN
];
114 static const char *sub_peername
= NULL
;
115 static char sub_sockaddr
[INET6_ADDRSTRLEN
];
117 void sub_set_socket_ids(const char *peeraddr
, const char *peername
,
118 const char *sockaddr
)
120 const char *addr
= peeraddr
;
122 if (strnequal(addr
, "::ffff:", 7)) {
125 strlcpy(sub_peeraddr
, addr
, sizeof(sub_peeraddr
));
127 if (sub_peername
!= NULL
&&
128 sub_peername
!= sub_peeraddr
) {
129 talloc_free(discard_const_p(char,sub_peername
));
132 sub_peername
= talloc_strdup(NULL
, peername
);
133 if (sub_peername
== NULL
) {
134 sub_peername
= sub_peeraddr
;
138 * Shouldn't we do the ::ffff: cancellation here as well? The
139 * original code in talloc_sub_basic() did not do it, so I'm
140 * leaving it out here as well for compatibility.
142 strlcpy(sub_sockaddr
, sockaddr
, sizeof(sub_sockaddr
));
145 /*******************************************************************
146 Setup the strings used by substitutions. Called per packet. Ensure
147 %U name is set correctly also.
149 smb_name must be sanitized by alpha_strcpy
150 ********************************************************************/
152 void set_current_user_info(const char *smb_name
, const char *unix_name
,
155 static const void *last_smb_name
;
156 static const void *last_unix_name
;
157 static const void *last_domain
;
159 if (likely(last_smb_name
== smb_name
&&
160 last_unix_name
== unix_name
&&
161 last_domain
== domain
))
166 fstrcpy(current_user_info
.smb_name
, smb_name
);
167 fstrcpy(current_user_info
.unix_name
, unix_name
);
168 fstrcpy(current_user_info
.domain
, domain
);
170 last_smb_name
= smb_name
;
171 last_unix_name
= unix_name
;
172 last_domain
= domain
;
175 /*******************************************************************
176 Return the current active user name.
177 *******************************************************************/
179 const char *get_current_username(void)
181 return current_user_info
.smb_name
;
184 /*******************************************************************
185 Given a pointer to a %$(NAME) in p and the whole string in str
186 expand it as an environment variable.
187 str must be a talloced string.
188 Return a new allocated and expanded string.
189 Based on code by Branko Cibej <branko.cibej@hermes.si>
190 When this is called p points at the '%' character.
191 May substitute multiple occurrencies of the same env var.
192 ********************************************************************/
194 static char *realloc_expand_env_var(char *str
, char *p
)
201 if (p
[0] != '%' || p
[1] != '$' || p
[2] != '(') {
206 * Look for the terminating ')'.
209 if ((q
= strchr_m(p
,')')) == NULL
) {
210 DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p
));
215 * Extract the name from within the %$(NAME) string.
221 /* reserve space for use later add %$() chars */
222 if ( (envname
= talloc_array(talloc_tos(), char, copylen
+ 1 + 4)) == NULL
) {
226 strncpy(envname
,r
,copylen
);
227 envname
[copylen
] = '\0';
229 if ((envval
= getenv(envname
)) == NULL
) {
230 DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname
));
231 TALLOC_FREE(envname
);
236 * Copy the full %$(NAME) into envname so it
241 strncpy(envname
,p
,copylen
);
242 envname
[copylen
] = '\0';
243 r
= realloc_string_sub(str
, envname
, envval
);
244 TALLOC_FREE(envname
);
249 /****************************************************************************
250 Do some standard substitutions in a string.
251 len is the length in bytes of the space allowed in string str. If zero means
252 don't allow expansions.
253 ****************************************************************************/
255 void standard_sub_basic(const char *smb_name
, const char *domain_name
,
256 char *str
, size_t len
)
260 if ( (s
= talloc_sub_basic(talloc_tos(), smb_name
, domain_name
, str
)) != NULL
) {
261 strncpy( str
, s
, len
);
268 * Limit addresses to hexalpha charactes and underscore, safe for path
269 * components for Windows clients.
271 static void make_address_pathsafe(char *addr
)
273 while(addr
&& *addr
) {
274 if(!isxdigit(*addr
)) {
281 /****************************************************************************
282 Do some standard substitutions in a string.
283 This function will return a talloced string that has to be freed.
284 ****************************************************************************/
286 char *talloc_sub_basic(TALLOC_CTX
*mem_ctx
,
287 const char *smb_name
,
288 const char *domain_name
,
291 char *b
, *p
, *s
, *r
, *a_string
;
292 fstring pidstr
, vnnstr
;
293 const char *local_machine_name
= get_local_machine_name();
294 TALLOC_CTX
*tmp_ctx
= NULL
;
296 /* workaround to prevent a crash while looking at bug #687 */
299 DEBUG(0,("talloc_sub_basic: NULL source string! This should not happen\n"));
303 a_string
= talloc_strdup(mem_ctx
, str
);
304 if (a_string
== NULL
) {
305 DEBUG(0, ("talloc_sub_basic: Out of memory!\n"));
309 tmp_ctx
= talloc_stackframe();
311 for (s
= a_string
; (p
= strchr_m(s
, '%')); s
= a_string
+ (p
- b
)) {
318 r
= strlower_talloc(tmp_ctx
, smb_name
);
322 a_string
= realloc_string_sub(a_string
, "%U", r
);
326 bool is_domain_name
= false;
327 const char *sep
= lp_winbind_separator();
329 if (domain_name
!= NULL
&& domain_name
[0] != '\0' &&
330 (lp_security() == SEC_ADS
||
331 lp_security() == SEC_DOMAIN
)) {
332 r
= talloc_asprintf(tmp_ctx
,
337 is_domain_name
= true;
339 r
= talloc_strdup(tmp_ctx
, smb_name
);
345 pass
= Get_Pwnam_alloc(tmp_ctx
, r
);
349 group_name
= gidtoname(pass
->pw_gid
);
350 if (is_domain_name
) {
352 group_sep
= strchr_m(group_name
, *sep
);
353 if (group_sep
!= NULL
) {
354 group_name
= group_sep
+ 1;
357 a_string
= realloc_string_sub(a_string
,
365 r
= strupper_talloc(tmp_ctx
, domain_name
);
369 a_string
= realloc_string_sub(a_string
, "%D", r
);
372 a_string
= realloc_string_sub(
374 sub_peeraddr
[0] ? sub_peeraddr
: "0.0.0.0");
378 r
= talloc_strdup(tmp_ctx
,
379 sub_peeraddr
[0] ? sub_peeraddr
: "0.0.0.0");
380 make_address_pathsafe(r
);
381 a_string
= realloc_string_sub(a_string
, "%J", r
);
385 a_string
= realloc_string_sub(
387 sub_sockaddr
[0] ? sub_sockaddr
: "0.0.0.0");
390 r
= talloc_strdup(tmp_ctx
,
391 sub_sockaddr
[0] ? sub_sockaddr
: "0.0.0.0");
392 make_address_pathsafe(r
);
393 a_string
= realloc_string_sub(a_string
, "%j", r
);
397 if ( strncasecmp_m(p
, "%LOGONSERVER%", strlen("%LOGONSERVER%")) == 0 ) {
400 if (local_machine_name
&& *local_machine_name
) {
401 a_string
= realloc_string_sub(a_string
, "%L", local_machine_name
);
403 a_string
= realloc_string_sub(a_string
, "%L", lp_netbios_name());
407 a_string
= realloc_string_sub(a_string
,
412 a_string
= realloc_string_sub(a_string
, "%M",
413 sub_peername
? sub_peername
: "");
416 a_string
= realloc_string_sub(a_string
, "%R", remote_proto
);
419 a_string
= realloc_string_sub(a_string
, "%T", current_timestring(tmp_ctx
, False
));
422 a_string
= realloc_string_sub(a_string
, "%t",
423 current_minimal_timestring(tmp_ctx
, False
));
426 a_string
= realloc_string_sub(a_string
, "%a",
427 get_remote_arch_str());
430 slprintf(pidstr
,sizeof(pidstr
)-1, "%d",(int)getpid());
431 a_string
= realloc_string_sub(a_string
, "%d", pidstr
);
434 a_string
= realloc_string_sub(a_string
, "%h", myhostname());
437 a_string
= realloc_string_sub(a_string
, "%m",
441 a_string
= realloc_string_sub(a_string
, "%v", samba_version_string());
444 a_string
= realloc_string_sub(a_string
, "%w", lp_winbind_separator());
447 a_string
= realloc_expand_env_var(a_string
, p
); /* Expand environment variables */
450 slprintf(vnnstr
,sizeof(vnnstr
)-1, "%u", get_my_vnn());
451 a_string
= realloc_string_sub(a_string
, "%V", vnnstr
);
460 if (a_string
== NULL
) {
468 TALLOC_FREE(a_string
);
471 TALLOC_FREE(tmp_ctx
);
475 /****************************************************************************
476 Do some specific substitutions in a string.
477 This function will return an allocated string that have to be freed.
478 ****************************************************************************/
480 char *talloc_sub_specified(TALLOC_CTX
*mem_ctx
,
481 const char *input_string
,
482 const char *username
,
489 char *ret_string
= NULL
;
493 if (!(tmp_ctx
= talloc_new(mem_ctx
))) {
494 DEBUG(0, ("talloc_new failed\n"));
498 a_string
= talloc_strdup(tmp_ctx
, input_string
);
499 if (a_string
== NULL
) {
500 DEBUG(0, ("talloc_sub_specified: Out of memory!\n"));
504 for (s
= a_string
; (p
= strchr_m(s
, '%')); s
= a_string
+ (p
- b
)) {
510 a_string
= talloc_string_sub(
511 tmp_ctx
, a_string
, "%U", username
);
514 a_string
= talloc_string_sub(
515 tmp_ctx
, a_string
, "%u", username
);
521 if (grpname
!= NULL
) {
524 name
= gidtoname(gid
);
527 a_string
= talloc_string_sub(tmp_ctx
,
532 a_string
= talloc_string_sub(
541 if (grpname
!= NULL
) {
544 name
= gidtoname(gid
);
547 a_string
= talloc_string_sub(tmp_ctx
,
552 a_string
= talloc_string_sub(
553 tmp_ctx
, a_string
, "%g", "NO_GROUP");
557 a_string
= talloc_string_sub(tmp_ctx
, a_string
,
561 a_string
= talloc_string_sub(tmp_ctx
, a_string
,
562 "%N", lp_netbios_name());
569 if (a_string
== NULL
) {
574 /* Watch out, using "mem_ctx" here, so all intermediate stuff goes
575 * away with the TALLOC_FREE(tmp_ctx) further down. */
577 ret_string
= talloc_sub_basic(mem_ctx
, username
, domain
, a_string
);
580 TALLOC_FREE(tmp_ctx
);
584 /****************************************************************************
585 ****************************************************************************/
587 char *talloc_sub_advanced(TALLOC_CTX
*ctx
,
588 const char *servicename
,
590 const char *connectpath
,
597 a_string
= talloc_strdup(talloc_tos(), str
);
598 if (a_string
== NULL
) {
599 DEBUG(0, ("talloc_sub_advanced_only: Out of memory!\n"));
603 for (s
= a_string
; (p
= strchr_m(s
, '%')); s
= a_string
+ (p
- b
)) {
609 a_string
= realloc_string_sub(a_string
,
615 if ((h
= get_user_home_dir(talloc_tos(), user
)))
616 a_string
= realloc_string_sub(a_string
, "%H", h
);
621 a_string
= realloc_string_sub(a_string
, "%P", connectpath
);
624 a_string
= realloc_string_sub(a_string
, "%S", servicename
);
627 a_string
= realloc_string_sub(a_string
, "%g", gidtoname(gid
));
630 a_string
= realloc_string_sub(a_string
, "%u", user
);
637 if (a_string
== NULL
) {
645 char *talloc_sub_full(TALLOC_CTX
*ctx
,
646 const char *servicename
,
648 const char *connectpath
,
650 const char *smb_name
,
651 const char *domain_name
,
654 char *a_string
, *ret_string
;
656 a_string
= talloc_sub_advanced(ctx
, servicename
, user
, connectpath
,
658 if (a_string
== NULL
) {
662 ret_string
= talloc_sub_basic(ctx
, smb_name
, domain_name
, a_string
);
663 TALLOC_FREE(a_string
);