/src/samba/source3/lib/substitute.c
Line | Count | Source |
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 | | #include "substitute.h" |
24 | | #include "system/passwd.h" |
25 | | #include "secrets.h" |
26 | | #include "auth.h" |
27 | | #include "lib/util/string_wrappers.h" |
28 | | |
29 | | /* Max DNS name is 253 + '\0' */ |
30 | | #define MACHINE_NAME_SIZE 254 |
31 | | |
32 | | static char local_machine[MACHINE_NAME_SIZE]; |
33 | | static char remote_machine[MACHINE_NAME_SIZE]; |
34 | | |
35 | | userdom_struct current_user_info; |
36 | | static fstring remote_proto="UNKNOWN"; |
37 | | |
38 | | void set_remote_proto(const char *proto) |
39 | 0 | { |
40 | 0 | fstrcpy(remote_proto, proto); |
41 | 0 | } |
42 | | |
43 | | /** |
44 | | * Set the 'local' machine name |
45 | | * @param local_name the name we are being called |
46 | | * @param if this is the 'final' name for us, not be be changed again |
47 | | */ |
48 | | bool set_local_machine_name(const char *local_name, bool perm) |
49 | 0 | { |
50 | 0 | static bool already_perm = false; |
51 | 0 | char tmp[MACHINE_NAME_SIZE]; |
52 | |
|
53 | 0 | if (already_perm) { |
54 | 0 | return true; |
55 | 0 | } |
56 | | |
57 | 0 | strlcpy(tmp, local_name, sizeof(tmp)); |
58 | 0 | trim_char(tmp, ' ', ' '); |
59 | |
|
60 | 0 | alpha_strcpy(local_machine, |
61 | 0 | tmp, |
62 | 0 | SAFE_NETBIOS_CHARS, |
63 | 0 | sizeof(local_machine) - 1); |
64 | 0 | if (!strlower_m(local_machine)) { |
65 | 0 | return false; |
66 | 0 | } |
67 | | |
68 | 0 | already_perm = perm; |
69 | |
|
70 | 0 | return true; |
71 | 0 | } |
72 | | |
73 | | const char *get_local_machine_name(void) |
74 | 0 | { |
75 | 0 | if (local_machine[0] == '\0') { |
76 | 0 | return lp_netbios_name(); |
77 | 0 | } |
78 | | |
79 | 0 | return local_machine; |
80 | 0 | } |
81 | | |
82 | | /** |
83 | | * Set the 'remote' machine name |
84 | | * |
85 | | * @param remote_name the name our client wants to be called by |
86 | | * @param if this is the 'final' name for them, not be be changed again |
87 | | */ |
88 | | bool set_remote_machine_name(const char *remote_name, bool perm) |
89 | 0 | { |
90 | 0 | static bool already_perm = False; |
91 | 0 | char tmp[MACHINE_NAME_SIZE]; |
92 | |
|
93 | 0 | if (already_perm) { |
94 | 0 | return true; |
95 | 0 | } |
96 | | |
97 | 0 | strlcpy(tmp, remote_name, sizeof(tmp)); |
98 | 0 | trim_char(tmp, ' ', ' '); |
99 | |
|
100 | 0 | alpha_strcpy(remote_machine, |
101 | 0 | tmp, |
102 | 0 | SAFE_NETBIOS_CHARS, |
103 | 0 | sizeof(remote_machine) - 1); |
104 | 0 | if (!strlower_m(remote_machine)) { |
105 | 0 | return false; |
106 | 0 | } |
107 | | |
108 | 0 | already_perm = perm; |
109 | |
|
110 | 0 | return true; |
111 | 0 | } |
112 | | |
113 | | const char *get_remote_machine_name(void) |
114 | 0 | { |
115 | 0 | return remote_machine; |
116 | 0 | } |
117 | | |
118 | | static char sub_peeraddr[INET6_ADDRSTRLEN]; |
119 | | static const char *sub_peername = NULL; |
120 | | static char sub_sockaddr[INET6_ADDRSTRLEN]; |
121 | | |
122 | | void sub_set_socket_ids(const char *peeraddr, const char *peername, |
123 | | const char *sockaddr) |
124 | 0 | { |
125 | 0 | const char *addr = peeraddr; |
126 | |
|
127 | 0 | if (strnequal(addr, "::ffff:", 7)) { |
128 | 0 | addr += 7; |
129 | 0 | } |
130 | 0 | strlcpy(sub_peeraddr, addr, sizeof(sub_peeraddr)); |
131 | |
|
132 | 0 | if (sub_peername != NULL && |
133 | 0 | sub_peername != sub_peeraddr) { |
134 | 0 | talloc_free(discard_const_p(char,sub_peername)); |
135 | 0 | sub_peername = NULL; |
136 | 0 | } |
137 | 0 | sub_peername = talloc_strdup(NULL, peername); |
138 | 0 | if (sub_peername == NULL) { |
139 | 0 | sub_peername = sub_peeraddr; |
140 | 0 | } |
141 | | |
142 | | /* |
143 | | * Shouldn't we do the ::ffff: cancellation here as well? The |
144 | | * original code in talloc_sub_basic() did not do it, so I'm |
145 | | * leaving it out here as well for compatibility. |
146 | | */ |
147 | 0 | strlcpy(sub_sockaddr, sockaddr, sizeof(sub_sockaddr)); |
148 | 0 | } |
149 | | |
150 | | /******************************************************************* |
151 | | Setup the strings used by substitutions. Called per packet. Ensure |
152 | | %U name is set correctly also. |
153 | | |
154 | | smb_name must be sanitized by alpha_strcpy |
155 | | ********************************************************************/ |
156 | | |
157 | | void set_current_user_info(const char *smb_name, const char *unix_name, |
158 | | const char *domain) |
159 | 0 | { |
160 | 0 | static const void *last_smb_name; |
161 | 0 | static const void *last_unix_name; |
162 | 0 | static const void *last_domain; |
163 | |
|
164 | 0 | if (likely(last_smb_name == smb_name && |
165 | 0 | last_unix_name == unix_name && |
166 | 0 | last_domain == domain)) |
167 | 0 | { |
168 | 0 | return; |
169 | 0 | } |
170 | | |
171 | 0 | fstrcpy(current_user_info.smb_name, smb_name); |
172 | 0 | fstrcpy(current_user_info.unix_name, unix_name); |
173 | 0 | fstrcpy(current_user_info.domain, domain); |
174 | |
|
175 | 0 | last_smb_name = smb_name; |
176 | 0 | last_unix_name = unix_name; |
177 | 0 | last_domain = domain; |
178 | 0 | } |
179 | | |
180 | | /******************************************************************* |
181 | | Return the current active user name. |
182 | | *******************************************************************/ |
183 | | |
184 | | const char *get_current_username(void) |
185 | 0 | { |
186 | 0 | return current_user_info.smb_name; |
187 | 0 | } |
188 | | |
189 | | const char *get_current_user_info_domain(void) |
190 | 0 | { |
191 | 0 | return current_user_info.domain; |
192 | 0 | } |
193 | | |
194 | | /******************************************************************* |
195 | | Given a pointer to a %$(NAME) in p and the whole string in str |
196 | | expand it as an environment variable. |
197 | | str must be a talloced string. |
198 | | Return a new allocated and expanded string. |
199 | | Based on code by Branko Cibej <branko.cibej@hermes.si> |
200 | | When this is called p points at the '%' character. |
201 | | May substitute multiple occurrences of the same env var. |
202 | | ********************************************************************/ |
203 | | |
204 | | static char *realloc_expand_env_var(char *str, char *p) |
205 | 0 | { |
206 | 0 | char *envname; |
207 | 0 | char *envval; |
208 | 0 | char *q, *r; |
209 | 0 | int copylen; |
210 | |
|
211 | 0 | if (p[0] != '%' || p[1] != '$' || p[2] != '(') { |
212 | 0 | return str; |
213 | 0 | } |
214 | | |
215 | | /* |
216 | | * Look for the terminating ')'. |
217 | | */ |
218 | | |
219 | 0 | if ((q = strchr_m(p,')')) == NULL) { |
220 | 0 | DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p)); |
221 | 0 | return str; |
222 | 0 | } |
223 | | |
224 | | /* |
225 | | * Extract the name from within the %$(NAME) string. |
226 | | */ |
227 | | |
228 | 0 | r = p + 3; |
229 | 0 | copylen = q - r; |
230 | | |
231 | | /* reserve space for use later add %$() chars */ |
232 | 0 | if ( (envname = talloc_array(talloc_tos(), char, copylen + 1 + 4)) == NULL ) { |
233 | 0 | return NULL; |
234 | 0 | } |
235 | | |
236 | 0 | strncpy(envname,r,copylen); |
237 | 0 | envname[copylen] = '\0'; |
238 | |
|
239 | 0 | if ((envval = getenv(envname)) == NULL) { |
240 | 0 | DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname)); |
241 | 0 | TALLOC_FREE(envname); |
242 | 0 | return str; |
243 | 0 | } |
244 | | |
245 | | /* |
246 | | * Copy the full %$(NAME) into envname so it |
247 | | * can be replaced. |
248 | | */ |
249 | | |
250 | 0 | copylen = q + 1 - p; |
251 | 0 | strncpy(envname,p,copylen); |
252 | 0 | envname[copylen] = '\0'; |
253 | 0 | r = realloc_string_sub(str, envname, envval); |
254 | 0 | TALLOC_FREE(envname); |
255 | |
|
256 | 0 | return r; |
257 | 0 | } |
258 | | |
259 | | /**************************************************************************** |
260 | | Do some standard substitutions in a string. |
261 | | len is the length in bytes of the space allowed in string str. If zero means |
262 | | don't allow expansions. |
263 | | ****************************************************************************/ |
264 | | |
265 | | void standard_sub_basic(const char *smb_name, const char *domain_name, |
266 | | char *str, size_t len) |
267 | 0 | { |
268 | 0 | char *s; |
269 | |
|
270 | 0 | if ( (s = talloc_sub_basic(talloc_tos(), smb_name, domain_name, str )) != NULL ) { |
271 | 0 | strncpy( str, s, len ); |
272 | 0 | } |
273 | |
|
274 | 0 | TALLOC_FREE( s ); |
275 | 0 | } |
276 | | |
277 | | /* |
278 | | * Limit addresses to hexalpha characters and underscore, safe for path |
279 | | * components for Windows clients. |
280 | | */ |
281 | | static void make_address_pathsafe(char *addr) |
282 | 0 | { |
283 | 0 | while(addr && *addr) { |
284 | 0 | if(!isxdigit(*addr)) { |
285 | 0 | *addr = '_'; |
286 | 0 | } |
287 | 0 | ++addr; |
288 | 0 | } |
289 | 0 | } |
290 | | |
291 | | /**************************************************************************** |
292 | | Do some standard substitutions in a string. |
293 | | This function will return a talloced string that has to be freed. |
294 | | ****************************************************************************/ |
295 | | |
296 | | char *talloc_sub_basic(TALLOC_CTX *mem_ctx, |
297 | | const char *smb_name, |
298 | | const char *domain_name, |
299 | | const char *str) |
300 | 0 | { |
301 | 0 | char *b, *p, *s, *r, *a_string; |
302 | 0 | fstring pidstr, vnnstr; |
303 | 0 | const char *local_machine_name = get_local_machine_name(); |
304 | 0 | TALLOC_CTX *tmp_ctx = NULL; |
305 | | |
306 | | /* workaround to prevent a crash while looking at bug #687 */ |
307 | |
|
308 | 0 | if (!str) { |
309 | 0 | DEBUG(0,("talloc_sub_basic: NULL source string! This should not happen\n")); |
310 | 0 | return NULL; |
311 | 0 | } |
312 | | |
313 | 0 | a_string = talloc_strdup(mem_ctx, str); |
314 | 0 | if (a_string == NULL) { |
315 | 0 | DEBUG(0, ("talloc_sub_basic: Out of memory!\n")); |
316 | 0 | return NULL; |
317 | 0 | } |
318 | | |
319 | 0 | tmp_ctx = talloc_stackframe(); |
320 | |
|
321 | 0 | for (s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) { |
322 | |
|
323 | 0 | r = NULL; |
324 | 0 | b = a_string; |
325 | |
|
326 | 0 | switch (*(p+1)) { |
327 | 0 | case 'U' : |
328 | 0 | r = strlower_talloc(tmp_ctx, smb_name); |
329 | 0 | if (r == NULL) { |
330 | 0 | goto error; |
331 | 0 | } |
332 | 0 | a_string = realloc_string_sub(a_string, "%U", r); |
333 | 0 | break; |
334 | 0 | case 'G' : { |
335 | 0 | struct passwd *pass; |
336 | 0 | bool is_domain_name = false; |
337 | 0 | const char *sep = lp_winbind_separator(); |
338 | |
|
339 | 0 | if (domain_name != NULL && domain_name[0] != '\0' && |
340 | 0 | (lp_security() == SEC_ADS || |
341 | 0 | lp_security() == SEC_DOMAIN)) { |
342 | 0 | r = talloc_asprintf(tmp_ctx, |
343 | 0 | "%s%c%s", |
344 | 0 | domain_name, |
345 | 0 | *sep, |
346 | 0 | smb_name); |
347 | 0 | is_domain_name = true; |
348 | 0 | } else { |
349 | 0 | r = talloc_strdup(tmp_ctx, smb_name); |
350 | 0 | } |
351 | 0 | if (r == NULL) { |
352 | 0 | goto error; |
353 | 0 | } |
354 | | |
355 | 0 | pass = Get_Pwnam_alloc(tmp_ctx, r); |
356 | 0 | if (pass != NULL) { |
357 | 0 | char *group_name; |
358 | |
|
359 | 0 | group_name = gidtoname(pass->pw_gid); |
360 | 0 | if (is_domain_name) { |
361 | 0 | char *group_sep; |
362 | 0 | group_sep = strchr_m(group_name, *sep); |
363 | 0 | if (group_sep != NULL) { |
364 | 0 | group_name = group_sep + 1; |
365 | 0 | } |
366 | 0 | } |
367 | 0 | a_string = realloc_string_sub(a_string, |
368 | 0 | "%G", |
369 | 0 | group_name); |
370 | 0 | } |
371 | 0 | TALLOC_FREE(pass); |
372 | 0 | break; |
373 | 0 | } |
374 | 0 | case 'D' : |
375 | 0 | r = strupper_talloc(tmp_ctx, domain_name); |
376 | 0 | if (r == NULL) { |
377 | 0 | goto error; |
378 | 0 | } |
379 | 0 | a_string = realloc_string_sub(a_string, "%D", r); |
380 | 0 | break; |
381 | 0 | case 'I' : { |
382 | 0 | a_string = realloc_string_sub( |
383 | 0 | a_string, "%I", |
384 | 0 | sub_peeraddr[0] ? sub_peeraddr : "0.0.0.0"); |
385 | 0 | break; |
386 | 0 | } |
387 | 0 | case 'J' : { |
388 | 0 | r = talloc_strdup(tmp_ctx, |
389 | 0 | sub_peeraddr[0] ? sub_peeraddr : "0.0.0.0"); |
390 | 0 | make_address_pathsafe(r); |
391 | 0 | a_string = realloc_string_sub(a_string, "%J", r); |
392 | 0 | break; |
393 | 0 | } |
394 | 0 | case 'i': |
395 | 0 | a_string = realloc_string_sub( |
396 | 0 | a_string, "%i", |
397 | 0 | sub_sockaddr[0] ? sub_sockaddr : "0.0.0.0"); |
398 | 0 | break; |
399 | 0 | case 'j' : { |
400 | 0 | r = talloc_strdup(tmp_ctx, |
401 | 0 | sub_sockaddr[0] ? sub_sockaddr : "0.0.0.0"); |
402 | 0 | make_address_pathsafe(r); |
403 | 0 | a_string = realloc_string_sub(a_string, "%j", r); |
404 | 0 | break; |
405 | 0 | } |
406 | 0 | case 'L' : |
407 | 0 | if ( strncasecmp_m(p, "%LOGONSERVER%", strlen("%LOGONSERVER%")) == 0 ) { |
408 | 0 | break; |
409 | 0 | } |
410 | 0 | if (local_machine_name && *local_machine_name) { |
411 | 0 | a_string = realloc_string_sub(a_string, "%L", local_machine_name); |
412 | 0 | } else { |
413 | 0 | a_string = realloc_string_sub(a_string, "%L", lp_netbios_name()); |
414 | 0 | } |
415 | 0 | break; |
416 | 0 | case 'N' : |
417 | 0 | a_string = realloc_string_sub(a_string, |
418 | 0 | "%N", |
419 | 0 | lp_netbios_name()); |
420 | 0 | break; |
421 | 0 | case 'M' : |
422 | 0 | a_string = realloc_string_sub(a_string, "%M", |
423 | 0 | sub_peername ? sub_peername : ""); |
424 | 0 | break; |
425 | 0 | case 'R' : |
426 | 0 | a_string = realloc_string_sub(a_string, "%R", remote_proto); |
427 | 0 | break; |
428 | 0 | case 'T' : |
429 | 0 | a_string = realloc_string_sub(a_string, "%T", current_timestring(tmp_ctx, False)); |
430 | 0 | break; |
431 | 0 | case 't' : |
432 | 0 | a_string = realloc_string_sub(a_string, "%t", |
433 | 0 | current_minimal_timestring(tmp_ctx, False)); |
434 | 0 | break; |
435 | 0 | case 'a' : |
436 | 0 | a_string = realloc_string_sub(a_string, "%a", |
437 | 0 | get_remote_arch_str()); |
438 | 0 | break; |
439 | 0 | case 'd' : |
440 | 0 | slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)getpid()); |
441 | 0 | a_string = realloc_string_sub(a_string, "%d", pidstr); |
442 | 0 | break; |
443 | 0 | case 'h' : |
444 | 0 | a_string = realloc_string_sub(a_string, "%h", myhostname()); |
445 | 0 | break; |
446 | 0 | case 'm' : |
447 | 0 | a_string = realloc_string_sub(a_string, "%m", |
448 | 0 | remote_machine); |
449 | 0 | break; |
450 | 0 | case 'v' : |
451 | 0 | a_string = realloc_string_sub(a_string, "%v", samba_version_string()); |
452 | 0 | break; |
453 | 0 | case 'w' : |
454 | 0 | a_string = realloc_string_sub(a_string, "%w", lp_winbind_separator()); |
455 | 0 | break; |
456 | 0 | case '$' : |
457 | 0 | a_string = realloc_expand_env_var(a_string, p); /* Expand environment variables */ |
458 | 0 | break; |
459 | 0 | case 'V' : |
460 | 0 | slprintf(vnnstr,sizeof(vnnstr)-1, "%u", get_my_vnn()); |
461 | 0 | a_string = realloc_string_sub(a_string, "%V", vnnstr); |
462 | 0 | break; |
463 | 0 | default: |
464 | 0 | break; |
465 | 0 | } |
466 | | |
467 | 0 | p++; |
468 | 0 | TALLOC_FREE(r); |
469 | |
|
470 | 0 | if (a_string == NULL) { |
471 | 0 | goto done; |
472 | 0 | } |
473 | 0 | } |
474 | | |
475 | 0 | goto done; |
476 | | |
477 | 0 | error: |
478 | 0 | TALLOC_FREE(a_string); |
479 | |
|
480 | 0 | done: |
481 | 0 | TALLOC_FREE(tmp_ctx); |
482 | 0 | return a_string; |
483 | 0 | } |
484 | | |
485 | | /**************************************************************************** |
486 | | Do some specific substitutions in a string. |
487 | | This function will return an allocated string that have to be freed. |
488 | | ****************************************************************************/ |
489 | | |
490 | | char *talloc_sub_specified(TALLOC_CTX *mem_ctx, |
491 | | const char *input_string, |
492 | | const char *username, |
493 | | const char *grpname, |
494 | | const char *domain, |
495 | | uid_t uid, |
496 | | gid_t gid) |
497 | 0 | { |
498 | 0 | char *a_string; |
499 | 0 | char *ret_string = NULL; |
500 | 0 | char *b, *p, *s; |
501 | 0 | TALLOC_CTX *tmp_ctx; |
502 | |
|
503 | 0 | if (!(tmp_ctx = talloc_new(mem_ctx))) { |
504 | 0 | DEBUG(0, ("talloc_new failed\n")); |
505 | 0 | return NULL; |
506 | 0 | } |
507 | | |
508 | 0 | a_string = talloc_strdup(tmp_ctx, input_string); |
509 | 0 | if (a_string == NULL) { |
510 | 0 | DEBUG(0, ("talloc_sub_specified: Out of memory!\n")); |
511 | 0 | goto done; |
512 | 0 | } |
513 | | |
514 | 0 | for (s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) { |
515 | |
|
516 | 0 | b = a_string; |
517 | |
|
518 | 0 | switch (*(p+1)) { |
519 | 0 | case 'U' : |
520 | 0 | a_string = talloc_string_sub( |
521 | 0 | tmp_ctx, a_string, "%U", username); |
522 | 0 | break; |
523 | 0 | case 'u' : |
524 | 0 | a_string = talloc_string_sub( |
525 | 0 | tmp_ctx, a_string, "%u", username); |
526 | 0 | break; |
527 | 0 | case 'G' : |
528 | 0 | if (gid != -1) { |
529 | 0 | const char *name; |
530 | |
|
531 | 0 | if (grpname != NULL) { |
532 | 0 | name = grpname; |
533 | 0 | } else { |
534 | 0 | name = gidtoname(gid); |
535 | 0 | } |
536 | |
|
537 | 0 | a_string = talloc_string_sub(tmp_ctx, |
538 | 0 | a_string, |
539 | 0 | "%G", |
540 | 0 | name); |
541 | 0 | } else { |
542 | 0 | a_string = talloc_string_sub( |
543 | 0 | tmp_ctx, a_string, |
544 | 0 | "%G", "NO_GROUP"); |
545 | 0 | } |
546 | 0 | break; |
547 | 0 | case 'g' : |
548 | 0 | if (gid != -1) { |
549 | 0 | const char *name; |
550 | |
|
551 | 0 | if (grpname != NULL) { |
552 | 0 | name = grpname; |
553 | 0 | } else { |
554 | 0 | name = gidtoname(gid); |
555 | 0 | } |
556 | |
|
557 | 0 | a_string = talloc_string_sub(tmp_ctx, |
558 | 0 | a_string, |
559 | 0 | "%g", |
560 | 0 | name); |
561 | 0 | } else { |
562 | 0 | a_string = talloc_string_sub( |
563 | 0 | tmp_ctx, a_string, "%g", "NO_GROUP"); |
564 | 0 | } |
565 | 0 | break; |
566 | 0 | case 'D' : |
567 | 0 | a_string = talloc_string_sub(tmp_ctx, a_string, |
568 | 0 | "%D", domain); |
569 | 0 | break; |
570 | 0 | case 'N' : |
571 | 0 | a_string = talloc_string_sub(tmp_ctx, a_string, |
572 | 0 | "%N", lp_netbios_name()); |
573 | 0 | break; |
574 | 0 | default: |
575 | 0 | break; |
576 | 0 | } |
577 | | |
578 | 0 | p++; |
579 | 0 | if (a_string == NULL) { |
580 | 0 | goto done; |
581 | 0 | } |
582 | 0 | } |
583 | | |
584 | | /* Watch out, using "mem_ctx" here, so all intermediate stuff goes |
585 | | * away with the TALLOC_FREE(tmp_ctx) further down. */ |
586 | | |
587 | 0 | ret_string = talloc_sub_basic(mem_ctx, username, domain, a_string); |
588 | |
|
589 | 0 | done: |
590 | 0 | TALLOC_FREE(tmp_ctx); |
591 | 0 | return ret_string; |
592 | 0 | } |
593 | | |
594 | | /**************************************************************************** |
595 | | ****************************************************************************/ |
596 | | |
597 | | char *talloc_sub_advanced(TALLOC_CTX *ctx, |
598 | | const char *servicename, |
599 | | const char *user, |
600 | | const char *connectpath, |
601 | | gid_t gid, |
602 | | const char *str) |
603 | 0 | { |
604 | 0 | char *a_string; |
605 | 0 | char *b, *p, *s; |
606 | |
|
607 | 0 | a_string = talloc_strdup(talloc_tos(), str); |
608 | 0 | if (a_string == NULL) { |
609 | 0 | DEBUG(0, ("talloc_sub_advanced_only: Out of memory!\n")); |
610 | 0 | return NULL; |
611 | 0 | } |
612 | | |
613 | 0 | for (s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) { |
614 | |
|
615 | 0 | b = a_string; |
616 | |
|
617 | 0 | switch (*(p+1)) { |
618 | 0 | case 'N': |
619 | 0 | a_string = realloc_string_sub(a_string, |
620 | 0 | "%N", |
621 | 0 | lp_netbios_name()); |
622 | 0 | break; |
623 | 0 | case 'H': { |
624 | 0 | char *h; |
625 | 0 | if ((h = get_user_home_dir(talloc_tos(), user))) |
626 | 0 | a_string = realloc_string_sub(a_string, "%H", h); |
627 | 0 | TALLOC_FREE(h); |
628 | 0 | break; |
629 | 0 | } |
630 | 0 | case 'P': |
631 | 0 | a_string = realloc_string_sub(a_string, "%P", connectpath); |
632 | 0 | break; |
633 | 0 | case 'S': |
634 | 0 | a_string = realloc_string_sub(a_string, "%S", servicename); |
635 | 0 | break; |
636 | 0 | case 'g': |
637 | 0 | a_string = realloc_string_sub(a_string, "%g", gidtoname(gid)); |
638 | 0 | break; |
639 | 0 | case 'u': |
640 | 0 | a_string = realloc_string_sub(a_string, "%u", user); |
641 | 0 | break; |
642 | 0 | default: |
643 | 0 | break; |
644 | 0 | } |
645 | | |
646 | 0 | p++; |
647 | 0 | if (a_string == NULL) { |
648 | 0 | return NULL; |
649 | 0 | } |
650 | 0 | } |
651 | | |
652 | 0 | return a_string; |
653 | 0 | } |
654 | | |
655 | | char *talloc_sub_full(TALLOC_CTX *ctx, |
656 | | const char *servicename, |
657 | | const char *user, |
658 | | const char *connectpath, |
659 | | gid_t gid, |
660 | | const char *smb_name, |
661 | | const char *domain_name, |
662 | | const char *str) |
663 | 0 | { |
664 | 0 | char *a_string, *ret_string; |
665 | |
|
666 | 0 | a_string = talloc_sub_advanced(ctx, servicename, user, connectpath, |
667 | 0 | gid, str); |
668 | 0 | if (a_string == NULL) { |
669 | 0 | return NULL; |
670 | 0 | } |
671 | | |
672 | 0 | ret_string = talloc_sub_basic(ctx, smb_name, domain_name, a_string); |
673 | | TALLOC_FREE(a_string); |
674 | 0 | return ret_string; |
675 | 0 | } |