nsswitch: explicitly mark nss_module_register() _PUBLIC_ on FreeBSD
[Samba.git] / source3 / lib / substitute.c
bloba941b89f82a6092502a41888bc0b8dc1b16069ca
1 /*
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/>.
22 #include "includes.h"
23 #include "substitute.h"
24 #include "system/passwd.h"
25 #include "secrets.h"
26 #include "auth.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";
38 /**
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];
48 if (already_perm) {
49 return true;
52 strlcpy(tmp, local_name, sizeof(tmp));
53 trim_char(tmp, ' ', ' ');
55 alpha_strcpy(local_machine,
56 tmp,
57 SAFE_NETBIOS_CHARS,
58 sizeof(local_machine) - 1);
59 if (!strlower_m(local_machine)) {
60 return false;
63 already_perm = perm;
65 return true;
68 const char *get_local_machine_name(void)
70 if (local_machine[0] == '\0') {
71 return lp_netbios_name();
74 return local_machine;
77 /**
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];
88 if (already_perm) {
89 return true;
92 strlcpy(tmp, remote_name, sizeof(tmp));
93 trim_char(tmp, ' ', ' ');
95 alpha_strcpy(remote_machine,
96 tmp,
97 SAFE_NETBIOS_CHARS,
98 sizeof(remote_machine) - 1);
99 if (!strlower_m(remote_machine)) {
100 return false;
103 already_perm = perm;
105 return true;
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)) {
123 addr += 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));
130 sub_peername = NULL;
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,
153 const char *domain)
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))
163 return;
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)
196 char *envname;
197 char *envval;
198 char *q, *r;
199 int copylen;
201 if (p[0] != '%' || p[1] != '$' || p[2] != '(') {
202 return str;
206 * Look for the terminating ')'.
209 if ((q = strchr_m(p,')')) == NULL) {
210 DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
211 return str;
215 * Extract the name from within the %$(NAME) string.
218 r = p + 3;
219 copylen = q - r;
221 /* reserve space for use later add %$() chars */
222 if ( (envname = talloc_array(talloc_tos(), char, copylen + 1 + 4)) == NULL ) {
223 return 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);
232 return str;
236 * Copy the full %$(NAME) into envname so it
237 * can be replaced.
240 copylen = q + 1 - p;
241 strncpy(envname,p,copylen);
242 envname[copylen] = '\0';
243 r = realloc_string_sub(str, envname, envval);
244 TALLOC_FREE(envname);
246 return r;
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)
258 char *s;
260 if ( (s = talloc_sub_basic(talloc_tos(), smb_name, domain_name, str )) != NULL ) {
261 strncpy( str, s, len );
264 TALLOC_FREE( s );
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)) {
275 *addr = '_';
277 ++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,
289 const char *str)
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 */
298 if (!str) {
299 DEBUG(0,("talloc_sub_basic: NULL source string! This should not happen\n"));
300 return NULL;
303 a_string = talloc_strdup(mem_ctx, str);
304 if (a_string == NULL) {
305 DEBUG(0, ("talloc_sub_basic: Out of memory!\n"));
306 return NULL;
309 tmp_ctx = talloc_stackframe();
311 for (s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
313 r = NULL;
314 b = a_string;
316 switch (*(p+1)) {
317 case 'U' :
318 r = strlower_talloc(tmp_ctx, smb_name);
319 if (r == NULL) {
320 goto error;
322 a_string = realloc_string_sub(a_string, "%U", r);
323 break;
324 case 'G' : {
325 struct passwd *pass;
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,
333 "%s%c%s",
334 domain_name,
335 *sep,
336 smb_name);
337 is_domain_name = true;
338 } else {
339 r = talloc_strdup(tmp_ctx, smb_name);
341 if (r == NULL) {
342 goto error;
345 pass = Get_Pwnam_alloc(tmp_ctx, r);
346 if (pass != NULL) {
347 char *group_name;
349 group_name = gidtoname(pass->pw_gid);
350 if (is_domain_name) {
351 char *group_sep;
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,
358 "%G",
359 group_name);
361 TALLOC_FREE(pass);
362 break;
364 case 'D' :
365 r = strupper_talloc(tmp_ctx, domain_name);
366 if (r == NULL) {
367 goto error;
369 a_string = realloc_string_sub(a_string, "%D", r);
370 break;
371 case 'I' : {
372 a_string = realloc_string_sub(
373 a_string, "%I",
374 sub_peeraddr[0] ? sub_peeraddr : "0.0.0.0");
375 break;
377 case 'J' : {
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);
382 break;
384 case 'i':
385 a_string = realloc_string_sub(
386 a_string, "%i",
387 sub_sockaddr[0] ? sub_sockaddr : "0.0.0.0");
388 break;
389 case 'j' : {
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);
394 break;
396 case 'L' :
397 if ( strncasecmp_m(p, "%LOGONSERVER%", strlen("%LOGONSERVER%")) == 0 ) {
398 break;
400 if (local_machine_name && *local_machine_name) {
401 a_string = realloc_string_sub(a_string, "%L", local_machine_name);
402 } else {
403 a_string = realloc_string_sub(a_string, "%L", lp_netbios_name());
405 break;
406 case 'N' :
407 a_string = realloc_string_sub(a_string,
408 "%N",
409 lp_netbios_name());
410 break;
411 case 'M' :
412 a_string = realloc_string_sub(a_string, "%M",
413 sub_peername ? sub_peername : "");
414 break;
415 case 'R' :
416 a_string = realloc_string_sub(a_string, "%R", remote_proto);
417 break;
418 case 'T' :
419 a_string = realloc_string_sub(a_string, "%T", current_timestring(tmp_ctx, False));
420 break;
421 case 't' :
422 a_string = realloc_string_sub(a_string, "%t",
423 current_minimal_timestring(tmp_ctx, False));
424 break;
425 case 'a' :
426 a_string = realloc_string_sub(a_string, "%a",
427 get_remote_arch_str());
428 break;
429 case 'd' :
430 slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)getpid());
431 a_string = realloc_string_sub(a_string, "%d", pidstr);
432 break;
433 case 'h' :
434 a_string = realloc_string_sub(a_string, "%h", myhostname());
435 break;
436 case 'm' :
437 a_string = realloc_string_sub(a_string, "%m",
438 remote_machine);
439 break;
440 case 'v' :
441 a_string = realloc_string_sub(a_string, "%v", samba_version_string());
442 break;
443 case 'w' :
444 a_string = realloc_string_sub(a_string, "%w", lp_winbind_separator());
445 break;
446 case '$' :
447 a_string = realloc_expand_env_var(a_string, p); /* Expand environment variables */
448 break;
449 case 'V' :
450 slprintf(vnnstr,sizeof(vnnstr)-1, "%u", get_my_vnn());
451 a_string = realloc_string_sub(a_string, "%V", vnnstr);
452 break;
453 default:
454 break;
457 p++;
458 TALLOC_FREE(r);
460 if (a_string == NULL) {
461 goto done;
465 goto done;
467 error:
468 TALLOC_FREE(a_string);
470 done:
471 TALLOC_FREE(tmp_ctx);
472 return a_string;
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,
483 const char *grpname,
484 const char *domain,
485 uid_t uid,
486 gid_t gid)
488 char *a_string;
489 char *ret_string = NULL;
490 char *b, *p, *s;
491 TALLOC_CTX *tmp_ctx;
493 if (!(tmp_ctx = talloc_new(mem_ctx))) {
494 DEBUG(0, ("talloc_new failed\n"));
495 return NULL;
498 a_string = talloc_strdup(tmp_ctx, input_string);
499 if (a_string == NULL) {
500 DEBUG(0, ("talloc_sub_specified: Out of memory!\n"));
501 goto done;
504 for (s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
506 b = a_string;
508 switch (*(p+1)) {
509 case 'U' :
510 a_string = talloc_string_sub(
511 tmp_ctx, a_string, "%U", username);
512 break;
513 case 'u' :
514 a_string = talloc_string_sub(
515 tmp_ctx, a_string, "%u", username);
516 break;
517 case 'G' :
518 if (gid != -1) {
519 const char *name;
521 if (grpname != NULL) {
522 name = grpname;
523 } else {
524 name = gidtoname(gid);
527 a_string = talloc_string_sub(tmp_ctx,
528 a_string,
529 "%G",
530 name);
531 } else {
532 a_string = talloc_string_sub(
533 tmp_ctx, a_string,
534 "%G", "NO_GROUP");
536 break;
537 case 'g' :
538 if (gid != -1) {
539 const char *name;
541 if (grpname != NULL) {
542 name = grpname;
543 } else {
544 name = gidtoname(gid);
547 a_string = talloc_string_sub(tmp_ctx,
548 a_string,
549 "%g",
550 name);
551 } else {
552 a_string = talloc_string_sub(
553 tmp_ctx, a_string, "%g", "NO_GROUP");
555 break;
556 case 'D' :
557 a_string = talloc_string_sub(tmp_ctx, a_string,
558 "%D", domain);
559 break;
560 case 'N' :
561 a_string = talloc_string_sub(tmp_ctx, a_string,
562 "%N", lp_netbios_name());
563 break;
564 default:
565 break;
568 p++;
569 if (a_string == NULL) {
570 goto done;
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);
579 done:
580 TALLOC_FREE(tmp_ctx);
581 return ret_string;
584 /****************************************************************************
585 ****************************************************************************/
587 char *talloc_sub_advanced(TALLOC_CTX *ctx,
588 const char *servicename,
589 const char *user,
590 const char *connectpath,
591 gid_t gid,
592 const char *str)
594 char *a_string;
595 char *b, *p, *s;
597 a_string = talloc_strdup(talloc_tos(), str);
598 if (a_string == NULL) {
599 DEBUG(0, ("talloc_sub_advanced_only: Out of memory!\n"));
600 return NULL;
603 for (s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
605 b = a_string;
607 switch (*(p+1)) {
608 case 'N':
609 a_string = realloc_string_sub(a_string,
610 "%N",
611 lp_netbios_name());
612 break;
613 case 'H': {
614 char *h;
615 if ((h = get_user_home_dir(talloc_tos(), user)))
616 a_string = realloc_string_sub(a_string, "%H", h);
617 TALLOC_FREE(h);
618 break;
620 case 'P':
621 a_string = realloc_string_sub(a_string, "%P", connectpath);
622 break;
623 case 'S':
624 a_string = realloc_string_sub(a_string, "%S", servicename);
625 break;
626 case 'g':
627 a_string = realloc_string_sub(a_string, "%g", gidtoname(gid));
628 break;
629 case 'u':
630 a_string = realloc_string_sub(a_string, "%u", user);
631 break;
632 default:
633 break;
636 p++;
637 if (a_string == NULL) {
638 return NULL;
642 return a_string;
645 char *talloc_sub_full(TALLOC_CTX *ctx,
646 const char *servicename,
647 const char *user,
648 const char *connectpath,
649 gid_t gid,
650 const char *smb_name,
651 const char *domain_name,
652 const char *str)
654 char *a_string, *ret_string;
656 a_string = talloc_sub_advanced(ctx, servicename, user, connectpath,
657 gid, str);
658 if (a_string == NULL) {
659 return NULL;
662 ret_string = talloc_sub_basic(ctx, smb_name, domain_name, a_string);
663 TALLOC_FREE(a_string);
664 return ret_string;