Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Parameter loading functions
4 : Copyright (C) Karl Auer 1993-1998
5 :
6 : Largely re-written by Andrew Tridgell, September 1994
7 :
8 : Copyright (C) Simo Sorce 2001
9 : Copyright (C) Alexander Bokovoy 2002
10 : Copyright (C) Stefan (metze) Metzmacher 2002
11 : Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12 : Copyright (C) Michael Adam 2008
13 : Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14 : Copyright (C) Andrew Bartlett 2011
15 :
16 : This program is free software; you can redistribute it and/or modify
17 : it under the terms of the GNU General Public License as published by
18 : the Free Software Foundation; either version 3 of the License, or
19 : (at your option) any later version.
20 :
21 : This program is distributed in the hope that it will be useful,
22 : but WITHOUT ANY WARRANTY; without even the implied warranty of
23 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 : GNU General Public License for more details.
25 :
26 : You should have received a copy of the GNU General Public License
27 : along with this program. If not, see <http://www.gnu.org/licenses/>.
28 : */
29 :
30 : /*
31 : * Load parameters.
32 : *
33 : * This module provides suitable callback functions for the params
34 : * module. It builds the internal table of service details which is
35 : * then used by the rest of the server.
36 : *
37 : * To add a parameter:
38 : *
39 : * 1) add it to the global or service structure definition
40 : * 2) add it to the parm_table
41 : * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42 : * 4) If it's a global then initialise it in init_globals. If a local
43 : * (ie. service) parameter then initialise it in the sDefault structure
44 : *
45 : *
46 : * Notes:
47 : * The configuration file is processed sequentially for speed. It is NOT
48 : * accessed randomly as happens in 'real' Windows. For this reason, there
49 : * is a fair bit of sequence-dependent code here - ie., code which assumes
50 : * that certain things happen before others. In particular, the code which
51 : * happens at the boundary between sections is delicately poised, so be
52 : * careful!
53 : *
54 : */
55 :
56 : #define LOADPARM_SUBSTITUTION_INTERNALS 1
57 : #include "includes.h"
58 : #include "system/filesys.h"
59 : #include "util_tdb.h"
60 : #include "lib/param/loadparm.h"
61 : #include "lib/param/param.h"
62 : #include "printing.h"
63 : #include "lib/smbconf/smbconf.h"
64 : #include "lib/smbconf/smbconf_init.h"
65 :
66 : #include "include/smb_ldap.h"
67 : #include "../librpc/gen_ndr/svcctl.h"
68 : #include "intl.h"
69 : #include "../libcli/smb/smb_signing.h"
70 : #include "dbwrap/dbwrap.h"
71 : #include "dbwrap/dbwrap_rbt.h"
72 : #include "../lib/util/bitmap.h"
73 : #include "librpc/gen_ndr/nbt.h"
74 : #include "librpc/gen_ndr/dns.h"
75 : #include "source4/lib/tls/tls.h"
76 : #include "libcli/auth/ntlm_check.h"
77 : #include "lib/crypto/gnutls_helpers.h"
78 : #include "lib/util/string_wrappers.h"
79 : #include "auth/credentials/credentials.h"
80 : #include "source3/lib/substitute.h"
81 : #include "source3/librpc/gen_ndr/ads.h"
82 : #include "lib/util/time_basic.h"
83 :
84 : #ifdef HAVE_SYS_SYSCTL_H
85 : #include <sys/sysctl.h>
86 : #endif
87 :
88 : bool bLoaded = false;
89 :
90 : /* the special value for the include parameter
91 : * to be interpreted not as a file name but to
92 : * trigger loading of the global smb.conf options
93 : * from registry. */
94 : #ifndef INCLUDE_REGISTRY_NAME
95 : #define INCLUDE_REGISTRY_NAME "registry"
96 : #endif
97 :
98 : static bool in_client = false; /* Not in the client by default */
99 : static struct smbconf_csn conf_last_csn;
100 :
101 : static int config_backend = CONFIG_BACKEND_FILE;
102 :
103 : /* some helpful bits */
104 : #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && \
105 : (ServicePtrs != NULL) && \
106 : (ServicePtrs[(i)] != NULL) && ServicePtrs[(i)]->valid)
107 : #define VALID(i) ((ServicePtrs != NULL) && (ServicePtrs[i]!= NULL) && \
108 : ServicePtrs[i]->valid)
109 :
110 : #define USERSHARE_VALID 1
111 : #define USERSHARE_PENDING_DELETE 2
112 :
113 : static bool defaults_saved = false;
114 :
115 : #include "lib/param/param_global.h"
116 :
117 : static struct loadparm_global Globals;
118 :
119 : /* This is a default service used to prime a services structure */
120 : static const struct loadparm_service _sDefault =
121 : {
122 : .valid = true,
123 : .autoloaded = false,
124 : .usershare = 0,
125 : .usershare_last_mod = {0, 0},
126 : .szService = NULL,
127 : .path = NULL,
128 : .invalid_users = NULL,
129 : .valid_users = NULL,
130 : .admin_users = NULL,
131 : .copy = NULL,
132 : .include = NULL,
133 : .preexec = NULL,
134 : .postexec = NULL,
135 : .root_preexec = NULL,
136 : .root_postexec = NULL,
137 : .cups_options = NULL,
138 : .print_command = NULL,
139 : .lpq_command = NULL,
140 : .lprm_command = NULL,
141 : .lppause_command = NULL,
142 : .lpresume_command = NULL,
143 : .queuepause_command = NULL,
144 : .queueresume_command = NULL,
145 : ._printername = NULL,
146 : .printjob_username = NULL,
147 : .dont_descend = NULL,
148 : .hosts_allow = NULL,
149 : .hosts_deny = NULL,
150 : .magic_script = NULL,
151 : .magic_output = NULL,
152 : .veto_files = NULL,
153 : .hide_files = NULL,
154 : .veto_oplock_files = NULL,
155 : .comment = NULL,
156 : .force_user = NULL,
157 : .force_group = NULL,
158 : .read_list = NULL,
159 : .write_list = NULL,
160 : .volume = NULL,
161 : .fstype = NULL,
162 : .vfs_objects = NULL,
163 : .msdfs_proxy = NULL,
164 : .aio_write_behind = NULL,
165 : .dfree_command = NULL,
166 : .min_print_space = 0,
167 : .max_print_jobs = 1000,
168 : .max_reported_print_jobs = 0,
169 : .create_mask = 0744,
170 : .force_create_mode = 0,
171 : .directory_mask = 0755,
172 : .force_directory_mode = 0,
173 : .max_connections = 0,
174 : .default_case = CASE_LOWER,
175 : .printing = DEFAULT_PRINTING,
176 : .csc_policy = 0,
177 : .block_size = 1024,
178 : .dfree_cache_time = 0,
179 : .preexec_close = false,
180 : .root_preexec_close = false,
181 : .case_sensitive = Auto,
182 : .preserve_case = true,
183 : .short_preserve_case = true,
184 : .hide_dot_files = true,
185 : .hide_special_files = false,
186 : .hide_unreadable = false,
187 : .hide_unwriteable_files = false,
188 : .browseable = true,
189 : .access_based_share_enum = false,
190 : .available = true,
191 : .read_only = true,
192 : .spotlight = false,
193 : .guest_only = false,
194 : .administrative_share = false,
195 : .guest_ok = false,
196 : .printable = false,
197 : .print_notify_backchannel = false,
198 : .map_system = false,
199 : .map_hidden = false,
200 : .map_archive = true,
201 : .store_dos_attributes = true,
202 : .smbd_max_xattr_size = 65536,
203 : .dmapi_support = false,
204 : .locking = true,
205 : .strict_locking = Auto,
206 : .posix_locking = true,
207 : .oplocks = true,
208 : .kernel_oplocks = false,
209 : .level2_oplocks = true,
210 : .mangled_names = MANGLED_NAMES_ILLEGAL,
211 : .wide_links = false,
212 : .follow_symlinks = true,
213 : .sync_always = false,
214 : .strict_allocate = false,
215 : .strict_rename = false,
216 : .strict_sync = true,
217 : .mangling_char = '~',
218 : .copymap = NULL,
219 : .delete_readonly = false,
220 : .fake_oplocks = false,
221 : .delete_veto_files = false,
222 : .dos_filemode = false,
223 : .dos_filetimes = true,
224 : .dos_filetime_resolution = false,
225 : .fake_directory_create_times = false,
226 : .blocking_locks = true,
227 : .inherit_permissions = false,
228 : .inherit_acls = false,
229 : .inherit_owner = false,
230 : .msdfs_root = false,
231 : .msdfs_shuffle_referrals = false,
232 : .use_client_driver = false,
233 : .default_devmode = true,
234 : .force_printername = false,
235 : .nt_acl_support = true,
236 : .force_unknown_acl_user = false,
237 : ._use_sendfile = false,
238 : .map_acl_inherit = false,
239 : .afs_share = false,
240 : .ea_support = true,
241 : .acl_check_permissions = true,
242 : .acl_map_full_control = true,
243 : .acl_group_control = false,
244 : .acl_allow_execute_always = false,
245 : .acl_flag_inherited_canonicalization = true,
246 : .aio_read_size = 1,
247 : .aio_write_size = 1,
248 : .map_readonly = MAP_READONLY_NO,
249 : .directory_name_cache_size = 100,
250 : .server_smb_encrypt = SMB_ENCRYPTION_DEFAULT,
251 : .kernel_share_modes = false,
252 : .durable_handles = true,
253 : .check_parent_directory_delete_on_close = false,
254 : .param_opt = NULL,
255 : .smbd_search_ask_sharemode = true,
256 : .smbd_getinfo_ask_sharemode = true,
257 : .spotlight_backend = SPOTLIGHT_BACKEND_NOINDEX,
258 : .honor_change_notify_privilege = false,
259 : .volume_serial_number = -1,
260 : .dummy = ""
261 : };
262 :
263 : /*
264 : * This is a copy of the default service structure. Service options in the
265 : * global section would otherwise overwrite the initial default values.
266 : */
267 : static struct loadparm_service sDefault;
268 :
269 : /* local variables */
270 : static struct loadparm_service **ServicePtrs = NULL;
271 : static int iNumServices = 0;
272 : static int iServiceIndex = 0;
273 : static struct db_context *ServiceHash;
274 : static bool bInGlobalSection = true;
275 : static bool bGlobalOnly = false;
276 : static struct file_lists *file_lists = NULL;
277 : static unsigned int *flags_list = NULL;
278 :
279 : static void set_allowed_client_auth(void);
280 :
281 : static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue);
282 : static void free_param_opts(struct parmlist_entry **popts);
283 :
284 : /**
285 : * Function to return the default value for the maximum number of open
286 : * file descriptors permitted. This function tries to consult the
287 : * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
288 : * the smaller of those.
289 : */
290 7553 : static int max_open_files(void)
291 : {
292 7553 : int sysctl_max = MAX_OPEN_FILES;
293 7553 : int rlimit_max = MAX_OPEN_FILES;
294 :
295 : #ifdef HAVE_SYSCTLBYNAME
296 : {
297 : size_t size = sizeof(sysctl_max);
298 : sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
299 : 0);
300 : }
301 : #endif
302 :
303 : #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
304 : {
305 : struct rlimit rl;
306 :
307 7553 : ZERO_STRUCT(rl);
308 :
309 7553 : if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
310 7553 : rlimit_max = rl.rlim_cur;
311 :
312 : #if defined(RLIM_INFINITY)
313 7553 : if(rl.rlim_cur == RLIM_INFINITY)
314 0 : rlimit_max = MAX_OPEN_FILES;
315 : #endif
316 : }
317 : #endif
318 :
319 7553 : if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
320 0 : DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
321 : "minimum Windows limit (%d)\n",
322 : sysctl_max,
323 : MIN_OPEN_FILES_WINDOWS));
324 0 : sysctl_max = MIN_OPEN_FILES_WINDOWS;
325 : }
326 :
327 7553 : if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
328 271 : DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
329 : "minimum Windows limit (%d)\n",
330 : rlimit_max,
331 : MIN_OPEN_FILES_WINDOWS));
332 271 : rlimit_max = MIN_OPEN_FILES_WINDOWS;
333 : }
334 :
335 7553 : return MIN(sysctl_max, rlimit_max);
336 : }
337 :
338 : /**
339 : * Common part of freeing allocated data for one parameter.
340 : */
341 6834826 : static void free_one_parameter_common(void *parm_ptr,
342 : struct parm_struct parm)
343 : {
344 6834826 : if ((parm.type == P_STRING) ||
345 5208446 : (parm.type == P_USTRING))
346 : {
347 1638830 : lpcfg_string_free((char**)parm_ptr);
348 5195996 : } else if (parm.type == P_LIST || parm.type == P_CMDLIST) {
349 570884 : TALLOC_FREE(*((char***)parm_ptr));
350 : }
351 6834826 : }
352 :
353 : /**
354 : * Free the allocated data for one parameter for a share
355 : * given as a service struct.
356 : */
357 15441756 : static void free_one_parameter(struct loadparm_service *service,
358 : struct parm_struct parm)
359 : {
360 : void *parm_ptr;
361 :
362 15441756 : if (parm.p_class != P_LOCAL) {
363 10752480 : return;
364 : }
365 :
366 4689276 : parm_ptr = lp_parm_ptr(service, &parm);
367 :
368 4689276 : free_one_parameter_common(parm_ptr, parm);
369 : }
370 :
371 : /**
372 : * Free the allocated parameter data of a share given
373 : * as a service struct.
374 : */
375 29868 : static void free_parameters(struct loadparm_service *service)
376 : {
377 : uint32_t i;
378 :
379 15471624 : for (i=0; parm_table[i].label; i++) {
380 15441756 : free_one_parameter(service, parm_table[i]);
381 : }
382 29868 : }
383 :
384 : /**
385 : * Free the allocated data for one parameter for a given share
386 : * specified by an snum.
387 : */
388 2145550 : static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
389 : {
390 : void *parm_ptr;
391 :
392 2145550 : if (snum < 0) {
393 2145550 : parm_ptr = lp_parm_ptr(NULL, &parm);
394 0 : } else if (parm.p_class != P_LOCAL) {
395 0 : return;
396 : } else {
397 0 : parm_ptr = lp_parm_ptr(ServicePtrs[snum], &parm);
398 : }
399 :
400 2145550 : free_one_parameter_common(parm_ptr, parm);
401 : }
402 :
403 : /**
404 : * Free the allocated parameter data for a share specified
405 : * by an snum.
406 : */
407 4150 : static void free_parameters_by_snum(int snum)
408 : {
409 : uint32_t i;
410 :
411 2149700 : for (i=0; parm_table[i].label; i++) {
412 2145550 : free_one_parameter_by_snum(snum, parm_table[i]);
413 : }
414 4150 : }
415 :
416 : /**
417 : * Free the allocated global parameters.
418 : */
419 4150 : static void free_global_parameters(void)
420 : {
421 : uint32_t i;
422 : struct parm_struct *parm;
423 :
424 4150 : free_param_opts(&Globals.param_opt);
425 4150 : free_parameters_by_snum(GLOBAL_SECTION_SNUM);
426 :
427 : /* Reset references in the defaults because the context is going to be freed */
428 2149700 : for (i=0; parm_table[i].label; i++) {
429 2145550 : parm = &parm_table[i];
430 2145550 : if ((parm->type == P_STRING) ||
431 1564550 : (parm->type == P_USTRING)) {
432 593450 : if ((parm->def.svalue != NULL) &&
433 239014 : (*(parm->def.svalue) != '\0')) {
434 73572 : if (talloc_parent(parm->def.svalue) == Globals.ctx) {
435 73572 : parm->def.svalue = NULL;
436 : }
437 : }
438 : }
439 : }
440 4150 : TALLOC_FREE(Globals.ctx);
441 4150 : }
442 :
443 : struct lp_stored_option {
444 : struct lp_stored_option *prev, *next;
445 : const char *label;
446 : const char *value;
447 : };
448 :
449 : static struct lp_stored_option *stored_options;
450 :
451 : /*
452 : save options set by lp_set_cmdline() into a list. This list is
453 : re-applied when we do a globals reset, so that cmdline set options
454 : are sticky across reloads of smb.conf
455 : */
456 6861 : bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
457 : {
458 : struct lp_stored_option *entry, *entry_next;
459 9348 : for (entry = stored_options; entry != NULL; entry = entry_next) {
460 2624 : entry_next = entry->next;
461 2624 : if (strcmp(pszParmName, entry->label) == 0) {
462 137 : DLIST_REMOVE(stored_options, entry);
463 137 : talloc_free(entry);
464 137 : break;
465 : }
466 : }
467 :
468 6861 : entry = talloc(NULL, struct lp_stored_option);
469 6861 : if (!entry) {
470 0 : return false;
471 : }
472 :
473 6861 : entry->label = talloc_strdup(entry, pszParmName);
474 6861 : if (!entry->label) {
475 0 : talloc_free(entry);
476 0 : return false;
477 : }
478 :
479 6861 : entry->value = talloc_strdup(entry, pszParmValue);
480 6861 : if (!entry->value) {
481 0 : talloc_free(entry);
482 0 : return false;
483 : }
484 :
485 6861 : DLIST_ADD_END(stored_options, entry);
486 :
487 6861 : return true;
488 : }
489 :
490 8356 : static bool apply_lp_set_cmdline(void)
491 : {
492 8356 : struct lp_stored_option *entry = NULL;
493 17207 : for (entry = stored_options; entry != NULL; entry = entry->next) {
494 8851 : if (!lp_set_cmdline_helper(entry->label, entry->value)) {
495 0 : DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
496 : entry->label, entry->value));
497 0 : return false;
498 : }
499 : }
500 8356 : return true;
501 : }
502 :
503 : /***************************************************************************
504 : Initialise the global parameter structure.
505 : ***************************************************************************/
506 :
507 8224 : static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
508 : {
509 : static bool done_init = false;
510 8224 : char *s = NULL;
511 : int i;
512 :
513 : /* If requested to initialize only once and we've already done it... */
514 8224 : if (!reinit_globals && done_init) {
515 : /* ... then we have nothing more to do */
516 671 : return;
517 : }
518 :
519 7553 : if (!done_init) {
520 : /* The logfile can be set before this is invoked. Free it if so. */
521 5512 : lpcfg_string_free(&Globals.logfile);
522 5512 : done_init = true;
523 : } else {
524 2041 : free_global_parameters();
525 : }
526 :
527 : /* This memset and the free_global_parameters() above will
528 : * wipe out smb.conf options set with lp_set_cmdline(). The
529 : * apply_lp_set_cmdline() call puts these values back in the
530 : * table once the defaults are set */
531 7553 : ZERO_STRUCT(Globals);
532 :
533 7553 : Globals.ctx = talloc_pooled_object(NULL, char, 272, 2048);
534 :
535 : /* Initialize the flags list if necessary */
536 7553 : if (flags_list == NULL) {
537 0 : get_flags();
538 : }
539 :
540 3912454 : for (i = 0; parm_table[i].label; i++) {
541 3904901 : if ((parm_table[i].type == P_STRING ||
542 2847481 : parm_table[i].type == P_USTRING))
543 : {
544 1080079 : lpcfg_string_set(
545 : Globals.ctx,
546 1080079 : (char **)lp_parm_ptr(NULL, &parm_table[i]),
547 : "");
548 : }
549 : }
550 :
551 :
552 7553 : lpcfg_string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
553 7553 : lpcfg_string_set(Globals.ctx, &sDefault.printjob_username, "%U");
554 :
555 7553 : init_printer_values(lp_ctx, Globals.ctx, &sDefault);
556 :
557 7553 : sDefault.ntvfs_handler = str_list_make_v3_const(Globals.ctx, "unixuid default", NULL);
558 :
559 7553 : DEBUG(3, ("Initialising global parameters\n"));
560 :
561 : /* Must manually force to upper case here, as this does not go via the handler */
562 7553 : lpcfg_string_set(Globals.ctx, &Globals.netbios_name,
563 7553 : myhostname_upper());
564 :
565 7553 : lpcfg_string_set(Globals.ctx, &Globals.smb_passwd_file,
566 : get_dyn_SMB_PASSWD_FILE());
567 7553 : lpcfg_string_set(Globals.ctx, &Globals.private_dir,
568 : get_dyn_PRIVATE_DIR());
569 7553 : lpcfg_string_set(Globals.ctx, &Globals.binddns_dir,
570 : get_dyn_BINDDNS_DIR());
571 :
572 : /* use the new 'hash2' method by default, with a prefix of 1 */
573 7553 : lpcfg_string_set(Globals.ctx, &Globals.mangling_method, "hash2");
574 7553 : Globals.mangle_prefix = 1;
575 :
576 7553 : lpcfg_string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
577 :
578 : /* using UTF8 by default allows us to support all chars */
579 7553 : lpcfg_string_set(Globals.ctx, &Globals.unix_charset,
580 : DEFAULT_UNIX_CHARSET);
581 :
582 : /* Use codepage 850 as a default for the dos character set */
583 7553 : lpcfg_string_set(Globals.ctx, &Globals.dos_charset,
584 : DEFAULT_DOS_CHARSET);
585 :
586 : /*
587 : * Allow the default PASSWD_CHAT to be overridden in local.h.
588 : */
589 7553 : lpcfg_string_set(Globals.ctx, &Globals.passwd_chat,
590 : DEFAULT_PASSWD_CHAT);
591 :
592 7553 : lpcfg_string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
593 :
594 7553 : lpcfg_string_set(Globals.ctx, &Globals.passwd_program, "");
595 7553 : lpcfg_string_set(Globals.ctx, &Globals.lock_directory,
596 : get_dyn_LOCKDIR());
597 7553 : lpcfg_string_set(Globals.ctx, &Globals.state_directory,
598 : get_dyn_STATEDIR());
599 7553 : lpcfg_string_set(Globals.ctx, &Globals.cache_directory,
600 : get_dyn_CACHEDIR());
601 7553 : lpcfg_string_set(Globals.ctx, &Globals.pid_directory,
602 : get_dyn_PIDDIR());
603 7553 : lpcfg_string_set(Globals.ctx, &Globals.nbt_client_socket_address,
604 : "0.0.0.0");
605 : /*
606 : * By default support explicit binding to broadcast
607 : * addresses.
608 : */
609 7553 : Globals.nmbd_bind_explicit_broadcast = true;
610 :
611 7553 : s = talloc_asprintf(talloc_tos(), "Samba %s", samba_version_string());
612 7553 : if (s == NULL) {
613 0 : smb_panic("init_globals: ENOMEM");
614 : }
615 7553 : lpcfg_string_set(Globals.ctx, &Globals.server_string, s);
616 7553 : TALLOC_FREE(s);
617 : #ifdef DEVELOPER
618 7553 : lpcfg_string_set(Globals.ctx, &Globals.panic_action,
619 : "/bin/sleep 999999999");
620 : #endif
621 :
622 7553 : lpcfg_string_set(Globals.ctx, &Globals.socket_options,
623 : DEFAULT_SOCKET_OPTIONS);
624 :
625 7553 : lpcfg_string_set(Globals.ctx, &Globals.logon_drive, "");
626 : /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
627 7553 : lpcfg_string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
628 7553 : lpcfg_string_set(Globals.ctx, &Globals.logon_path,
629 : "\\\\%N\\%U\\profile");
630 :
631 7553 : Globals.name_resolve_order =
632 7553 : str_list_make_v3_const(Globals.ctx,
633 : DEFAULT_NAME_RESOLVE_ORDER,
634 : NULL);
635 7553 : lpcfg_string_set(Globals.ctx, &Globals.password_server, "*");
636 :
637 7553 : Globals.algorithmic_rid_base = BASE_RID;
638 :
639 7553 : Globals.load_printers = true;
640 7553 : Globals.printcap_cache_time = 750; /* 12.5 minutes */
641 :
642 7553 : Globals.config_backend = config_backend;
643 7553 : Globals._server_role = ROLE_AUTO;
644 :
645 : /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
646 : /* Discovered by 2 days of pain by Don McCall @ HP :-). */
647 7553 : Globals.max_xmit = 0x4104;
648 7553 : Globals.max_mux = 50; /* This is *needed* for profile support. */
649 7553 : Globals.lpq_cache_time = 30; /* changed to handle large print servers better -- jerry */
650 7553 : Globals._disable_spoolss = false;
651 7553 : Globals.max_smbd_processes = 0;/* no limit specified */
652 7553 : Globals.username_level = 0;
653 7553 : Globals.deadtime = 10080;
654 7553 : Globals.getwd_cache = true;
655 7553 : Globals.large_readwrite = true;
656 7553 : Globals.max_log_size = 5000;
657 7553 : Globals.max_open_files = max_open_files();
658 7553 : Globals.server_max_protocol = PROTOCOL_SMB3_11;
659 7553 : Globals.server_min_protocol = PROTOCOL_SMB2_02;
660 7553 : Globals._client_max_protocol = PROTOCOL_DEFAULT;
661 7553 : Globals.client_min_protocol = PROTOCOL_SMB2_02;
662 7553 : Globals._client_ipc_max_protocol = PROTOCOL_DEFAULT;
663 7553 : Globals._client_ipc_min_protocol = PROTOCOL_DEFAULT;
664 7553 : Globals._security = SEC_AUTO;
665 7553 : Globals.encrypt_passwords = true;
666 7553 : Globals.client_schannel = true;
667 7553 : Globals.winbind_sealed_pipes = true;
668 7553 : Globals.require_strong_key = true;
669 7553 : Globals.reject_md5_servers = true;
670 7553 : Globals.server_schannel = true;
671 7553 : Globals.server_schannel_require_seal = true;
672 7553 : Globals.reject_md5_clients = true;
673 7553 : Globals.read_raw = true;
674 7553 : Globals.write_raw = true;
675 7553 : Globals.null_passwords = false;
676 7553 : Globals.old_password_allowed_period = 60;
677 7553 : Globals.obey_pam_restrictions = false;
678 7553 : Globals.syslog = 1;
679 7553 : Globals.syslog_only = false;
680 7553 : Globals.timestamp_logs = true;
681 7553 : lpcfg_string_set(Globals.ctx, &Globals.log_level, "0");
682 7553 : Globals.debug_prefix_timestamp = false;
683 7553 : Globals.debug_hires_timestamp = true;
684 7553 : Globals.debug_syslog_format = false;
685 7553 : Globals.debug_pid = false;
686 7553 : Globals.debug_uid = false;
687 7553 : Globals.debug_class = false;
688 7553 : Globals.enable_core_files = true;
689 7553 : Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
690 7553 : Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
691 7553 : Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
692 7553 : Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
693 7553 : Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
694 7553 : Globals.lm_interval = 60;
695 7553 : Globals.time_server = false;
696 7553 : Globals.bind_interfaces_only = false;
697 7553 : Globals.unix_password_sync = false;
698 7553 : Globals.pam_password_change = false;
699 7553 : Globals.passwd_chat_debug = false;
700 7553 : Globals.passwd_chat_timeout = 2; /* 2 second default. */
701 7553 : Globals.nt_pipe_support = true; /* Do NT pipes by default. */
702 7553 : Globals.nt_status_support = true; /* Use NT status by default. */
703 7553 : Globals.smbd_profiling_level = 0;
704 7553 : Globals.stat_cache = true; /* use stat cache by default */
705 7553 : Globals.max_stat_cache_size = 512; /* 512k by default */
706 7553 : Globals.restrict_anonymous = 0;
707 7553 : Globals.client_lanman_auth = false; /* Do NOT use the LanMan hash if it is available */
708 7553 : Globals.client_plaintext_auth = false; /* Do NOT use a plaintext password even if is requested by the server */
709 7553 : Globals._lanman_auth = false; /* Do NOT use the LanMan hash, even if it is supplied */
710 7553 : Globals.ntlm_auth = NTLM_AUTH_NTLMV2_ONLY; /* Do NOT use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
711 7553 : Globals.nt_hash_store = NT_HASH_STORE_ALWAYS; /* Fill in NT hash when setting password */
712 7553 : Globals.raw_ntlmv2_auth = false; /* Reject NTLMv2 without NTLMSSP */
713 7553 : Globals.client_ntlmv2_auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
714 : /* Note, that we will also use NTLM2 session security (which is different), if it is available */
715 :
716 7553 : Globals.allow_dcerpc_auth_level_connect = false; /* we don't allow this by default */
717 :
718 7553 : Globals.map_to_guest = 0; /* By Default, "Never" */
719 7553 : Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
720 7553 : Globals.enhanced_browsing = true;
721 7553 : Globals.lock_spin_time = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
722 7553 : Globals.use_mmap = true;
723 7553 : Globals.unicode = true;
724 7553 : Globals.smb1_unix_extensions = true;
725 7553 : Globals.reset_on_zero_vc = false;
726 7553 : Globals.log_writeable_files_on_exit = false;
727 7553 : Globals.create_krb5_conf = true;
728 7553 : Globals.include_system_krb5_conf = true;
729 7553 : Globals._winbind_max_domain_connections = 1;
730 :
731 : /* hostname lookups can be very expensive and are broken on
732 : a large number of sites (tridge) */
733 7553 : Globals.hostname_lookups = false;
734 :
735 7553 : Globals.change_notify = true,
736 7553 : Globals.kernel_change_notify = true,
737 :
738 7553 : lpcfg_string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
739 7553 : lpcfg_string_set(Globals.ctx, &Globals.ldap_suffix, "");
740 7553 : lpcfg_string_set(Globals.ctx, &Globals._ldap_machine_suffix, "");
741 7553 : lpcfg_string_set(Globals.ctx, &Globals._ldap_user_suffix, "");
742 7553 : lpcfg_string_set(Globals.ctx, &Globals._ldap_group_suffix, "");
743 7553 : lpcfg_string_set(Globals.ctx, &Globals._ldap_idmap_suffix, "");
744 :
745 7553 : lpcfg_string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
746 7553 : Globals.ldap_ssl = LDAP_SSL_START_TLS;
747 7553 : Globals.ldap_deref = -1;
748 7553 : Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
749 7553 : Globals.ldap_delete_dn = false;
750 7553 : Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
751 7553 : Globals.ldap_follow_referral = Auto;
752 7553 : Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
753 7553 : Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
754 7553 : Globals.ldap_page_size = LDAP_PAGE_SIZE;
755 :
756 7553 : Globals.ldap_debug_level = 0;
757 7553 : Globals.ldap_debug_threshold = 10;
758 :
759 7553 : Globals.client_ldap_sasl_wrapping = ADS_AUTH_SASL_SEAL;
760 :
761 7553 : Globals.ldap_server_require_strong_auth =
762 : LDAP_SERVER_REQUIRE_STRONG_AUTH_YES;
763 :
764 : /* This is what we tell the afs client. in reality we set the token
765 : * to never expire, though, when this runs out the afs client will
766 : * forget the token. Set to 0 to get NEVERDATE.*/
767 7553 : Globals.afs_token_lifetime = 604800;
768 7553 : Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
769 :
770 : /* these parameters are set to defaults that are more appropriate
771 : for the increasing samba install base:
772 :
773 : as a member of the workgroup, that will possibly become a
774 : _local_ master browser (lm = true). this is opposed to a forced
775 : local master browser startup (pm = true).
776 :
777 : doesn't provide WINS server service by default (wsupp = false),
778 : and doesn't provide domain master browser services by default, either.
779 :
780 : */
781 :
782 7553 : Globals.show_add_printer_wizard = true;
783 7553 : Globals.os_level = 20;
784 7553 : Globals.local_master = true;
785 7553 : Globals._domain_master = Auto; /* depending on _domain_logons */
786 7553 : Globals._domain_logons = false;
787 7553 : Globals.browse_list = true;
788 7553 : Globals.we_are_a_wins_server = false;
789 7553 : Globals.wins_proxy = false;
790 :
791 7553 : TALLOC_FREE(Globals.init_logon_delayed_hosts);
792 7553 : Globals.init_logon_delay = 100; /* 100 ms default delay */
793 :
794 7553 : Globals.wins_dns_proxy = true;
795 7553 : Globals.dns_port = DNS_SERVICE_PORT;
796 :
797 7553 : Globals.allow_trusted_domains = true;
798 7553 : lpcfg_string_set(Globals.ctx, &Globals.idmap_backend, "tdb");
799 :
800 7553 : lpcfg_string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
801 7553 : lpcfg_string_set(Globals.ctx, &Globals.template_homedir,
802 : "/home/%D/%U");
803 7553 : lpcfg_string_set(Globals.ctx, &Globals.winbind_separator, "\\");
804 7553 : lpcfg_string_set(Globals.ctx, &Globals.winbindd_socket_directory,
805 : dyn_WINBINDD_SOCKET_DIR);
806 :
807 7553 : lpcfg_string_set(Globals.ctx, &Globals.cups_server, "");
808 7553 : lpcfg_string_set(Globals.ctx, &Globals.iprint_server, "");
809 :
810 7553 : lpcfg_string_set(Globals.ctx, &Globals._ctdbd_socket, "");
811 :
812 7553 : Globals.cluster_addresses = NULL;
813 7553 : Globals.clustering = false;
814 7553 : Globals.ctdb_timeout = 0;
815 7553 : Globals.ctdb_locktime_warn_threshold = 0;
816 :
817 7553 : Globals.winbind_cache_time = 300; /* 5 minutes */
818 7553 : Globals.winbind_reconnect_delay = 30; /* 30 seconds */
819 7553 : Globals.winbind_request_timeout = 60; /* 60 seconds */
820 7553 : Globals.winbind_max_clients = 200;
821 7553 : Globals.winbind_enum_users = false;
822 7553 : Globals.winbind_enum_groups = false;
823 7553 : Globals.winbind_use_default_domain = false;
824 7553 : Globals.winbind_nested_groups = true;
825 7553 : Globals.winbind_expand_groups = 0;
826 7553 : Globals.winbind_nss_info = str_list_make_v3_const(NULL, "template", NULL);
827 7553 : Globals.winbind_refresh_tickets = false;
828 7553 : Globals.winbind_offline_logon = false;
829 7553 : Globals.winbind_scan_trusted_domains = false;
830 :
831 7553 : Globals.idmap_cache_time = 86400 * 7; /* a week by default */
832 7553 : Globals.idmap_negative_cache_time = 120; /* 2 minutes by default */
833 :
834 7553 : Globals.passdb_expand_explicit = false;
835 :
836 7553 : Globals.name_cache_timeout = 660; /* In seconds */
837 :
838 7553 : Globals.client_use_spnego = true;
839 :
840 7553 : Globals.client_signing = SMB_SIGNING_DEFAULT;
841 7553 : Globals._client_ipc_signing = SMB_SIGNING_DEFAULT;
842 7553 : Globals.server_signing = SMB_SIGNING_DEFAULT;
843 :
844 7553 : Globals.defer_sharing_violations = true;
845 7553 : Globals.smb_ports = str_list_make_v3_const(NULL, SMB_PORTS, NULL);
846 :
847 7553 : Globals.enable_privileges = true;
848 7553 : Globals.host_msdfs = true;
849 7553 : Globals.enable_asu_support = false;
850 :
851 : /* User defined shares. */
852 7553 : s = talloc_asprintf(talloc_tos(), "%s/usershares", get_dyn_STATEDIR());
853 7553 : if (s == NULL) {
854 0 : smb_panic("init_globals: ENOMEM");
855 : }
856 7553 : lpcfg_string_set(Globals.ctx, &Globals.usershare_path, s);
857 7553 : TALLOC_FREE(s);
858 7553 : lpcfg_string_set(Globals.ctx, &Globals.usershare_template_share, "");
859 7553 : Globals.usershare_max_shares = 0;
860 : /* By default disallow sharing of directories not owned by the sharer. */
861 7553 : Globals.usershare_owner_only = true;
862 : /* By default disallow guest access to usershares. */
863 7553 : Globals.usershare_allow_guests = false;
864 :
865 7553 : Globals.keepalive = DEFAULT_KEEPALIVE;
866 :
867 : /* By default no shares out of the registry */
868 7553 : Globals.registry_shares = false;
869 :
870 7553 : Globals.min_receivefile_size = 0;
871 :
872 7553 : Globals.multicast_dns_register = true;
873 :
874 7553 : Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
875 7553 : Globals.smb2_max_write = DEFAULT_SMB2_MAX_WRITE;
876 7553 : Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
877 7553 : Globals.smb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
878 7553 : Globals.smb2_leases = true;
879 7553 : Globals.server_multi_channel_support = true;
880 :
881 7553 : lpcfg_string_set(Globals.ctx, &Globals.ncalrpc_dir,
882 : get_dyn_NCALRPCDIR());
883 :
884 7553 : Globals.server_services = str_list_make_v3_const(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns", NULL);
885 :
886 7553 : Globals.dcerpc_endpoint_servers = str_list_make_v3_const(NULL, "epmapper wkssvc samr netlogon lsarpc drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver", NULL);
887 :
888 7553 : Globals.tls_enabled = true;
889 7553 : Globals.tls_verify_peer = TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE;
890 :
891 7553 : lpcfg_string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
892 7553 : lpcfg_string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
893 7553 : lpcfg_string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
894 7553 : lpcfg_string_set(Globals.ctx,
895 : &Globals.tls_priority,
896 : "NORMAL:-VERS-SSL3.0");
897 :
898 7553 : Globals._preferred_master = Auto;
899 :
900 7553 : Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
901 7553 : Globals.dns_zone_scavenging = false;
902 :
903 7553 : lpcfg_string_set(Globals.ctx, &Globals.ntp_signd_socket_directory,
904 : get_dyn_NTP_SIGND_SOCKET_DIR());
905 :
906 7553 : s = talloc_asprintf(talloc_tos(), "%s/samba_kcc", get_dyn_SCRIPTSBINDIR());
907 7553 : if (s == NULL) {
908 0 : smb_panic("init_globals: ENOMEM");
909 : }
910 7553 : Globals.samba_kcc_command = str_list_make_v3_const(NULL, s, NULL);
911 7553 : TALLOC_FREE(s);
912 :
913 : #ifdef MIT_KDC_PATH
914 2295 : Globals.mit_kdc_command = str_list_make_v3_const(NULL, MIT_KDC_PATH, NULL);
915 : #endif
916 :
917 7553 : s = talloc_asprintf(talloc_tos(), "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR());
918 7553 : if (s == NULL) {
919 0 : smb_panic("init_globals: ENOMEM");
920 : }
921 7553 : Globals.dns_update_command = str_list_make_v3_const(NULL, s, NULL);
922 7553 : TALLOC_FREE(s);
923 :
924 7553 : s = talloc_asprintf(talloc_tos(), "%s/samba-gpupdate", get_dyn_SCRIPTSBINDIR());
925 7553 : if (s == NULL) {
926 0 : smb_panic("init_globals: ENOMEM");
927 : }
928 7553 : Globals.gpo_update_command = str_list_make_v3_const(NULL, s, NULL);
929 7553 : TALLOC_FREE(s);
930 :
931 7553 : Globals.apply_group_policies = false;
932 :
933 7553 : s = talloc_asprintf(talloc_tos(), "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR());
934 7553 : if (s == NULL) {
935 0 : smb_panic("init_globals: ENOMEM");
936 : }
937 7553 : Globals.spn_update_command = str_list_make_v3_const(NULL, s, NULL);
938 7553 : TALLOC_FREE(s);
939 :
940 7553 : Globals.nsupdate_command = str_list_make_v3_const(NULL, "/usr/bin/nsupdate -g", NULL);
941 :
942 7553 : Globals.cldap_port = 389;
943 :
944 7553 : Globals.dgram_port = NBT_DGRAM_SERVICE_PORT;
945 :
946 7553 : Globals.nbt_port = NBT_NAME_SERVICE_PORT;
947 :
948 7553 : Globals.krb5_port = 88;
949 :
950 7553 : Globals.kpasswd_port = 464;
951 :
952 7553 : Globals.kdc_enable_fast = true;
953 :
954 7553 : Globals.aio_max_threads = 100;
955 :
956 7553 : lpcfg_string_set(Globals.ctx,
957 : &Globals.rpc_server_dynamic_port_range,
958 : "49152-65535");
959 7553 : Globals.rpc_low_port = SERVER_TCP_LOW_PORT;
960 7553 : Globals.rpc_high_port = SERVER_TCP_HIGH_PORT;
961 7553 : Globals.prefork_children = 4;
962 7553 : Globals.prefork_backoff_increment = 10;
963 7553 : Globals.prefork_maximum_backoff = 120;
964 :
965 7553 : Globals.ldap_max_anonymous_request_size = 256000;
966 7553 : Globals.ldap_max_authenticated_request_size = 16777216;
967 7553 : Globals.ldap_max_search_request_size = 256000;
968 :
969 : /* Async DNS query timeout (in seconds). */
970 7553 : Globals.async_dns_timeout = 10;
971 :
972 7553 : Globals.client_smb_encrypt = SMB_ENCRYPTION_DEFAULT;
973 :
974 7553 : Globals._client_use_kerberos = CRED_USE_KERBEROS_DESIRED;
975 :
976 7553 : Globals.client_protection = CRED_CLIENT_PROTECTION_DEFAULT;
977 :
978 7553 : Globals.winbind_use_krb5_enterprise_principals = true;
979 :
980 7553 : Globals.client_smb3_signing_algorithms =
981 7553 : str_list_make_v3_const(NULL, DEFAULT_SMB3_SIGNING_ALGORITHMS, NULL);
982 7553 : Globals.server_smb3_signing_algorithms =
983 7553 : str_list_make_v3_const(NULL, DEFAULT_SMB3_SIGNING_ALGORITHMS, NULL);
984 :
985 7553 : Globals.client_smb3_encryption_algorithms =
986 7553 : str_list_make_v3_const(NULL, DEFAULT_SMB3_ENCRYPTION_ALGORITHMS, NULL);
987 7553 : Globals.server_smb3_encryption_algorithms =
988 7553 : str_list_make_v3_const(NULL, DEFAULT_SMB3_ENCRYPTION_ALGORITHMS, NULL);
989 :
990 7553 : Globals.min_domain_uid = 1000;
991 :
992 : /*
993 : * By default allow smbd and winbindd to start samba-dcerpcd as
994 : * a named-pipe helper.
995 : */
996 7553 : Globals.rpc_start_on_demand_helpers = true;
997 :
998 : /* Now put back the settings that were set with lp_set_cmdline() */
999 7553 : apply_lp_set_cmdline();
1000 : }
1001 :
1002 : /* Convenience routine to setup an lp_context with additional s3 variables */
1003 88096 : static struct loadparm_context *setup_lp_context(TALLOC_CTX *mem_ctx)
1004 : {
1005 : struct loadparm_context *lp_ctx;
1006 :
1007 88096 : lp_ctx = loadparm_init_s3(mem_ctx,
1008 : loadparm_s3_helpers());
1009 88096 : if (lp_ctx == NULL) {
1010 0 : DEBUG(0, ("loadparm_init_s3 failed\n"));
1011 0 : return NULL;
1012 : }
1013 :
1014 88096 : lp_ctx->sDefault = talloc_zero(lp_ctx, struct loadparm_service);
1015 88096 : if (lp_ctx->sDefault == NULL) {
1016 0 : DBG_ERR("talloc_zero failed\n");
1017 0 : TALLOC_FREE(lp_ctx);
1018 0 : return NULL;
1019 : }
1020 :
1021 88096 : *lp_ctx->sDefault = _sDefault;
1022 88096 : lp_ctx->services = NULL; /* We do not want to access this directly */
1023 88096 : lp_ctx->bInGlobalSection = bInGlobalSection;
1024 88096 : lp_ctx->flags = flags_list;
1025 :
1026 88096 : return lp_ctx;
1027 : }
1028 :
1029 : /*******************************************************************
1030 : Convenience routine to grab string parameters into talloced memory
1031 : and run standard_sub_basic on them. The buffers can be written to by
1032 : callers without affecting the source string.
1033 : ********************************************************************/
1034 :
1035 247859 : static char *loadparm_s3_global_substitution_fn(
1036 : TALLOC_CTX *mem_ctx,
1037 : const struct loadparm_substitution *lp_sub,
1038 : const char *s,
1039 : void *private_data)
1040 : {
1041 : char *ret;
1042 :
1043 : /* The follow debug is useful for tracking down memory problems
1044 : especially if you have an inner loop that is calling a lp_*()
1045 : function that returns a string. Perhaps this debug should be
1046 : present all the time? */
1047 :
1048 : #if 0
1049 : DEBUG(10, ("lp_string(%s)\n", s));
1050 : #endif
1051 247859 : if (!s) {
1052 4 : return NULL;
1053 : }
1054 :
1055 247855 : ret = talloc_sub_basic(mem_ctx,
1056 : get_current_username(),
1057 : get_current_user_info_domain(),
1058 : s);
1059 247855 : if (trim_char(ret, '\"', '\"')) {
1060 0 : if (strchr(ret,'\"') != NULL) {
1061 0 : TALLOC_FREE(ret);
1062 0 : ret = talloc_sub_basic(mem_ctx,
1063 : get_current_username(),
1064 : get_current_user_info_domain(),
1065 : s);
1066 : }
1067 : }
1068 247855 : return ret;
1069 : }
1070 :
1071 : static const struct loadparm_substitution s3_global_substitution = {
1072 : .substituted_string_fn = loadparm_s3_global_substitution_fn,
1073 : };
1074 :
1075 354156 : const struct loadparm_substitution *loadparm_s3_global_substitution(void)
1076 : {
1077 354156 : return &s3_global_substitution;
1078 : }
1079 :
1080 : /*
1081 : In this section all the functions that are used to access the
1082 : parameters from the rest of the program are defined
1083 : */
1084 :
1085 : #define FN_GLOBAL_SUBSTITUTED_STRING(fn_name,ptr) \
1086 : char *lp_ ## fn_name(TALLOC_CTX *ctx, const struct loadparm_substitution *lp_sub) \
1087 : {return lpcfg_substituted_string(ctx, lp_sub, *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : "");}
1088 : #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1089 : const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1090 : #define FN_GLOBAL_LIST(fn_name,ptr) \
1091 : const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1092 : #define FN_GLOBAL_BOOL(fn_name,ptr) \
1093 : bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1094 : #define FN_GLOBAL_CHAR(fn_name,ptr) \
1095 : char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1096 : #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1097 : int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1098 :
1099 : #define FN_LOCAL_SUBSTITUTED_STRING(fn_name,val) \
1100 : char *lp_ ## fn_name(TALLOC_CTX *ctx, const struct loadparm_substitution *lp_sub, int i) \
1101 : {return lpcfg_substituted_string((ctx), lp_sub, (LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1102 : #define FN_LOCAL_CONST_STRING(fn_name,val) \
1103 : const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1104 : #define FN_LOCAL_LIST(fn_name,val) \
1105 : const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1106 : #define FN_LOCAL_BOOL(fn_name,val) \
1107 : bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1108 : #define FN_LOCAL_INTEGER(fn_name,val) \
1109 : int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1110 :
1111 : #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1112 : bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1113 : #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1114 : int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1115 : #define FN_LOCAL_PARM_CHAR(fn_name,val) \
1116 : char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1117 :
1118 3484 : int lp_winbind_max_domain_connections(void)
1119 : {
1120 3668 : if (lp_winbind_offline_logon() &&
1121 184 : lp__winbind_max_domain_connections() > 1) {
1122 0 : DEBUG(1, ("offline logons active, restricting max domain "
1123 : "connections to 1\n"));
1124 0 : return 1;
1125 : }
1126 3484 : return MAX(1, lp__winbind_max_domain_connections());
1127 : }
1128 :
1129 : /* These functions remain in source3/param for now */
1130 :
1131 : #include "lib/param/param_functions.c"
1132 :
1133 24495 : FN_LOCAL_SUBSTITUTED_STRING(servicename, szService)
1134 25033 : FN_LOCAL_CONST_STRING(const_servicename, szService)
1135 :
1136 : /* These functions cannot be auto-generated */
1137 30 : FN_LOCAL_BOOL(autoloaded, autoloaded)
1138 3380 : FN_GLOBAL_CONST_STRING(dnsdomain, dnsdomain)
1139 :
1140 : /* local prototypes */
1141 :
1142 : static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1143 : static const char *get_boolean(bool bool_value);
1144 : static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1145 : void *userdata);
1146 : static bool hash_a_service(const char *name, int number);
1147 : static void free_service_byindex(int iService);
1148 : static void show_parameter(int parmIndex);
1149 : static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1150 : static bool lp_parameter_value_is_valid(const char *parm_name, const char *val);
1151 :
1152 : /*
1153 : * This is a helper function for parametrical options support. It returns a
1154 : * pointer to parametrical option value if it exists or NULL otherwise. Actual
1155 : * parametrical functions are quite simple
1156 : */
1157 183227 : static struct parmlist_entry *get_parametrics(int snum, const char *type,
1158 : const char *option)
1159 : {
1160 183227 : if (snum >= iNumServices) return NULL;
1161 :
1162 183227 : if (snum < 0) {
1163 106902 : return get_parametric_helper(NULL, type, option, Globals.param_opt);
1164 : } else {
1165 76325 : return get_parametric_helper(ServicePtrs[snum],
1166 : type, option, Globals.param_opt);
1167 : }
1168 : }
1169 :
1170 551 : static void discard_whitespace(char *str)
1171 : {
1172 551 : size_t len = strlen(str);
1173 551 : size_t i = 0;
1174 :
1175 13183 : while (i < len) {
1176 12632 : if (isspace(str[i])) {
1177 738 : memmove(&str[i], &str[i+1], len-i);
1178 738 : len -= 1;
1179 738 : continue;
1180 : }
1181 11894 : i += 1;
1182 : }
1183 551 : }
1184 :
1185 : /**
1186 : * @brief Go through all global parametric parameters
1187 : *
1188 : * @param regex_str A regular expression to scan param for
1189 : * @param max_matches Max number of submatches the regexp expects
1190 : * @param cb Function to call on match. Should return true
1191 : * when it wants wi_scan_global_parametrics to stop
1192 : * scanning
1193 : * @param private_data Anonymous pointer passed to cb
1194 : *
1195 : * @return 0: success, regcomp/regexec return value on error.
1196 : * See "man regexec" for possible errors
1197 : */
1198 :
1199 34 : int lp_wi_scan_global_parametrics(
1200 : const char *regex_str, size_t max_matches,
1201 : bool (*cb)(const char *string, regmatch_t matches[],
1202 : void *private_data),
1203 : void *private_data)
1204 : {
1205 : struct parmlist_entry *data;
1206 : regex_t regex;
1207 : int ret;
1208 :
1209 34 : ret = regcomp(®ex, regex_str, REG_ICASE);
1210 34 : if (ret != 0) {
1211 0 : return ret;
1212 : }
1213 :
1214 585 : for (data = Globals.param_opt; data != NULL; data = data->next) {
1215 551 : size_t keylen = strlen(data->key);
1216 551 : char key[keylen+1];
1217 551 : regmatch_t matches[max_matches];
1218 : bool stop;
1219 :
1220 551 : memcpy(key, data->key, sizeof(key));
1221 551 : discard_whitespace(key);
1222 :
1223 551 : ret = regexec(®ex, key, max_matches, matches, 0);
1224 551 : if (ret == REG_NOMATCH) {
1225 507 : continue;
1226 : }
1227 44 : if (ret != 0) {
1228 0 : goto fail;
1229 : }
1230 :
1231 44 : stop = cb(key, matches, private_data);
1232 44 : if (stop) {
1233 0 : break;
1234 : }
1235 : }
1236 :
1237 34 : ret = 0;
1238 34 : fail:
1239 34 : regfree(®ex);
1240 34 : return ret;
1241 : }
1242 :
1243 :
1244 : #define MISSING_PARAMETER(name) \
1245 : DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1246 :
1247 : /*******************************************************************
1248 : convenience routine to return enum parameters.
1249 : ********************************************************************/
1250 0 : static int lp_enum(const char *s,const struct enum_list *_enum)
1251 : {
1252 : int i;
1253 :
1254 0 : if (!s || !*s || !_enum) {
1255 0 : MISSING_PARAMETER(lp_enum);
1256 0 : return (-1);
1257 : }
1258 :
1259 0 : for (i=0; _enum[i].name; i++) {
1260 0 : if (strequal(_enum[i].name,s))
1261 0 : return _enum[i].value;
1262 : }
1263 :
1264 0 : DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1265 0 : return (-1);
1266 : }
1267 :
1268 : #undef MISSING_PARAMETER
1269 :
1270 : /* Return parametric option from a given service. Type is a part of option before ':' */
1271 : /* Parametric option has following syntax: 'Type: option = value' */
1272 4286 : char *lp_parm_substituted_string(TALLOC_CTX *mem_ctx,
1273 : const struct loadparm_substitution *lp_sub,
1274 : int snum,
1275 : const char *type,
1276 : const char *option,
1277 : const char *def)
1278 : {
1279 4286 : struct parmlist_entry *data = get_parametrics(snum, type, option);
1280 :
1281 4286 : SMB_ASSERT(lp_sub != NULL);
1282 :
1283 4286 : if (data == NULL||data->value==NULL) {
1284 4286 : if (def) {
1285 4286 : return lpcfg_substituted_string(mem_ctx, lp_sub, def);
1286 : } else {
1287 0 : return NULL;
1288 : }
1289 : }
1290 :
1291 0 : return lpcfg_substituted_string(mem_ctx, lp_sub, data->value);
1292 : }
1293 :
1294 : /* Return parametric option from a given service. Type is a part of option before ':' */
1295 : /* Parametric option has following syntax: 'Type: option = value' */
1296 23789 : const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1297 : {
1298 23789 : struct parmlist_entry *data = get_parametrics(snum, type, option);
1299 :
1300 23789 : if (data == NULL||data->value==NULL)
1301 20134 : return def;
1302 :
1303 3655 : return data->value;
1304 : }
1305 :
1306 :
1307 : /* Return parametric option from a given service. Type is a part of option before ':' */
1308 : /* Parametric option has following syntax: 'Type: option = value' */
1309 :
1310 8475 : const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1311 : {
1312 8475 : struct parmlist_entry *data = get_parametrics(snum, type, option);
1313 :
1314 8475 : if (data == NULL||data->value==NULL)
1315 3315 : return (const char **)def;
1316 :
1317 5160 : if (data->list==NULL) {
1318 2266 : data->list = str_list_make_v3(NULL, data->value, NULL);
1319 : }
1320 :
1321 5160 : return discard_const_p(const char *, data->list);
1322 : }
1323 :
1324 : /* Return parametric option from a given service. Type is a part of option before ':' */
1325 : /* Parametric option has following syntax: 'Type: option = value' */
1326 :
1327 76604 : int lp_parm_int(int snum, const char *type, const char *option, int def)
1328 : {
1329 76604 : struct parmlist_entry *data = get_parametrics(snum, type, option);
1330 :
1331 76604 : if (data && data->value && *data->value)
1332 63 : return lp_int(data->value);
1333 :
1334 76541 : return def;
1335 : }
1336 :
1337 : /* Return parametric option from a given service. Type is a part of option before ':' */
1338 : /* Parametric option has following syntax: 'Type: option = value' */
1339 :
1340 4299 : unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1341 : {
1342 4299 : struct parmlist_entry *data = get_parametrics(snum, type, option);
1343 :
1344 4299 : if (data && data->value && *data->value)
1345 0 : return lp_ulong(data->value);
1346 :
1347 4299 : return def;
1348 : }
1349 :
1350 : /* Return parametric option from a given service. Type is a part of option before ':' */
1351 : /* Parametric option has following syntax: 'Type: option = value' */
1352 :
1353 0 : unsigned long long lp_parm_ulonglong(int snum, const char *type,
1354 : const char *option, unsigned long long def)
1355 : {
1356 0 : struct parmlist_entry *data = get_parametrics(snum, type, option);
1357 :
1358 0 : if (data && data->value && *data->value) {
1359 0 : return lp_ulonglong(data->value);
1360 : }
1361 :
1362 0 : return def;
1363 : }
1364 :
1365 : /* Return parametric option from a given service. Type is a part of option
1366 : * before ':' */
1367 : /* Parametric option has following syntax: 'Type: option = value' */
1368 :
1369 52660 : bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1370 : {
1371 52660 : struct parmlist_entry *data = get_parametrics(snum, type, option);
1372 :
1373 52660 : if (data && data->value && *data->value)
1374 15998 : return lp_bool(data->value);
1375 :
1376 36662 : return def;
1377 : }
1378 :
1379 : /* Return parametric option from a given service. Type is a part of option before ':' */
1380 : /* Parametric option has following syntax: 'Type: option = value' */
1381 :
1382 13114 : int lp_parm_enum(int snum, const char *type, const char *option,
1383 : const struct enum_list *_enum, int def)
1384 : {
1385 13114 : struct parmlist_entry *data = get_parametrics(snum, type, option);
1386 :
1387 13114 : if (data && data->value && *data->value && _enum)
1388 0 : return lp_enum(data->value, _enum);
1389 :
1390 13114 : return def;
1391 : }
1392 :
1393 : /**
1394 : * free a param_opts structure.
1395 : * param_opts handling should be moved to talloc;
1396 : * then this whole functions reduces to a TALLOC_FREE().
1397 : */
1398 :
1399 237021 : static void free_param_opts(struct parmlist_entry **popts)
1400 : {
1401 : struct parmlist_entry *opt, *next_opt;
1402 :
1403 237021 : if (*popts != NULL) {
1404 76570 : DEBUG(5, ("Freeing parametrics:\n"));
1405 : }
1406 237021 : opt = *popts;
1407 502713 : while (opt != NULL) {
1408 265692 : lpcfg_string_free(&opt->key);
1409 265692 : lpcfg_string_free(&opt->value);
1410 265692 : TALLOC_FREE(opt->list);
1411 265692 : next_opt = opt->next;
1412 265692 : TALLOC_FREE(opt);
1413 265692 : opt = next_opt;
1414 : }
1415 237021 : *popts = NULL;
1416 237021 : }
1417 :
1418 : /***************************************************************************
1419 : Free the dynamically allocated parts of a service struct.
1420 : ***************************************************************************/
1421 :
1422 29868 : static void free_service(struct loadparm_service *pservice)
1423 : {
1424 29868 : if (!pservice)
1425 0 : return;
1426 :
1427 29868 : if (pservice->szService)
1428 29868 : DEBUG(5, ("free_service: Freeing service %s\n",
1429 : pservice->szService));
1430 :
1431 29868 : free_parameters(pservice);
1432 :
1433 29868 : lpcfg_string_free(&pservice->szService);
1434 29868 : TALLOC_FREE(pservice->copymap);
1435 :
1436 29868 : free_param_opts(&pservice->param_opt);
1437 :
1438 29868 : ZERO_STRUCTP(pservice);
1439 : }
1440 :
1441 :
1442 : /***************************************************************************
1443 : remove a service indexed in the ServicePtrs array from the ServiceHash
1444 : and free the dynamically allocated parts
1445 : ***************************************************************************/
1446 :
1447 29868 : static void free_service_byindex(int idx)
1448 : {
1449 29868 : if ( !LP_SNUM_OK(idx) )
1450 0 : return;
1451 :
1452 29868 : ServicePtrs[idx]->valid = false;
1453 :
1454 : /* we have to cleanup the hash record */
1455 :
1456 29868 : if (ServicePtrs[idx]->szService) {
1457 29868 : char *canon_name = canonicalize_servicename(
1458 : talloc_tos(),
1459 29868 : ServicePtrs[idx]->szService );
1460 :
1461 29868 : dbwrap_delete_bystring(ServiceHash, canon_name );
1462 29868 : TALLOC_FREE(canon_name);
1463 : }
1464 :
1465 29868 : free_service(ServicePtrs[idx]);
1466 29868 : TALLOC_FREE(ServicePtrs[idx]);
1467 : }
1468 :
1469 : /***************************************************************************
1470 : Add a new service to the services array initialising it with the given
1471 : service.
1472 : ***************************************************************************/
1473 :
1474 203911 : static int add_a_service(const struct loadparm_service *pservice, const char *name)
1475 : {
1476 : int i;
1477 203911 : struct loadparm_service **tsp = NULL;
1478 :
1479 : /* it might already exist */
1480 203911 : if (name) {
1481 203911 : i = getservicebyname(name, NULL);
1482 203911 : if (i >= 0) {
1483 162933 : return (i);
1484 : }
1485 : }
1486 :
1487 : /* Re use empty slots if any before allocating new one.*/
1488 2217794 : for (i=0; i < iNumServices; i++) {
1489 2205032 : if (ServicePtrs[i] == NULL) {
1490 28216 : break;
1491 : }
1492 : }
1493 40978 : if (i == iNumServices) {
1494 : /* if not, then create one */
1495 12762 : tsp = talloc_realloc(NULL, ServicePtrs,
1496 : struct loadparm_service *,
1497 : iNumServices + 1);
1498 12762 : if (tsp == NULL) {
1499 0 : DEBUG(0, ("add_a_service: failed to enlarge "
1500 : "ServicePtrs!\n"));
1501 0 : return (-1);
1502 : }
1503 12762 : ServicePtrs = tsp;
1504 12762 : iNumServices++;
1505 : }
1506 40978 : ServicePtrs[i] = talloc_zero(ServicePtrs, struct loadparm_service);
1507 40978 : if (!ServicePtrs[i]) {
1508 0 : DEBUG(0,("add_a_service: out of memory!\n"));
1509 0 : return (-1);
1510 : }
1511 :
1512 40978 : ServicePtrs[i]->valid = true;
1513 :
1514 40978 : copy_service(ServicePtrs[i], pservice, NULL);
1515 40978 : if (name)
1516 40978 : lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->szService,
1517 : name);
1518 :
1519 40978 : DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1520 : i, ServicePtrs[i]->szService));
1521 :
1522 40978 : if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1523 0 : return (-1);
1524 : }
1525 :
1526 40978 : return (i);
1527 : }
1528 :
1529 : /***************************************************************************
1530 : Convert a string to uppercase and remove whitespaces.
1531 : ***************************************************************************/
1532 :
1533 345234 : char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1534 : {
1535 : char *result;
1536 :
1537 345234 : if ( !src ) {
1538 0 : DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1539 0 : return NULL;
1540 : }
1541 :
1542 345234 : result = talloc_strdup(ctx, src);
1543 345234 : SMB_ASSERT(result != NULL);
1544 :
1545 345234 : if (!strlower_m(result)) {
1546 0 : TALLOC_FREE(result);
1547 0 : return NULL;
1548 : }
1549 345234 : return result;
1550 : }
1551 :
1552 : /***************************************************************************
1553 : Add a name/index pair for the services array to the hash table.
1554 : ***************************************************************************/
1555 :
1556 40978 : static bool hash_a_service(const char *name, int idx)
1557 : {
1558 : char *canon_name;
1559 :
1560 40978 : if ( !ServiceHash ) {
1561 1608 : DEBUG(10,("hash_a_service: creating servicehash\n"));
1562 1608 : ServiceHash = db_open_rbt(NULL);
1563 1608 : if ( !ServiceHash ) {
1564 0 : DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1565 0 : return false;
1566 : }
1567 : }
1568 :
1569 40978 : DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1570 : idx, name));
1571 :
1572 40978 : canon_name = canonicalize_servicename(talloc_tos(), name );
1573 :
1574 40978 : dbwrap_store_bystring(ServiceHash, canon_name,
1575 : make_tdb_data((uint8_t *)&idx, sizeof(idx)),
1576 : TDB_REPLACE);
1577 :
1578 40978 : TALLOC_FREE(canon_name);
1579 :
1580 40978 : return true;
1581 : }
1582 :
1583 : /***************************************************************************
1584 : Add a new home service, with the specified home directory, defaults coming
1585 : from service ifrom.
1586 : ***************************************************************************/
1587 :
1588 3 : bool lp_add_home(const char *pszHomename, int iDefaultService,
1589 : const char *user, const char *pszHomedir)
1590 : {
1591 : const struct loadparm_substitution *lp_sub =
1592 3 : loadparm_s3_global_substitution();
1593 : int i;
1594 : char *global_path;
1595 :
1596 3 : if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1597 3 : pszHomedir[0] == '\0') {
1598 0 : return false;
1599 : }
1600 :
1601 3 : i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1602 :
1603 3 : if (i < 0)
1604 0 : return false;
1605 :
1606 3 : global_path = lp_path(talloc_tos(), lp_sub, GLOBAL_SECTION_SNUM);
1607 3 : if (!(*(ServicePtrs[iDefaultService]->path))
1608 0 : || strequal(ServicePtrs[iDefaultService]->path, global_path)) {
1609 3 : lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path,
1610 : pszHomedir);
1611 : }
1612 3 : TALLOC_FREE(global_path);
1613 :
1614 3 : if (!(*(ServicePtrs[i]->comment))) {
1615 0 : char *comment = talloc_asprintf(talloc_tos(), "Home directory of %s", user);
1616 0 : if (comment == NULL) {
1617 0 : return false;
1618 : }
1619 0 : lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment,
1620 : comment);
1621 0 : TALLOC_FREE(comment);
1622 : }
1623 :
1624 : /* set the browseable flag from the global default */
1625 :
1626 3 : ServicePtrs[i]->browseable = sDefault.browseable;
1627 3 : ServicePtrs[i]->access_based_share_enum = sDefault.access_based_share_enum;
1628 :
1629 3 : ServicePtrs[i]->autoloaded = true;
1630 :
1631 3 : DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1632 : user, ServicePtrs[i]->path ));
1633 :
1634 3 : return true;
1635 : }
1636 :
1637 : /***************************************************************************
1638 : Add a new service, based on an old one.
1639 : ***************************************************************************/
1640 :
1641 0 : int lp_add_service(const char *pszService, int iDefaultService)
1642 : {
1643 0 : if (iDefaultService < 0) {
1644 0 : return add_a_service(&sDefault, pszService);
1645 : }
1646 :
1647 0 : return (add_a_service(ServicePtrs[iDefaultService], pszService));
1648 : }
1649 :
1650 : /***************************************************************************
1651 : Add the IPC service.
1652 : ***************************************************************************/
1653 :
1654 1708 : static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1655 : {
1656 1708 : char *comment = NULL;
1657 1708 : int i = add_a_service(&sDefault, ipc_name);
1658 :
1659 1708 : if (i < 0)
1660 0 : return false;
1661 :
1662 1708 : comment = talloc_asprintf(talloc_tos(), "IPC Service (%s)",
1663 : Globals.server_string);
1664 1708 : if (comment == NULL) {
1665 0 : return false;
1666 : }
1667 :
1668 1708 : lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
1669 1708 : lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1670 1708 : lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
1671 1708 : ServicePtrs[i]->max_connections = 0;
1672 1708 : ServicePtrs[i]->available = true;
1673 1708 : ServicePtrs[i]->read_only = true;
1674 1708 : ServicePtrs[i]->guest_only = false;
1675 1708 : ServicePtrs[i]->administrative_share = true;
1676 1708 : ServicePtrs[i]->guest_ok = guest_ok;
1677 1708 : ServicePtrs[i]->printable = false;
1678 1708 : ServicePtrs[i]->browseable = sDefault.browseable;
1679 1708 : ServicePtrs[i]->autoloaded = false;
1680 :
1681 1708 : DEBUG(3, ("adding IPC service\n"));
1682 :
1683 1708 : TALLOC_FREE(comment);
1684 1708 : return true;
1685 : }
1686 :
1687 : /***************************************************************************
1688 : Add a new printer service, with defaults coming from service iFrom.
1689 : ***************************************************************************/
1690 :
1691 0 : bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1692 : {
1693 0 : const char *comment = "From Printcap";
1694 0 : int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1695 :
1696 0 : if (i < 0)
1697 0 : return false;
1698 :
1699 : /* note that we do NOT default the availability flag to true - */
1700 : /* we take it from the default service passed. This allows all */
1701 : /* dynamic printers to be disabled by disabling the [printers] */
1702 : /* entry (if/when the 'available' keyword is implemented!). */
1703 :
1704 : /* the printer name is set to the service name. */
1705 0 : lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->_printername,
1706 : pszPrintername);
1707 0 : lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1708 :
1709 : /* set the browseable flag from the gloabl default */
1710 0 : ServicePtrs[i]->browseable = sDefault.browseable;
1711 :
1712 : /* Printers cannot be read_only. */
1713 0 : ServicePtrs[i]->read_only = false;
1714 : /* No oplocks on printer services. */
1715 0 : ServicePtrs[i]->oplocks = false;
1716 : /* Printer services must be printable. */
1717 0 : ServicePtrs[i]->printable = true;
1718 :
1719 0 : DEBUG(3, ("adding printer service %s\n", pszPrintername));
1720 :
1721 0 : return true;
1722 : }
1723 :
1724 :
1725 : /***************************************************************************
1726 : Check whether the given parameter name is valid.
1727 : Parametric options (names containing a colon) are considered valid.
1728 : ***************************************************************************/
1729 :
1730 53 : bool lp_parameter_is_valid(const char *pszParmName)
1731 : {
1732 53 : return ((lpcfg_map_parameter(pszParmName) != -1) ||
1733 0 : (strchr(pszParmName, ':') != NULL));
1734 : }
1735 :
1736 : /***************************************************************************
1737 : Check whether the given name is the name of a global parameter.
1738 : Returns true for strings belonging to parameters of class
1739 : P_GLOBAL, false for all other strings, also for parametric options
1740 : and strings not belonging to any option.
1741 : ***************************************************************************/
1742 :
1743 14 : bool lp_parameter_is_global(const char *pszParmName)
1744 : {
1745 14 : int num = lpcfg_map_parameter(pszParmName);
1746 :
1747 14 : if (num >= 0) {
1748 14 : return (parm_table[num].p_class == P_GLOBAL);
1749 : }
1750 :
1751 0 : return false;
1752 : }
1753 :
1754 : /**************************************************************************
1755 : Determine the canonical name for a parameter.
1756 : Indicate when it is an inverse (boolean) synonym instead of a
1757 : "usual" synonym.
1758 : **************************************************************************/
1759 :
1760 0 : bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1761 : bool *inverse)
1762 : {
1763 : int num;
1764 :
1765 0 : if (!lp_parameter_is_valid(parm_name)) {
1766 0 : *canon_parm = NULL;
1767 0 : return false;
1768 : }
1769 :
1770 0 : num = map_parameter_canonical(parm_name, inverse);
1771 0 : if (num < 0) {
1772 : /* parametric option */
1773 0 : *canon_parm = parm_name;
1774 : } else {
1775 0 : *canon_parm = parm_table[num].label;
1776 : }
1777 :
1778 0 : return true;
1779 :
1780 : }
1781 :
1782 : /**************************************************************************
1783 : Determine the canonical name for a parameter.
1784 : Turn the value given into the inverse boolean expression when
1785 : the synonym is an invers boolean synonym.
1786 :
1787 : Return true if
1788 : - parm_name is a valid parameter name and
1789 : - val is a valid value for this parameter and
1790 : - in case the parameter is an inverse boolean synonym, if the val
1791 : string could successfully be converted to the reverse bool.
1792 : Return false in all other cases.
1793 : **************************************************************************/
1794 :
1795 14 : bool lp_canonicalize_parameter_with_value(const char *parm_name,
1796 : const char *val,
1797 : const char **canon_parm,
1798 : const char **canon_val)
1799 : {
1800 : int num;
1801 : bool inverse;
1802 : bool ret;
1803 :
1804 14 : if (!lp_parameter_is_valid(parm_name)) {
1805 0 : *canon_parm = NULL;
1806 0 : *canon_val = NULL;
1807 0 : return false;
1808 : }
1809 :
1810 14 : num = map_parameter_canonical(parm_name, &inverse);
1811 14 : if (num < 0) {
1812 : /* parametric option */
1813 0 : *canon_parm = parm_name;
1814 0 : *canon_val = val;
1815 0 : return true;
1816 : }
1817 :
1818 14 : *canon_parm = parm_table[num].label;
1819 14 : if (inverse) {
1820 1 : if (!lp_invert_boolean(val, canon_val)) {
1821 0 : *canon_val = NULL;
1822 0 : return false;
1823 : }
1824 : } else {
1825 13 : *canon_val = val;
1826 : }
1827 :
1828 14 : ret = lp_parameter_value_is_valid(*canon_parm, *canon_val);
1829 :
1830 14 : return ret;
1831 : }
1832 :
1833 : /***************************************************************************
1834 : Map a parameter's string representation to the index of the canonical
1835 : form of the parameter (it might be a synonym).
1836 : Returns -1 if the parameter string is not recognised.
1837 : ***************************************************************************/
1838 :
1839 14 : static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1840 : {
1841 : int parm_num, canon_num;
1842 14 : bool loc_inverse = false;
1843 :
1844 14 : parm_num = lpcfg_map_parameter(pszParmName);
1845 14 : if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_SYNONYM)) {
1846 : /* invalid, parametric or no canidate for synonyms ... */
1847 13 : goto done;
1848 : }
1849 :
1850 367 : for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1851 367 : if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1852 1 : parm_num = canon_num;
1853 1 : goto done;
1854 : }
1855 : }
1856 :
1857 0 : done:
1858 14 : if (inverse != NULL) {
1859 14 : *inverse = loc_inverse;
1860 : }
1861 14 : return parm_num;
1862 : }
1863 :
1864 : /***************************************************************************
1865 : return true if parameter number parm1 is a synonym of parameter
1866 : number parm2 (parm2 being the principal name).
1867 : set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1868 : false otherwise.
1869 : ***************************************************************************/
1870 :
1871 367 : static bool is_synonym_of(int parm1, int parm2, bool *inverse)
1872 : {
1873 367 : if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
1874 2 : (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
1875 1 : (parm_table[parm1].flags & FLAG_SYNONYM) &&
1876 1 : !(parm_table[parm2].flags & FLAG_SYNONYM))
1877 : {
1878 1 : if (inverse != NULL) {
1879 1 : if ((parm_table[parm1].type == P_BOOLREV) &&
1880 1 : (parm_table[parm2].type == P_BOOL))
1881 : {
1882 1 : *inverse = true;
1883 : } else {
1884 0 : *inverse = false;
1885 : }
1886 : }
1887 1 : return true;
1888 : }
1889 366 : return false;
1890 : }
1891 :
1892 : /***************************************************************************
1893 : Show one parameter's name, type, [values,] and flags.
1894 : (helper functions for show_parameter_list)
1895 : ***************************************************************************/
1896 :
1897 0 : static void show_parameter(int parmIndex)
1898 : {
1899 : size_t enumIndex, flagIndex;
1900 : size_t parmIndex2;
1901 : bool hadFlag;
1902 : bool hadSyn;
1903 : bool inverse;
1904 0 : const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
1905 : "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
1906 : "P_ENUM", "P_BYTES", "P_CMDLIST" };
1907 0 : unsigned flags[] = { FLAG_DEPRECATED, FLAG_SYNONYM };
1908 0 : const char *flag_names[] = { "FLAG_DEPRECATED", "FLAG_SYNONYM", NULL};
1909 :
1910 0 : printf("%s=%s", parm_table[parmIndex].label,
1911 0 : type[parm_table[parmIndex].type]);
1912 0 : if (parm_table[parmIndex].type == P_ENUM) {
1913 0 : printf(",");
1914 0 : for (enumIndex=0;
1915 0 : parm_table[parmIndex].enum_list[enumIndex].name;
1916 0 : enumIndex++)
1917 : {
1918 0 : printf("%s%s",
1919 : enumIndex ? "|" : "",
1920 0 : parm_table[parmIndex].enum_list[enumIndex].name);
1921 : }
1922 : }
1923 0 : printf(",");
1924 0 : hadFlag = false;
1925 0 : for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
1926 0 : if (parm_table[parmIndex].flags & flags[flagIndex]) {
1927 0 : printf("%s%s",
1928 : hadFlag ? "|" : "",
1929 : flag_names[flagIndex]);
1930 0 : hadFlag = true;
1931 : }
1932 : }
1933 :
1934 : /* output synonyms */
1935 0 : hadSyn = false;
1936 0 : for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
1937 0 : if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
1938 0 : printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
1939 : parm_table[parmIndex2].label);
1940 0 : } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
1941 0 : if (!hadSyn) {
1942 0 : printf(" (synonyms: ");
1943 0 : hadSyn = true;
1944 : } else {
1945 0 : printf(", ");
1946 : }
1947 0 : printf("%s%s", parm_table[parmIndex2].label,
1948 0 : inverse ? "[i]" : "");
1949 : }
1950 : }
1951 0 : if (hadSyn) {
1952 0 : printf(")");
1953 : }
1954 :
1955 0 : printf("\n");
1956 0 : }
1957 :
1958 : /*
1959 : * Check the value for a P_ENUM
1960 : */
1961 2 : static bool check_enum_parameter(struct parm_struct *parm, const char *value)
1962 : {
1963 : int i;
1964 :
1965 8 : for (i = 0; parm->enum_list[i].name; i++) {
1966 8 : if (strwicmp(value, parm->enum_list[i].name) == 0) {
1967 2 : return true;
1968 : }
1969 : }
1970 0 : return false;
1971 : }
1972 :
1973 : /**************************************************************************
1974 : Check whether the given value is valid for the given parameter name.
1975 : **************************************************************************/
1976 :
1977 14 : static bool lp_parameter_value_is_valid(const char *parm_name, const char *val)
1978 : {
1979 14 : bool ret = false, tmp_bool;
1980 14 : int num = lpcfg_map_parameter(parm_name), tmp_int;
1981 14 : uint64_t tmp_int64 = 0;
1982 : struct parm_struct *parm;
1983 :
1984 : /* parametric options (parameter names containing a colon) cannot
1985 : be checked and are therefore considered valid. */
1986 14 : if (strchr(parm_name, ':') != NULL) {
1987 0 : return true;
1988 : }
1989 :
1990 14 : if (num >= 0) {
1991 14 : parm = &parm_table[num];
1992 14 : switch (parm->type) {
1993 2 : case P_BOOL:
1994 : case P_BOOLREV:
1995 2 : ret = set_boolean(val, &tmp_bool);
1996 2 : break;
1997 :
1998 4 : case P_INTEGER:
1999 4 : ret = (sscanf(val, "%d", &tmp_int) == 1);
2000 4 : break;
2001 :
2002 0 : case P_OCTAL:
2003 0 : ret = (sscanf(val, "%o", &tmp_int) == 1);
2004 0 : break;
2005 :
2006 2 : case P_ENUM:
2007 2 : ret = check_enum_parameter(parm, val);
2008 2 : break;
2009 :
2010 0 : case P_BYTES:
2011 0 : if (conv_str_size_error(val, &tmp_int64) &&
2012 0 : tmp_int64 <= INT_MAX) {
2013 0 : ret = true;
2014 : }
2015 0 : break;
2016 :
2017 6 : case P_CHAR:
2018 : case P_LIST:
2019 : case P_STRING:
2020 : case P_USTRING:
2021 : case P_CMDLIST:
2022 6 : ret = true;
2023 6 : break;
2024 : }
2025 : }
2026 14 : return ret;
2027 : }
2028 :
2029 : /***************************************************************************
2030 : Show all parameter's name, type, [values,] and flags.
2031 : ***************************************************************************/
2032 :
2033 0 : void show_parameter_list(void)
2034 : {
2035 : int classIndex, parmIndex;
2036 0 : const char *section_names[] = { "local", "global", NULL};
2037 :
2038 0 : for (classIndex=0; section_names[classIndex]; classIndex++) {
2039 0 : printf("[%s]\n", section_names[classIndex]);
2040 0 : for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2041 0 : if (parm_table[parmIndex].p_class == classIndex) {
2042 0 : show_parameter(parmIndex);
2043 : }
2044 : }
2045 : }
2046 0 : }
2047 :
2048 : /***************************************************************************
2049 : Get the standard string representation of a boolean value ("yes" or "no")
2050 : ***************************************************************************/
2051 :
2052 1 : static const char *get_boolean(bool bool_value)
2053 : {
2054 : static const char *yes_str = "yes";
2055 : static const char *no_str = "no";
2056 :
2057 1 : return (bool_value ? yes_str : no_str);
2058 : }
2059 :
2060 : /***************************************************************************
2061 : Provide the string of the negated boolean value associated to the boolean
2062 : given as a string. Returns false if the passed string does not correctly
2063 : represent a boolean.
2064 : ***************************************************************************/
2065 :
2066 1 : bool lp_invert_boolean(const char *str, const char **inverse_str)
2067 : {
2068 : bool val;
2069 :
2070 1 : if (!set_boolean(str, &val)) {
2071 0 : return false;
2072 : }
2073 :
2074 1 : *inverse_str = get_boolean(!val);
2075 1 : return true;
2076 : }
2077 :
2078 : /***************************************************************************
2079 : Provide the canonical string representation of a boolean value given
2080 : as a string. Return true on success, false if the string given does
2081 : not correctly represent a boolean.
2082 : ***************************************************************************/
2083 :
2084 0 : bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2085 : {
2086 : bool val;
2087 :
2088 0 : if (!set_boolean(str, &val)) {
2089 0 : return false;
2090 : }
2091 :
2092 0 : *canon_str = get_boolean(val);
2093 0 : return true;
2094 : }
2095 :
2096 : /***************************************************************************
2097 : Find a service by name. Otherwise works like get_service.
2098 : ***************************************************************************/
2099 :
2100 262352 : int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2101 : {
2102 262352 : int iService = -1;
2103 : char *canon_name;
2104 : TDB_DATA data;
2105 : NTSTATUS status;
2106 :
2107 262352 : if (ServiceHash == NULL) {
2108 1609 : return -1;
2109 : }
2110 :
2111 260743 : canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2112 :
2113 260743 : status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2114 : &data);
2115 :
2116 260743 : if (NT_STATUS_IS_OK(status) &&
2117 221373 : (data.dptr != NULL) &&
2118 221373 : (data.dsize == sizeof(iService)))
2119 : {
2120 221373 : memcpy(&iService, data.dptr, sizeof(iService));
2121 : }
2122 :
2123 260743 : TALLOC_FREE(canon_name);
2124 :
2125 260743 : if ((iService != -1) && (LP_SNUM_OK(iService))
2126 221373 : && (pserviceDest != NULL)) {
2127 0 : copy_service(pserviceDest, ServicePtrs[iService], NULL);
2128 : }
2129 :
2130 260743 : return (iService);
2131 : }
2132 :
2133 : /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2134 58441 : struct loadparm_service *lp_service(const char *pszServiceName)
2135 : {
2136 58441 : int iService = getservicebyname(pszServiceName, NULL);
2137 58441 : if (iService == -1 || !LP_SNUM_OK(iService)) {
2138 1 : return NULL;
2139 : }
2140 58440 : return ServicePtrs[iService];
2141 : }
2142 :
2143 0 : struct loadparm_service *lp_servicebynum(int snum)
2144 : {
2145 0 : if ((snum == -1) || !LP_SNUM_OK(snum)) {
2146 0 : return NULL;
2147 : }
2148 0 : return ServicePtrs[snum];
2149 : }
2150 :
2151 0 : struct loadparm_service *lp_default_loadparm_service(void)
2152 : {
2153 0 : return &sDefault;
2154 : }
2155 :
2156 197270 : static struct smbconf_ctx *lp_smbconf_ctx(void)
2157 : {
2158 : sbcErr err;
2159 : static struct smbconf_ctx *conf_ctx = NULL;
2160 :
2161 197270 : if (conf_ctx == NULL) {
2162 86 : err = smbconf_init(NULL, &conf_ctx, "registry:");
2163 86 : if (!SBC_ERROR_IS_OK(err)) {
2164 0 : DEBUG(1, ("error initializing registry configuration: "
2165 : "%s\n", sbcErrorString(err)));
2166 0 : conf_ctx = NULL;
2167 : }
2168 : }
2169 :
2170 197270 : return conf_ctx;
2171 : }
2172 :
2173 2 : static bool process_smbconf_service(struct smbconf_service *service)
2174 : {
2175 : uint32_t count;
2176 : bool ret;
2177 :
2178 2 : if (service == NULL) {
2179 0 : return false;
2180 : }
2181 :
2182 2 : ret = lp_do_section(service->name, NULL);
2183 2 : if (ret != true) {
2184 0 : return false;
2185 : }
2186 13 : for (count = 0; count < service->num_params; count++) {
2187 :
2188 11 : if (!bInGlobalSection && bGlobalOnly) {
2189 0 : ret = true;
2190 : } else {
2191 11 : const char *pszParmName = service->param_names[count];
2192 11 : const char *pszParmValue = service->param_values[count];
2193 :
2194 11 : DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2195 :
2196 11 : ret = lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2197 : pszParmName, pszParmValue);
2198 : }
2199 :
2200 11 : if (ret != true) {
2201 0 : return false;
2202 : }
2203 : }
2204 2 : if (iServiceIndex >= 0) {
2205 2 : return lpcfg_service_ok(ServicePtrs[iServiceIndex]);
2206 : }
2207 0 : return true;
2208 : }
2209 :
2210 : /**
2211 : * load a service from registry and activate it
2212 : */
2213 197209 : bool process_registry_service(const char *service_name)
2214 : {
2215 : sbcErr err;
2216 197209 : struct smbconf_service *service = NULL;
2217 197209 : TALLOC_CTX *mem_ctx = talloc_stackframe();
2218 197209 : struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2219 197209 : bool ret = false;
2220 :
2221 197209 : if (conf_ctx == NULL) {
2222 0 : goto done;
2223 : }
2224 :
2225 197209 : DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2226 :
2227 197209 : if (!smbconf_share_exists(conf_ctx, service_name)) {
2228 : /*
2229 : * Registry does not contain data for this service (yet),
2230 : * but make sure lp_load doesn't return false.
2231 : */
2232 197207 : ret = true;
2233 197207 : goto done;
2234 : }
2235 :
2236 2 : err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2237 2 : if (!SBC_ERROR_IS_OK(err)) {
2238 0 : goto done;
2239 : }
2240 :
2241 2 : ret = process_smbconf_service(service);
2242 2 : if (!ret) {
2243 0 : goto done;
2244 : }
2245 :
2246 : /* store the csn */
2247 2 : smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2248 :
2249 197209 : done:
2250 197209 : TALLOC_FREE(mem_ctx);
2251 197209 : return ret;
2252 : }
2253 :
2254 : /*
2255 : * process_registry_globals
2256 : */
2257 0 : static bool process_registry_globals(void)
2258 : {
2259 : bool ret;
2260 :
2261 0 : add_to_file_list(NULL, &file_lists, INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2262 :
2263 0 : if (!bInGlobalSection && bGlobalOnly) {
2264 0 : ret = true;
2265 : } else {
2266 0 : const char *pszParmName = "registry shares";
2267 0 : const char *pszParmValue = "yes";
2268 :
2269 0 : DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2270 :
2271 0 : ret = lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2272 : pszParmName, pszParmValue);
2273 : }
2274 :
2275 0 : if (!ret) {
2276 0 : return ret;
2277 : }
2278 :
2279 0 : return process_registry_service(GLOBAL_NAME);
2280 : }
2281 :
2282 61 : bool process_registry_shares(void)
2283 : {
2284 : sbcErr err;
2285 : uint32_t count;
2286 61 : struct smbconf_service **service = NULL;
2287 61 : uint32_t num_shares = 0;
2288 61 : TALLOC_CTX *mem_ctx = talloc_stackframe();
2289 61 : struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2290 61 : bool ret = false;
2291 :
2292 61 : if (conf_ctx == NULL) {
2293 0 : goto done;
2294 : }
2295 :
2296 61 : err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2297 61 : if (!SBC_ERROR_IS_OK(err)) {
2298 0 : goto done;
2299 : }
2300 :
2301 61 : ret = true;
2302 :
2303 61 : for (count = 0; count < num_shares; count++) {
2304 0 : if (strequal(service[count]->name, GLOBAL_NAME)) {
2305 0 : continue;
2306 : }
2307 0 : ret = process_smbconf_service(service[count]);
2308 0 : if (!ret) {
2309 0 : goto done;
2310 : }
2311 : }
2312 :
2313 : /* store the csn */
2314 61 : smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2315 :
2316 61 : done:
2317 61 : TALLOC_FREE(mem_ctx);
2318 61 : return ret;
2319 : }
2320 :
2321 : /**
2322 : * reload those shares from registry that are already
2323 : * activated in the services array.
2324 : */
2325 3589 : static bool reload_registry_shares(void)
2326 : {
2327 : int i;
2328 3589 : bool ret = true;
2329 :
2330 199967 : for (i = 0; i < iNumServices; i++) {
2331 196378 : if (!VALID(i)) {
2332 249 : continue;
2333 : }
2334 :
2335 196129 : if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2336 0 : continue;
2337 : }
2338 :
2339 196129 : ret = process_registry_service(ServicePtrs[i]->szService);
2340 196129 : if (!ret) {
2341 0 : goto done;
2342 : }
2343 : }
2344 :
2345 3589 : done:
2346 3589 : return ret;
2347 : }
2348 :
2349 :
2350 : #define MAX_INCLUDE_DEPTH 100
2351 :
2352 : static uint8_t include_depth;
2353 :
2354 : /**
2355 : * Free the file lists
2356 : */
2357 10333 : static void free_file_list(void)
2358 : {
2359 : struct file_lists *f;
2360 : struct file_lists *next;
2361 :
2362 10333 : f = file_lists;
2363 23700 : while( f ) {
2364 13367 : next = f->next;
2365 13367 : TALLOC_FREE( f );
2366 13367 : f = next;
2367 : }
2368 10333 : file_lists = NULL;
2369 10333 : }
2370 :
2371 :
2372 : /**
2373 : * Utility function for outsiders to check if we're running on registry.
2374 : */
2375 8252 : bool lp_config_backend_is_registry(void)
2376 : {
2377 8252 : return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2378 : }
2379 :
2380 : /**
2381 : * Utility function to check if the config backend is FILE.
2382 : */
2383 8224 : bool lp_config_backend_is_file(void)
2384 : {
2385 8224 : return (lp_config_backend() == CONFIG_BACKEND_FILE);
2386 : }
2387 :
2388 : /*******************************************************************
2389 : Check if a config file has changed date.
2390 : ********************************************************************/
2391 :
2392 25855 : bool lp_file_list_changed(void)
2393 : {
2394 25855 : struct file_lists *f = file_lists;
2395 :
2396 25855 : DEBUG(6, ("lp_file_list_changed()\n"));
2397 :
2398 86261 : while (f) {
2399 60586 : if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2400 0 : struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2401 :
2402 0 : if (conf_ctx == NULL) {
2403 0 : return false;
2404 : }
2405 0 : if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2406 : NULL))
2407 : {
2408 0 : DEBUGADD(6, ("registry config changed\n"));
2409 0 : return true;
2410 : }
2411 : } else {
2412 60586 : struct timespec mod_time = {
2413 : .tv_sec = 0,
2414 : };
2415 60586 : struct timeval_buf tbuf = {
2416 : .buf = {0},
2417 : };
2418 60586 : char *n2 = NULL;
2419 60586 : struct stat sb = {0};
2420 : int rc;
2421 :
2422 60586 : n2 = talloc_sub_basic(talloc_tos(),
2423 : get_current_username(),
2424 : get_current_user_info_domain(),
2425 60586 : f->name);
2426 60586 : if (!n2) {
2427 180 : return false;
2428 : }
2429 60586 : DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2430 : f->name, n2,
2431 : timespec_string_buf(&f->modtime,
2432 : true,
2433 : &tbuf)));
2434 :
2435 60586 : rc = stat(n2, &sb);
2436 60586 : if (rc == 0) {
2437 53606 : mod_time = get_mtimespec(&sb);
2438 : }
2439 :
2440 114192 : if (mod_time.tv_sec > 0 &&
2441 53606 : ((timespec_compare(&mod_time, &f->modtime) != 0) ||
2442 53426 : (f->subfname == NULL) ||
2443 53426 : (strcmp(n2, f->subfname) != 0)))
2444 : {
2445 180 : f->modtime = mod_time;
2446 :
2447 180 : DEBUGADD(6,
2448 : ("file %s modified: %s\n", n2,
2449 : timespec_string_buf(&f->modtime,
2450 : true,
2451 : &tbuf)));
2452 :
2453 180 : TALLOC_FREE(f->subfname);
2454 180 : f->subfname = talloc_strdup(f, n2);
2455 180 : if (f->subfname == NULL) {
2456 0 : smb_panic("talloc_strdup failed");
2457 : }
2458 180 : TALLOC_FREE(n2);
2459 180 : return true;
2460 : }
2461 60406 : TALLOC_FREE(n2);
2462 : }
2463 60406 : f = f->next;
2464 : }
2465 25675 : return false;
2466 : }
2467 :
2468 :
2469 : /**
2470 : * Initialize iconv conversion descriptors.
2471 : *
2472 : * This is called the first time it is needed, and also called again
2473 : * every time the configuration is reloaded, because the charset or
2474 : * codepage might have changed.
2475 : **/
2476 8224 : static void init_iconv(void)
2477 : {
2478 8224 : struct smb_iconv_handle *ret = NULL;
2479 :
2480 8224 : ret = reinit_iconv_handle(NULL,
2481 : lp_dos_charset(),
2482 : lp_unix_charset());
2483 8224 : if (ret == NULL) {
2484 0 : smb_panic("reinit_iconv_handle failed");
2485 : }
2486 8224 : }
2487 :
2488 : /***************************************************************************
2489 : Handle the include operation.
2490 : ***************************************************************************/
2491 : static bool bAllowIncludeRegistry = true;
2492 :
2493 14032 : bool lp_include(struct loadparm_context *lp_ctx, struct loadparm_service *service,
2494 : const char *pszParmValue, char **ptr)
2495 : {
2496 : char *fname;
2497 :
2498 14032 : if (include_depth >= MAX_INCLUDE_DEPTH) {
2499 0 : DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2500 : include_depth));
2501 0 : return false;
2502 : }
2503 :
2504 14032 : if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2505 0 : if (!bAllowIncludeRegistry) {
2506 0 : return true;
2507 : }
2508 0 : if (lp_ctx->bInGlobalSection) {
2509 : bool ret;
2510 0 : include_depth++;
2511 0 : ret = process_registry_globals();
2512 0 : include_depth--;
2513 0 : return ret;
2514 : } else {
2515 0 : DEBUG(1, ("\"include = registry\" only effective "
2516 : "in %s section\n", GLOBAL_NAME));
2517 0 : return false;
2518 : }
2519 : }
2520 :
2521 14032 : fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2522 : get_current_user_info_domain(),
2523 : pszParmValue);
2524 :
2525 14032 : add_to_file_list(NULL, &file_lists, pszParmValue, fname);
2526 :
2527 14032 : if (service == NULL) {
2528 3595 : lpcfg_string_set(Globals.ctx, ptr, fname);
2529 : } else {
2530 10437 : lpcfg_string_set(service, ptr, fname);
2531 : }
2532 :
2533 14032 : if (file_exist(fname)) {
2534 : bool ret;
2535 12292 : include_depth++;
2536 12292 : ret = pm_process(fname, lp_do_section, do_parameter, lp_ctx);
2537 12292 : include_depth--;
2538 12292 : TALLOC_FREE(fname);
2539 12292 : return ret;
2540 : }
2541 :
2542 1740 : DEBUG(2, ("Can't find include file %s\n", fname));
2543 1740 : TALLOC_FREE(fname);
2544 1740 : return true;
2545 : }
2546 :
2547 730 : bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2548 : {
2549 730 : char *config_option = NULL;
2550 730 : const char *range = NULL;
2551 730 : bool ret = false;
2552 :
2553 730 : SMB_ASSERT(low != NULL);
2554 730 : SMB_ASSERT(high != NULL);
2555 :
2556 730 : if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2557 0 : domain_name = "*";
2558 : }
2559 :
2560 730 : config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2561 : domain_name);
2562 730 : if (config_option == NULL) {
2563 0 : DEBUG(0, ("out of memory\n"));
2564 0 : return false;
2565 : }
2566 :
2567 730 : range = lp_parm_const_string(-1, config_option, "range", NULL);
2568 730 : if (range == NULL) {
2569 626 : DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2570 626 : goto done;
2571 : }
2572 :
2573 104 : if (sscanf(range, "%u - %u", low, high) != 2) {
2574 0 : DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2575 : range, domain_name));
2576 0 : goto done;
2577 : }
2578 :
2579 104 : ret = true;
2580 :
2581 730 : done:
2582 730 : talloc_free(config_option);
2583 730 : return ret;
2584 :
2585 : }
2586 :
2587 726 : bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2588 : {
2589 726 : return lp_idmap_range("*", low, high);
2590 : }
2591 :
2592 42 : const char *lp_idmap_backend(const char *domain_name)
2593 : {
2594 42 : char *config_option = NULL;
2595 42 : const char *backend = NULL;
2596 :
2597 42 : if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2598 0 : domain_name = "*";
2599 : }
2600 :
2601 42 : config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2602 : domain_name);
2603 42 : if (config_option == NULL) {
2604 0 : DEBUG(0, ("out of memory\n"));
2605 0 : return false;
2606 : }
2607 :
2608 42 : backend = lp_parm_const_string(-1, config_option, "backend", NULL);
2609 42 : if (backend == NULL) {
2610 0 : DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
2611 0 : goto done;
2612 : }
2613 :
2614 42 : done:
2615 42 : talloc_free(config_option);
2616 42 : return backend;
2617 : }
2618 :
2619 38 : const char *lp_idmap_default_backend(void)
2620 : {
2621 38 : return lp_idmap_backend("*");
2622 : }
2623 :
2624 : /***************************************************************************
2625 : Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2626 : ***************************************************************************/
2627 :
2628 0 : static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2629 : {
2630 : const char *suffix_string;
2631 :
2632 0 : suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2633 : Globals.ldap_suffix );
2634 0 : if ( !suffix_string ) {
2635 0 : DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2636 0 : return "";
2637 : }
2638 :
2639 0 : return suffix_string;
2640 : }
2641 :
2642 0 : const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2643 : {
2644 0 : if (Globals._ldap_machine_suffix[0])
2645 0 : return append_ldap_suffix(ctx, Globals._ldap_machine_suffix);
2646 :
2647 0 : return talloc_strdup(ctx, Globals.ldap_suffix);
2648 : }
2649 :
2650 0 : const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
2651 : {
2652 0 : if (Globals._ldap_user_suffix[0])
2653 0 : return append_ldap_suffix(ctx, Globals._ldap_user_suffix);
2654 :
2655 0 : return talloc_strdup(ctx, Globals.ldap_suffix);
2656 : }
2657 :
2658 0 : const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
2659 : {
2660 0 : if (Globals._ldap_group_suffix[0])
2661 0 : return append_ldap_suffix(ctx, Globals._ldap_group_suffix);
2662 :
2663 0 : return talloc_strdup(ctx, Globals.ldap_suffix);
2664 : }
2665 :
2666 0 : const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
2667 : {
2668 0 : if (Globals._ldap_idmap_suffix[0])
2669 0 : return append_ldap_suffix(ctx, Globals._ldap_idmap_suffix);
2670 :
2671 0 : return talloc_strdup(ctx, Globals.ldap_suffix);
2672 : }
2673 :
2674 : /**
2675 : return the parameter pointer for a parameter
2676 : */
2677 9227028 : void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
2678 : {
2679 9227028 : if (service == NULL) {
2680 4537362 : if (parm->p_class == P_LOCAL)
2681 1278945 : return (void *)(((char *)&sDefault)+parm->offset);
2682 3258417 : else if (parm->p_class == P_GLOBAL)
2683 3258417 : return (void *)(((char *)&Globals)+parm->offset);
2684 0 : else return NULL;
2685 : } else {
2686 4689666 : return (void *)(((char *)service) + parm->offset);
2687 : }
2688 : }
2689 :
2690 : /***************************************************************************
2691 : Process a parameter for a particular service number. If snum < 0
2692 : then assume we are in the globals.
2693 : ***************************************************************************/
2694 :
2695 73738 : bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
2696 : {
2697 73738 : TALLOC_CTX *frame = talloc_stackframe();
2698 : struct loadparm_context *lp_ctx;
2699 : bool ok;
2700 :
2701 73738 : lp_ctx = setup_lp_context(frame);
2702 73738 : if (lp_ctx == NULL) {
2703 0 : TALLOC_FREE(frame);
2704 0 : return false;
2705 : }
2706 :
2707 73738 : if (snum < 0) {
2708 43401 : ok = lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue);
2709 : } else {
2710 30337 : ok = lpcfg_do_service_parameter(lp_ctx, ServicePtrs[snum],
2711 : pszParmName, pszParmValue);
2712 : }
2713 :
2714 73738 : TALLOC_FREE(frame);
2715 :
2716 73738 : return ok;
2717 : }
2718 :
2719 : /***************************************************************************
2720 : set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
2721 : FLAG_CMDLINE won't be overridden by loads from smb.conf.
2722 : ***************************************************************************/
2723 :
2724 8851 : static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue)
2725 : {
2726 : int parmnum, i;
2727 8851 : parmnum = lpcfg_map_parameter(pszParmName);
2728 8851 : if (parmnum >= 0) {
2729 8738 : flags_list[parmnum] &= ~FLAG_CMDLINE;
2730 8738 : if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
2731 0 : return false;
2732 : }
2733 8738 : flags_list[parmnum] |= FLAG_CMDLINE;
2734 :
2735 : /* we have to also set FLAG_CMDLINE on aliases. Aliases must
2736 : * be grouped in the table, so we don't have to search the
2737 : * whole table */
2738 8738 : for (i=parmnum-1;
2739 8735 : i>=0 && parm_table[i].offset == parm_table[parmnum].offset
2740 8738 : && parm_table[i].p_class == parm_table[parmnum].p_class;
2741 0 : i--) {
2742 0 : flags_list[i] |= FLAG_CMDLINE;
2743 : }
2744 27052 : for (i=parmnum+1;i<num_parameters() && parm_table[i].offset == parm_table[parmnum].offset
2745 18314 : && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
2746 4788 : flags_list[i] |= FLAG_CMDLINE;
2747 : }
2748 :
2749 8738 : return true;
2750 : }
2751 :
2752 : /* it might be parametric */
2753 113 : if (strchr(pszParmName, ':') != NULL) {
2754 113 : set_param_opt(NULL, &Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
2755 113 : return true;
2756 : }
2757 :
2758 0 : DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2759 0 : return false;
2760 : }
2761 :
2762 4252 : bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
2763 : {
2764 : bool ret;
2765 4252 : TALLOC_CTX *frame = talloc_stackframe();
2766 : struct loadparm_context *lp_ctx;
2767 :
2768 4252 : lp_ctx = setup_lp_context(frame);
2769 4252 : if (lp_ctx == NULL) {
2770 0 : TALLOC_FREE(frame);
2771 0 : return false;
2772 : }
2773 :
2774 4252 : ret = lpcfg_set_cmdline(lp_ctx, pszParmName, pszParmValue);
2775 :
2776 4252 : TALLOC_FREE(frame);
2777 4252 : return ret;
2778 : }
2779 :
2780 : /***************************************************************************
2781 : Process a parameter.
2782 : ***************************************************************************/
2783 :
2784 2085192 : static bool do_parameter(const char *pszParmName, const char *pszParmValue,
2785 : void *userdata)
2786 : {
2787 2085192 : if (!bInGlobalSection && bGlobalOnly)
2788 834153 : return true;
2789 :
2790 1251039 : DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2791 :
2792 1251039 : if (bInGlobalSection) {
2793 474292 : return lpcfg_do_global_parameter(userdata, pszParmName, pszParmValue);
2794 : } else {
2795 776747 : return lpcfg_do_service_parameter(userdata, ServicePtrs[iServiceIndex],
2796 : pszParmName, pszParmValue);
2797 : }
2798 : }
2799 :
2800 :
2801 : static const char *ad_dc_req_vfs_mods[] = {"dfs_samba4", "acl_xattr", NULL};
2802 :
2803 : /*
2804 : * check that @vfs_objects includes all vfs modules required by an AD DC.
2805 : */
2806 1533 : static bool check_ad_dc_required_mods(const char **vfs_objects)
2807 : {
2808 : int i;
2809 : int j;
2810 : int got_req;
2811 :
2812 4599 : for (i = 0; ad_dc_req_vfs_mods[i] != NULL; i++) {
2813 3066 : got_req = false;
2814 4599 : for (j = 0; vfs_objects[j] != NULL; j++) {
2815 4599 : if (!strwicmp(ad_dc_req_vfs_mods[i], vfs_objects[j])) {
2816 3066 : got_req = true;
2817 3066 : break;
2818 : }
2819 : }
2820 3066 : if (!got_req) {
2821 0 : DEBUG(0, ("vfs objects specified without required AD "
2822 : "DC module: %s\n", ad_dc_req_vfs_mods[i]));
2823 0 : return false;
2824 : }
2825 : }
2826 :
2827 1533 : DEBUG(6, ("vfs objects specified with all required AD DC modules\n"));
2828 1533 : return true;
2829 : }
2830 :
2831 :
2832 : /***************************************************************************
2833 : Initialize any local variables in the sDefault table, after parsing a
2834 : [globals] section.
2835 : ***************************************************************************/
2836 :
2837 8446 : static void init_locals(void)
2838 : {
2839 : /*
2840 : * We run this check once the [globals] is parsed, to force
2841 : * the VFS objects and other per-share settings we need for
2842 : * the standard way a AD DC is operated. We may change these
2843 : * as our code evolves, which is why we force these settings.
2844 : *
2845 : * We can't do this at the end of lp_load_ex(), as by that
2846 : * point the services have been loaded and they will already
2847 : * have "" as their vfs objects.
2848 : */
2849 8446 : if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
2850 1533 : const char **vfs_objects = lp_vfs_objects(-1);
2851 1533 : if (vfs_objects != NULL) {
2852 : /* ignore return, only warn if modules are missing */
2853 1533 : check_ad_dc_required_mods(vfs_objects);
2854 : } else {
2855 0 : if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
2856 0 : lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
2857 0 : } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
2858 0 : lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
2859 : } else {
2860 0 : lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
2861 : }
2862 : }
2863 :
2864 1533 : lp_do_parameter(-1, "map hidden", "no");
2865 1533 : lp_do_parameter(-1, "map system", "no");
2866 1533 : lp_do_parameter(-1, "map readonly", "no");
2867 1533 : lp_do_parameter(-1, "map archive", "no");
2868 1533 : lp_do_parameter(-1, "store dos attributes", "yes");
2869 : }
2870 8446 : }
2871 :
2872 : /***************************************************************************
2873 : Process a new section (service). At this stage all sections are services.
2874 : Later we'll have special sections that permit server parameters to be set.
2875 : Returns true on success, false on failure.
2876 : ***************************************************************************/
2877 :
2878 421794 : bool lp_do_section(const char *pszSectionName, void *userdata)
2879 : {
2880 421794 : struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
2881 : bool bRetval;
2882 837240 : bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2883 415446 : (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2884 :
2885 : /* if we were in a global section then do the local inits */
2886 421794 : if (bInGlobalSection && !isglobal)
2887 6564 : init_locals();
2888 :
2889 : /* if we've just struck a global section, note the fact. */
2890 421794 : bInGlobalSection = isglobal;
2891 421794 : if (lp_ctx != NULL) {
2892 421792 : lp_ctx->bInGlobalSection = isglobal;
2893 : }
2894 :
2895 : /* check for multiple global sections */
2896 421794 : if (bInGlobalSection) {
2897 6348 : DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2898 6348 : return true;
2899 : }
2900 :
2901 415446 : if (!bInGlobalSection && bGlobalOnly)
2902 213246 : return true;
2903 :
2904 : /* if we have a current service, tidy it up before moving on */
2905 202200 : bRetval = true;
2906 :
2907 202200 : if ((iServiceIndex >= 0) && (ServicePtrs[iServiceIndex] != NULL))
2908 198330 : bRetval = lpcfg_service_ok(ServicePtrs[iServiceIndex]);
2909 :
2910 : /* if all is still well, move to the next record in the services array */
2911 202200 : if (bRetval) {
2912 : /* We put this here to avoid an odd message order if messages are */
2913 : /* issued by the post-processing of a previous section. */
2914 202200 : DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2915 :
2916 202200 : iServiceIndex = add_a_service(&sDefault, pszSectionName);
2917 202200 : if (iServiceIndex < 0) {
2918 0 : DEBUG(0, ("Failed to add a new service\n"));
2919 0 : return false;
2920 : }
2921 : /* Clean all parametric options for service */
2922 : /* They will be added during parsing again */
2923 202200 : free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
2924 : }
2925 :
2926 202200 : return bRetval;
2927 : }
2928 :
2929 : /***************************************************************************
2930 : Display the contents of a parameter of a single services record.
2931 : ***************************************************************************/
2932 :
2933 1416 : bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
2934 : {
2935 1416 : bool result = false;
2936 : struct loadparm_context *lp_ctx;
2937 :
2938 1416 : lp_ctx = setup_lp_context(talloc_tos());
2939 1416 : if (lp_ctx == NULL) {
2940 0 : return false;
2941 : }
2942 :
2943 1416 : if (isGlobal) {
2944 1016 : result = lpcfg_dump_a_parameter(lp_ctx, NULL, parm_name, f);
2945 : } else {
2946 400 : result = lpcfg_dump_a_parameter(lp_ctx, ServicePtrs[snum], parm_name, f);
2947 : }
2948 1416 : TALLOC_FREE(lp_ctx);
2949 1416 : return result;
2950 : }
2951 :
2952 : #if 0
2953 : /***************************************************************************
2954 : Display the contents of a single copy structure.
2955 : ***************************************************************************/
2956 : static void dump_copy_map(bool *pcopymap)
2957 : {
2958 : int i;
2959 : if (!pcopymap)
2960 : return;
2961 :
2962 : printf("\n\tNon-Copied parameters:\n");
2963 :
2964 : for (i = 0; parm_table[i].label; i++)
2965 : if (parm_table[i].p_class == P_LOCAL &&
2966 : parm_table[i].ptr && !pcopymap[i] &&
2967 : (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
2968 : {
2969 : printf("\t\t%s\n", parm_table[i].label);
2970 : }
2971 : }
2972 : #endif
2973 :
2974 : /***************************************************************************
2975 : Return TRUE if the passed service number is within range.
2976 : ***************************************************************************/
2977 :
2978 1909624 : bool lp_snum_ok(int iService)
2979 : {
2980 1909624 : return (LP_SNUM_OK(iService) && ServicePtrs[iService]->available);
2981 : }
2982 :
2983 : /***************************************************************************
2984 : Auto-load some home services.
2985 : ***************************************************************************/
2986 :
2987 8224 : static void lp_add_auto_services(const char *str)
2988 : {
2989 : char *s;
2990 : char *p;
2991 : int homes;
2992 : char *saveptr;
2993 :
2994 8224 : if (!str)
2995 0 : return;
2996 :
2997 8224 : s = talloc_strdup(talloc_tos(), str);
2998 8224 : if (!s) {
2999 0 : smb_panic("talloc_strdup failed");
3000 : return;
3001 : }
3002 :
3003 8224 : homes = lp_servicenumber(HOMES_NAME);
3004 :
3005 8226 : for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3006 2 : p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3007 : char *home;
3008 :
3009 2 : if (lp_servicenumber(p) >= 0)
3010 0 : continue;
3011 :
3012 2 : home = get_user_home_dir(talloc_tos(), p);
3013 :
3014 2 : if (home && home[0] && homes >= 0)
3015 0 : lp_add_home(p, homes, p, home);
3016 :
3017 2 : TALLOC_FREE(home);
3018 : }
3019 8224 : TALLOC_FREE(s);
3020 : }
3021 :
3022 : /***************************************************************************
3023 : Auto-load one printer.
3024 : ***************************************************************************/
3025 :
3026 0 : void lp_add_one_printer(const char *name, const char *comment,
3027 : const char *location, void *pdata)
3028 : {
3029 0 : int printers = lp_servicenumber(PRINTERS_NAME);
3030 : int i;
3031 :
3032 0 : if (lp_servicenumber(name) < 0) {
3033 0 : lp_add_printer(name, printers);
3034 0 : if ((i = lp_servicenumber(name)) >= 0) {
3035 0 : lpcfg_string_set(ServicePtrs[i],
3036 0 : &ServicePtrs[i]->comment, comment);
3037 0 : ServicePtrs[i]->autoloaded = true;
3038 : }
3039 : }
3040 0 : }
3041 :
3042 : /***************************************************************************
3043 : Have we loaded a services file yet?
3044 : ***************************************************************************/
3045 :
3046 53675 : bool lp_loaded(void)
3047 : {
3048 53675 : return (bLoaded);
3049 : }
3050 :
3051 : /***************************************************************************
3052 : Unload unused services.
3053 : ***************************************************************************/
3054 :
3055 248 : void lp_killunused(struct smbd_server_connection *sconn,
3056 : bool (*snumused) (struct smbd_server_connection *, int))
3057 : {
3058 : int i;
3059 28477 : for (i = 0; i < iNumServices; i++) {
3060 28229 : if (!VALID(i))
3061 8 : continue;
3062 :
3063 : /* don't kill autoloaded or usershare services */
3064 28221 : if ( ServicePtrs[i]->autoloaded ||
3065 28221 : ServicePtrs[i]->usershare == USERSHARE_VALID) {
3066 0 : continue;
3067 : }
3068 :
3069 28221 : if (!snumused || !snumused(sconn, i)) {
3070 28218 : free_service_byindex(i);
3071 : }
3072 : }
3073 248 : }
3074 :
3075 : /**
3076 : * Kill all except autoloaded and usershare services - convenience wrapper
3077 : */
3078 64 : void lp_kill_all_services(void)
3079 : {
3080 64 : lp_killunused(NULL, NULL);
3081 64 : }
3082 :
3083 : /***************************************************************************
3084 : Unload a service.
3085 : ***************************************************************************/
3086 :
3087 2 : void lp_killservice(int iServiceIn)
3088 : {
3089 2 : if (VALID(iServiceIn)) {
3090 2 : free_service_byindex(iServiceIn);
3091 : }
3092 2 : }
3093 :
3094 : /***************************************************************************
3095 : Save the curent values of all global and sDefault parameters into the
3096 : defaults union. This allows testparm to show only the
3097 : changed (ie. non-default) parameters.
3098 : ***************************************************************************/
3099 :
3100 1882 : static void lp_save_defaults(void)
3101 : {
3102 : int i;
3103 : struct parmlist_entry * parm;
3104 974876 : for (i = 0; parm_table[i].label; i++) {
3105 972994 : if (!(flags_list[i] & FLAG_CMDLINE)) {
3106 967822 : flags_list[i] |= FLAG_DEFAULT;
3107 : }
3108 :
3109 972994 : if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3110 65870 : && parm_table[i].p_class == parm_table[i - 1].p_class)
3111 65870 : continue;
3112 907124 : switch (parm_table[i].type) {
3113 77162 : case P_LIST:
3114 : case P_CMDLIST:
3115 77162 : parm_table[i].def.lvalue = str_list_copy(
3116 77162 : NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3117 77162 : break;
3118 239014 : case P_STRING:
3119 : case P_USTRING:
3120 239014 : lpcfg_string_set(
3121 : Globals.ctx,
3122 : &parm_table[i].def.svalue,
3123 239014 : *(char **)lp_parm_ptr(
3124 : NULL, &parm_table[i]));
3125 239014 : if (parm_table[i].def.svalue == NULL) {
3126 0 : smb_panic("lpcfg_string_set() failed");
3127 : }
3128 239014 : break;
3129 333114 : case P_BOOL:
3130 : case P_BOOLREV:
3131 333114 : parm_table[i].def.bvalue =
3132 333114 : *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3133 333114 : break;
3134 1882 : case P_CHAR:
3135 1882 : parm_table[i].def.cvalue =
3136 1882 : *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3137 1882 : break;
3138 255952 : case P_INTEGER:
3139 : case P_OCTAL:
3140 : case P_ENUM:
3141 : case P_BYTES:
3142 255952 : parm_table[i].def.ivalue =
3143 255952 : *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3144 255952 : break;
3145 : }
3146 : }
3147 :
3148 1998 : for (parm=Globals.param_opt; parm; parm=parm->next) {
3149 116 : if (!(parm->priority & FLAG_CMDLINE)) {
3150 9 : parm->priority |= FLAG_DEFAULT;
3151 : }
3152 : }
3153 :
3154 1882 : for (parm=sDefault.param_opt; parm; parm=parm->next) {
3155 0 : if (!(parm->priority & FLAG_CMDLINE)) {
3156 0 : parm->priority |= FLAG_DEFAULT;
3157 : }
3158 : }
3159 :
3160 1882 : defaults_saved = true;
3161 1882 : }
3162 :
3163 : /***********************************************************
3164 : If we should send plaintext/LANMAN passwords in the clinet
3165 : ************************************************************/
3166 :
3167 8224 : static void set_allowed_client_auth(void)
3168 : {
3169 8224 : if (Globals.client_ntlmv2_auth) {
3170 8108 : Globals.client_lanman_auth = false;
3171 : }
3172 8224 : if (!Globals.client_lanman_auth) {
3173 8111 : Globals.client_plaintext_auth = false;
3174 : }
3175 8224 : }
3176 :
3177 : /***************************************************************************
3178 : JRA.
3179 : The following code allows smbd to read a user defined share file.
3180 : Yes, this is my intent. Yes, I'm comfortable with that...
3181 :
3182 : THE FOLLOWING IS SECURITY CRITICAL CODE.
3183 :
3184 : It washes your clothes, it cleans your house, it guards you while you sleep...
3185 : Do not f%^k with it....
3186 : ***************************************************************************/
3187 :
3188 : #define MAX_USERSHARE_FILE_SIZE (10*1024)
3189 :
3190 : /***************************************************************************
3191 : Check allowed stat state of a usershare file.
3192 : Ensure we print out who is dicking with us so the admin can
3193 : get their sorry ass fired.
3194 : ***************************************************************************/
3195 :
3196 0 : static bool check_usershare_stat(const char *fname,
3197 : const SMB_STRUCT_STAT *psbuf)
3198 : {
3199 0 : if (!S_ISREG(psbuf->st_ex_mode)) {
3200 0 : DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3201 : "not a regular file\n",
3202 : fname, (unsigned int)psbuf->st_ex_uid ));
3203 0 : return false;
3204 : }
3205 :
3206 : /* Ensure this doesn't have the other write bit set. */
3207 0 : if (psbuf->st_ex_mode & S_IWOTH) {
3208 0 : DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
3209 : "public write. Refusing to allow as a usershare file.\n",
3210 : fname, (unsigned int)psbuf->st_ex_uid ));
3211 0 : return false;
3212 : }
3213 :
3214 : /* Should be 10k or less. */
3215 0 : if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
3216 0 : DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3217 : "too large (%u) to be a user share file.\n",
3218 : fname, (unsigned int)psbuf->st_ex_uid,
3219 : (unsigned int)psbuf->st_ex_size ));
3220 0 : return false;
3221 : }
3222 :
3223 0 : return true;
3224 : }
3225 :
3226 : /***************************************************************************
3227 : Parse the contents of a usershare file.
3228 : ***************************************************************************/
3229 :
3230 0 : enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
3231 : SMB_STRUCT_STAT *psbuf,
3232 : const char *servicename,
3233 : int snum,
3234 : char **lines,
3235 : int numlines,
3236 : char **pp_sharepath,
3237 : char **pp_comment,
3238 : char **pp_cp_servicename,
3239 : struct security_descriptor **ppsd,
3240 : bool *pallow_guest)
3241 : {
3242 0 : const char **prefixallowlist = lp_usershare_prefix_allow_list();
3243 0 : const char **prefixdenylist = lp_usershare_prefix_deny_list();
3244 : int us_vers;
3245 : DIR *dp;
3246 : SMB_STRUCT_STAT sbuf;
3247 0 : char *sharepath = NULL;
3248 0 : char *comment = NULL;
3249 :
3250 0 : *pp_sharepath = NULL;
3251 0 : *pp_comment = NULL;
3252 :
3253 0 : *pallow_guest = false;
3254 :
3255 0 : if (numlines < 4) {
3256 0 : return USERSHARE_MALFORMED_FILE;
3257 : }
3258 :
3259 0 : if (strcmp(lines[0], "#VERSION 1") == 0) {
3260 0 : us_vers = 1;
3261 0 : } else if (strcmp(lines[0], "#VERSION 2") == 0) {
3262 0 : us_vers = 2;
3263 0 : if (numlines < 5) {
3264 0 : return USERSHARE_MALFORMED_FILE;
3265 : }
3266 : } else {
3267 0 : return USERSHARE_BAD_VERSION;
3268 : }
3269 :
3270 0 : if (strncmp(lines[1], "path=", 5) != 0) {
3271 0 : return USERSHARE_MALFORMED_PATH;
3272 : }
3273 :
3274 0 : sharepath = talloc_strdup(ctx, &lines[1][5]);
3275 0 : if (!sharepath) {
3276 0 : return USERSHARE_POSIX_ERR;
3277 : }
3278 0 : trim_string(sharepath, " ", " ");
3279 :
3280 0 : if (strncmp(lines[2], "comment=", 8) != 0) {
3281 0 : return USERSHARE_MALFORMED_COMMENT_DEF;
3282 : }
3283 :
3284 0 : comment = talloc_strdup(ctx, &lines[2][8]);
3285 0 : if (!comment) {
3286 0 : return USERSHARE_POSIX_ERR;
3287 : }
3288 0 : trim_string(comment, " ", " ");
3289 0 : trim_char(comment, '"', '"');
3290 :
3291 0 : if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
3292 0 : return USERSHARE_MALFORMED_ACL_DEF;
3293 : }
3294 :
3295 0 : if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
3296 0 : return USERSHARE_ACL_ERR;
3297 : }
3298 :
3299 0 : if (us_vers == 2) {
3300 0 : if (strncmp(lines[4], "guest_ok=", 9) != 0) {
3301 0 : return USERSHARE_MALFORMED_ACL_DEF;
3302 : }
3303 0 : if (lines[4][9] == 'y') {
3304 0 : *pallow_guest = true;
3305 : }
3306 :
3307 : /* Backwards compatible extension to file version #2. */
3308 0 : if (numlines > 5) {
3309 0 : if (strncmp(lines[5], "sharename=", 10) != 0) {
3310 0 : return USERSHARE_MALFORMED_SHARENAME_DEF;
3311 : }
3312 0 : if (!strequal(&lines[5][10], servicename)) {
3313 0 : return USERSHARE_BAD_SHARENAME;
3314 : }
3315 0 : *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
3316 0 : if (!*pp_cp_servicename) {
3317 0 : return USERSHARE_POSIX_ERR;
3318 : }
3319 : }
3320 : }
3321 :
3322 0 : if (*pp_cp_servicename == NULL) {
3323 0 : *pp_cp_servicename = talloc_strdup(ctx, servicename);
3324 0 : if (!*pp_cp_servicename) {
3325 0 : return USERSHARE_POSIX_ERR;
3326 : }
3327 : }
3328 :
3329 0 : if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->path) == 0)) {
3330 : /* Path didn't change, no checks needed. */
3331 0 : *pp_sharepath = sharepath;
3332 0 : *pp_comment = comment;
3333 0 : return USERSHARE_OK;
3334 : }
3335 :
3336 : /* The path *must* be absolute. */
3337 0 : if (sharepath[0] != '/') {
3338 0 : DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
3339 : servicename, sharepath));
3340 0 : return USERSHARE_PATH_NOT_ABSOLUTE;
3341 : }
3342 :
3343 : /* If there is a usershare prefix deny list ensure one of these paths
3344 : doesn't match the start of the user given path. */
3345 0 : if (prefixdenylist) {
3346 : int i;
3347 0 : for ( i=0; prefixdenylist[i]; i++ ) {
3348 0 : DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
3349 : servicename, i, prefixdenylist[i], sharepath ));
3350 0 : if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
3351 0 : DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
3352 : "usershare prefix deny list entries.\n",
3353 : servicename, sharepath));
3354 0 : return USERSHARE_PATH_IS_DENIED;
3355 : }
3356 : }
3357 : }
3358 :
3359 : /* If there is a usershare prefix allow list ensure one of these paths
3360 : does match the start of the user given path. */
3361 :
3362 0 : if (prefixallowlist) {
3363 : int i;
3364 0 : for ( i=0; prefixallowlist[i]; i++ ) {
3365 0 : DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
3366 : servicename, i, prefixallowlist[i], sharepath ));
3367 0 : if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
3368 0 : break;
3369 : }
3370 : }
3371 0 : if (prefixallowlist[i] == NULL) {
3372 0 : DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
3373 : "usershare prefix allow list entries.\n",
3374 : servicename, sharepath));
3375 0 : return USERSHARE_PATH_NOT_ALLOWED;
3376 : }
3377 : }
3378 :
3379 : /* Ensure this is pointing to a directory. */
3380 0 : dp = opendir(sharepath);
3381 :
3382 0 : if (!dp) {
3383 0 : DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3384 : servicename, sharepath));
3385 0 : return USERSHARE_PATH_NOT_DIRECTORY;
3386 : }
3387 :
3388 : /* Ensure the owner of the usershare file has permission to share
3389 : this directory. */
3390 :
3391 0 : if (sys_stat(sharepath, &sbuf, false) == -1) {
3392 0 : DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
3393 : servicename, sharepath, strerror(errno) ));
3394 0 : closedir(dp);
3395 0 : return USERSHARE_POSIX_ERR;
3396 : }
3397 :
3398 0 : closedir(dp);
3399 :
3400 0 : if (!S_ISDIR(sbuf.st_ex_mode)) {
3401 0 : DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3402 : servicename, sharepath ));
3403 0 : return USERSHARE_PATH_NOT_DIRECTORY;
3404 : }
3405 :
3406 : /* Check if sharing is restricted to owner-only. */
3407 : /* psbuf is the stat of the usershare definition file,
3408 : sbuf is the stat of the target directory to be shared. */
3409 :
3410 0 : if (lp_usershare_owner_only()) {
3411 : /* root can share anything. */
3412 0 : if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
3413 0 : return USERSHARE_PATH_NOT_ALLOWED;
3414 : }
3415 : }
3416 :
3417 0 : *pp_sharepath = sharepath;
3418 0 : *pp_comment = comment;
3419 0 : return USERSHARE_OK;
3420 : }
3421 :
3422 : /***************************************************************************
3423 : Deal with a usershare file.
3424 : Returns:
3425 : >= 0 - snum
3426 : -1 - Bad name, invalid contents.
3427 : - service name already existed and not a usershare, problem
3428 : with permissions to share directory etc.
3429 : ***************************************************************************/
3430 :
3431 0 : static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
3432 : {
3433 : SMB_STRUCT_STAT sbuf;
3434 : SMB_STRUCT_STAT lsbuf;
3435 0 : char *fname = NULL;
3436 0 : char *sharepath = NULL;
3437 0 : char *comment = NULL;
3438 0 : char *cp_service_name = NULL;
3439 0 : char **lines = NULL;
3440 0 : int numlines = 0;
3441 0 : int fd = -1;
3442 0 : int iService = -1;
3443 0 : TALLOC_CTX *ctx = talloc_stackframe();
3444 0 : struct security_descriptor *psd = NULL;
3445 0 : bool guest_ok = false;
3446 0 : char *canon_name = NULL;
3447 0 : bool added_service = false;
3448 0 : int ret = -1;
3449 : NTSTATUS status;
3450 :
3451 : /* Ensure share name doesn't contain invalid characters. */
3452 0 : if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
3453 0 : DEBUG(0,("process_usershare_file: share name %s contains "
3454 : "invalid characters (any of %s)\n",
3455 : file_name, INVALID_SHARENAME_CHARS ));
3456 0 : goto out;
3457 : }
3458 :
3459 0 : canon_name = canonicalize_servicename(ctx, file_name);
3460 0 : if (!canon_name) {
3461 0 : goto out;
3462 : }
3463 :
3464 0 : fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
3465 0 : if (!fname) {
3466 0 : goto out;
3467 : }
3468 :
3469 : /* Minimize the race condition by doing an lstat before we
3470 : open and fstat. Ensure this isn't a symlink link. */
3471 :
3472 0 : if (sys_lstat(fname, &lsbuf, false) != 0) {
3473 0 : if (errno == ENOENT) {
3474 : /* Unknown share requested. Just ignore. */
3475 0 : goto out;
3476 : }
3477 : /* Only log messages for meaningful problems. */
3478 0 : DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
3479 : fname, strerror(errno) ));
3480 0 : goto out;
3481 : }
3482 :
3483 : /* This must be a regular file, not a symlink, directory or
3484 : other strange filetype. */
3485 0 : if (!check_usershare_stat(fname, &lsbuf)) {
3486 0 : goto out;
3487 : }
3488 :
3489 : {
3490 : TDB_DATA data;
3491 :
3492 0 : status = dbwrap_fetch_bystring(ServiceHash, canon_name,
3493 : canon_name, &data);
3494 :
3495 0 : iService = -1;
3496 :
3497 0 : if (NT_STATUS_IS_OK(status) &&
3498 0 : (data.dptr != NULL) &&
3499 0 : (data.dsize == sizeof(iService))) {
3500 0 : memcpy(&iService, data.dptr, sizeof(iService));
3501 : }
3502 : }
3503 :
3504 0 : if (iService != -1 &&
3505 0 : timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
3506 : &lsbuf.st_ex_mtime) == 0) {
3507 : /* Nothing changed - Mark valid and return. */
3508 0 : DEBUG(10,("process_usershare_file: service %s not changed.\n",
3509 : canon_name ));
3510 0 : ServicePtrs[iService]->usershare = USERSHARE_VALID;
3511 0 : ret = iService;
3512 0 : goto out;
3513 : }
3514 :
3515 : /* Try and open the file read only - no symlinks allowed. */
3516 : #ifdef O_NOFOLLOW
3517 0 : fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
3518 : #else
3519 : fd = open(fname, O_RDONLY, 0);
3520 : #endif
3521 :
3522 0 : if (fd == -1) {
3523 0 : DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
3524 : fname, strerror(errno) ));
3525 0 : goto out;
3526 : }
3527 :
3528 : /* Now fstat to be *SURE* it's a regular file. */
3529 0 : if (sys_fstat(fd, &sbuf, false) != 0) {
3530 0 : close(fd);
3531 0 : DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
3532 : fname, strerror(errno) ));
3533 0 : goto out;
3534 : }
3535 :
3536 : /* Is it the same dev/inode as was lstated ? */
3537 0 : if (!check_same_stat(&lsbuf, &sbuf)) {
3538 0 : close(fd);
3539 0 : DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
3540 : "Symlink spoofing going on ?\n", fname ));
3541 0 : goto out;
3542 : }
3543 :
3544 : /* This must be a regular file, not a symlink, directory or
3545 : other strange filetype. */
3546 0 : if (!check_usershare_stat(fname, &sbuf)) {
3547 0 : close(fd);
3548 0 : goto out;
3549 : }
3550 :
3551 0 : lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
3552 :
3553 0 : close(fd);
3554 0 : if (lines == NULL) {
3555 0 : DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
3556 : fname, (unsigned int)sbuf.st_ex_uid ));
3557 0 : goto out;
3558 : }
3559 :
3560 0 : if (parse_usershare_file(ctx, &sbuf, file_name,
3561 : iService, lines, numlines, &sharepath,
3562 : &comment, &cp_service_name,
3563 : &psd, &guest_ok) != USERSHARE_OK) {
3564 0 : goto out;
3565 : }
3566 :
3567 : /* Everything ok - add the service possibly using a template. */
3568 0 : if (iService < 0) {
3569 0 : const struct loadparm_service *sp = &sDefault;
3570 0 : if (snum_template != -1) {
3571 0 : sp = ServicePtrs[snum_template];
3572 : }
3573 :
3574 0 : if ((iService = add_a_service(sp, cp_service_name)) < 0) {
3575 0 : DEBUG(0, ("process_usershare_file: Failed to add "
3576 : "new service %s\n", cp_service_name));
3577 0 : goto out;
3578 : }
3579 :
3580 0 : added_service = true;
3581 :
3582 : /* Read only is controlled by usershare ACL below. */
3583 0 : ServicePtrs[iService]->read_only = false;
3584 : }
3585 :
3586 : /* Write the ACL of the new/modified share. */
3587 0 : status = set_share_security(canon_name, psd);
3588 0 : if (!NT_STATUS_IS_OK(status)) {
3589 0 : DEBUG(0, ("process_usershare_file: Failed to set share "
3590 : "security for user share %s\n",
3591 : canon_name ));
3592 0 : goto out;
3593 : }
3594 :
3595 : /* If from a template it may be marked invalid. */
3596 0 : ServicePtrs[iService]->valid = true;
3597 :
3598 : /* Set the service as a valid usershare. */
3599 0 : ServicePtrs[iService]->usershare = USERSHARE_VALID;
3600 :
3601 : /* Set guest access. */
3602 0 : if (lp_usershare_allow_guests()) {
3603 0 : ServicePtrs[iService]->guest_ok = guest_ok;
3604 : }
3605 :
3606 : /* And note when it was loaded. */
3607 0 : ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
3608 0 : lpcfg_string_set(ServicePtrs[iService], &ServicePtrs[iService]->path,
3609 : sharepath);
3610 0 : lpcfg_string_set(ServicePtrs[iService],
3611 0 : &ServicePtrs[iService]->comment, comment);
3612 :
3613 0 : ret = iService;
3614 :
3615 0 : out:
3616 :
3617 0 : if (ret == -1 && iService != -1 && added_service) {
3618 0 : lp_remove_service(iService);
3619 : }
3620 :
3621 0 : TALLOC_FREE(lines);
3622 0 : TALLOC_FREE(ctx);
3623 0 : return ret;
3624 : }
3625 :
3626 : /***************************************************************************
3627 : Checks if a usershare entry has been modified since last load.
3628 : ***************************************************************************/
3629 :
3630 0 : static bool usershare_exists(int iService, struct timespec *last_mod)
3631 : {
3632 : SMB_STRUCT_STAT lsbuf;
3633 0 : const char *usersharepath = Globals.usershare_path;
3634 : char *fname;
3635 :
3636 0 : fname = talloc_asprintf(talloc_tos(),
3637 : "%s/%s",
3638 : usersharepath,
3639 0 : ServicePtrs[iService]->szService);
3640 0 : if (fname == NULL) {
3641 0 : return false;
3642 : }
3643 :
3644 0 : if (sys_lstat(fname, &lsbuf, false) != 0) {
3645 0 : TALLOC_FREE(fname);
3646 0 : return false;
3647 : }
3648 :
3649 0 : if (!S_ISREG(lsbuf.st_ex_mode)) {
3650 0 : TALLOC_FREE(fname);
3651 0 : return false;
3652 : }
3653 :
3654 0 : TALLOC_FREE(fname);
3655 0 : *last_mod = lsbuf.st_ex_mtime;
3656 0 : return true;
3657 : }
3658 :
3659 0 : static bool usershare_directory_is_root(uid_t uid)
3660 : {
3661 0 : if (uid == 0) {
3662 0 : return true;
3663 : }
3664 :
3665 0 : if (uid_wrapper_enabled()) {
3666 0 : return true;
3667 : }
3668 :
3669 0 : return false;
3670 : }
3671 :
3672 : /***************************************************************************
3673 : Load a usershare service by name. Returns a valid servicenumber or -1.
3674 : ***************************************************************************/
3675 :
3676 385 : int load_usershare_service(const char *servicename)
3677 : {
3678 : SMB_STRUCT_STAT sbuf;
3679 385 : const char *usersharepath = Globals.usershare_path;
3680 385 : int max_user_shares = Globals.usershare_max_shares;
3681 385 : int snum_template = -1;
3682 :
3683 385 : if (servicename[0] == '\0') {
3684 : /* Invalid service name. */
3685 0 : return -1;
3686 : }
3687 :
3688 385 : if (*usersharepath == 0 || max_user_shares == 0) {
3689 385 : return -1;
3690 : }
3691 :
3692 0 : if (sys_stat(usersharepath, &sbuf, false) != 0) {
3693 0 : DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
3694 : usersharepath, strerror(errno) ));
3695 0 : return -1;
3696 : }
3697 :
3698 0 : if (!S_ISDIR(sbuf.st_ex_mode)) {
3699 0 : DEBUG(0,("load_usershare_service: %s is not a directory.\n",
3700 : usersharepath ));
3701 0 : return -1;
3702 : }
3703 :
3704 : /*
3705 : * This directory must be owned by root, and have the 't' bit set.
3706 : * It also must not be writable by "other".
3707 : */
3708 :
3709 : #ifdef S_ISVTX
3710 0 : if (!usershare_directory_is_root(sbuf.st_ex_uid) ||
3711 0 : !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
3712 : #else
3713 : if (!usershare_directory_is_root(sbuf.st_ex_uid) ||
3714 : (sbuf.st_ex_mode & S_IWOTH)) {
3715 : #endif
3716 0 : DEBUG(0,("load_usershare_service: directory %s is not owned by root "
3717 : "or does not have the sticky bit 't' set or is writable by anyone.\n",
3718 : usersharepath ));
3719 0 : return -1;
3720 : }
3721 :
3722 : /* Ensure the template share exists if it's set. */
3723 0 : if (Globals.usershare_template_share[0]) {
3724 : /* We can't use lp_servicenumber here as we are recommending that
3725 : template shares have -valid=false set. */
3726 0 : for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
3727 0 : if (ServicePtrs[snum_template]->szService &&
3728 0 : strequal(ServicePtrs[snum_template]->szService,
3729 0 : Globals.usershare_template_share)) {
3730 0 : break;
3731 : }
3732 : }
3733 :
3734 0 : if (snum_template == -1) {
3735 0 : DEBUG(0,("load_usershare_service: usershare template share %s "
3736 : "does not exist.\n",
3737 : Globals.usershare_template_share ));
3738 0 : return -1;
3739 : }
3740 : }
3741 :
3742 0 : return process_usershare_file(usersharepath, servicename, snum_template);
3743 : }
3744 :
3745 : /***************************************************************************
3746 : Load all user defined shares from the user share directory.
3747 : We only do this if we're enumerating the share list.
3748 : This is the function that can delete usershares that have
3749 : been removed.
3750 : ***************************************************************************/
3751 :
3752 64 : int load_usershare_shares(struct smbd_server_connection *sconn,
3753 : bool (*snumused) (struct smbd_server_connection *, int))
3754 : {
3755 : DIR *dp;
3756 : SMB_STRUCT_STAT sbuf;
3757 : struct dirent *de;
3758 64 : int num_usershares = 0;
3759 64 : int max_user_shares = Globals.usershare_max_shares;
3760 : unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
3761 64 : unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
3762 64 : unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
3763 : int iService;
3764 64 : int snum_template = -1;
3765 64 : const char *usersharepath = Globals.usershare_path;
3766 64 : int ret = lp_numservices();
3767 : TALLOC_CTX *tmp_ctx;
3768 :
3769 64 : if (max_user_shares == 0 || *usersharepath == '\0') {
3770 63 : return lp_numservices();
3771 : }
3772 :
3773 1 : if (sys_stat(usersharepath, &sbuf, false) != 0) {
3774 0 : DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
3775 : usersharepath, strerror(errno) ));
3776 0 : return ret;
3777 : }
3778 :
3779 : /*
3780 : * This directory must be owned by root, and have the 't' bit set.
3781 : * It also must not be writable by "other".
3782 : */
3783 :
3784 : #ifdef S_ISVTX
3785 1 : if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
3786 : #else
3787 : if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
3788 : #endif
3789 1 : DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
3790 : "or does not have the sticky bit 't' set or is writable by anyone.\n",
3791 : usersharepath ));
3792 1 : return ret;
3793 : }
3794 :
3795 : /* Ensure the template share exists if it's set. */
3796 0 : if (Globals.usershare_template_share[0]) {
3797 : /* We can't use lp_servicenumber here as we are recommending that
3798 : template shares have -valid=false set. */
3799 0 : for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
3800 0 : if (ServicePtrs[snum_template]->szService &&
3801 0 : strequal(ServicePtrs[snum_template]->szService,
3802 0 : Globals.usershare_template_share)) {
3803 0 : break;
3804 : }
3805 : }
3806 :
3807 0 : if (snum_template == -1) {
3808 0 : DEBUG(0,("load_usershare_shares: usershare template share %s "
3809 : "does not exist.\n",
3810 : Globals.usershare_template_share ));
3811 0 : return ret;
3812 : }
3813 : }
3814 :
3815 : /* Mark all existing usershares as pending delete. */
3816 0 : for (iService = iNumServices - 1; iService >= 0; iService--) {
3817 0 : if (VALID(iService) && ServicePtrs[iService]->usershare) {
3818 0 : ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
3819 : }
3820 : }
3821 :
3822 0 : dp = opendir(usersharepath);
3823 0 : if (!dp) {
3824 0 : DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
3825 : usersharepath, strerror(errno) ));
3826 0 : return ret;
3827 : }
3828 :
3829 0 : for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
3830 0 : (de = readdir(dp));
3831 0 : num_dir_entries++ ) {
3832 : int r;
3833 0 : const char *n = de->d_name;
3834 :
3835 : /* Ignore . and .. */
3836 0 : if (*n == '.') {
3837 0 : if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
3838 0 : continue;
3839 : }
3840 : }
3841 :
3842 0 : if (n[0] == ':') {
3843 : /* Temporary file used when creating a share. */
3844 0 : num_tmp_dir_entries++;
3845 : }
3846 :
3847 : /* Allow 20% tmp entries. */
3848 0 : if (num_tmp_dir_entries > allowed_tmp_entries) {
3849 0 : DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
3850 : "in directory %s\n",
3851 : num_tmp_dir_entries, usersharepath));
3852 0 : break;
3853 : }
3854 :
3855 0 : r = process_usershare_file(usersharepath, n, snum_template);
3856 0 : if (r == 0) {
3857 : /* Update the services count. */
3858 0 : num_usershares++;
3859 0 : if (num_usershares >= max_user_shares) {
3860 0 : DEBUG(0,("load_usershare_shares: max user shares reached "
3861 : "on file %s in directory %s\n",
3862 : n, usersharepath ));
3863 0 : break;
3864 : }
3865 0 : } else if (r == -1) {
3866 0 : num_bad_dir_entries++;
3867 : }
3868 :
3869 : /* Allow 20% bad entries. */
3870 0 : if (num_bad_dir_entries > allowed_bad_entries) {
3871 0 : DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
3872 : "in directory %s\n",
3873 : num_bad_dir_entries, usersharepath));
3874 0 : break;
3875 : }
3876 :
3877 : /* Allow 20% bad entries. */
3878 0 : if (num_dir_entries > max_user_shares + allowed_bad_entries) {
3879 0 : DEBUG(0,("load_usershare_shares: too many total entries (%u) "
3880 : "in directory %s\n",
3881 : num_dir_entries, usersharepath));
3882 0 : break;
3883 : }
3884 : }
3885 :
3886 0 : closedir(dp);
3887 :
3888 : /* Sweep through and delete any non-refreshed usershares that are
3889 : not currently in use. */
3890 0 : tmp_ctx = talloc_stackframe();
3891 0 : for (iService = iNumServices - 1; iService >= 0; iService--) {
3892 0 : if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
3893 : const struct loadparm_substitution *lp_sub =
3894 0 : loadparm_s3_global_substitution();
3895 : char *servname;
3896 :
3897 0 : if (snumused && snumused(sconn, iService)) {
3898 0 : continue;
3899 : }
3900 :
3901 0 : servname = lp_servicename(tmp_ctx, lp_sub, iService);
3902 :
3903 : /* Remove from the share ACL db. */
3904 0 : DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
3905 : servname ));
3906 0 : delete_share_security(servname);
3907 0 : free_service_byindex(iService);
3908 : }
3909 : }
3910 0 : talloc_free(tmp_ctx);
3911 :
3912 0 : return lp_numservices();
3913 : }
3914 :
3915 : /********************************************************
3916 : Destroy global resources allocated in this file
3917 : ********************************************************/
3918 :
3919 2109 : void gfree_loadparm(void)
3920 : {
3921 : int i;
3922 :
3923 2109 : free_file_list();
3924 :
3925 : /* Free resources allocated to services */
3926 :
3927 3757 : for ( i = 0; i < iNumServices; i++ ) {
3928 1648 : if ( VALID(i) ) {
3929 1648 : free_service_byindex(i);
3930 : }
3931 : }
3932 :
3933 2109 : TALLOC_FREE( ServicePtrs );
3934 2109 : iNumServices = 0;
3935 :
3936 : /* Now release all resources allocated to global
3937 : parameters and the default service */
3938 :
3939 2109 : free_global_parameters();
3940 2109 : }
3941 :
3942 :
3943 : /***************************************************************************
3944 : Allow client apps to specify that they are a client
3945 : ***************************************************************************/
3946 2953 : static void lp_set_in_client(bool b)
3947 : {
3948 2953 : in_client = b;
3949 2953 : }
3950 :
3951 :
3952 : /***************************************************************************
3953 : Determine if we're running in a client app
3954 : ***************************************************************************/
3955 8224 : static bool lp_is_in_client(void)
3956 : {
3957 8224 : return in_client;
3958 : }
3959 :
3960 1533 : static void lp_enforce_ad_dc_settings(void)
3961 : {
3962 1533 : lp_do_parameter(GLOBAL_SECTION_SNUM, "passdb backend", "samba_dsdb");
3963 1533 : lp_do_parameter(GLOBAL_SECTION_SNUM,
3964 : "winbindd:use external pipes", "true");
3965 1533 : lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:default", "external");
3966 1533 : lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:svcctl", "embedded");
3967 1533 : lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:srvsvc", "embedded");
3968 1533 : lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:eventlog", "embedded");
3969 1533 : lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:ntsvcs", "embedded");
3970 1533 : lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:winreg", "embedded");
3971 1533 : lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:spoolss", "embedded");
3972 1533 : lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_daemon:spoolssd", "embedded");
3973 1533 : lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:tcpip", "no");
3974 1533 : }
3975 :
3976 : /***************************************************************************
3977 : Load the services array from the services file. Return true on success,
3978 : false on failure.
3979 : ***************************************************************************/
3980 :
3981 8224 : static bool lp_load_ex(const char *pszFname,
3982 : bool global_only,
3983 : bool save_defaults,
3984 : bool add_ipc,
3985 : bool reinit_globals,
3986 : bool allow_include_registry,
3987 : bool load_all_shares)
3988 : {
3989 8224 : char *n2 = NULL;
3990 : bool bRetval;
3991 8224 : TALLOC_CTX *frame = talloc_stackframe();
3992 : struct loadparm_context *lp_ctx;
3993 : int max_protocol, min_protocol;
3994 :
3995 8224 : DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
3996 :
3997 8224 : bInGlobalSection = true;
3998 8224 : bGlobalOnly = global_only;
3999 8224 : bAllowIncludeRegistry = allow_include_registry;
4000 8224 : sDefault = _sDefault;
4001 :
4002 8224 : lp_ctx = setup_lp_context(talloc_tos());
4003 :
4004 8224 : init_globals(lp_ctx, reinit_globals);
4005 :
4006 8224 : free_file_list();
4007 :
4008 8224 : if (save_defaults) {
4009 1882 : init_locals();
4010 1882 : lp_save_defaults();
4011 : }
4012 :
4013 8224 : if (!reinit_globals) {
4014 803 : free_param_opts(&Globals.param_opt);
4015 803 : apply_lp_set_cmdline();
4016 : }
4017 :
4018 8224 : lp_do_parameter(-1, "idmap config * : backend", Globals.idmap_backend);
4019 :
4020 : /* We get sections first, so have to start 'behind' to make up */
4021 8224 : iServiceIndex = -1;
4022 :
4023 8224 : if (lp_config_backend_is_file()) {
4024 8224 : n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4025 : get_current_user_info_domain(),
4026 : pszFname);
4027 8224 : if (!n2) {
4028 0 : smb_panic("lp_load_ex: out of memory");
4029 : }
4030 :
4031 8224 : add_to_file_list(NULL, &file_lists, pszFname, n2);
4032 :
4033 8224 : bRetval = pm_process(n2, lp_do_section, do_parameter, lp_ctx);
4034 8224 : TALLOC_FREE(n2);
4035 :
4036 : /* finish up the last section */
4037 8224 : DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4038 8224 : if (bRetval) {
4039 8224 : if (iServiceIndex >= 0) {
4040 3870 : bRetval = lpcfg_service_ok(ServicePtrs[iServiceIndex]);
4041 : }
4042 : }
4043 :
4044 8224 : if (lp_config_backend_is_registry()) {
4045 : bool ok;
4046 : /* config backend changed to registry in config file */
4047 : /*
4048 : * We need to use this extra global variable here to
4049 : * survive restart: init_globals uses this as a default
4050 : * for config_backend. Otherwise, init_globals would
4051 : * send us into an endless loop here.
4052 : */
4053 :
4054 0 : config_backend = CONFIG_BACKEND_REGISTRY;
4055 : /* start over */
4056 0 : DEBUG(1, ("lp_load_ex: changing to config backend "
4057 : "registry\n"));
4058 0 : init_globals(lp_ctx, true);
4059 :
4060 0 : TALLOC_FREE(lp_ctx);
4061 :
4062 0 : lp_kill_all_services();
4063 0 : ok = lp_load_ex(pszFname, global_only, save_defaults,
4064 : add_ipc, reinit_globals,
4065 : allow_include_registry,
4066 : load_all_shares);
4067 0 : TALLOC_FREE(frame);
4068 0 : return ok;
4069 : }
4070 0 : } else if (lp_config_backend_is_registry()) {
4071 0 : bRetval = process_registry_globals();
4072 : } else {
4073 0 : DEBUG(0, ("Illegal config backend given: %d\n",
4074 : lp_config_backend()));
4075 0 : bRetval = false;
4076 : }
4077 :
4078 8224 : if (bRetval && lp_registry_shares()) {
4079 3591 : if (load_all_shares) {
4080 2 : bRetval = process_registry_shares();
4081 : } else {
4082 3589 : bRetval = reload_registry_shares();
4083 : }
4084 : }
4085 :
4086 : {
4087 : const struct loadparm_substitution *lp_sub =
4088 8224 : loadparm_s3_global_substitution();
4089 8224 : char *serv = lp_auto_services(talloc_tos(), lp_sub);
4090 8224 : lp_add_auto_services(serv);
4091 8224 : TALLOC_FREE(serv);
4092 : }
4093 :
4094 8224 : if (add_ipc) {
4095 : /* When 'restrict anonymous = 2' guest connections to ipc$
4096 : are denied */
4097 1708 : lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4098 1708 : if ( lp_enable_asu_support() ) {
4099 0 : lp_add_ipc("ADMIN$", false);
4100 : }
4101 : }
4102 :
4103 8224 : set_allowed_client_auth();
4104 :
4105 8224 : if (lp_security() == SEC_ADS && strchr(lp_password_server(), ':')) {
4106 0 : DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4107 : lp_password_server()));
4108 : }
4109 :
4110 8224 : bLoaded = true;
4111 :
4112 : /* Now we check we_are_a_wins_server and set szWINSserver to 127.0.0.1 */
4113 : /* if we_are_a_wins_server is true and we are in the client */
4114 8224 : if (lp_is_in_client() && Globals.we_are_a_wins_server) {
4115 777 : lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4116 : }
4117 :
4118 8224 : init_iconv();
4119 :
4120 8224 : fault_configure(smb_panic_s3);
4121 :
4122 : /*
4123 : * We run this check once the whole smb.conf is parsed, to
4124 : * force some settings for the standard way a AD DC is
4125 : * operated. We may change these as our code evolves, which
4126 : * is why we force these settings.
4127 : */
4128 8224 : if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4129 1533 : lp_enforce_ad_dc_settings();
4130 : }
4131 :
4132 8224 : bAllowIncludeRegistry = true;
4133 :
4134 : /* Check if command line max protocol < min protocol, if so
4135 : * report a warning to the user.
4136 : */
4137 8224 : max_protocol = lp_client_max_protocol();
4138 8224 : min_protocol = lp_client_min_protocol();
4139 8224 : if (max_protocol < min_protocol) {
4140 : const char *max_protocolp, *min_protocolp;
4141 0 : max_protocolp = lpcfg_get_smb_protocol(max_protocol);
4142 0 : min_protocolp = lpcfg_get_smb_protocol(min_protocol);
4143 0 : DBG_ERR("Max protocol %s is less than min protocol %s.\n",
4144 : max_protocolp, min_protocolp);
4145 : }
4146 :
4147 8224 : TALLOC_FREE(frame);
4148 8224 : return (bRetval);
4149 : }
4150 :
4151 6342 : static bool lp_load(const char *pszFname,
4152 : bool global_only,
4153 : bool save_defaults,
4154 : bool add_ipc,
4155 : bool reinit_globals)
4156 : {
4157 6342 : return lp_load_ex(pszFname,
4158 : global_only,
4159 : save_defaults,
4160 : add_ipc,
4161 : reinit_globals,
4162 : true, /* allow_include_registry */
4163 : false); /* load_all_shares*/
4164 : }
4165 :
4166 0 : bool lp_load_initial_only(const char *pszFname)
4167 : {
4168 0 : return lp_load_ex(pszFname,
4169 : true, /* global only */
4170 : true, /* save_defaults */
4171 : false, /* add_ipc */
4172 : true, /* reinit_globals */
4173 : false, /* allow_include_registry */
4174 : false); /* load_all_shares*/
4175 : }
4176 :
4177 : /**
4178 : * most common lp_load wrapper, loading only the globals
4179 : *
4180 : * If this is used in a daemon or client utility it should be called
4181 : * after processing popt.
4182 : */
4183 3831 : bool lp_load_global(const char *file_name)
4184 : {
4185 3831 : return lp_load(file_name,
4186 : true, /* global_only */
4187 : false, /* save_defaults */
4188 : false, /* add_ipc */
4189 : true); /* reinit_globals */
4190 : }
4191 :
4192 : /**
4193 : * The typical lp_load wrapper with shares, loads global and
4194 : * shares, including IPC, but does not force immediate
4195 : * loading of all shares from registry.
4196 : */
4197 1708 : bool lp_load_with_shares(const char *file_name)
4198 : {
4199 1708 : return lp_load(file_name,
4200 : false, /* global_only */
4201 : false, /* save_defaults */
4202 : true, /* add_ipc */
4203 : true); /* reinit_globals */
4204 : }
4205 :
4206 : /**
4207 : * lp_load wrapper, especially for clients
4208 : */
4209 2953 : bool lp_load_client(const char *file_name)
4210 : {
4211 2953 : lp_set_in_client(true);
4212 :
4213 2953 : return lp_load_global(file_name);
4214 : }
4215 :
4216 : /**
4217 : * lp_load wrapper, loading only globals, but intended
4218 : * for subsequent calls, not reinitializing the globals
4219 : * to default values
4220 : */
4221 0 : bool lp_load_global_no_reinit(const char *file_name)
4222 : {
4223 0 : return lp_load(file_name,
4224 : true, /* global_only */
4225 : false, /* save_defaults */
4226 : false, /* add_ipc */
4227 : false); /* reinit_globals */
4228 : }
4229 :
4230 : /**
4231 : * lp_load wrapper, loading globals and shares,
4232 : * intended for subsequent calls, i.e. not reinitializing
4233 : * the globals to default values.
4234 : */
4235 803 : bool lp_load_no_reinit(const char *file_name)
4236 : {
4237 803 : return lp_load(file_name,
4238 : false, /* global_only */
4239 : false, /* save_defaults */
4240 : false, /* add_ipc */
4241 : false); /* reinit_globals */
4242 : }
4243 :
4244 :
4245 : /**
4246 : * lp_load wrapper, especially for clients, no reinitialization
4247 : */
4248 0 : bool lp_load_client_no_reinit(const char *file_name)
4249 : {
4250 0 : lp_set_in_client(true);
4251 :
4252 0 : return lp_load_global_no_reinit(file_name);
4253 : }
4254 :
4255 1882 : bool lp_load_with_registry_shares(const char *pszFname)
4256 : {
4257 1882 : return lp_load_ex(pszFname,
4258 : false, /* global_only */
4259 : true, /* save_defaults */
4260 : false, /* add_ipc */
4261 : true, /* reinit_globals */
4262 : true, /* allow_include_registry */
4263 : true); /* load_all_shares*/
4264 : }
4265 :
4266 : /***************************************************************************
4267 : Return the max number of services.
4268 : ***************************************************************************/
4269 :
4270 677 : int lp_numservices(void)
4271 : {
4272 677 : return (iNumServices);
4273 : }
4274 :
4275 : /***************************************************************************
4276 : Display the contents of the services array in human-readable form.
4277 : ***************************************************************************/
4278 :
4279 466 : void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4280 : {
4281 : int iService;
4282 : struct loadparm_context *lp_ctx;
4283 :
4284 466 : if (show_defaults)
4285 0 : defaults_saved = false;
4286 :
4287 466 : lp_ctx = setup_lp_context(talloc_tos());
4288 466 : if (lp_ctx == NULL) {
4289 0 : return;
4290 : }
4291 :
4292 466 : lpcfg_dump_globals(lp_ctx, f, !defaults_saved);
4293 :
4294 466 : lpcfg_dump_a_service(&sDefault, &sDefault, f, flags_list, show_defaults);
4295 :
4296 698 : for (iService = 0; iService < maxtoprint; iService++) {
4297 232 : fprintf(f,"\n");
4298 232 : lp_dump_one(f, show_defaults, iService);
4299 : }
4300 466 : TALLOC_FREE(lp_ctx);
4301 : }
4302 :
4303 : /***************************************************************************
4304 : Display the contents of one service in human-readable form.
4305 : ***************************************************************************/
4306 :
4307 232 : void lp_dump_one(FILE * f, bool show_defaults, int snum)
4308 : {
4309 232 : if (VALID(snum)) {
4310 232 : if (ServicePtrs[snum]->szService[0] == '\0')
4311 0 : return;
4312 232 : lpcfg_dump_a_service(ServicePtrs[snum], &sDefault, f,
4313 : flags_list, show_defaults);
4314 : }
4315 : }
4316 :
4317 : /***************************************************************************
4318 : Return the number of the service with the given name, or -1 if it doesn't
4319 : exist. Note that this is a DIFFERENT ANIMAL from the internal function
4320 : getservicebyname()! This works ONLY if all services have been loaded, and
4321 : does not copy the found service.
4322 : ***************************************************************************/
4323 :
4324 35671 : int lp_servicenumber(const char *pszServiceName)
4325 : {
4326 : int iService;
4327 : fstring serviceName;
4328 :
4329 35671 : if (!pszServiceName) {
4330 0 : return GLOBAL_SECTION_SNUM;
4331 : }
4332 :
4333 1137153 : for (iService = iNumServices - 1; iService >= 0; iService--) {
4334 1117973 : if (VALID(iService) && ServicePtrs[iService]->szService) {
4335 : /*
4336 : * The substitution here is used to support %U in
4337 : * service names
4338 : */
4339 1117674 : fstrcpy(serviceName, ServicePtrs[iService]->szService);
4340 1117674 : standard_sub_basic(get_current_username(),
4341 : get_current_user_info_domain(),
4342 : serviceName,sizeof(serviceName));
4343 1117674 : if (strequal(serviceName, pszServiceName)) {
4344 16491 : break;
4345 : }
4346 : }
4347 : }
4348 :
4349 35671 : if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
4350 : struct timespec last_mod;
4351 :
4352 0 : if (!usershare_exists(iService, &last_mod)) {
4353 : /* Remove the share security tdb entry for it. */
4354 0 : delete_share_security(lp_const_servicename(iService));
4355 : /* Remove it from the array. */
4356 0 : free_service_byindex(iService);
4357 : /* Doesn't exist anymore. */
4358 0 : return GLOBAL_SECTION_SNUM;
4359 : }
4360 :
4361 : /* Has it been modified ? If so delete and reload. */
4362 0 : if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4363 : &last_mod) < 0) {
4364 : /* Remove it from the array. */
4365 0 : free_service_byindex(iService);
4366 : /* and now reload it. */
4367 0 : iService = load_usershare_service(pszServiceName);
4368 : }
4369 : }
4370 :
4371 35671 : if (iService < 0) {
4372 19180 : DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
4373 19180 : return GLOBAL_SECTION_SNUM;
4374 : }
4375 :
4376 16491 : return (iService);
4377 : }
4378 :
4379 : /*******************************************************************
4380 : A useful volume label function.
4381 : ********************************************************************/
4382 :
4383 387 : const char *volume_label(TALLOC_CTX *ctx, int snum)
4384 : {
4385 : const struct loadparm_substitution *lp_sub =
4386 387 : loadparm_s3_global_substitution();
4387 : char *ret;
4388 387 : const char *label = lp_volume(ctx, lp_sub, snum);
4389 387 : size_t end = 32;
4390 :
4391 387 : if (!*label) {
4392 387 : label = lp_servicename(ctx, lp_sub, snum);
4393 : }
4394 :
4395 : /*
4396 : * Volume label can be a max of 32 bytes. Make sure to truncate
4397 : * it at a codepoint boundary if it's longer than 32 and contains
4398 : * multibyte characters. Windows insists on a volume label being
4399 : * a valid mb sequence, and errors out if not.
4400 : */
4401 387 : if (strlen(label) > 32) {
4402 : /*
4403 : * A MB char can be a max of 5 bytes, thus
4404 : * we should have a valid mb character at a
4405 : * minimum position of (32-5) = 27.
4406 : */
4407 0 : while (end >= 27) {
4408 : /*
4409 : * Check if a codepoint starting from next byte
4410 : * is valid. If yes, then the current byte is the
4411 : * end of a MB or ascii sequence and the label can
4412 : * be safely truncated here. If not, keep going
4413 : * backwards till a valid codepoint is found.
4414 : */
4415 0 : size_t len = 0;
4416 0 : const char *s = &label[end];
4417 0 : codepoint_t c = next_codepoint(s, &len);
4418 0 : if (c != INVALID_CODEPOINT) {
4419 0 : break;
4420 : }
4421 0 : end--;
4422 : }
4423 : }
4424 :
4425 : /* This returns a max of 33 byte guarenteed null terminated string. */
4426 387 : ret = talloc_strndup(ctx, label, end);
4427 387 : if (!ret) {
4428 0 : return "";
4429 : }
4430 387 : return ret;
4431 : }
4432 :
4433 : /*******************************************************************
4434 : Get the default server type we will announce as via nmbd.
4435 : ********************************************************************/
4436 :
4437 6235 : int lp_default_server_announce(void)
4438 : {
4439 6235 : int default_server_announce = 0;
4440 6235 : default_server_announce |= SV_TYPE_WORKSTATION;
4441 6235 : default_server_announce |= SV_TYPE_SERVER;
4442 6235 : default_server_announce |= SV_TYPE_SERVER_UNIX;
4443 :
4444 : /* note that the flag should be set only if we have a
4445 : printer service but nmbd doesn't actually load the
4446 : services so we can't tell --jerry */
4447 :
4448 6235 : default_server_announce |= SV_TYPE_PRINTQ_SERVER;
4449 :
4450 6235 : default_server_announce |= SV_TYPE_SERVER_NT;
4451 6235 : default_server_announce |= SV_TYPE_NT;
4452 :
4453 6235 : switch (lp_server_role()) {
4454 5283 : case ROLE_DOMAIN_MEMBER:
4455 5283 : default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
4456 5283 : break;
4457 220 : case ROLE_DOMAIN_PDC:
4458 : case ROLE_IPA_DC:
4459 220 : default_server_announce |= SV_TYPE_DOMAIN_CTRL;
4460 220 : break;
4461 0 : case ROLE_DOMAIN_BDC:
4462 0 : default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
4463 0 : break;
4464 732 : case ROLE_STANDALONE:
4465 : default:
4466 732 : break;
4467 : }
4468 6235 : if (lp_time_server())
4469 6235 : default_server_announce |= SV_TYPE_TIME_SOURCE;
4470 :
4471 6235 : if (lp_host_msdfs())
4472 6235 : default_server_announce |= SV_TYPE_DFS_SERVER;
4473 :
4474 6235 : return default_server_announce;
4475 : }
4476 :
4477 : /***********************************************************
4478 : If we are PDC then prefer us as DMB
4479 : ************************************************************/
4480 :
4481 94 : bool lp_domain_master(void)
4482 : {
4483 94 : if (Globals._domain_master == Auto)
4484 176 : return (lp_server_role() == ROLE_DOMAIN_PDC ||
4485 88 : lp_server_role() == ROLE_IPA_DC);
4486 :
4487 6 : return (bool)Globals._domain_master;
4488 : }
4489 :
4490 : /***********************************************************
4491 : If we are PDC then prefer us as DMB
4492 : ************************************************************/
4493 :
4494 239775 : static bool lp_domain_master_true_or_auto(void)
4495 : {
4496 239775 : if (Globals._domain_master) /* auto or yes */
4497 237943 : return true;
4498 :
4499 1832 : return false;
4500 : }
4501 :
4502 : /***********************************************************
4503 : If we are DMB then prefer us as LMB
4504 : ************************************************************/
4505 :
4506 23 : bool lp_preferred_master(void)
4507 : {
4508 23 : int preferred_master = lp__preferred_master();
4509 :
4510 23 : if (preferred_master == Auto)
4511 23 : return (lp_local_master() && lp_domain_master());
4512 :
4513 0 : return (bool)preferred_master;
4514 : }
4515 :
4516 : /*******************************************************************
4517 : Remove a service.
4518 : ********************************************************************/
4519 :
4520 0 : void lp_remove_service(int snum)
4521 : {
4522 0 : ServicePtrs[snum]->valid = false;
4523 0 : }
4524 :
4525 30 : const char *lp_printername(TALLOC_CTX *ctx,
4526 : const struct loadparm_substitution *lp_sub,
4527 : int snum)
4528 : {
4529 30 : const char *ret = lp__printername(ctx, lp_sub, snum);
4530 :
4531 30 : if (ret == NULL || *ret == '\0') {
4532 30 : ret = lp_const_servicename(snum);
4533 : }
4534 :
4535 30 : return ret;
4536 : }
4537 :
4538 :
4539 : /***********************************************************
4540 : Allow daemons such as winbindd to fix their logfile name.
4541 : ************************************************************/
4542 :
4543 0 : void lp_set_logfile(const char *name)
4544 : {
4545 0 : lpcfg_string_set(Globals.ctx, &Globals.logfile, name);
4546 0 : debug_set_logfile(name);
4547 0 : }
4548 :
4549 : /*******************************************************************
4550 : Return the max print jobs per queue.
4551 : ********************************************************************/
4552 :
4553 0 : int lp_maxprintjobs(int snum)
4554 : {
4555 0 : int maxjobs = lp_max_print_jobs(snum);
4556 :
4557 0 : if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
4558 0 : maxjobs = PRINT_MAX_JOBID - 1;
4559 :
4560 0 : return maxjobs;
4561 : }
4562 :
4563 0 : const char *lp_printcapname(void)
4564 : {
4565 0 : const char *printcap_name = lp_printcap_name();
4566 :
4567 0 : if ((printcap_name != NULL) &&
4568 0 : (printcap_name[0] != '\0'))
4569 0 : return printcap_name;
4570 :
4571 0 : if (sDefault.printing == PRINT_CUPS) {
4572 0 : return "cups";
4573 : }
4574 :
4575 0 : if (sDefault.printing == PRINT_BSD)
4576 0 : return "/etc/printcap";
4577 :
4578 0 : return PRINTCAP_NAME;
4579 : }
4580 :
4581 : static uint32_t spoolss_state;
4582 :
4583 0 : bool lp_disable_spoolss( void )
4584 : {
4585 0 : if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
4586 0 : spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
4587 :
4588 0 : return spoolss_state == SVCCTL_STOPPED ? true : false;
4589 : }
4590 :
4591 0 : void lp_set_spoolss_state( uint32_t state )
4592 : {
4593 0 : SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
4594 :
4595 0 : spoolss_state = state;
4596 0 : }
4597 :
4598 0 : uint32_t lp_get_spoolss_state( void )
4599 : {
4600 0 : return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
4601 : }
4602 :
4603 : /*******************************************************************
4604 : Turn off sendfile if we find the underlying OS doesn't support it.
4605 : ********************************************************************/
4606 :
4607 0 : void set_use_sendfile(int snum, bool val)
4608 : {
4609 0 : if (LP_SNUM_OK(snum))
4610 0 : ServicePtrs[snum]->_use_sendfile = val;
4611 : else
4612 0 : sDefault._use_sendfile = val;
4613 0 : }
4614 :
4615 0 : void lp_set_mangling_method(const char *new_method)
4616 : {
4617 0 : lpcfg_string_set(Globals.ctx, &Globals.mangling_method, new_method);
4618 0 : }
4619 :
4620 : /*******************************************************************
4621 : Global state for POSIX pathname processing.
4622 : ********************************************************************/
4623 :
4624 : static bool posix_pathnames;
4625 :
4626 5943 : bool lp_posix_pathnames(void)
4627 : {
4628 5943 : return posix_pathnames;
4629 : }
4630 :
4631 : /*******************************************************************
4632 : Change everything needed to ensure POSIX pathname processing (currently
4633 : not much).
4634 : ********************************************************************/
4635 :
4636 0 : void lp_set_posix_pathnames(void)
4637 : {
4638 0 : posix_pathnames = true;
4639 0 : }
4640 :
4641 : /*******************************************************************
4642 : Global state for POSIX lock processing - CIFS unix extensions.
4643 : ********************************************************************/
4644 :
4645 : bool posix_default_lock_was_set;
4646 : static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
4647 :
4648 1652 : enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
4649 : {
4650 1652 : if (posix_default_lock_was_set) {
4651 0 : return posix_cifsx_locktype;
4652 : } else {
4653 1652 : return (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
4654 1652 : POSIX_LOCK : WINDOWS_LOCK;
4655 : }
4656 : }
4657 :
4658 : /*******************************************************************
4659 : ********************************************************************/
4660 :
4661 0 : void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
4662 : {
4663 0 : posix_default_lock_was_set = true;
4664 0 : posix_cifsx_locktype = val;
4665 0 : }
4666 :
4667 157357 : int lp_min_receive_file_size(void)
4668 : {
4669 157357 : int min_receivefile_size = lp_min_receivefile_size();
4670 :
4671 157357 : if (min_receivefile_size < 0) {
4672 0 : return 0;
4673 : }
4674 157357 : return min_receivefile_size;
4675 : }
4676 :
4677 : /*******************************************************************
4678 : Safe wide links checks.
4679 : This helper function always verify the validity of wide links,
4680 : even after a configuration file reload.
4681 : ********************************************************************/
4682 :
4683 5615 : void widelinks_warning(int snum)
4684 : {
4685 5615 : if (lp_allow_insecure_wide_links()) {
4686 1747 : return;
4687 : }
4688 :
4689 3868 : if (lp_wide_links(snum)) {
4690 0 : if (lp_smb1_unix_extensions()) {
4691 0 : DBG_ERR("Share '%s' has wide links and SMB1 unix "
4692 : "extensions enabled. "
4693 : "These parameters are incompatible. "
4694 : "Wide links will be disabled for this share.\n",
4695 : lp_const_servicename(snum));
4696 0 : } else if (lp_smb3_unix_extensions()) {
4697 0 : DBG_ERR("Share '%s' has wide links and SMB3 unix "
4698 : "extensions enabled. "
4699 : "These parameters are incompatible. "
4700 : "Wide links will be disabled for this share.\n",
4701 : lp_const_servicename(snum));
4702 : }
4703 : }
4704 : }
4705 :
4706 7978 : bool lp_widelinks(int snum)
4707 : {
4708 : /* wide links is always incompatible with unix extensions */
4709 7978 : if (lp_smb1_unix_extensions() || lp_smb3_unix_extensions()) {
4710 : /*
4711 : * Unless we have "allow insecure widelinks"
4712 : * turned on.
4713 : */
4714 7978 : if (!lp_allow_insecure_wide_links()) {
4715 5377 : return false;
4716 : }
4717 : }
4718 :
4719 2601 : return lp_wide_links(snum);
4720 : }
4721 :
4722 239775 : int lp_server_role(void)
4723 : {
4724 239775 : return lp_find_server_role(lp__server_role(),
4725 : lp__security(),
4726 239775 : lp__domain_logons(),
4727 239775 : lp_domain_master_true_or_auto());
4728 : }
4729 :
4730 22624 : int lp_security(void)
4731 : {
4732 22624 : return lp_find_security(lp__server_role(),
4733 : lp__security());
4734 : }
4735 :
4736 10246 : int lp_client_max_protocol(void)
4737 : {
4738 10246 : int client_max_protocol = lp__client_max_protocol();
4739 10246 : if (client_max_protocol == PROTOCOL_DEFAULT) {
4740 8867 : return PROTOCOL_LATEST;
4741 : }
4742 1379 : return client_max_protocol;
4743 : }
4744 :
4745 451 : int lp_client_ipc_min_protocol(void)
4746 : {
4747 451 : int client_ipc_min_protocol = lp__client_ipc_min_protocol();
4748 451 : if (client_ipc_min_protocol == PROTOCOL_DEFAULT) {
4749 451 : client_ipc_min_protocol = lp_client_min_protocol();
4750 : }
4751 451 : if (client_ipc_min_protocol < PROTOCOL_NT1) {
4752 222 : return PROTOCOL_NT1;
4753 : }
4754 229 : return client_ipc_min_protocol;
4755 : }
4756 :
4757 451 : int lp_client_ipc_max_protocol(void)
4758 : {
4759 451 : int client_ipc_max_protocol = lp__client_ipc_max_protocol();
4760 451 : if (client_ipc_max_protocol == PROTOCOL_DEFAULT) {
4761 451 : return PROTOCOL_LATEST;
4762 : }
4763 0 : if (client_ipc_max_protocol < PROTOCOL_NT1) {
4764 0 : return PROTOCOL_NT1;
4765 : }
4766 0 : return client_ipc_max_protocol;
4767 : }
4768 :
4769 3771 : int lp_client_ipc_signing(void)
4770 : {
4771 3771 : int client_ipc_signing = lp__client_ipc_signing();
4772 3771 : if (client_ipc_signing == SMB_SIGNING_DEFAULT) {
4773 3771 : return SMB_SIGNING_REQUIRED;
4774 : }
4775 0 : return client_ipc_signing;
4776 : }
4777 :
4778 48 : enum credentials_use_kerberos lp_client_use_kerberos(void)
4779 : {
4780 48 : if (lp_weak_crypto() == SAMBA_WEAK_CRYPTO_DISALLOWED) {
4781 0 : return CRED_USE_KERBEROS_REQUIRED;
4782 : }
4783 :
4784 48 : return lp__client_use_kerberos();
4785 : }
4786 :
4787 :
4788 8 : int lp_rpc_low_port(void)
4789 : {
4790 8 : return Globals.rpc_low_port;
4791 : }
4792 :
4793 32 : int lp_rpc_high_port(void)
4794 : {
4795 32 : return Globals.rpc_high_port;
4796 : }
4797 :
4798 : /*
4799 : * Do not allow LanMan auth if unless NTLMv1 is also allowed
4800 : *
4801 : * This also ensures it is disabled if NTLM is totally disabled
4802 : */
4803 790 : bool lp_lanman_auth(void)
4804 : {
4805 790 : enum ntlm_auth_level ntlm_auth_level = lp_ntlm_auth();
4806 :
4807 790 : if (ntlm_auth_level == NTLM_AUTH_ON) {
4808 288 : return lp__lanman_auth();
4809 : } else {
4810 502 : return false;
4811 : }
4812 : }
4813 :
4814 154678 : struct loadparm_global * get_globals(void)
4815 : {
4816 154678 : return &Globals;
4817 : }
4818 :
4819 154678 : unsigned int * get_flags(void)
4820 : {
4821 154678 : if (flags_list == NULL) {
4822 21271 : flags_list = talloc_zero_array(NULL, unsigned int, num_parameters());
4823 : }
4824 :
4825 154678 : return flags_list;
4826 : }
4827 :
4828 80 : enum samba_weak_crypto lp_weak_crypto(void)
4829 : {
4830 80 : if (Globals.weak_crypto == SAMBA_WEAK_CRYPTO_UNKNOWN) {
4831 12 : Globals.weak_crypto = SAMBA_WEAK_CRYPTO_DISALLOWED;
4832 :
4833 12 : if (samba_gnutls_weak_crypto_allowed()) {
4834 11 : Globals.weak_crypto = SAMBA_WEAK_CRYPTO_ALLOWED;
4835 : }
4836 : }
4837 :
4838 80 : return Globals.weak_crypto;
4839 : }
4840 :
4841 58 : uint32_t lp_get_async_dns_timeout(void)
4842 : {
4843 : /*
4844 : * Clamp minimum async dns timeout to 1 second
4845 : * as per the man page.
4846 : */
4847 58 : return MAX(Globals.async_dns_timeout, 1);
4848 : }
4849 :
4850 2824 : bool lp_smb3_unix_extensions(void)
4851 : {
4852 : /*
4853 : * FIXME: If this gets always enabled, check source3/selftest/tests.py
4854 : * and source3/wscript for HAVE_SMB3_UNIX_EXTENSIONS.
4855 : */
4856 : #if defined(DEVELOPER)
4857 2824 : return lp__smb3_unix_extensions();
4858 : #else
4859 : return false;
4860 : #endif
4861 : }
|