s3:param: move a variable into scope in lp_file_list_changed
[Samba.git] / source3 / param / loadparm.c
blob6b3e46ec816645c5a00e9e3c3d134b275d0e8036
1 /*
2 Unix SMB/CIFS implementation.
3 Parameter loading functions
4 Copyright (C) Karl Auer 1993-1998
6 Largely re-written by Andrew Tridgell, September 1994
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
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.
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.
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/>.
31 * Load parameters.
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.
37 * To add a parameter:
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
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!
56 #include "includes.h"
57 #include "system/filesys.h"
58 #include "util_tdb.h"
59 #include "lib/param/loadparm.h"
60 #include "lib/param/param.h"
61 #include "printing.h"
62 #include "lib/smbconf/smbconf.h"
63 #include "lib/smbconf/smbconf_init.h"
65 #include "ads.h"
66 #include "../librpc/gen_ndr/svcctl.h"
67 #include "intl.h"
68 #include "../libcli/smb/smb_signing.h"
69 #include "dbwrap/dbwrap.h"
70 #include "dbwrap/dbwrap_rbt.h"
71 #include "../lib/util/bitmap.h"
73 #ifdef HAVE_SYS_SYSCTL_H
74 #include <sys/sysctl.h>
75 #endif
77 #ifdef HAVE_HTTPCONNECTENCRYPT
78 #include <cups/http.h>
79 #endif
81 bool bLoaded = false;
83 extern userdom_struct current_user_info;
85 /* the special value for the include parameter
86 * to be interpreted not as a file name but to
87 * trigger loading of the global smb.conf options
88 * from registry. */
89 #ifndef INCLUDE_REGISTRY_NAME
90 #define INCLUDE_REGISTRY_NAME "registry"
91 #endif
93 static bool in_client = false; /* Not in the client by default */
94 static struct smbconf_csn conf_last_csn;
96 static int config_backend = CONFIG_BACKEND_FILE;
98 /* some helpful bits */
99 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
100 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
102 #define USERSHARE_VALID 1
103 #define USERSHARE_PENDING_DELETE 2
105 static bool defaults_saved = false;
107 #include "lib/param/param_global.h"
109 static struct loadparm_global Globals;
111 /* This is a default service used to prime a services structure */
112 static struct loadparm_service sDefault =
114 .valid = true,
115 .autoloaded = false,
116 .usershare = 0,
117 .usershare_last_mod = {0, 0},
118 .szService = NULL,
119 .path = NULL,
120 .username = NULL,
121 .invalid_users = NULL,
122 .valid_users = NULL,
123 .admin_users = NULL,
124 .szCopy = NULL,
125 .szInclude = NULL,
126 .preexec = NULL,
127 .postexec = NULL,
128 .root_preexec = NULL,
129 .root_postexec = NULL,
130 .cups_options = NULL,
131 .print_command = NULL,
132 .lpq_command = NULL,
133 .lprm_command = NULL,
134 .lppause_command = NULL,
135 .lpresume_command = NULL,
136 .queuepause_command = NULL,
137 .queueresume_command = NULL,
138 ._printername = NULL,
139 .printjob_username = NULL,
140 .dont_descend = NULL,
141 .hosts_allow = NULL,
142 .hosts_deny = NULL,
143 .magic_script = NULL,
144 .magic_output = NULL,
145 .veto_files = NULL,
146 .hide_files = NULL,
147 .veto_oplock_files = NULL,
148 .comment = NULL,
149 .force_user = NULL,
150 .force_group = NULL,
151 .read_list = NULL,
152 .write_list = NULL,
153 .volume = NULL,
154 .fstype = NULL,
155 .vfs_objects = NULL,
156 .msdfs_proxy = NULL,
157 .aio_write_behind = NULL,
158 .dfree_command = NULL,
159 .min_print_space = 0,
160 .iMaxPrintJobs = 1000,
161 .max_reported_print_jobs = 0,
162 .write_cache_size = 0,
163 .create_mask = 0744,
164 .force_create_mode = 0,
165 .directory_mask = 0755,
166 .force_directory_mode = 0,
167 .max_connections = 0,
168 .default_case = CASE_LOWER,
169 .printing = DEFAULT_PRINTING,
170 .oplock_contention_limit = 2,
171 .csc_policy = 0,
172 .block_size = 1024,
173 .dfree_cache_time = 0,
174 .preexec_close = false,
175 .root_preexec_close = false,
176 .case_sensitive = Auto,
177 .preserve_case = true,
178 .short_preserve_case = true,
179 .hide_dot_files = true,
180 .hide_special_files = false,
181 .hide_unreadable = false,
182 .hide_unwriteable_files = false,
183 .browseable = true,
184 .access_based_share_enum = false,
185 .bAvailable = true,
186 .read_only = true,
187 .guest_only = false,
188 .administrative_share = false,
189 .guest_ok = false,
190 .printable = false,
191 .print_notify_backchannel = false,
192 .map_system = false,
193 .map_hidden = false,
194 .map_archive = true,
195 .store_dos_attributes = false,
196 .dmapi_support = false,
197 .locking = true,
198 .strict_locking = Auto,
199 .posix_locking = true,
200 .oplocks = true,
201 .kernel_oplocks = false,
202 .level2_oplocks = true,
203 .only_user = false,
204 .mangled_names = true,
205 .bWidelinks = false,
206 .follow_symlinks = true,
207 .sync_always = false,
208 .strict_allocate = false,
209 .strict_sync = false,
210 .mangling_char = '~',
211 .copymap = NULL,
212 .delete_readonly = false,
213 .fake_oplocks = false,
214 .delete_veto_files = false,
215 .dos_filemode = false,
216 .dos_filetimes = true,
217 .dos_filetime_resolution = false,
218 .fake_directory_create_times = false,
219 .blocking_locks = true,
220 .inherit_permissions = false,
221 .inherit_acls = false,
222 .inherit_owner = false,
223 .msdfs_root = false,
224 .use_client_driver = false,
225 .default_devmode = true,
226 .force_printername = false,
227 .nt_acl_support = true,
228 .force_unknown_acl_user = false,
229 ._use_sendfile = false,
230 .profile_acls = false,
231 .map_acl_inherit = false,
232 .afs_share = false,
233 .ea_support = false,
234 .acl_check_permissions = true,
235 .acl_map_full_control = true,
236 .acl_group_control = false,
237 .acl_allow_execute_always = false,
238 .change_notify = true,
239 .kernel_change_notify = true,
240 .allocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
241 .aio_read_size = 0,
242 .aio_write_size = 0,
243 .map_readonly = MAP_READONLY_YES,
244 .directory_name_cache_size = 100,
245 .smb_encrypt = SMB_SIGNING_DEFAULT,
246 .kernel_share_modes = true,
247 .durable_handles = true,
248 .param_opt = NULL,
249 .dummy = ""
252 /* local variables */
253 static struct loadparm_service **ServicePtrs = NULL;
254 static int iNumServices = 0;
255 static int iServiceIndex = 0;
256 static struct db_context *ServiceHash;
257 static bool bInGlobalSection = true;
258 static bool bGlobalOnly = false;
259 static struct file_lists *file_lists = NULL;
260 static unsigned int *flags_list = NULL;
262 static void set_allowed_client_auth(void);
264 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue);
265 static void free_param_opts(struct parmlist_entry **popts);
267 /* this is used to prevent lots of mallocs of size 1 */
268 static const char null_string[] = "";
271 Free a string value.
274 static void string_free(char **s)
276 if (!s || !(*s))
277 return;
278 if (*s == null_string)
279 *s = NULL;
280 TALLOC_FREE(*s);
284 Set a string value, deallocating any existing space, and allocing the space
285 for the string
288 static bool string_set(TALLOC_CTX *mem_ctx, char **dest,const char *src)
290 string_free(dest);
292 if (!src) {
293 src = "";
296 (*dest) = talloc_strdup(mem_ctx, src);
297 if ((*dest) == NULL) {
298 DEBUG(0,("Out of memory in string_init\n"));
299 return false;
302 return true;
305 bool lp_string_set(char **dest, const char *src) {
306 return string_set(Globals.ctx, dest, src);
309 /***************************************************************************
310 Initialise the sDefault parameter structure for the printer values.
311 ***************************************************************************/
313 void init_printer_values(TALLOC_CTX *ctx, struct loadparm_service *pService)
315 /* choose defaults depending on the type of printing */
316 switch (pService->printing) {
317 case PRINT_BSD:
318 case PRINT_AIX:
319 case PRINT_LPRNT:
320 case PRINT_LPROS2:
321 lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
322 lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
323 lpcfg_string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
324 break;
326 case PRINT_LPRNG:
327 case PRINT_PLP:
328 lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
329 lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
330 lpcfg_string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
331 lpcfg_string_set(ctx, &pService->queuepause_command, "lpc stop '%p'");
332 lpcfg_string_set(ctx, &pService->queueresume_command, "lpc start '%p'");
333 lpcfg_string_set(ctx, &pService->lppause_command, "lpc hold '%p' %j");
334 lpcfg_string_set(ctx, &pService->lpresume_command, "lpc release '%p' %j");
335 break;
337 case PRINT_CUPS:
338 case PRINT_IPRINT:
339 /* set the lpq command to contain the destination printer
340 name only. This is used by cups_queue_get() */
341 lpcfg_string_set(ctx, &pService->lpq_command, "%p");
342 lpcfg_string_set(ctx, &pService->lprm_command, "");
343 lpcfg_string_set(ctx, &pService->print_command, "");
344 lpcfg_string_set(ctx, &pService->lppause_command, "");
345 lpcfg_string_set(ctx, &pService->lpresume_command, "");
346 lpcfg_string_set(ctx, &pService->queuepause_command, "");
347 lpcfg_string_set(ctx, &pService->queueresume_command, "");
348 break;
350 case PRINT_SYSV:
351 case PRINT_HPUX:
352 lpcfg_string_set(ctx, &pService->lpq_command, "lpstat -o%p");
353 lpcfg_string_set(ctx, &pService->lprm_command, "cancel %p-%j");
354 lpcfg_string_set(ctx, &pService->print_command, "lp -c -d%p %s; rm %s");
355 lpcfg_string_set(ctx, &pService->queuepause_command, "disable %p");
356 lpcfg_string_set(ctx, &pService->queueresume_command, "enable %p");
357 #ifndef HPUX
358 lpcfg_string_set(ctx, &pService->lppause_command, "lp -i %p-%j -H hold");
359 lpcfg_string_set(ctx, &pService->lpresume_command, "lp -i %p-%j -H resume");
360 #endif /* HPUX */
361 break;
363 case PRINT_QNX:
364 lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P%p");
365 lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P%p %j");
366 lpcfg_string_set(ctx, &pService->print_command, "lp -r -P%p %s");
367 break;
369 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
371 case PRINT_TEST:
372 case PRINT_VLP: {
373 const char *tdbfile;
374 TALLOC_CTX *tmp_ctx = talloc_new(ctx);
375 char *tmp;
377 tdbfile = talloc_asprintf(
378 tmp_ctx, "tdbfile=%s",
379 lp_parm_const_string(-1, "vlp", "tdbfile",
380 "/tmp/vlp.tdb"));
381 if (tdbfile == NULL) {
382 tdbfile="tdbfile=/tmp/vlp.tdb";
385 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
386 tdbfile);
387 lpcfg_string_set(ctx, &pService->print_command,
388 tmp ? tmp : "vlp print %p %s");
390 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
391 tdbfile);
392 lpcfg_string_set(ctx, &pService->lpq_command,
393 tmp ? tmp : "vlp lpq %p");
395 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
396 tdbfile);
397 lpcfg_string_set(ctx, &pService->lprm_command,
398 tmp ? tmp : "vlp lprm %p %j");
400 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
401 tdbfile);
402 lpcfg_string_set(ctx, &pService->lppause_command,
403 tmp ? tmp : "vlp lppause %p %j");
405 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
406 tdbfile);
407 lpcfg_string_set(ctx, &pService->lpresume_command,
408 tmp ? tmp : "vlp lpresume %p %j");
410 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
411 tdbfile);
412 lpcfg_string_set(ctx, &pService->queuepause_command,
413 tmp ? tmp : "vlp queuepause %p");
415 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
416 tdbfile);
417 lpcfg_string_set(ctx, &pService->queueresume_command,
418 tmp ? tmp : "vlp queueresume %p");
419 TALLOC_FREE(tmp_ctx);
421 break;
423 #endif /* DEVELOPER */
428 * Function to return the default value for the maximum number of open
429 * file descriptors permitted. This function tries to consult the
430 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
431 * the smaller of those.
433 static int max_open_files(void)
435 int sysctl_max = MAX_OPEN_FILES;
436 int rlimit_max = MAX_OPEN_FILES;
438 #ifdef HAVE_SYSCTLBYNAME
440 size_t size = sizeof(sysctl_max);
441 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
444 #endif
446 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
448 struct rlimit rl;
450 ZERO_STRUCT(rl);
452 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
453 rlimit_max = rl.rlim_cur;
455 #if defined(RLIM_INFINITY)
456 if(rl.rlim_cur == RLIM_INFINITY)
457 rlimit_max = MAX_OPEN_FILES;
458 #endif
460 #endif
462 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
463 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
464 "minimum Windows limit (%d)\n",
465 sysctl_max,
466 MIN_OPEN_FILES_WINDOWS));
467 sysctl_max = MIN_OPEN_FILES_WINDOWS;
470 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
471 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
472 "minimum Windows limit (%d)\n",
473 rlimit_max,
474 MIN_OPEN_FILES_WINDOWS));
475 rlimit_max = MIN_OPEN_FILES_WINDOWS;
478 return MIN(sysctl_max, rlimit_max);
482 * Common part of freeing allocated data for one parameter.
484 static void free_one_parameter_common(void *parm_ptr,
485 struct parm_struct parm)
487 if ((parm.type == P_STRING) ||
488 (parm.type == P_USTRING))
490 string_free((char**)parm_ptr);
491 } else if (parm.type == P_LIST || parm.type == P_CMDLIST) {
492 TALLOC_FREE(*((char***)parm_ptr));
497 * Free the allocated data for one parameter for a share
498 * given as a service struct.
500 static void free_one_parameter(struct loadparm_service *service,
501 struct parm_struct parm)
503 void *parm_ptr;
505 if (parm.p_class != P_LOCAL) {
506 return;
509 parm_ptr = lp_parm_ptr(service, &parm);
511 free_one_parameter_common(parm_ptr, parm);
515 * Free the allocated parameter data of a share given
516 * as a service struct.
518 static void free_parameters(struct loadparm_service *service)
520 uint32_t i;
522 for (i=0; parm_table[i].label; i++) {
523 free_one_parameter(service, parm_table[i]);
528 * Free the allocated data for one parameter for a given share
529 * specified by an snum.
531 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
533 void *parm_ptr;
535 if (snum < 0) {
536 parm_ptr = lp_parm_ptr(NULL, &parm);
537 } else if (parm.p_class != P_LOCAL) {
538 return;
539 } else {
540 parm_ptr = lp_parm_ptr(ServicePtrs[snum], &parm);
543 free_one_parameter_common(parm_ptr, parm);
547 * Free the allocated parameter data for a share specified
548 * by an snum.
550 static void free_parameters_by_snum(int snum)
552 uint32_t i;
554 for (i=0; parm_table[i].label; i++) {
555 free_one_parameter_by_snum(snum, parm_table[i]);
560 * Free the allocated global parameters.
562 static void free_global_parameters(void)
564 free_param_opts(&Globals.param_opt);
565 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
566 TALLOC_FREE(Globals.ctx);
569 struct lp_stored_option {
570 struct lp_stored_option *prev, *next;
571 const char *label;
572 const char *value;
575 static struct lp_stored_option *stored_options;
578 save options set by lp_set_cmdline() into a list. This list is
579 re-applied when we do a globals reset, so that cmdline set options
580 are sticky across reloads of smb.conf
582 bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
584 struct lp_stored_option *entry, *entry_next;
585 for (entry = stored_options; entry != NULL; entry = entry_next) {
586 entry_next = entry->next;
587 if (strcmp(pszParmName, entry->label) == 0) {
588 DLIST_REMOVE(stored_options, entry);
589 talloc_free(entry);
590 break;
594 entry = talloc(NULL, struct lp_stored_option);
595 if (!entry) {
596 return false;
599 entry->label = talloc_strdup(entry, pszParmName);
600 if (!entry->label) {
601 talloc_free(entry);
602 return false;
605 entry->value = talloc_strdup(entry, pszParmValue);
606 if (!entry->value) {
607 talloc_free(entry);
608 return false;
611 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
613 return true;
616 static bool apply_lp_set_cmdline(void)
618 struct lp_stored_option *entry = NULL;
619 for (entry = stored_options; entry != NULL; entry = entry->next) {
620 if (!lp_set_cmdline_helper(entry->label, entry->value)) {
621 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
622 entry->label, entry->value));
623 return false;
626 return true;
629 /***************************************************************************
630 Initialise the global parameter structure.
631 ***************************************************************************/
633 static void init_globals(bool reinit_globals)
635 static bool done_init = false;
636 char *s = NULL;
637 int i;
639 /* If requested to initialize only once and we've already done it... */
640 if (!reinit_globals && done_init) {
641 /* ... then we have nothing more to do */
642 return;
645 if (!done_init) {
646 /* The logfile can be set before this is invoked. Free it if so. */
647 if (Globals.logfile != NULL) {
648 string_free(&Globals.logfile);
649 Globals.logfile = NULL;
651 done_init = true;
652 } else {
653 free_global_parameters();
656 /* This memset and the free_global_parameters() above will
657 * wipe out smb.conf options set with lp_set_cmdline(). The
658 * apply_lp_set_cmdline() call puts these values back in the
659 * table once the defaults are set */
660 ZERO_STRUCT(Globals);
662 Globals.ctx = talloc_pooled_object(NULL, char, 272, 2048);
664 /* Initialize the flags list if necessary */
665 if (flags_list == NULL) {
666 get_flags();
669 for (i = 0; parm_table[i].label; i++) {
670 if ((parm_table[i].type == P_STRING ||
671 parm_table[i].type == P_USTRING))
673 string_set(Globals.ctx, (char **)lp_parm_ptr(NULL, &parm_table[i]), "");
678 string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
679 string_set(Globals.ctx, &sDefault.printjob_username, "%U");
681 init_printer_values(Globals.ctx, &sDefault);
683 sDefault.ntvfs_handler = (const char **)str_list_make_v3(NULL, "unixuid default", NULL);
685 DEBUG(3, ("Initialising global parameters\n"));
687 /* Must manually force to upper case here, as this does not go via the handler */
688 string_set(Globals.ctx, &Globals.netbios_name, myhostname_upper());
690 string_set(Globals.ctx, &Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
691 string_set(Globals.ctx, &Globals.private_dir, get_dyn_PRIVATE_DIR());
693 /* use the new 'hash2' method by default, with a prefix of 1 */
694 string_set(Globals.ctx, &Globals.mangling_method, "hash2");
695 Globals.mangle_prefix = 1;
697 string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
699 /* using UTF8 by default allows us to support all chars */
700 string_set(Globals.ctx, &Globals.unix_charset, DEFAULT_UNIX_CHARSET);
702 /* Use codepage 850 as a default for the dos character set */
703 string_set(Globals.ctx, &Globals.dos_charset, DEFAULT_DOS_CHARSET);
706 * Allow the default PASSWD_CHAT to be overridden in local.h.
708 string_set(Globals.ctx, &Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
710 string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
712 string_set(Globals.ctx, &Globals.passwd_program, "");
713 string_set(Globals.ctx, &Globals.lock_directory, get_dyn_LOCKDIR());
714 string_set(Globals.ctx, &Globals.state_directory, get_dyn_STATEDIR());
715 string_set(Globals.ctx, &Globals.cache_directory, get_dyn_CACHEDIR());
716 string_set(Globals.ctx, &Globals.pid_directory, get_dyn_PIDDIR());
717 string_set(Globals.ctx, &Globals.nbt_client_socket_address, "0.0.0.0");
719 * By default support explicit binding to broadcast
720 * addresses.
722 Globals.nmbd_bind_explicit_broadcast = true;
724 s = talloc_asprintf(talloc_tos(), "Samba %s", samba_version_string());
725 if (s == NULL) {
726 smb_panic("init_globals: ENOMEM");
728 string_set(Globals.ctx, &Globals.server_string, s);
729 TALLOC_FREE(s);
730 #ifdef DEVELOPER
731 string_set(Globals.ctx, &Globals.panic_action, "/bin/sleep 999999999");
732 #endif
734 string_set(Globals.ctx, &Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
736 string_set(Globals.ctx, &Globals.logon_drive, "");
737 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
738 string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
739 string_set(Globals.ctx, &Globals.logon_path, "\\\\%N\\%U\\profile");
741 Globals.name_resolve_order = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
742 string_set(Globals.ctx, &Globals.password_server, "*");
744 Globals.algorithmic_rid_base = BASE_RID;
746 Globals.load_printers = true;
747 Globals.printcap_cache_time = 750; /* 12.5 minutes */
749 Globals.config_backend = config_backend;
750 Globals._server_role = ROLE_AUTO;
752 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
753 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
754 Globals.max_xmit = 0x4104;
755 Globals.max_mux = 50; /* This is *needed* for profile support. */
756 Globals.lpq_cache_time = 30; /* changed to handle large print servers better -- jerry */
757 Globals._disable_spoolss = false;
758 Globals.max_smbd_processes = 0;/* no limit specified */
759 Globals.username_level = 0;
760 Globals.deadtime = 0;
761 Globals.getwd_cache = true;
762 Globals.large_readwrite = true;
763 Globals.max_log_size = 5000;
764 Globals.max_open_files = max_open_files();
765 Globals.server_max_protocol = PROTOCOL_SMB3_00;
766 Globals.server_min_protocol = PROTOCOL_LANMAN1;
767 Globals.client_max_protocol = PROTOCOL_NT1;
768 Globals.client_min_protocol = PROTOCOL_CORE;
769 Globals._security = SEC_AUTO;
770 Globals.encrypt_passwords = true;
771 Globals.client_schannel = Auto;
772 Globals.winbind_sealed_pipes = true;
773 Globals.require_strong_key = true;
774 Globals.server_schannel = Auto;
775 Globals.read_raw = true;
776 Globals.write_raw = true;
777 Globals.null_passwords = false;
778 Globals.old_password_allowed_period = 60;
779 Globals.obey_pam_restrictions = false;
780 Globals.syslog = 1;
781 Globals.syslog_only = false;
782 Globals.timestamp_logs = true;
783 string_set(Globals.ctx, &Globals.log_level, "0");
784 Globals.debug_prefix_timestamp = false;
785 Globals.debug_hires_timestamp = true;
786 Globals.debug_pid = false;
787 Globals.debug_uid = false;
788 Globals.debug_class = false;
789 Globals.enable_core_files = true;
790 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
791 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
792 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
793 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
794 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
795 Globals.lm_interval = 60;
796 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
797 Globals.nis_homedir = false;
798 #ifdef WITH_NISPLUS_HOME
799 string_set(Globals.ctx, &Globals.homedir_map, "auto_home.org_dir");
800 #else
801 string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
802 #endif
803 #endif
804 Globals.time_server = false;
805 Globals.bind_interfaces_only = false;
806 Globals.unix_password_sync = false;
807 Globals.pam_password_change = false;
808 Globals.passwd_chat_debug = false;
809 Globals.passwd_chat_timeout = 2; /* 2 second default. */
810 Globals.nt_pipe_support = true; /* Do NT pipes by default. */
811 Globals.nt_status_support = true; /* Use NT status by default. */
812 Globals.stat_cache = true; /* use stat cache by default */
813 Globals.max_stat_cache_size = 256; /* 256k by default */
814 Globals.restrict_anonymous = 0;
815 Globals.client_lanman_auth = false; /* Do NOT use the LanMan hash if it is available */
816 Globals.client_plaintext_auth = false; /* Do NOT use a plaintext password even if is requested by the server */
817 Globals.lanman_auth = false; /* Do NOT use the LanMan hash, even if it is supplied */
818 Globals.ntlm_auth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
819 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 */
820 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
822 Globals.map_to_guest = 0; /* By Default, "Never" */
823 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
824 Globals.enhanced_browsing = true;
825 Globals.lock_spin_time = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
826 #ifdef MMAP_BLACKLIST
827 Globals.use_mmap = false;
828 #else
829 Globals.use_mmap = true;
830 #endif
831 Globals.unicode = true;
832 Globals.unix_extensions = true;
833 Globals.reset_on_zero_vc = false;
834 Globals.log_writeable_files_on_exit = false;
835 Globals.create_krb5_conf = true;
836 Globals.winbindMaxDomainConnections = 1;
838 /* hostname lookups can be very expensive and are broken on
839 a large number of sites (tridge) */
840 Globals.hostname_lookups = false;
842 string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
843 string_set(Globals.ctx, &Globals.ldap_suffix, "");
844 string_set(Globals.ctx, &Globals.szLdapMachineSuffix, "");
845 string_set(Globals.ctx, &Globals.szLdapUserSuffix, "");
846 string_set(Globals.ctx, &Globals.szLdapGroupSuffix, "");
847 string_set(Globals.ctx, &Globals.szLdapIdmapSuffix, "");
849 string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
850 Globals.ldap_ssl = LDAP_SSL_START_TLS;
851 Globals.ldap_ssl_ads = false;
852 Globals.ldap_deref = -1;
853 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
854 Globals.ldap_delete_dn = false;
855 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
856 Globals.ldap_follow_referral = Auto;
857 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
858 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
859 Globals.ldap_page_size = LDAP_PAGE_SIZE;
861 Globals.ldap_debug_level = 0;
862 Globals.ldap_debug_threshold = 10;
864 /* This is what we tell the afs client. in reality we set the token
865 * to never expire, though, when this runs out the afs client will
866 * forget the token. Set to 0 to get NEVERDATE.*/
867 Globals.afs_token_lifetime = 604800;
868 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
870 /* these parameters are set to defaults that are more appropriate
871 for the increasing samba install base:
873 as a member of the workgroup, that will possibly become a
874 _local_ master browser (lm = true). this is opposed to a forced
875 local master browser startup (pm = true).
877 doesn't provide WINS server service by default (wsupp = false),
878 and doesn't provide domain master browser services by default, either.
882 Globals.show_add_printer_wizard = true;
883 Globals.os_level = 20;
884 Globals.local_master = true;
885 Globals._domain_master = Auto; /* depending on _domain_logons */
886 Globals._domain_logons = false;
887 Globals.browse_list = true;
888 Globals.we_are_a_wins_server = false;
889 Globals.wins_proxy = false;
891 TALLOC_FREE(Globals.init_logon_delayed_hosts);
892 Globals.init_logon_delay = 100; /* 100 ms default delay */
894 Globals.wins_dns_proxy = true;
896 Globals.allow_trusted_domains = true;
897 string_set(Globals.ctx, &Globals.szIdmapBackend, "tdb");
899 string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
900 string_set(Globals.ctx, &Globals.template_homedir, "/home/%D/%U");
901 string_set(Globals.ctx, &Globals.winbind_separator, "\\");
902 string_set(Globals.ctx, &Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
904 string_set(Globals.ctx, &Globals.cups_server, "");
905 string_set(Globals.ctx, &Globals.iprint_server, "");
907 string_set(Globals.ctx, &Globals._ctdbd_socket, "");
909 Globals.cluster_addresses = NULL;
910 Globals.clustering = false;
911 Globals.ctdb_timeout = 0;
912 Globals.ctdb_locktime_warn_threshold = 0;
914 Globals.winbind_cache_time = 300; /* 5 minutes */
915 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
916 Globals.winbind_request_timeout = 60; /* 60 seconds */
917 Globals.winbind_max_clients = 200;
918 Globals.winbind_enum_users = false;
919 Globals.winbind_enum_groups = false;
920 Globals.winbind_use_default_domain = false;
921 Globals.winbind_trusted_domains_only = false;
922 Globals.winbind_nested_groups = true;
923 Globals.winbind_expand_groups = 1;
924 Globals.winbind_nss_info = (const char **)str_list_make_v3(NULL, "template", NULL);
925 Globals.winbind_refresh_tickets = false;
926 Globals.winbind_offline_logon = false;
928 Globals.idmap_cache_time = 86400 * 7; /* a week by default */
929 Globals.idmap_negative_cache_time = 120; /* 2 minutes by default */
931 Globals.passdb_expand_explicit = false;
933 Globals.name_cache_timeout = 660; /* In seconds */
935 Globals.use_spnego = true;
936 Globals.client_use_spnego = true;
938 Globals.client_signing = SMB_SIGNING_DEFAULT;
939 Globals.server_signing = SMB_SIGNING_DEFAULT;
941 Globals.defer_sharing_violations = true;
942 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
944 Globals.enable_privileges = true;
945 Globals.host_msdfs = true;
946 Globals.enable_asu_support = false;
948 /* User defined shares. */
949 s = talloc_asprintf(talloc_tos(), "%s/usershares", get_dyn_STATEDIR());
950 if (s == NULL) {
951 smb_panic("init_globals: ENOMEM");
953 string_set(Globals.ctx, &Globals.usershare_path, s);
954 TALLOC_FREE(s);
955 string_set(Globals.ctx, &Globals.usershare_template_share, "");
956 Globals.usershare_max_shares = 0;
957 /* By default disallow sharing of directories not owned by the sharer. */
958 Globals.usershare_owner_only = true;
959 /* By default disallow guest access to usershares. */
960 Globals.usershare_allow_guests = false;
962 Globals.keepalive = DEFAULT_KEEPALIVE;
964 /* By default no shares out of the registry */
965 Globals.registry_shares = false;
967 Globals.iminreceivefile = 0;
969 Globals.map_untrusted_to_domain = false;
970 Globals.multicast_dns_register = true;
972 Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
973 Globals.smb2_max_write = DEFAULT_SMB2_MAX_WRITE;
974 Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
975 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
977 string_set(Globals.ctx, &Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
979 Globals.server_services = (const char **)str_list_make_v3(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns", NULL);
981 Globals.dcerpc_endpoint_servers = (const char **)str_list_make_v3(NULL, "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver", NULL);
983 Globals.tls_enabled = true;
985 string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
986 string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
987 string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
989 string_set(Globals.ctx, &Globals.share_backend, "classic");
991 Globals.iPreferredMaster = Auto;
993 Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
995 string_set(Globals.ctx, &Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
997 string_set(Globals.ctx, &Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
999 s = talloc_asprintf(talloc_tos(), "%s/samba_kcc", get_dyn_SCRIPTSBINDIR());
1000 if (s == NULL) {
1001 smb_panic("init_globals: ENOMEM");
1003 Globals.samba_kcc_command = (const char **)str_list_make_v3(NULL, s, NULL);
1004 TALLOC_FREE(s);
1006 s = talloc_asprintf(talloc_tos(), "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR());
1007 if (s == NULL) {
1008 smb_panic("init_globals: ENOMEM");
1010 Globals.dns_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1011 TALLOC_FREE(s);
1013 s = talloc_asprintf(talloc_tos(), "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR());
1014 if (s == NULL) {
1015 smb_panic("init_globals: ENOMEM");
1017 Globals.spn_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1018 TALLOC_FREE(s);
1020 Globals.nsupdate_command = (const char **)str_list_make_v3(NULL, "/usr/bin/nsupdate -g", NULL);
1022 Globals.rndc_command = (const char **)str_list_make_v3(NULL, "/usr/sbin/rndc", NULL);
1024 Globals.cldap_port = 389;
1026 Globals.dgram_port = 138;
1028 Globals.nbt_port = 137;
1030 Globals.krb5_port = 88;
1032 Globals.kpasswd_port = 464;
1034 Globals.web_port = 901;
1036 /* Now put back the settings that were set with lp_set_cmdline() */
1037 apply_lp_set_cmdline();
1040 /*******************************************************************
1041 Convenience routine to grab string parameters into talloced memory
1042 and run standard_sub_basic on them. The buffers can be written to by
1043 callers without affecting the source string.
1044 ********************************************************************/
1046 char *lp_string(TALLOC_CTX *ctx, const char *s)
1048 char *ret;
1050 /* The follow debug is useful for tracking down memory problems
1051 especially if you have an inner loop that is calling a lp_*()
1052 function that returns a string. Perhaps this debug should be
1053 present all the time? */
1055 #if 0
1056 DEBUG(10, ("lp_string(%s)\n", s));
1057 #endif
1058 if (!s) {
1059 return NULL;
1062 ret = talloc_sub_basic(ctx,
1063 get_current_username(),
1064 current_user_info.domain,
1066 if (trim_char(ret, '\"', '\"')) {
1067 if (strchr(ret,'\"') != NULL) {
1068 TALLOC_FREE(ret);
1069 ret = talloc_sub_basic(ctx,
1070 get_current_username(),
1071 current_user_info.domain,
1075 return ret;
1079 In this section all the functions that are used to access the
1080 parameters from the rest of the program are defined
1083 #define FN_GLOBAL_STRING(fn_name,ptr) \
1084 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1085 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1086 const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1087 #define FN_GLOBAL_LIST(fn_name,ptr) \
1088 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1089 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1090 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1091 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1092 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1093 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1094 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1096 #define FN_LOCAL_STRING(fn_name,val) \
1097 char *lp_ ## fn_name(TALLOC_CTX *ctx,int i) {return(lp_string((ctx), (LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1098 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1099 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1100 #define FN_LOCAL_LIST(fn_name,val) \
1101 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1102 #define FN_LOCAL_BOOL(fn_name,val) \
1103 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1104 #define FN_LOCAL_INTEGER(fn_name,val) \
1105 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1107 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1108 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1109 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1110 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1111 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
1112 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1114 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1115 winbindMaxDomainConnections)
1117 int lp_winbind_max_domain_connections(void)
1119 if (lp_winbind_offline_logon() &&
1120 lp_winbind_max_domain_connections_int() > 1) {
1121 DEBUG(1, ("offline logons active, restricting max domain "
1122 "connections to 1\n"));
1123 return 1;
1125 return MAX(1, lp_winbind_max_domain_connections_int());
1128 int lp_smb2_max_credits(void)
1130 if (Globals.ismb2_max_credits == 0) {
1131 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1133 return Globals.ismb2_max_credits;
1135 int lp_cups_encrypt(void)
1137 int result = 0;
1138 #ifdef HAVE_HTTPCONNECTENCRYPT
1139 switch (Globals.CupsEncrypt) {
1140 case Auto:
1141 result = HTTP_ENCRYPT_REQUIRED;
1142 break;
1143 case true:
1144 result = HTTP_ENCRYPT_ALWAYS;
1145 break;
1146 case false:
1147 result = HTTP_ENCRYPT_NEVER;
1148 break;
1150 #endif
1151 return result;
1154 /* These functions remain in source3/param for now */
1156 #include "lib/param/param_functions.c"
1158 FN_LOCAL_STRING(servicename, szService)
1159 FN_LOCAL_CONST_STRING(const_servicename, szService)
1161 /* These functions cannot be auto-generated */
1162 FN_LOCAL_BOOL(autoloaded, autoloaded)
1163 FN_GLOBAL_CONST_STRING(dnsdomain, dnsdomain)
1165 /* local prototypes */
1167 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1168 static const char *get_boolean(bool bool_value);
1169 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1170 void *userdata);
1171 static bool hash_a_service(const char *name, int number);
1172 static void free_service_byindex(int iService);
1173 static void show_parameter(int parmIndex);
1174 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1177 * This is a helper function for parametrical options support. It returns a
1178 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1179 * parametrical functions are quite simple
1181 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1182 const char *option)
1184 if (snum >= iNumServices) return NULL;
1186 if (snum < 0) {
1187 return get_parametric_helper(NULL, type, option, Globals.param_opt);
1188 } else {
1189 return get_parametric_helper(ServicePtrs[snum],
1190 type, option, Globals.param_opt);
1195 #define MISSING_PARAMETER(name) \
1196 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1198 /*******************************************************************
1199 convenience routine to return enum parameters.
1200 ********************************************************************/
1201 static int lp_enum(const char *s,const struct enum_list *_enum)
1203 int i;
1205 if (!s || !*s || !_enum) {
1206 MISSING_PARAMETER(lp_enum);
1207 return (-1);
1210 for (i=0; _enum[i].name; i++) {
1211 if (strequal(_enum[i].name,s))
1212 return _enum[i].value;
1215 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1216 return (-1);
1219 #undef MISSING_PARAMETER
1221 /* Return parametric option from a given service. Type is a part of option before ':' */
1222 /* Parametric option has following syntax: 'Type: option = value' */
1223 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1225 struct parmlist_entry *data = get_parametrics(snum, type, option);
1227 if (data == NULL||data->value==NULL) {
1228 if (def) {
1229 return lp_string(ctx, def);
1230 } else {
1231 return NULL;
1235 return lp_string(ctx, data->value);
1238 /* Return parametric option from a given service. Type is a part of option before ':' */
1239 /* Parametric option has following syntax: 'Type: option = value' */
1240 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1242 struct parmlist_entry *data = get_parametrics(snum, type, option);
1244 if (data == NULL||data->value==NULL)
1245 return def;
1247 return data->value;
1251 /* Return parametric option from a given service. Type is a part of option before ':' */
1252 /* Parametric option has following syntax: 'Type: option = value' */
1254 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1256 struct parmlist_entry *data = get_parametrics(snum, type, option);
1258 if (data == NULL||data->value==NULL)
1259 return (const char **)def;
1261 if (data->list==NULL) {
1262 data->list = str_list_make_v3(NULL, data->value, NULL);
1265 return (const char **)data->list;
1268 /* Return parametric option from a given service. Type is a part of option before ':' */
1269 /* Parametric option has following syntax: 'Type: option = value' */
1271 int lp_parm_int(int snum, const char *type, const char *option, int def)
1273 struct parmlist_entry *data = get_parametrics(snum, type, option);
1275 if (data && data->value && *data->value)
1276 return lp_int(data->value);
1278 return def;
1281 /* Return parametric option from a given service. Type is a part of option before ':' */
1282 /* Parametric option has following syntax: 'Type: option = value' */
1284 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1286 struct parmlist_entry *data = get_parametrics(snum, type, option);
1288 if (data && data->value && *data->value)
1289 return lp_ulong(data->value);
1291 return def;
1294 /* Return parametric option from a given service. Type is a part of option before ':' */
1295 /* Parametric option has following syntax: 'Type: option = value' */
1297 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1299 struct parmlist_entry *data = get_parametrics(snum, type, option);
1301 if (data && data->value && *data->value)
1302 return lp_bool(data->value);
1304 return def;
1307 /* Return parametric option from a given service. Type is a part of option before ':' */
1308 /* Parametric option has following syntax: 'Type: option = value' */
1310 int lp_parm_enum(int snum, const char *type, const char *option,
1311 const struct enum_list *_enum, int def)
1313 struct parmlist_entry *data = get_parametrics(snum, type, option);
1315 if (data && data->value && *data->value && _enum)
1316 return lp_enum(data->value, _enum);
1318 return def;
1322 * free a param_opts structure.
1323 * param_opts handling should be moved to talloc;
1324 * then this whole functions reduces to a TALLOC_FREE().
1327 static void free_param_opts(struct parmlist_entry **popts)
1329 struct parmlist_entry *opt, *next_opt;
1331 if (*popts != NULL) {
1332 DEBUG(5, ("Freeing parametrics:\n"));
1334 opt = *popts;
1335 while (opt != NULL) {
1336 string_free(&opt->key);
1337 string_free(&opt->value);
1338 TALLOC_FREE(opt->list);
1339 next_opt = opt->next;
1340 TALLOC_FREE(opt);
1341 opt = next_opt;
1343 *popts = NULL;
1346 /***************************************************************************
1347 Free the dynamically allocated parts of a service struct.
1348 ***************************************************************************/
1350 static void free_service(struct loadparm_service *pservice)
1352 if (!pservice)
1353 return;
1355 if (pservice->szService)
1356 DEBUG(5, ("free_service: Freeing service %s\n",
1357 pservice->szService));
1359 free_parameters(pservice);
1361 string_free(&pservice->szService);
1362 TALLOC_FREE(pservice->copymap);
1364 free_param_opts(&pservice->param_opt);
1366 ZERO_STRUCTP(pservice);
1370 /***************************************************************************
1371 remove a service indexed in the ServicePtrs array from the ServiceHash
1372 and free the dynamically allocated parts
1373 ***************************************************************************/
1375 static void free_service_byindex(int idx)
1377 if ( !LP_SNUM_OK(idx) )
1378 return;
1380 ServicePtrs[idx]->valid = false;
1382 /* we have to cleanup the hash record */
1384 if (ServicePtrs[idx]->szService) {
1385 char *canon_name = canonicalize_servicename(
1386 talloc_tos(),
1387 ServicePtrs[idx]->szService );
1389 dbwrap_delete_bystring(ServiceHash, canon_name );
1390 TALLOC_FREE(canon_name);
1393 free_service(ServicePtrs[idx]);
1394 talloc_free_children(ServicePtrs[idx]);
1397 /***************************************************************************
1398 Add a new service to the services array initialising it with the given
1399 service.
1400 ***************************************************************************/
1402 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1404 int i;
1405 int num_to_alloc = iNumServices + 1;
1406 struct loadparm_service **tsp = NULL;
1408 /* it might already exist */
1409 if (name) {
1410 i = getservicebyname(name, NULL);
1411 if (i >= 0) {
1412 return (i);
1416 /* if not, then create one */
1417 i = iNumServices;
1418 tsp = talloc_realloc(NULL, ServicePtrs, struct loadparm_service *, num_to_alloc);
1419 if (tsp == NULL) {
1420 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1421 return (-1);
1423 ServicePtrs = tsp;
1424 ServicePtrs[iNumServices] = talloc_zero(NULL, struct loadparm_service);
1425 if (!ServicePtrs[iNumServices]) {
1426 DEBUG(0,("add_a_service: out of memory!\n"));
1427 return (-1);
1429 iNumServices++;
1431 ServicePtrs[i]->valid = true;
1433 copy_service(ServicePtrs[i], pservice, NULL);
1434 if (name)
1435 string_set(ServicePtrs[i], &ServicePtrs[i]->szService, name);
1437 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1438 i, ServicePtrs[i]->szService));
1440 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1441 return (-1);
1444 return (i);
1447 /***************************************************************************
1448 Convert a string to uppercase and remove whitespaces.
1449 ***************************************************************************/
1451 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1453 char *result;
1455 if ( !src ) {
1456 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1457 return NULL;
1460 result = talloc_strdup(ctx, src);
1461 SMB_ASSERT(result != NULL);
1463 if (!strlower_m(result)) {
1464 TALLOC_FREE(result);
1465 return NULL;
1467 return result;
1470 /***************************************************************************
1471 Add a name/index pair for the services array to the hash table.
1472 ***************************************************************************/
1474 static bool hash_a_service(const char *name, int idx)
1476 char *canon_name;
1478 if ( !ServiceHash ) {
1479 DEBUG(10,("hash_a_service: creating servicehash\n"));
1480 ServiceHash = db_open_rbt(NULL);
1481 if ( !ServiceHash ) {
1482 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1483 return false;
1487 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1488 idx, name));
1490 canon_name = canonicalize_servicename(talloc_tos(), name );
1492 dbwrap_store_bystring(ServiceHash, canon_name,
1493 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1494 TDB_REPLACE);
1496 TALLOC_FREE(canon_name);
1498 return true;
1501 /***************************************************************************
1502 Add a new home service, with the specified home directory, defaults coming
1503 from service ifrom.
1504 ***************************************************************************/
1506 bool lp_add_home(const char *pszHomename, int iDefaultService,
1507 const char *user, const char *pszHomedir)
1509 int i;
1511 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1512 pszHomedir[0] == '\0') {
1513 return false;
1516 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1518 if (i < 0)
1519 return false;
1521 if (!(*(ServicePtrs[iDefaultService]->path))
1522 || strequal(ServicePtrs[iDefaultService]->path,
1523 lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1524 string_set(ServicePtrs[i], &ServicePtrs[i]->path, pszHomedir);
1527 if (!(*(ServicePtrs[i]->comment))) {
1528 char *comment = talloc_asprintf(talloc_tos(), "Home directory of %s", user);
1529 if (comment == NULL) {
1530 return false;
1532 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1533 TALLOC_FREE(comment);
1536 /* set the browseable flag from the global default */
1538 ServicePtrs[i]->browseable = sDefault.browseable;
1539 ServicePtrs[i]->access_based_share_enum = sDefault.access_based_share_enum;
1541 ServicePtrs[i]->autoloaded = true;
1543 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1544 user, ServicePtrs[i]->path ));
1546 return true;
1549 /***************************************************************************
1550 Add a new service, based on an old one.
1551 ***************************************************************************/
1553 int lp_add_service(const char *pszService, int iDefaultService)
1555 if (iDefaultService < 0) {
1556 return add_a_service(&sDefault, pszService);
1559 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1562 /***************************************************************************
1563 Add the IPC service.
1564 ***************************************************************************/
1566 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1568 char *comment = NULL;
1569 int i = add_a_service(&sDefault, ipc_name);
1571 if (i < 0)
1572 return false;
1574 comment = talloc_asprintf(talloc_tos(), "IPC Service (%s)",
1575 Globals.server_string);
1576 if (comment == NULL) {
1577 return false;
1580 string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
1581 string_set(ServicePtrs[i], &ServicePtrs[i]->username, "");
1582 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1583 string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
1584 ServicePtrs[i]->max_connections = 0;
1585 ServicePtrs[i]->bAvailable = true;
1586 ServicePtrs[i]->read_only = true;
1587 ServicePtrs[i]->guest_only = false;
1588 ServicePtrs[i]->administrative_share = true;
1589 ServicePtrs[i]->guest_ok = guest_ok;
1590 ServicePtrs[i]->printable = false;
1591 ServicePtrs[i]->browseable = sDefault.browseable;
1593 DEBUG(3, ("adding IPC service\n"));
1595 TALLOC_FREE(comment);
1596 return true;
1599 /***************************************************************************
1600 Add a new printer service, with defaults coming from service iFrom.
1601 ***************************************************************************/
1603 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1605 const char *comment = "From Printcap";
1606 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1608 if (i < 0)
1609 return false;
1611 /* note that we do NOT default the availability flag to true - */
1612 /* we take it from the default service passed. This allows all */
1613 /* dynamic printers to be disabled by disabling the [printers] */
1614 /* entry (if/when the 'available' keyword is implemented!). */
1616 /* the printer name is set to the service name. */
1617 string_set(ServicePtrs[i], &ServicePtrs[i]->_printername, pszPrintername);
1618 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1620 /* set the browseable flag from the gloabl default */
1621 ServicePtrs[i]->browseable = sDefault.browseable;
1623 /* Printers cannot be read_only. */
1624 ServicePtrs[i]->read_only = false;
1625 /* No oplocks on printer services. */
1626 ServicePtrs[i]->oplocks = false;
1627 /* Printer services must be printable. */
1628 ServicePtrs[i]->printable = true;
1630 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1632 return true;
1636 /***************************************************************************
1637 Check whether the given parameter name is valid.
1638 Parametric options (names containing a colon) are considered valid.
1639 ***************************************************************************/
1641 bool lp_parameter_is_valid(const char *pszParmName)
1643 return ((lpcfg_map_parameter(pszParmName) != -1) ||
1644 (strchr(pszParmName, ':') != NULL));
1647 /***************************************************************************
1648 Check whether the given name is the name of a global parameter.
1649 Returns true for strings belonging to parameters of class
1650 P_GLOBAL, false for all other strings, also for parametric options
1651 and strings not belonging to any option.
1652 ***************************************************************************/
1654 bool lp_parameter_is_global(const char *pszParmName)
1656 int num = lpcfg_map_parameter(pszParmName);
1658 if (num >= 0) {
1659 return (parm_table[num].p_class == P_GLOBAL);
1662 return false;
1665 /**************************************************************************
1666 Check whether the given name is the canonical name of a parameter.
1667 Returns false if it is not a valid parameter Name.
1668 For parametric options, true is returned.
1669 **************************************************************************/
1671 bool lp_parameter_is_canonical(const char *parm_name)
1673 if (!lp_parameter_is_valid(parm_name)) {
1674 return false;
1677 return (lpcfg_map_parameter(parm_name) ==
1678 map_parameter_canonical(parm_name, NULL));
1681 /**************************************************************************
1682 Determine the canonical name for a parameter.
1683 Indicate when it is an inverse (boolean) synonym instead of a
1684 "usual" synonym.
1685 **************************************************************************/
1687 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1688 bool *inverse)
1690 int num;
1692 if (!lp_parameter_is_valid(parm_name)) {
1693 *canon_parm = NULL;
1694 return false;
1697 num = map_parameter_canonical(parm_name, inverse);
1698 if (num < 0) {
1699 /* parametric option */
1700 *canon_parm = parm_name;
1701 } else {
1702 *canon_parm = parm_table[num].label;
1705 return true;
1709 /**************************************************************************
1710 Determine the canonical name for a parameter.
1711 Turn the value given into the inverse boolean expression when
1712 the synonym is an invers boolean synonym.
1714 Return true if parm_name is a valid parameter name and
1715 in case it is an invers boolean synonym, if the val string could
1716 successfully be converted to the reverse bool.
1717 Return false in all other cases.
1718 **************************************************************************/
1720 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1721 const char *val,
1722 const char **canon_parm,
1723 const char **canon_val)
1725 int num;
1726 bool inverse;
1728 if (!lp_parameter_is_valid(parm_name)) {
1729 *canon_parm = NULL;
1730 *canon_val = NULL;
1731 return false;
1734 num = map_parameter_canonical(parm_name, &inverse);
1735 if (num < 0) {
1736 /* parametric option */
1737 *canon_parm = parm_name;
1738 *canon_val = val;
1739 } else {
1740 *canon_parm = parm_table[num].label;
1741 if (inverse) {
1742 if (!lp_invert_boolean(val, canon_val)) {
1743 *canon_val = NULL;
1744 return false;
1746 } else {
1747 *canon_val = val;
1751 return true;
1754 /***************************************************************************
1755 Map a parameter's string representation to the index of the canonical
1756 form of the parameter (it might be a synonym).
1757 Returns -1 if the parameter string is not recognised.
1758 ***************************************************************************/
1760 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1762 int parm_num, canon_num;
1763 bool loc_inverse = false;
1765 parm_num = lpcfg_map_parameter(pszParmName);
1766 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1767 /* invalid, parametric or no canidate for synonyms ... */
1768 goto done;
1771 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1772 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1773 parm_num = canon_num;
1774 goto done;
1778 done:
1779 if (inverse != NULL) {
1780 *inverse = loc_inverse;
1782 return parm_num;
1785 /***************************************************************************
1786 return true if parameter number parm1 is a synonym of parameter
1787 number parm2 (parm2 being the principal name).
1788 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1789 false otherwise.
1790 ***************************************************************************/
1792 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
1794 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
1795 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
1796 (parm_table[parm1].flags & FLAG_HIDE) &&
1797 !(parm_table[parm2].flags & FLAG_HIDE))
1799 if (inverse != NULL) {
1800 if ((parm_table[parm1].type == P_BOOLREV) &&
1801 (parm_table[parm2].type == P_BOOL))
1803 *inverse = true;
1804 } else {
1805 *inverse = false;
1808 return true;
1810 return false;
1813 /***************************************************************************
1814 Show one parameter's name, type, [values,] and flags.
1815 (helper functions for show_parameter_list)
1816 ***************************************************************************/
1818 static void show_parameter(int parmIndex)
1820 int enumIndex, flagIndex;
1821 int parmIndex2;
1822 bool hadFlag;
1823 bool hadSyn;
1824 bool inverse;
1825 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
1826 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
1827 "P_ENUM", "P_SEP"};
1828 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
1829 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
1830 FLAG_HIDE};
1831 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
1832 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
1833 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
1835 printf("%s=%s", parm_table[parmIndex].label,
1836 type[parm_table[parmIndex].type]);
1837 if (parm_table[parmIndex].type == P_ENUM) {
1838 printf(",");
1839 for (enumIndex=0;
1840 parm_table[parmIndex].enum_list[enumIndex].name;
1841 enumIndex++)
1843 printf("%s%s",
1844 enumIndex ? "|" : "",
1845 parm_table[parmIndex].enum_list[enumIndex].name);
1848 printf(",");
1849 hadFlag = false;
1850 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
1851 if (parm_table[parmIndex].flags & flags[flagIndex]) {
1852 printf("%s%s",
1853 hadFlag ? "|" : "",
1854 flag_names[flagIndex]);
1855 hadFlag = true;
1859 /* output synonyms */
1860 hadSyn = false;
1861 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
1862 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
1863 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
1864 parm_table[parmIndex2].label);
1865 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
1866 if (!hadSyn) {
1867 printf(" (synonyms: ");
1868 hadSyn = true;
1869 } else {
1870 printf(", ");
1872 printf("%s%s", parm_table[parmIndex2].label,
1873 inverse ? "[i]" : "");
1876 if (hadSyn) {
1877 printf(")");
1880 printf("\n");
1883 /***************************************************************************
1884 Show all parameter's name, type, [values,] and flags.
1885 ***************************************************************************/
1887 void show_parameter_list(void)
1889 int classIndex, parmIndex;
1890 const char *section_names[] = { "local", "global", NULL};
1892 for (classIndex=0; section_names[classIndex]; classIndex++) {
1893 printf("[%s]\n", section_names[classIndex]);
1894 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
1895 if (parm_table[parmIndex].p_class == classIndex) {
1896 show_parameter(parmIndex);
1902 /***************************************************************************
1903 Get the standard string representation of a boolean value ("yes" or "no")
1904 ***************************************************************************/
1906 static const char *get_boolean(bool bool_value)
1908 static const char *yes_str = "yes";
1909 static const char *no_str = "no";
1911 return (bool_value ? yes_str : no_str);
1914 /***************************************************************************
1915 Provide the string of the negated boolean value associated to the boolean
1916 given as a string. Returns false if the passed string does not correctly
1917 represent a boolean.
1918 ***************************************************************************/
1920 bool lp_invert_boolean(const char *str, const char **inverse_str)
1922 bool val;
1924 if (!set_boolean(str, &val)) {
1925 return false;
1928 *inverse_str = get_boolean(!val);
1929 return true;
1932 /***************************************************************************
1933 Provide the canonical string representation of a boolean value given
1934 as a string. Return true on success, false if the string given does
1935 not correctly represent a boolean.
1936 ***************************************************************************/
1938 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
1940 bool val;
1942 if (!set_boolean(str, &val)) {
1943 return false;
1946 *canon_str = get_boolean(val);
1947 return true;
1950 /***************************************************************************
1951 Find a service by name. Otherwise works like get_service.
1952 ***************************************************************************/
1954 int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
1956 int iService = -1;
1957 char *canon_name;
1958 TDB_DATA data;
1959 NTSTATUS status;
1961 if (ServiceHash == NULL) {
1962 return -1;
1965 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
1967 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
1968 &data);
1970 if (NT_STATUS_IS_OK(status) &&
1971 (data.dptr != NULL) &&
1972 (data.dsize == sizeof(iService)))
1974 iService = *(int *)data.dptr;
1977 TALLOC_FREE(canon_name);
1979 if ((iService != -1) && (LP_SNUM_OK(iService))
1980 && (pserviceDest != NULL)) {
1981 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1984 return (iService);
1987 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
1988 struct loadparm_service *lp_service(const char *pszServiceName)
1990 int iService = getservicebyname(pszServiceName, NULL);
1991 if (iService == -1 || !LP_SNUM_OK(iService)) {
1992 return NULL;
1994 return ServicePtrs[iService];
1997 struct loadparm_service *lp_servicebynum(int snum)
1999 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2000 return NULL;
2002 return ServicePtrs[snum];
2005 struct loadparm_service *lp_default_loadparm_service()
2007 return &sDefault;
2010 /***************************************************************************
2011 Check a service for consistency. Return false if the service is in any way
2012 incomplete or faulty, else true.
2013 ***************************************************************************/
2015 bool service_ok(int iService)
2017 bool bRetval;
2019 bRetval = true;
2020 if (ServicePtrs[iService]->szService[0] == '\0') {
2021 DEBUG(0, ("The following message indicates an internal error:\n"));
2022 DEBUG(0, ("No service name in service entry.\n"));
2023 bRetval = false;
2026 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2027 /* I can't see why you'd want a non-printable printer service... */
2028 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2029 if (!ServicePtrs[iService]->printable) {
2030 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2031 ServicePtrs[iService]->szService));
2032 ServicePtrs[iService]->printable = true;
2034 /* [printers] service must also be non-browsable. */
2035 if (ServicePtrs[iService]->browseable)
2036 ServicePtrs[iService]->browseable = false;
2039 if (ServicePtrs[iService]->path[0] == '\0' &&
2040 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2041 ServicePtrs[iService]->msdfs_proxy[0] == '\0'
2043 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2044 ServicePtrs[iService]->szService));
2045 ServicePtrs[iService]->bAvailable = false;
2048 /* If a service is flagged unavailable, log the fact at level 1. */
2049 if (!ServicePtrs[iService]->bAvailable)
2050 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2051 ServicePtrs[iService]->szService));
2053 return (bRetval);
2056 static struct smbconf_ctx *lp_smbconf_ctx(void)
2058 sbcErr err;
2059 static struct smbconf_ctx *conf_ctx = NULL;
2061 if (conf_ctx == NULL) {
2062 err = smbconf_init(NULL, &conf_ctx, "registry:");
2063 if (!SBC_ERROR_IS_OK(err)) {
2064 DEBUG(1, ("error initializing registry configuration: "
2065 "%s\n", sbcErrorString(err)));
2066 conf_ctx = NULL;
2070 return conf_ctx;
2073 static bool process_smbconf_service(struct smbconf_service *service)
2075 uint32_t count;
2076 bool ret;
2078 if (service == NULL) {
2079 return false;
2082 ret = lp_do_section(service->name, NULL);
2083 if (ret != true) {
2084 return false;
2086 for (count = 0; count < service->num_params; count++) {
2088 if (!bInGlobalSection && bGlobalOnly) {
2089 ret = true;
2090 } else {
2091 const char *pszParmName = service->param_names[count];
2092 const char *pszParmValue = service->param_values[count];
2094 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2096 ret = lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2097 pszParmName, pszParmValue);
2100 if (ret != true) {
2101 return false;
2104 if (iServiceIndex >= 0) {
2105 return service_ok(iServiceIndex);
2107 return true;
2111 * load a service from registry and activate it
2113 bool process_registry_service(const char *service_name)
2115 sbcErr err;
2116 struct smbconf_service *service = NULL;
2117 TALLOC_CTX *mem_ctx = talloc_stackframe();
2118 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2119 bool ret = false;
2121 if (conf_ctx == NULL) {
2122 goto done;
2125 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2127 if (!smbconf_share_exists(conf_ctx, service_name)) {
2129 * Registry does not contain data for this service (yet),
2130 * but make sure lp_load doesn't return false.
2132 ret = true;
2133 goto done;
2136 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2137 if (!SBC_ERROR_IS_OK(err)) {
2138 goto done;
2141 ret = process_smbconf_service(service);
2142 if (!ret) {
2143 goto done;
2146 /* store the csn */
2147 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2149 done:
2150 TALLOC_FREE(mem_ctx);
2151 return ret;
2155 * process_registry_globals
2157 static bool process_registry_globals(void)
2159 bool ret;
2161 add_to_file_list(NULL, &file_lists, INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2163 if (!bInGlobalSection && bGlobalOnly) {
2164 ret = true;
2165 } else {
2166 const char *pszParmName = "registry shares";
2167 const char *pszParmValue = "yes";
2169 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2171 ret = lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2172 pszParmName, pszParmValue);
2175 if (!ret) {
2176 return ret;
2179 return process_registry_service(GLOBAL_NAME);
2182 bool process_registry_shares(void)
2184 sbcErr err;
2185 uint32_t count;
2186 struct smbconf_service **service = NULL;
2187 uint32_t num_shares = 0;
2188 TALLOC_CTX *mem_ctx = talloc_stackframe();
2189 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2190 bool ret = false;
2192 if (conf_ctx == NULL) {
2193 goto done;
2196 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2197 if (!SBC_ERROR_IS_OK(err)) {
2198 goto done;
2201 ret = true;
2203 for (count = 0; count < num_shares; count++) {
2204 if (strequal(service[count]->name, GLOBAL_NAME)) {
2205 continue;
2207 ret = process_smbconf_service(service[count]);
2208 if (!ret) {
2209 goto done;
2213 /* store the csn */
2214 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2216 done:
2217 TALLOC_FREE(mem_ctx);
2218 return ret;
2222 * reload those shares from registry that are already
2223 * activated in the services array.
2225 static bool reload_registry_shares(void)
2227 int i;
2228 bool ret = true;
2230 for (i = 0; i < iNumServices; i++) {
2231 if (!VALID(i)) {
2232 continue;
2235 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2236 continue;
2239 ret = process_registry_service(ServicePtrs[i]->szService);
2240 if (!ret) {
2241 goto done;
2245 done:
2246 return ret;
2250 #define MAX_INCLUDE_DEPTH 100
2252 static uint8_t include_depth;
2255 * Free the file lists
2257 static void free_file_list(void)
2259 struct file_lists *f;
2260 struct file_lists *next;
2262 f = file_lists;
2263 while( f ) {
2264 next = f->next;
2265 TALLOC_FREE( f );
2266 f = next;
2268 file_lists = NULL;
2273 * Utility function for outsiders to check if we're running on registry.
2275 bool lp_config_backend_is_registry(void)
2277 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2281 * Utility function to check if the config backend is FILE.
2283 bool lp_config_backend_is_file(void)
2285 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2288 /*******************************************************************
2289 Check if a config file has changed date.
2290 ********************************************************************/
2292 bool lp_file_list_changed(void)
2294 struct file_lists *f = file_lists;
2296 DEBUG(6, ("lp_file_list_changed()\n"));
2298 while (f) {
2299 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2300 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2302 if (conf_ctx == NULL) {
2303 return false;
2305 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2306 NULL))
2308 DEBUGADD(6, ("registry config changed\n"));
2309 return true;
2311 } else {
2312 time_t mod_time;
2313 char *n2 = NULL;
2315 n2 = talloc_sub_basic(talloc_tos(),
2316 get_current_username(),
2317 current_user_info.domain,
2318 f->name);
2319 if (!n2) {
2320 return false;
2322 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2323 f->name, n2, ctime(&f->modtime)));
2325 mod_time = file_modtime(n2);
2327 if (mod_time &&
2328 ((f->modtime != mod_time) ||
2329 (f->subfname == NULL) ||
2330 (strcmp(n2, f->subfname) != 0)))
2332 DEBUGADD(6,
2333 ("file %s modified: %s\n", n2,
2334 ctime(&mod_time)));
2335 f->modtime = mod_time;
2336 TALLOC_FREE(f->subfname);
2337 f->subfname = talloc_strdup(f, n2);
2338 if (f->subfname == NULL) {
2339 smb_panic("talloc_strdup failed");
2341 TALLOC_FREE(n2);
2342 return true;
2344 TALLOC_FREE(n2);
2346 f = f->next;
2348 return false;
2353 * Initialize iconv conversion descriptors.
2355 * This is called the first time it is needed, and also called again
2356 * every time the configuration is reloaded, because the charset or
2357 * codepage might have changed.
2359 static void init_iconv(void)
2361 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2362 lp_unix_charset(),
2363 true, global_iconv_handle);
2366 /***************************************************************************
2367 Handle the include operation.
2368 ***************************************************************************/
2369 static bool bAllowIncludeRegistry = true;
2371 bool lp_include(struct loadparm_context *lp_ctx, struct loadparm_service *service,
2372 const char *pszParmValue, char **ptr)
2374 char *fname;
2376 if (include_depth >= MAX_INCLUDE_DEPTH) {
2377 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2378 include_depth));
2379 return false;
2382 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2383 if (!bAllowIncludeRegistry) {
2384 return true;
2386 if (lp_ctx->bInGlobalSection) {
2387 bool ret;
2388 include_depth++;
2389 ret = process_registry_globals();
2390 include_depth--;
2391 return ret;
2392 } else {
2393 DEBUG(1, ("\"include = registry\" only effective "
2394 "in %s section\n", GLOBAL_NAME));
2395 return false;
2399 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2400 current_user_info.domain,
2401 pszParmValue);
2403 add_to_file_list(NULL, &file_lists, pszParmValue, fname);
2405 if (service == NULL) {
2406 string_set(Globals.ctx, ptr, fname);
2407 } else {
2408 string_set(service, ptr, fname);
2411 if (file_exist(fname)) {
2412 bool ret;
2413 include_depth++;
2414 ret = pm_process(fname, lp_do_section, do_parameter, lp_ctx);
2415 include_depth--;
2416 TALLOC_FREE(fname);
2417 return ret;
2420 DEBUG(2, ("Can't find include file %s\n", fname));
2421 TALLOC_FREE(fname);
2422 return true;
2425 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2427 char *config_option = NULL;
2428 const char *range = NULL;
2429 bool ret = false;
2431 SMB_ASSERT(low != NULL);
2432 SMB_ASSERT(high != NULL);
2434 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2435 domain_name = "*";
2438 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2439 domain_name);
2440 if (config_option == NULL) {
2441 DEBUG(0, ("out of memory\n"));
2442 return false;
2445 range = lp_parm_const_string(-1, config_option, "range", NULL);
2446 if (range == NULL) {
2447 DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2448 goto done;
2451 if (sscanf(range, "%u - %u", low, high) != 2) {
2452 DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2453 range, domain_name));
2454 goto done;
2457 ret = true;
2459 done:
2460 talloc_free(config_option);
2461 return ret;
2465 bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2467 return lp_idmap_range("*", low, high);
2470 const char *lp_idmap_backend(const char *domain_name)
2472 char *config_option = NULL;
2473 const char *backend = NULL;
2475 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2476 domain_name = "*";
2479 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2480 domain_name);
2481 if (config_option == NULL) {
2482 DEBUG(0, ("out of memory\n"));
2483 return false;
2486 backend = lp_parm_const_string(-1, config_option, "backend", NULL);
2487 if (backend == NULL) {
2488 DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
2489 goto done;
2492 done:
2493 talloc_free(config_option);
2494 return backend;
2497 const char *lp_idmap_default_backend(void)
2499 return lp_idmap_backend("*");
2502 /***************************************************************************
2503 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2504 ***************************************************************************/
2506 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2508 const char *suffix_string;
2510 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2511 Globals.ldap_suffix );
2512 if ( !suffix_string ) {
2513 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2514 return "";
2517 return suffix_string;
2520 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2522 if (Globals.szLdapMachineSuffix[0])
2523 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
2525 return lp_string(ctx, Globals.ldap_suffix);
2528 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
2530 if (Globals.szLdapUserSuffix[0])
2531 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
2533 return lp_string(ctx, Globals.ldap_suffix);
2536 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
2538 if (Globals.szLdapGroupSuffix[0])
2539 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
2541 return lp_string(ctx, Globals.ldap_suffix);
2544 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
2546 if (Globals.szLdapIdmapSuffix[0])
2547 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
2549 return lp_string(ctx, Globals.ldap_suffix);
2553 return the parameter pointer for a parameter
2555 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
2557 if (service == NULL) {
2558 if (parm->p_class == P_LOCAL)
2559 return (void *)(((char *)&sDefault)+parm->offset);
2560 else if (parm->p_class == P_GLOBAL)
2561 return (void *)(((char *)&Globals)+parm->offset);
2562 else return NULL;
2563 } else {
2564 return (void *)(((char *)service) + parm->offset);
2568 /***************************************************************************
2569 Process a parameter for a particular service number. If snum < 0
2570 then assume we are in the globals.
2571 ***************************************************************************/
2573 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
2575 int parmnum, i;
2576 void *parm_ptr = NULL; /* where we are going to store the result */
2577 struct parmlist_entry **opt_list;
2578 TALLOC_CTX *mem_ctx;
2579 TALLOC_CTX *frame = talloc_stackframe();
2580 bool ok;
2581 struct loadparm_context *lp_ctx;
2582 struct loadparm_service *service = NULL;
2584 parmnum = lpcfg_map_parameter(pszParmName);
2586 if (parmnum < 0) {
2587 if (strchr(pszParmName, ':') == NULL) {
2588 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
2589 pszParmName));
2590 TALLOC_FREE(frame);
2591 return true;
2595 * We've got a parametric option
2598 if (snum < 0) {
2599 opt_list = &Globals.param_opt;
2600 set_param_opt(NULL, opt_list, pszParmName, pszParmValue, 0);
2601 } else {
2602 opt_list = &ServicePtrs[snum]->param_opt;
2603 set_param_opt(ServicePtrs[snum], opt_list, pszParmName, pszParmValue, 0);
2606 TALLOC_FREE(frame);
2607 return true;
2610 /* if it's already been set by the command line, then we don't
2611 override here */
2612 if (flags_list[parmnum] & FLAG_CMDLINE) {
2613 TALLOC_FREE(frame);
2614 return true;
2617 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
2618 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
2619 pszParmName));
2622 /* we might point at a service, the default service or a global */
2623 if (snum < 0) {
2624 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
2625 mem_ctx = Globals.ctx;
2626 } else {
2627 if (parm_table[parmnum].p_class == P_GLOBAL) {
2628 DEBUG(0,
2629 ("Global parameter %s found in service section!\n",
2630 pszParmName));
2631 TALLOC_FREE(frame);
2632 return true;
2634 parm_ptr = lp_parm_ptr(ServicePtrs[snum], &parm_table[parmnum]);
2636 if (!ServicePtrs[snum]->copymap)
2637 init_copymap(ServicePtrs[snum]);
2639 /* this handles the aliases - set the copymap for other entries with
2640 the same data pointer */
2641 for (i = 0; parm_table[i].label; i++) {
2642 if ((parm_table[i].offset == parm_table[parmnum].offset)
2643 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
2644 bitmap_clear(ServicePtrs[snum]->copymap, i);
2648 mem_ctx = ServicePtrs[snum];
2649 service = ServicePtrs[snum];
2652 lp_ctx = loadparm_init_s3(frame,
2653 loadparm_s3_helpers());
2654 if (lp_ctx == NULL) {
2655 DEBUG(0, ("loadparm_init_s3 failed\n"));
2656 TALLOC_FREE(frame);
2657 return false;
2660 lp_ctx->sDefault = &sDefault;
2661 lp_ctx->services = ServicePtrs;
2662 lp_ctx->bInGlobalSection = bInGlobalSection;
2663 lp_ctx->flags = flags_list;
2665 ok = set_variable(mem_ctx, service, parmnum, parm_ptr, pszParmName, pszParmValue,
2666 lp_ctx, (snum < 0));
2667 TALLOC_FREE(frame);
2669 return ok;
2672 /***************************************************************************
2673 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
2674 FLAG_CMDLINE won't be overridden by loads from smb.conf.
2675 ***************************************************************************/
2677 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue)
2679 int parmnum, i;
2680 parmnum = lpcfg_map_parameter(pszParmName);
2681 if (parmnum >= 0) {
2682 flags_list[parmnum] &= ~FLAG_CMDLINE;
2683 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
2684 return false;
2686 flags_list[parmnum] |= FLAG_CMDLINE;
2688 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
2689 * be grouped in the table, so we don't have to search the
2690 * whole table */
2691 for (i=parmnum-1;
2692 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
2693 && parm_table[i].p_class == parm_table[parmnum].p_class;
2694 i--) {
2695 flags_list[i] |= FLAG_CMDLINE;
2697 for (i=parmnum+1;i<num_parameters() && parm_table[i].offset == parm_table[parmnum].offset
2698 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
2699 flags_list[i] |= FLAG_CMDLINE;
2702 return true;
2705 /* it might be parametric */
2706 if (strchr(pszParmName, ':') != NULL) {
2707 set_param_opt(NULL, &Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
2708 return true;
2711 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2712 return false;
2715 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
2717 bool ret;
2718 TALLOC_CTX *frame = talloc_stackframe();
2719 struct loadparm_context *lp_ctx;
2721 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
2722 if (lp_ctx == NULL) {
2723 DEBUG(0, ("loadparm_init_s3 failed\n"));
2724 return false;
2727 ret = lpcfg_set_cmdline(lp_ctx, pszParmName, pszParmValue);
2729 TALLOC_FREE(frame);
2730 return ret;
2733 /***************************************************************************
2734 Process a parameter.
2735 ***************************************************************************/
2737 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
2738 void *userdata)
2740 if (!bInGlobalSection && bGlobalOnly)
2741 return true;
2743 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2745 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2746 pszParmName, pszParmValue));
2749 /***************************************************************************
2750 Initialize any local variables in the sDefault table, after parsing a
2751 [globals] section.
2752 ***************************************************************************/
2754 static void init_locals(void)
2757 * We run this check once the [globals] is parsed, to force
2758 * the VFS objects and other per-share settings we need for
2759 * the standard way a AD DC is operated. We may change these
2760 * as our code evolves, which is why we force these settings.
2762 * We can't do this at the end of lp_load_ex(), as by that
2763 * point the services have been loaded and they will already
2764 * have "" as their vfs objects.
2766 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
2767 const char **vfs_objects = lp_vfs_objects(-1);
2768 if (!vfs_objects || !vfs_objects[0]) {
2769 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
2770 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
2771 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
2772 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
2773 } else {
2774 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
2778 lp_do_parameter(-1, "map hidden", "no");
2779 lp_do_parameter(-1, "map system", "no");
2780 lp_do_parameter(-1, "map readonly", "no");
2781 lp_do_parameter(-1, "map archive", "no");
2782 lp_do_parameter(-1, "store dos attributes", "yes");
2786 /***************************************************************************
2787 Process a new section (service). At this stage all sections are services.
2788 Later we'll have special sections that permit server parameters to be set.
2789 Returns true on success, false on failure.
2790 ***************************************************************************/
2792 bool lp_do_section(const char *pszSectionName, void *userdata)
2794 bool bRetval;
2795 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2796 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2797 bRetval = false;
2799 /* if we were in a global section then do the local inits */
2800 if (bInGlobalSection && !isglobal)
2801 init_locals();
2803 /* if we've just struck a global section, note the fact. */
2804 bInGlobalSection = isglobal;
2806 /* check for multiple global sections */
2807 if (bInGlobalSection) {
2808 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2809 return true;
2812 if (!bInGlobalSection && bGlobalOnly)
2813 return true;
2815 /* if we have a current service, tidy it up before moving on */
2816 bRetval = true;
2818 if (iServiceIndex >= 0)
2819 bRetval = service_ok(iServiceIndex);
2821 /* if all is still well, move to the next record in the services array */
2822 if (bRetval) {
2823 /* We put this here to avoid an odd message order if messages are */
2824 /* issued by the post-processing of a previous section. */
2825 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2827 iServiceIndex = add_a_service(&sDefault, pszSectionName);
2828 if (iServiceIndex < 0) {
2829 DEBUG(0, ("Failed to add a new service\n"));
2830 return false;
2832 /* Clean all parametric options for service */
2833 /* They will be added during parsing again */
2834 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
2837 return bRetval;
2841 /***************************************************************************
2842 Determine if a partcular base parameter is currentl set to the default value.
2843 ***************************************************************************/
2845 static bool is_default(int i)
2847 switch (parm_table[i].type) {
2848 case P_LIST:
2849 case P_CMDLIST:
2850 return str_list_equal((const char * const *)parm_table[i].def.lvalue,
2851 *(const char ***)lp_parm_ptr(NULL,
2852 &parm_table[i]));
2853 case P_STRING:
2854 case P_USTRING:
2855 return strequal(parm_table[i].def.svalue,
2856 *(char **)lp_parm_ptr(NULL,
2857 &parm_table[i]));
2858 case P_BOOL:
2859 case P_BOOLREV:
2860 return parm_table[i].def.bvalue ==
2861 *(bool *)lp_parm_ptr(NULL,
2862 &parm_table[i]);
2863 case P_CHAR:
2864 return parm_table[i].def.cvalue ==
2865 *(char *)lp_parm_ptr(NULL,
2866 &parm_table[i]);
2867 case P_INTEGER:
2868 case P_OCTAL:
2869 case P_ENUM:
2870 case P_BYTES:
2871 return parm_table[i].def.ivalue ==
2872 *(int *)lp_parm_ptr(NULL,
2873 &parm_table[i]);
2874 case P_SEP:
2875 break;
2877 return false;
2880 /***************************************************************************
2881 Display the contents of the global structure.
2882 ***************************************************************************/
2884 static void dump_globals(FILE *f, bool show_defaults)
2886 int i;
2887 struct parmlist_entry *data;
2889 fprintf(f, "[global]\n");
2891 for (i = 0; parm_table[i].label; i++)
2892 if (parm_table[i].p_class == P_GLOBAL &&
2893 !(parm_table[i].flags & FLAG_META) &&
2894 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
2895 if (show_defaults && is_default(i))
2896 continue;
2897 fprintf(f, "\t%s = ", parm_table[i].label);
2898 lpcfg_print_parameter(&parm_table[i], lp_parm_ptr(NULL,
2899 &parm_table[i]),
2901 fprintf(f, "\n");
2903 if (Globals.param_opt != NULL) {
2904 data = Globals.param_opt;
2905 while(data) {
2906 if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
2907 data = data->next;
2908 continue;
2910 fprintf(f, "\t%s = %s\n", data->key, data->value);
2911 data = data->next;
2917 /***************************************************************************
2918 Display the contents of a parameter of a single services record.
2919 ***************************************************************************/
2921 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
2923 bool result = false;
2925 struct loadparm_context *lp_ctx;
2927 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
2928 if (lp_ctx == NULL) {
2929 return false;
2932 if (isGlobal) {
2933 result = lpcfg_dump_a_parameter(lp_ctx, NULL, parm_name, f);
2934 } else {
2935 result = lpcfg_dump_a_parameter(lp_ctx, ServicePtrs[snum], parm_name, f);
2937 TALLOC_FREE(lp_ctx);
2938 return result;
2941 /***************************************************************************
2942 Return info about the requested parameter (given as a string).
2943 Return NULL when the string is not a valid parameter name.
2944 ***************************************************************************/
2946 struct parm_struct *lp_get_parameter(const char *param_name)
2948 int num = lpcfg_map_parameter(param_name);
2950 if (num < 0) {
2951 return NULL;
2954 return &parm_table[num];
2957 #if 0
2958 /***************************************************************************
2959 Display the contents of a single copy structure.
2960 ***************************************************************************/
2961 static void dump_copy_map(bool *pcopymap)
2963 int i;
2964 if (!pcopymap)
2965 return;
2967 printf("\n\tNon-Copied parameters:\n");
2969 for (i = 0; parm_table[i].label; i++)
2970 if (parm_table[i].p_class == P_LOCAL &&
2971 parm_table[i].ptr && !pcopymap[i] &&
2972 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
2974 printf("\t\t%s\n", parm_table[i].label);
2977 #endif
2979 /***************************************************************************
2980 Return TRUE if the passed service number is within range.
2981 ***************************************************************************/
2983 bool lp_snum_ok(int iService)
2985 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2988 /***************************************************************************
2989 Auto-load some home services.
2990 ***************************************************************************/
2992 static void lp_add_auto_services(char *str)
2994 char *s;
2995 char *p;
2996 int homes;
2997 char *saveptr;
2999 if (!str)
3000 return;
3002 s = talloc_strdup(talloc_tos(), str);
3003 if (!s) {
3004 smb_panic("talloc_strdup failed");
3005 return;
3008 homes = lp_servicenumber(HOMES_NAME);
3010 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3011 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3012 char *home;
3014 if (lp_servicenumber(p) >= 0)
3015 continue;
3017 home = get_user_home_dir(talloc_tos(), p);
3019 if (home && home[0] && homes >= 0)
3020 lp_add_home(p, homes, p, home);
3022 TALLOC_FREE(home);
3024 TALLOC_FREE(s);
3027 /***************************************************************************
3028 Auto-load one printer.
3029 ***************************************************************************/
3031 void lp_add_one_printer(const char *name, const char *comment,
3032 const char *location, void *pdata)
3034 int printers = lp_servicenumber(PRINTERS_NAME);
3035 int i;
3037 if (lp_servicenumber(name) < 0) {
3038 lp_add_printer(name, printers);
3039 if ((i = lp_servicenumber(name)) >= 0) {
3040 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
3041 ServicePtrs[i]->autoloaded = true;
3046 /***************************************************************************
3047 Have we loaded a services file yet?
3048 ***************************************************************************/
3050 bool lp_loaded(void)
3052 return (bLoaded);
3055 /***************************************************************************
3056 Unload unused services.
3057 ***************************************************************************/
3059 void lp_killunused(struct smbd_server_connection *sconn,
3060 bool (*snumused) (struct smbd_server_connection *, int))
3062 int i;
3063 for (i = 0; i < iNumServices; i++) {
3064 if (!VALID(i))
3065 continue;
3067 /* don't kill autoloaded or usershare services */
3068 if ( ServicePtrs[i]->autoloaded ||
3069 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3070 continue;
3073 if (!snumused || !snumused(sconn, i)) {
3074 free_service_byindex(i);
3080 * Kill all except autoloaded and usershare services - convenience wrapper
3082 void lp_kill_all_services(void)
3084 lp_killunused(NULL, NULL);
3087 /***************************************************************************
3088 Unload a service.
3089 ***************************************************************************/
3091 void lp_killservice(int iServiceIn)
3093 if (VALID(iServiceIn)) {
3094 free_service_byindex(iServiceIn);
3098 /***************************************************************************
3099 Save the curent values of all global and sDefault parameters into the
3100 defaults union. This allows testparm to show only the
3101 changed (ie. non-default) parameters.
3102 ***************************************************************************/
3104 static void lp_save_defaults(void)
3106 int i;
3107 struct parmlist_entry * parm;
3108 for (i = 0; parm_table[i].label; i++) {
3109 if (!(flags_list[i] & FLAG_CMDLINE)) {
3110 flags_list[i] |= FLAG_DEFAULT;
3113 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3114 && parm_table[i].p_class == parm_table[i - 1].p_class)
3115 continue;
3116 switch (parm_table[i].type) {
3117 case P_LIST:
3118 case P_CMDLIST:
3119 parm_table[i].def.lvalue = str_list_copy(
3120 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3121 break;
3122 case P_STRING:
3123 case P_USTRING:
3124 parm_table[i].def.svalue = talloc_strdup(Globals.ctx, *(char **)lp_parm_ptr(NULL, &parm_table[i]));
3125 if (parm_table[i].def.svalue == NULL) {
3126 smb_panic("talloc_strdup failed");
3128 break;
3129 case P_BOOL:
3130 case P_BOOLREV:
3131 parm_table[i].def.bvalue =
3132 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3133 break;
3134 case P_CHAR:
3135 parm_table[i].def.cvalue =
3136 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3137 break;
3138 case P_INTEGER:
3139 case P_OCTAL:
3140 case P_ENUM:
3141 case P_BYTES:
3142 parm_table[i].def.ivalue =
3143 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3144 break;
3145 case P_SEP:
3146 break;
3150 for (parm=Globals.param_opt; parm; parm=parm->next) {
3151 if (!(parm->priority & FLAG_CMDLINE)) {
3152 parm->priority |= FLAG_DEFAULT;
3156 for (parm=sDefault.param_opt; parm; parm=parm->next) {
3157 if (!(parm->priority & FLAG_CMDLINE)) {
3158 parm->priority |= FLAG_DEFAULT;
3162 defaults_saved = true;
3165 /***********************************************************
3166 If we should send plaintext/LANMAN passwords in the clinet
3167 ************************************************************/
3169 static void set_allowed_client_auth(void)
3171 if (Globals.client_ntlmv2_auth) {
3172 Globals.client_lanman_auth = false;
3174 if (!Globals.client_lanman_auth) {
3175 Globals.client_plaintext_auth = false;
3179 /***************************************************************************
3180 JRA.
3181 The following code allows smbd to read a user defined share file.
3182 Yes, this is my intent. Yes, I'm comfortable with that...
3184 THE FOLLOWING IS SECURITY CRITICAL CODE.
3186 It washes your clothes, it cleans your house, it guards you while you sleep...
3187 Do not f%^k with it....
3188 ***************************************************************************/
3190 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3192 /***************************************************************************
3193 Check allowed stat state of a usershare file.
3194 Ensure we print out who is dicking with us so the admin can
3195 get their sorry ass fired.
3196 ***************************************************************************/
3198 static bool check_usershare_stat(const char *fname,
3199 const SMB_STRUCT_STAT *psbuf)
3201 if (!S_ISREG(psbuf->st_ex_mode)) {
3202 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3203 "not a regular file\n",
3204 fname, (unsigned int)psbuf->st_ex_uid ));
3205 return false;
3208 /* Ensure this doesn't have the other write bit set. */
3209 if (psbuf->st_ex_mode & S_IWOTH) {
3210 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
3211 "public write. Refusing to allow as a usershare file.\n",
3212 fname, (unsigned int)psbuf->st_ex_uid ));
3213 return false;
3216 /* Should be 10k or less. */
3217 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
3218 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3219 "too large (%u) to be a user share file.\n",
3220 fname, (unsigned int)psbuf->st_ex_uid,
3221 (unsigned int)psbuf->st_ex_size ));
3222 return false;
3225 return true;
3228 /***************************************************************************
3229 Parse the contents of a usershare file.
3230 ***************************************************************************/
3232 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
3233 SMB_STRUCT_STAT *psbuf,
3234 const char *servicename,
3235 int snum,
3236 char **lines,
3237 int numlines,
3238 char **pp_sharepath,
3239 char **pp_comment,
3240 char **pp_cp_servicename,
3241 struct security_descriptor **ppsd,
3242 bool *pallow_guest)
3244 const char **prefixallowlist = lp_usershare_prefix_allow_list();
3245 const char **prefixdenylist = lp_usershare_prefix_deny_list();
3246 int us_vers;
3247 DIR *dp;
3248 SMB_STRUCT_STAT sbuf;
3249 char *sharepath = NULL;
3250 char *comment = NULL;
3252 *pp_sharepath = NULL;
3253 *pp_comment = NULL;
3255 *pallow_guest = false;
3257 if (numlines < 4) {
3258 return USERSHARE_MALFORMED_FILE;
3261 if (strcmp(lines[0], "#VERSION 1") == 0) {
3262 us_vers = 1;
3263 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
3264 us_vers = 2;
3265 if (numlines < 5) {
3266 return USERSHARE_MALFORMED_FILE;
3268 } else {
3269 return USERSHARE_BAD_VERSION;
3272 if (strncmp(lines[1], "path=", 5) != 0) {
3273 return USERSHARE_MALFORMED_PATH;
3276 sharepath = talloc_strdup(ctx, &lines[1][5]);
3277 if (!sharepath) {
3278 return USERSHARE_POSIX_ERR;
3280 trim_string(sharepath, " ", " ");
3282 if (strncmp(lines[2], "comment=", 8) != 0) {
3283 return USERSHARE_MALFORMED_COMMENT_DEF;
3286 comment = talloc_strdup(ctx, &lines[2][8]);
3287 if (!comment) {
3288 return USERSHARE_POSIX_ERR;
3290 trim_string(comment, " ", " ");
3291 trim_char(comment, '"', '"');
3293 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
3294 return USERSHARE_MALFORMED_ACL_DEF;
3297 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
3298 return USERSHARE_ACL_ERR;
3301 if (us_vers == 2) {
3302 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
3303 return USERSHARE_MALFORMED_ACL_DEF;
3305 if (lines[4][9] == 'y') {
3306 *pallow_guest = true;
3309 /* Backwards compatible extension to file version #2. */
3310 if (numlines > 5) {
3311 if (strncmp(lines[5], "sharename=", 10) != 0) {
3312 return USERSHARE_MALFORMED_SHARENAME_DEF;
3314 if (!strequal(&lines[5][10], servicename)) {
3315 return USERSHARE_BAD_SHARENAME;
3317 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
3318 if (!*pp_cp_servicename) {
3319 return USERSHARE_POSIX_ERR;
3324 if (*pp_cp_servicename == NULL) {
3325 *pp_cp_servicename = talloc_strdup(ctx, servicename);
3326 if (!*pp_cp_servicename) {
3327 return USERSHARE_POSIX_ERR;
3331 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->path) == 0)) {
3332 /* Path didn't change, no checks needed. */
3333 *pp_sharepath = sharepath;
3334 *pp_comment = comment;
3335 return USERSHARE_OK;
3338 /* The path *must* be absolute. */
3339 if (sharepath[0] != '/') {
3340 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
3341 servicename, sharepath));
3342 return USERSHARE_PATH_NOT_ABSOLUTE;
3345 /* If there is a usershare prefix deny list ensure one of these paths
3346 doesn't match the start of the user given path. */
3347 if (prefixdenylist) {
3348 int i;
3349 for ( i=0; prefixdenylist[i]; i++ ) {
3350 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
3351 servicename, i, prefixdenylist[i], sharepath ));
3352 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
3353 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
3354 "usershare prefix deny list entries.\n",
3355 servicename, sharepath));
3356 return USERSHARE_PATH_IS_DENIED;
3361 /* If there is a usershare prefix allow list ensure one of these paths
3362 does match the start of the user given path. */
3364 if (prefixallowlist) {
3365 int i;
3366 for ( i=0; prefixallowlist[i]; i++ ) {
3367 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
3368 servicename, i, prefixallowlist[i], sharepath ));
3369 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
3370 break;
3373 if (prefixallowlist[i] == NULL) {
3374 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
3375 "usershare prefix allow list entries.\n",
3376 servicename, sharepath));
3377 return USERSHARE_PATH_NOT_ALLOWED;
3381 /* Ensure this is pointing to a directory. */
3382 dp = opendir(sharepath);
3384 if (!dp) {
3385 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3386 servicename, sharepath));
3387 return USERSHARE_PATH_NOT_DIRECTORY;
3390 /* Ensure the owner of the usershare file has permission to share
3391 this directory. */
3393 if (sys_stat(sharepath, &sbuf, false) == -1) {
3394 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
3395 servicename, sharepath, strerror(errno) ));
3396 closedir(dp);
3397 return USERSHARE_POSIX_ERR;
3400 closedir(dp);
3402 if (!S_ISDIR(sbuf.st_ex_mode)) {
3403 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3404 servicename, sharepath ));
3405 return USERSHARE_PATH_NOT_DIRECTORY;
3408 /* Check if sharing is restricted to owner-only. */
3409 /* psbuf is the stat of the usershare definition file,
3410 sbuf is the stat of the target directory to be shared. */
3412 if (lp_usershare_owner_only()) {
3413 /* root can share anything. */
3414 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
3415 return USERSHARE_PATH_NOT_ALLOWED;
3419 *pp_sharepath = sharepath;
3420 *pp_comment = comment;
3421 return USERSHARE_OK;
3424 /***************************************************************************
3425 Deal with a usershare file.
3426 Returns:
3427 >= 0 - snum
3428 -1 - Bad name, invalid contents.
3429 - service name already existed and not a usershare, problem
3430 with permissions to share directory etc.
3431 ***************************************************************************/
3433 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
3435 SMB_STRUCT_STAT sbuf;
3436 SMB_STRUCT_STAT lsbuf;
3437 char *fname = NULL;
3438 char *sharepath = NULL;
3439 char *comment = NULL;
3440 char *cp_service_name = NULL;
3441 char **lines = NULL;
3442 int numlines = 0;
3443 int fd = -1;
3444 int iService = -1;
3445 TALLOC_CTX *ctx = talloc_stackframe();
3446 struct security_descriptor *psd = NULL;
3447 bool guest_ok = false;
3448 char *canon_name = NULL;
3449 bool added_service = false;
3450 int ret = -1;
3452 /* Ensure share name doesn't contain invalid characters. */
3453 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
3454 DEBUG(0,("process_usershare_file: share name %s contains "
3455 "invalid characters (any of %s)\n",
3456 file_name, INVALID_SHARENAME_CHARS ));
3457 goto out;
3460 canon_name = canonicalize_servicename(ctx, file_name);
3461 if (!canon_name) {
3462 goto out;
3465 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
3466 if (!fname) {
3467 goto out;
3470 /* Minimize the race condition by doing an lstat before we
3471 open and fstat. Ensure this isn't a symlink link. */
3473 if (sys_lstat(fname, &lsbuf, false) != 0) {
3474 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
3475 fname, strerror(errno) ));
3476 goto out;
3479 /* This must be a regular file, not a symlink, directory or
3480 other strange filetype. */
3481 if (!check_usershare_stat(fname, &lsbuf)) {
3482 goto out;
3486 TDB_DATA data;
3487 NTSTATUS status;
3489 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
3490 canon_name, &data);
3492 iService = -1;
3494 if (NT_STATUS_IS_OK(status) &&
3495 (data.dptr != NULL) &&
3496 (data.dsize == sizeof(iService))) {
3497 memcpy(&iService, data.dptr, sizeof(iService));
3501 if (iService != -1 &&
3502 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
3503 &lsbuf.st_ex_mtime) == 0) {
3504 /* Nothing changed - Mark valid and return. */
3505 DEBUG(10,("process_usershare_file: service %s not changed.\n",
3506 canon_name ));
3507 ServicePtrs[iService]->usershare = USERSHARE_VALID;
3508 ret = iService;
3509 goto out;
3512 /* Try and open the file read only - no symlinks allowed. */
3513 #ifdef O_NOFOLLOW
3514 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
3515 #else
3516 fd = open(fname, O_RDONLY, 0);
3517 #endif
3519 if (fd == -1) {
3520 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
3521 fname, strerror(errno) ));
3522 goto out;
3525 /* Now fstat to be *SURE* it's a regular file. */
3526 if (sys_fstat(fd, &sbuf, false) != 0) {
3527 close(fd);
3528 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
3529 fname, strerror(errno) ));
3530 goto out;
3533 /* Is it the same dev/inode as was lstated ? */
3534 if (!check_same_stat(&lsbuf, &sbuf)) {
3535 close(fd);
3536 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
3537 "Symlink spoofing going on ?\n", fname ));
3538 goto out;
3541 /* This must be a regular file, not a symlink, directory or
3542 other strange filetype. */
3543 if (!check_usershare_stat(fname, &sbuf)) {
3544 close(fd);
3545 goto out;
3548 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
3550 close(fd);
3551 if (lines == NULL) {
3552 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
3553 fname, (unsigned int)sbuf.st_ex_uid ));
3554 goto out;
3557 if (parse_usershare_file(ctx, &sbuf, file_name,
3558 iService, lines, numlines, &sharepath,
3559 &comment, &cp_service_name,
3560 &psd, &guest_ok) != USERSHARE_OK) {
3561 goto out;
3564 /* Everything ok - add the service possibly using a template. */
3565 if (iService < 0) {
3566 const struct loadparm_service *sp = &sDefault;
3567 if (snum_template != -1) {
3568 sp = ServicePtrs[snum_template];
3571 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
3572 DEBUG(0, ("process_usershare_file: Failed to add "
3573 "new service %s\n", cp_service_name));
3574 goto out;
3577 added_service = true;
3579 /* Read only is controlled by usershare ACL below. */
3580 ServicePtrs[iService]->read_only = false;
3583 /* Write the ACL of the new/modified share. */
3584 if (!set_share_security(canon_name, psd)) {
3585 DEBUG(0, ("process_usershare_file: Failed to set share "
3586 "security for user share %s\n",
3587 canon_name ));
3588 goto out;
3591 /* If from a template it may be marked invalid. */
3592 ServicePtrs[iService]->valid = true;
3594 /* Set the service as a valid usershare. */
3595 ServicePtrs[iService]->usershare = USERSHARE_VALID;
3597 /* Set guest access. */
3598 if (lp_usershare_allow_guests()) {
3599 ServicePtrs[iService]->guest_ok = guest_ok;
3602 /* And note when it was loaded. */
3603 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
3604 string_set(ServicePtrs[iService], &ServicePtrs[iService]->path, sharepath);
3605 string_set(ServicePtrs[iService], &ServicePtrs[iService]->comment, comment);
3607 ret = iService;
3609 out:
3611 if (ret == -1 && iService != -1 && added_service) {
3612 lp_remove_service(iService);
3615 TALLOC_FREE(lines);
3616 TALLOC_FREE(ctx);
3617 return ret;
3620 /***************************************************************************
3621 Checks if a usershare entry has been modified since last load.
3622 ***************************************************************************/
3624 static bool usershare_exists(int iService, struct timespec *last_mod)
3626 SMB_STRUCT_STAT lsbuf;
3627 const char *usersharepath = Globals.usershare_path;
3628 char *fname;
3630 fname = talloc_asprintf(talloc_tos(),
3631 "%s/%s",
3632 usersharepath,
3633 ServicePtrs[iService]->szService);
3634 if (fname == NULL) {
3635 return false;
3638 if (sys_lstat(fname, &lsbuf, false) != 0) {
3639 TALLOC_FREE(fname);
3640 return false;
3643 if (!S_ISREG(lsbuf.st_ex_mode)) {
3644 TALLOC_FREE(fname);
3645 return false;
3648 TALLOC_FREE(fname);
3649 *last_mod = lsbuf.st_ex_mtime;
3650 return true;
3653 /***************************************************************************
3654 Load a usershare service by name. Returns a valid servicenumber or -1.
3655 ***************************************************************************/
3657 int load_usershare_service(const char *servicename)
3659 SMB_STRUCT_STAT sbuf;
3660 const char *usersharepath = Globals.usershare_path;
3661 int max_user_shares = Globals.usershare_max_shares;
3662 int snum_template = -1;
3664 if (*usersharepath == 0 || max_user_shares == 0) {
3665 return -1;
3668 if (sys_stat(usersharepath, &sbuf, false) != 0) {
3669 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
3670 usersharepath, strerror(errno) ));
3671 return -1;
3674 if (!S_ISDIR(sbuf.st_ex_mode)) {
3675 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
3676 usersharepath ));
3677 return -1;
3681 * This directory must be owned by root, and have the 't' bit set.
3682 * It also must not be writable by "other".
3685 #ifdef S_ISVTX
3686 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
3687 #else
3688 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
3689 #endif
3690 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
3691 "or does not have the sticky bit 't' set or is writable by anyone.\n",
3692 usersharepath ));
3693 return -1;
3696 /* Ensure the template share exists if it's set. */
3697 if (Globals.usershare_template_share[0]) {
3698 /* We can't use lp_servicenumber here as we are recommending that
3699 template shares have -valid=false set. */
3700 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
3701 if (ServicePtrs[snum_template]->szService &&
3702 strequal(ServicePtrs[snum_template]->szService,
3703 Globals.usershare_template_share)) {
3704 break;
3708 if (snum_template == -1) {
3709 DEBUG(0,("load_usershare_service: usershare template share %s "
3710 "does not exist.\n",
3711 Globals.usershare_template_share ));
3712 return -1;
3716 return process_usershare_file(usersharepath, servicename, snum_template);
3719 /***************************************************************************
3720 Load all user defined shares from the user share directory.
3721 We only do this if we're enumerating the share list.
3722 This is the function that can delete usershares that have
3723 been removed.
3724 ***************************************************************************/
3726 int load_usershare_shares(struct smbd_server_connection *sconn,
3727 bool (*snumused) (struct smbd_server_connection *, int))
3729 DIR *dp;
3730 SMB_STRUCT_STAT sbuf;
3731 struct dirent *de;
3732 int num_usershares = 0;
3733 int max_user_shares = Globals.usershare_max_shares;
3734 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
3735 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
3736 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
3737 int iService;
3738 int snum_template = -1;
3739 const char *usersharepath = Globals.usershare_path;
3740 int ret = lp_numservices();
3741 TALLOC_CTX *tmp_ctx;
3743 if (max_user_shares == 0 || *usersharepath == '\0') {
3744 return lp_numservices();
3747 if (sys_stat(usersharepath, &sbuf, false) != 0) {
3748 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
3749 usersharepath, strerror(errno) ));
3750 return ret;
3754 * This directory must be owned by root, and have the 't' bit set.
3755 * It also must not be writable by "other".
3758 #ifdef S_ISVTX
3759 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
3760 #else
3761 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
3762 #endif
3763 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
3764 "or does not have the sticky bit 't' set or is writable by anyone.\n",
3765 usersharepath ));
3766 return ret;
3769 /* Ensure the template share exists if it's set. */
3770 if (Globals.usershare_template_share[0]) {
3771 /* We can't use lp_servicenumber here as we are recommending that
3772 template shares have -valid=false set. */
3773 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
3774 if (ServicePtrs[snum_template]->szService &&
3775 strequal(ServicePtrs[snum_template]->szService,
3776 Globals.usershare_template_share)) {
3777 break;
3781 if (snum_template == -1) {
3782 DEBUG(0,("load_usershare_shares: usershare template share %s "
3783 "does not exist.\n",
3784 Globals.usershare_template_share ));
3785 return ret;
3789 /* Mark all existing usershares as pending delete. */
3790 for (iService = iNumServices - 1; iService >= 0; iService--) {
3791 if (VALID(iService) && ServicePtrs[iService]->usershare) {
3792 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
3796 dp = opendir(usersharepath);
3797 if (!dp) {
3798 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
3799 usersharepath, strerror(errno) ));
3800 return ret;
3803 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
3804 (de = readdir(dp));
3805 num_dir_entries++ ) {
3806 int r;
3807 const char *n = de->d_name;
3809 /* Ignore . and .. */
3810 if (*n == '.') {
3811 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
3812 continue;
3816 if (n[0] == ':') {
3817 /* Temporary file used when creating a share. */
3818 num_tmp_dir_entries++;
3821 /* Allow 20% tmp entries. */
3822 if (num_tmp_dir_entries > allowed_tmp_entries) {
3823 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
3824 "in directory %s\n",
3825 num_tmp_dir_entries, usersharepath));
3826 break;
3829 r = process_usershare_file(usersharepath, n, snum_template);
3830 if (r == 0) {
3831 /* Update the services count. */
3832 num_usershares++;
3833 if (num_usershares >= max_user_shares) {
3834 DEBUG(0,("load_usershare_shares: max user shares reached "
3835 "on file %s in directory %s\n",
3836 n, usersharepath ));
3837 break;
3839 } else if (r == -1) {
3840 num_bad_dir_entries++;
3843 /* Allow 20% bad entries. */
3844 if (num_bad_dir_entries > allowed_bad_entries) {
3845 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
3846 "in directory %s\n",
3847 num_bad_dir_entries, usersharepath));
3848 break;
3851 /* Allow 20% bad entries. */
3852 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
3853 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
3854 "in directory %s\n",
3855 num_dir_entries, usersharepath));
3856 break;
3860 closedir(dp);
3862 /* Sweep through and delete any non-refreshed usershares that are
3863 not currently in use. */
3864 tmp_ctx = talloc_stackframe();
3865 for (iService = iNumServices - 1; iService >= 0; iService--) {
3866 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
3867 char *servname;
3869 if (snumused && snumused(sconn, iService)) {
3870 continue;
3873 servname = lp_servicename(tmp_ctx, iService);
3875 /* Remove from the share ACL db. */
3876 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
3877 servname ));
3878 delete_share_security(servname);
3879 free_service_byindex(iService);
3882 talloc_free(tmp_ctx);
3884 return lp_numservices();
3887 /********************************************************
3888 Destroy global resources allocated in this file
3889 ********************************************************/
3891 void gfree_loadparm(void)
3893 int i;
3895 free_file_list();
3897 /* Free resources allocated to services */
3899 for ( i = 0; i < iNumServices; i++ ) {
3900 if ( VALID(i) ) {
3901 free_service_byindex(i);
3905 TALLOC_FREE( ServicePtrs );
3906 iNumServices = 0;
3908 /* Now release all resources allocated to global
3909 parameters and the default service */
3911 free_global_parameters();
3915 /***************************************************************************
3916 Allow client apps to specify that they are a client
3917 ***************************************************************************/
3918 static void lp_set_in_client(bool b)
3920 in_client = b;
3924 /***************************************************************************
3925 Determine if we're running in a client app
3926 ***************************************************************************/
3927 static bool lp_is_in_client(void)
3929 return in_client;
3932 /***************************************************************************
3933 Load the services array from the services file. Return true on success,
3934 false on failure.
3935 ***************************************************************************/
3937 static bool lp_load_ex(const char *pszFname,
3938 bool global_only,
3939 bool save_defaults,
3940 bool add_ipc,
3941 bool initialize_globals,
3942 bool allow_include_registry,
3943 bool load_all_shares)
3945 char *n2 = NULL;
3946 bool bRetval;
3947 TALLOC_CTX *frame = talloc_stackframe();
3949 bRetval = false;
3951 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
3953 bInGlobalSection = true;
3954 bGlobalOnly = global_only;
3955 bAllowIncludeRegistry = allow_include_registry;
3957 init_globals(initialize_globals);
3959 free_file_list();
3961 if (save_defaults) {
3962 init_locals();
3963 lp_save_defaults();
3966 if (!initialize_globals) {
3967 free_param_opts(&Globals.param_opt);
3968 apply_lp_set_cmdline();
3971 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
3973 /* We get sections first, so have to start 'behind' to make up */
3974 iServiceIndex = -1;
3976 if (lp_config_backend_is_file()) {
3977 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
3978 current_user_info.domain,
3979 pszFname);
3980 if (!n2) {
3981 smb_panic("lp_load_ex: out of memory");
3984 add_to_file_list(NULL, &file_lists, pszFname, n2);
3986 bRetval = pm_process(n2, lp_do_section, do_parameter, NULL);
3987 TALLOC_FREE(n2);
3989 /* finish up the last section */
3990 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
3991 if (bRetval) {
3992 if (iServiceIndex >= 0) {
3993 bRetval = service_ok(iServiceIndex);
3997 if (lp_config_backend_is_registry()) {
3998 bool ok;
3999 /* config backend changed to registry in config file */
4001 * We need to use this extra global variable here to
4002 * survive restart: init_globals uses this as a default
4003 * for config_backend. Otherwise, init_globals would
4004 * send us into an endless loop here.
4006 config_backend = CONFIG_BACKEND_REGISTRY;
4007 /* start over */
4008 DEBUG(1, ("lp_load_ex: changing to config backend "
4009 "registry\n"));
4010 init_globals(true);
4011 lp_kill_all_services();
4012 ok = lp_load_ex(pszFname, global_only, save_defaults,
4013 add_ipc, initialize_globals,
4014 allow_include_registry,
4015 load_all_shares);
4016 TALLOC_FREE(frame);
4017 return ok;
4019 } else if (lp_config_backend_is_registry()) {
4020 bRetval = process_registry_globals();
4021 } else {
4022 DEBUG(0, ("Illegal config backend given: %d\n",
4023 lp_config_backend()));
4024 bRetval = false;
4027 if (bRetval && lp_registry_shares()) {
4028 if (load_all_shares) {
4029 bRetval = process_registry_shares();
4030 } else {
4031 bRetval = reload_registry_shares();
4036 char *serv = lp_auto_services(talloc_tos());
4037 lp_add_auto_services(serv);
4038 TALLOC_FREE(serv);
4041 if (add_ipc) {
4042 /* When 'restrict anonymous = 2' guest connections to ipc$
4043 are denied */
4044 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4045 if ( lp_enable_asu_support() ) {
4046 lp_add_ipc("ADMIN$", false);
4050 set_allowed_client_auth();
4052 if (lp_security() == SEC_ADS && strchr(lp_password_server(), ':')) {
4053 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4054 lp_password_server()));
4057 bLoaded = true;
4059 /* Now we check we_are_a_wins_server and set szWINSserver to 127.0.0.1 */
4060 /* if we_are_a_wins_server is true and we are in the client */
4061 if (lp_is_in_client() && Globals.we_are_a_wins_server) {
4062 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4065 init_iconv();
4067 fault_configure(smb_panic_s3);
4070 * We run this check once the whole smb.conf is parsed, to
4071 * force some settings for the standard way a AD DC is
4072 * operated. We may changed these as our code evolves, which
4073 * is why we force these settings.
4075 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4076 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4078 lp_do_parameter(-1, "winbindd:use external pipes", "true");
4080 lp_do_parameter(-1, "rpc_server:default", "external");
4081 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4082 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4083 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4084 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4085 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4086 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4087 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4088 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4091 bAllowIncludeRegistry = true;
4093 TALLOC_FREE(frame);
4094 return (bRetval);
4097 bool lp_load(const char *pszFname,
4098 bool global_only,
4099 bool save_defaults,
4100 bool add_ipc,
4101 bool initialize_globals)
4103 return lp_load_ex(pszFname,
4104 global_only,
4105 save_defaults,
4106 add_ipc,
4107 initialize_globals,
4108 true, /* allow_include_registry */
4109 false); /* load_all_shares*/
4112 bool lp_load_initial_only(const char *pszFname)
4114 return lp_load_ex(pszFname,
4115 true, /* global only */
4116 false, /* save_defaults */
4117 false, /* add_ipc */
4118 true, /* initialize_globals */
4119 false, /* allow_include_registry */
4120 false); /* load_all_shares*/
4124 * most common lp_load wrapper, loading only the globals
4126 bool lp_load_global(const char *file_name)
4128 return lp_load_ex(file_name,
4129 true, /* global_only */
4130 false, /* save_defaults */
4131 false, /* add_ipc */
4132 true, /* initialize_globals */
4133 true, /* allow_include_registry */
4134 false); /* load_all_shares*/
4138 * lp_load wrapper, especially for clients
4140 bool lp_load_client(const char *file_name)
4142 lp_set_in_client(true);
4144 return lp_load_global(file_name);
4148 * lp_load wrapper, loading only globals, but intended
4149 * for subsequent calls, not reinitializing the globals
4150 * to default values
4152 bool lp_load_global_no_reinit(const char *file_name)
4154 return lp_load_ex(file_name,
4155 true, /* global_only */
4156 false, /* save_defaults */
4157 false, /* add_ipc */
4158 false, /* initialize_globals */
4159 true, /* allow_include_registry */
4160 false); /* load_all_shares*/
4164 * lp_load wrapper, especially for clients, no reinitialization
4166 bool lp_load_client_no_reinit(const char *file_name)
4168 lp_set_in_client(true);
4170 return lp_load_global_no_reinit(file_name);
4173 bool lp_load_with_registry_shares(const char *pszFname,
4174 bool global_only,
4175 bool save_defaults,
4176 bool add_ipc,
4177 bool initialize_globals)
4179 return lp_load_ex(pszFname,
4180 global_only,
4181 save_defaults,
4182 add_ipc,
4183 initialize_globals,
4184 true, /* allow_include_registry */
4185 true); /* load_all_shares*/
4188 /***************************************************************************
4189 Return the max number of services.
4190 ***************************************************************************/
4192 int lp_numservices(void)
4194 return (iNumServices);
4197 /***************************************************************************
4198 Display the contents of the services array in human-readable form.
4199 ***************************************************************************/
4201 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4203 int iService;
4205 if (show_defaults)
4206 defaults_saved = false;
4208 dump_globals(f, defaults_saved);
4210 lpcfg_dump_a_service(&sDefault, &sDefault, f, flags_list, show_defaults);
4212 for (iService = 0; iService < maxtoprint; iService++) {
4213 fprintf(f,"\n");
4214 lp_dump_one(f, show_defaults, iService);
4218 /***************************************************************************
4219 Display the contents of one service in human-readable form.
4220 ***************************************************************************/
4222 void lp_dump_one(FILE * f, bool show_defaults, int snum)
4224 if (VALID(snum)) {
4225 if (ServicePtrs[snum]->szService[0] == '\0')
4226 return;
4227 lpcfg_dump_a_service(ServicePtrs[snum], &sDefault, f,
4228 flags_list, show_defaults);
4232 /***************************************************************************
4233 Return the number of the service with the given name, or -1 if it doesn't
4234 exist. Note that this is a DIFFERENT ANIMAL from the internal function
4235 getservicebyname()! This works ONLY if all services have been loaded, and
4236 does not copy the found service.
4237 ***************************************************************************/
4239 int lp_servicenumber(const char *pszServiceName)
4241 int iService;
4242 fstring serviceName;
4244 if (!pszServiceName) {
4245 return GLOBAL_SECTION_SNUM;
4248 for (iService = iNumServices - 1; iService >= 0; iService--) {
4249 if (VALID(iService) && ServicePtrs[iService]->szService) {
4251 * The substitution here is used to support %U is
4252 * service names
4254 fstrcpy(serviceName, ServicePtrs[iService]->szService);
4255 standard_sub_basic(get_current_username(),
4256 current_user_info.domain,
4257 serviceName,sizeof(serviceName));
4258 if (strequal(serviceName, pszServiceName)) {
4259 break;
4264 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
4265 struct timespec last_mod;
4267 if (!usershare_exists(iService, &last_mod)) {
4268 /* Remove the share security tdb entry for it. */
4269 delete_share_security(lp_servicename(talloc_tos(), iService));
4270 /* Remove it from the array. */
4271 free_service_byindex(iService);
4272 /* Doesn't exist anymore. */
4273 return GLOBAL_SECTION_SNUM;
4276 /* Has it been modified ? If so delete and reload. */
4277 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4278 &last_mod) < 0) {
4279 /* Remove it from the array. */
4280 free_service_byindex(iService);
4281 /* and now reload it. */
4282 iService = load_usershare_service(pszServiceName);
4286 if (iService < 0) {
4287 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
4288 return GLOBAL_SECTION_SNUM;
4291 return (iService);
4294 /*******************************************************************
4295 A useful volume label function.
4296 ********************************************************************/
4298 const char *volume_label(TALLOC_CTX *ctx, int snum)
4300 char *ret;
4301 const char *label = lp_volume(ctx, snum);
4302 if (!*label) {
4303 label = lp_servicename(ctx, snum);
4306 /* This returns a 33 byte guarenteed null terminated string. */
4307 ret = talloc_strndup(ctx, label, 32);
4308 if (!ret) {
4309 return "";
4311 return ret;
4314 /*******************************************************************
4315 Get the default server type we will announce as via nmbd.
4316 ********************************************************************/
4318 int lp_default_server_announce(void)
4320 int default_server_announce = 0;
4321 default_server_announce |= SV_TYPE_WORKSTATION;
4322 default_server_announce |= SV_TYPE_SERVER;
4323 default_server_announce |= SV_TYPE_SERVER_UNIX;
4325 /* note that the flag should be set only if we have a
4326 printer service but nmbd doesn't actually load the
4327 services so we can't tell --jerry */
4329 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
4331 default_server_announce |= SV_TYPE_SERVER_NT;
4332 default_server_announce |= SV_TYPE_NT;
4334 switch (lp_server_role()) {
4335 case ROLE_DOMAIN_MEMBER:
4336 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
4337 break;
4338 case ROLE_DOMAIN_PDC:
4339 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
4340 break;
4341 case ROLE_DOMAIN_BDC:
4342 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
4343 break;
4344 case ROLE_STANDALONE:
4345 default:
4346 break;
4348 if (lp_time_server())
4349 default_server_announce |= SV_TYPE_TIME_SOURCE;
4351 if (lp_host_msdfs())
4352 default_server_announce |= SV_TYPE_DFS_SERVER;
4354 return default_server_announce;
4357 /***********************************************************
4358 If we are PDC then prefer us as DMB
4359 ************************************************************/
4361 bool lp_domain_master(void)
4363 if (Globals._domain_master == Auto)
4364 return (lp_server_role() == ROLE_DOMAIN_PDC);
4366 return (bool)Globals._domain_master;
4369 /***********************************************************
4370 If we are PDC then prefer us as DMB
4371 ************************************************************/
4373 static bool lp_domain_master_true_or_auto(void)
4375 if (Globals._domain_master) /* auto or yes */
4376 return true;
4378 return false;
4381 /***********************************************************
4382 If we are DMB then prefer us as LMB
4383 ************************************************************/
4385 bool lp_preferred_master(void)
4387 if (Globals.iPreferredMaster == Auto)
4388 return (lp_local_master() && lp_domain_master());
4390 return (bool)Globals.iPreferredMaster;
4393 /*******************************************************************
4394 Remove a service.
4395 ********************************************************************/
4397 void lp_remove_service(int snum)
4399 ServicePtrs[snum]->valid = false;
4402 const char *lp_printername(TALLOC_CTX *ctx, int snum)
4404 const char *ret = lp__printername(ctx, snum);
4405 if (ret == NULL || *ret == '\0') {
4406 ret = lp_const_servicename(snum);
4409 return ret;
4413 /***********************************************************
4414 Allow daemons such as winbindd to fix their logfile name.
4415 ************************************************************/
4417 void lp_set_logfile(const char *name)
4419 string_set(Globals.ctx, &Globals.logfile, name);
4420 debug_set_logfile(name);
4423 /*******************************************************************
4424 Return the max print jobs per queue.
4425 ********************************************************************/
4427 int lp_maxprintjobs(int snum)
4429 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
4430 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
4431 maxjobs = PRINT_MAX_JOBID - 1;
4433 return maxjobs;
4436 const char *lp_printcapname(void)
4438 if ((Globals.szPrintcapname != NULL) &&
4439 (Globals.szPrintcapname[0] != '\0'))
4440 return Globals.szPrintcapname;
4442 if (sDefault.printing == PRINT_CUPS) {
4443 return "cups";
4446 if (sDefault.printing == PRINT_BSD)
4447 return "/etc/printcap";
4449 return PRINTCAP_NAME;
4452 static uint32 spoolss_state;
4454 bool lp_disable_spoolss( void )
4456 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
4457 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
4459 return spoolss_state == SVCCTL_STOPPED ? true : false;
4462 void lp_set_spoolss_state( uint32 state )
4464 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
4466 spoolss_state = state;
4469 uint32 lp_get_spoolss_state( void )
4471 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
4474 /*******************************************************************
4475 Ensure we don't use sendfile if server smb signing is active.
4476 ********************************************************************/
4478 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
4480 bool sign_active = false;
4482 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
4483 if (get_Protocol() < PROTOCOL_NT1) {
4484 return false;
4486 if (signing_state) {
4487 sign_active = smb_signing_is_active(signing_state);
4489 return (lp__use_sendfile(snum) &&
4490 (get_remote_arch() != RA_WIN95) &&
4491 !sign_active);
4494 /*******************************************************************
4495 Turn off sendfile if we find the underlying OS doesn't support it.
4496 ********************************************************************/
4498 void set_use_sendfile(int snum, bool val)
4500 if (LP_SNUM_OK(snum))
4501 ServicePtrs[snum]->_use_sendfile = val;
4502 else
4503 sDefault._use_sendfile = val;
4506 /*******************************************************************
4507 Turn off storing DOS attributes if this share doesn't support it.
4508 ********************************************************************/
4510 void set_store_dos_attributes(int snum, bool val)
4512 if (!LP_SNUM_OK(snum))
4513 return;
4514 ServicePtrs[(snum)]->store_dos_attributes = val;
4517 void lp_set_mangling_method(const char *new_method)
4519 string_set(Globals.ctx, &Globals.mangling_method, new_method);
4522 /*******************************************************************
4523 Global state for POSIX pathname processing.
4524 ********************************************************************/
4526 static bool posix_pathnames;
4528 bool lp_posix_pathnames(void)
4530 return posix_pathnames;
4533 /*******************************************************************
4534 Change everything needed to ensure POSIX pathname processing (currently
4535 not much).
4536 ********************************************************************/
4538 void lp_set_posix_pathnames(void)
4540 posix_pathnames = true;
4543 /*******************************************************************
4544 Global state for POSIX lock processing - CIFS unix extensions.
4545 ********************************************************************/
4547 bool posix_default_lock_was_set;
4548 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
4550 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
4552 if (posix_default_lock_was_set) {
4553 return posix_cifsx_locktype;
4554 } else {
4555 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
4559 /*******************************************************************
4560 ********************************************************************/
4562 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
4564 posix_default_lock_was_set = true;
4565 posix_cifsx_locktype = val;
4568 int lp_min_receive_file_size(void)
4570 if (Globals.iminreceivefile < 0) {
4571 return 0;
4573 return Globals.iminreceivefile;
4576 /*******************************************************************
4577 Safe wide links checks.
4578 This helper function always verify the validity of wide links,
4579 even after a configuration file reload.
4580 ********************************************************************/
4582 static bool lp_widelinks_internal(int snum)
4584 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
4585 sDefault.bWidelinks);
4588 void widelinks_warning(int snum)
4590 if (lp_allow_insecure_wide_links()) {
4591 return;
4594 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
4595 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
4596 "These parameters are incompatible. "
4597 "Wide links will be disabled for this share.\n",
4598 lp_servicename(talloc_tos(), snum) ));
4602 bool lp_widelinks(int snum)
4604 /* wide links is always incompatible with unix extensions */
4605 if (lp_unix_extensions()) {
4607 * Unless we have "allow insecure widelinks"
4608 * turned on.
4610 if (!lp_allow_insecure_wide_links()) {
4611 return false;
4615 return lp_widelinks_internal(snum);
4618 int lp_server_role(void)
4620 return lp_find_server_role(lp__server_role(),
4621 lp__security(),
4622 lp__domain_logons(),
4623 lp_domain_master_true_or_auto());
4626 int lp_security(void)
4628 return lp_find_security(lp__server_role(),
4629 lp__security());
4632 struct loadparm_global * get_globals(void)
4634 return &Globals;
4637 unsigned int * get_flags(void)
4639 if (flags_list == NULL) {
4640 flags_list = talloc_zero_array(NULL, unsigned int, num_parameters());
4643 return flags_list;