s3:param: simplify lp_do_parameter to use lpcfg functions
[Samba.git] / source3 / param / loadparm.c
blob11a10d9b221bc9f2913f93e4452075c89b134e52
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 TALLOC_CTX *frame = talloc_stackframe();
2576 struct loadparm_context *lp_ctx;
2577 bool ok;
2579 lp_ctx = loadparm_init_s3(frame,
2580 loadparm_s3_helpers());
2581 if (lp_ctx == NULL) {
2582 DEBUG(0, ("loadparm_init_s3 failed\n"));
2583 TALLOC_FREE(frame);
2584 return false;
2587 lp_ctx->sDefault = &sDefault;
2588 lp_ctx->services = ServicePtrs;
2589 lp_ctx->bInGlobalSection = bInGlobalSection;
2590 lp_ctx->flags = flags_list;
2592 if (snum < 0) {
2593 ok = lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue);
2594 } else {
2595 ok = lpcfg_do_service_parameter(lp_ctx, ServicePtrs[snum],
2596 pszParmName, pszParmValue);
2599 TALLOC_FREE(frame);
2601 return ok;
2604 /***************************************************************************
2605 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
2606 FLAG_CMDLINE won't be overridden by loads from smb.conf.
2607 ***************************************************************************/
2609 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue)
2611 int parmnum, i;
2612 parmnum = lpcfg_map_parameter(pszParmName);
2613 if (parmnum >= 0) {
2614 flags_list[parmnum] &= ~FLAG_CMDLINE;
2615 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
2616 return false;
2618 flags_list[parmnum] |= FLAG_CMDLINE;
2620 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
2621 * be grouped in the table, so we don't have to search the
2622 * whole table */
2623 for (i=parmnum-1;
2624 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
2625 && parm_table[i].p_class == parm_table[parmnum].p_class;
2626 i--) {
2627 flags_list[i] |= FLAG_CMDLINE;
2629 for (i=parmnum+1;i<num_parameters() && parm_table[i].offset == parm_table[parmnum].offset
2630 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
2631 flags_list[i] |= FLAG_CMDLINE;
2634 return true;
2637 /* it might be parametric */
2638 if (strchr(pszParmName, ':') != NULL) {
2639 set_param_opt(NULL, &Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
2640 return true;
2643 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2644 return false;
2647 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
2649 bool ret;
2650 TALLOC_CTX *frame = talloc_stackframe();
2651 struct loadparm_context *lp_ctx;
2653 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
2654 if (lp_ctx == NULL) {
2655 DEBUG(0, ("loadparm_init_s3 failed\n"));
2656 return false;
2659 ret = lpcfg_set_cmdline(lp_ctx, pszParmName, pszParmValue);
2661 TALLOC_FREE(frame);
2662 return ret;
2665 /***************************************************************************
2666 Process a parameter.
2667 ***************************************************************************/
2669 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
2670 void *userdata)
2672 if (!bInGlobalSection && bGlobalOnly)
2673 return true;
2675 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2677 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2678 pszParmName, pszParmValue));
2681 /***************************************************************************
2682 Initialize any local variables in the sDefault table, after parsing a
2683 [globals] section.
2684 ***************************************************************************/
2686 static void init_locals(void)
2689 * We run this check once the [globals] is parsed, to force
2690 * the VFS objects and other per-share settings we need for
2691 * the standard way a AD DC is operated. We may change these
2692 * as our code evolves, which is why we force these settings.
2694 * We can't do this at the end of lp_load_ex(), as by that
2695 * point the services have been loaded and they will already
2696 * have "" as their vfs objects.
2698 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
2699 const char **vfs_objects = lp_vfs_objects(-1);
2700 if (!vfs_objects || !vfs_objects[0]) {
2701 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
2702 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
2703 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
2704 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
2705 } else {
2706 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
2710 lp_do_parameter(-1, "map hidden", "no");
2711 lp_do_parameter(-1, "map system", "no");
2712 lp_do_parameter(-1, "map readonly", "no");
2713 lp_do_parameter(-1, "map archive", "no");
2714 lp_do_parameter(-1, "store dos attributes", "yes");
2718 /***************************************************************************
2719 Process a new section (service). At this stage all sections are services.
2720 Later we'll have special sections that permit server parameters to be set.
2721 Returns true on success, false on failure.
2722 ***************************************************************************/
2724 bool lp_do_section(const char *pszSectionName, void *userdata)
2726 bool bRetval;
2727 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2728 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2729 bRetval = false;
2731 /* if we were in a global section then do the local inits */
2732 if (bInGlobalSection && !isglobal)
2733 init_locals();
2735 /* if we've just struck a global section, note the fact. */
2736 bInGlobalSection = isglobal;
2738 /* check for multiple global sections */
2739 if (bInGlobalSection) {
2740 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2741 return true;
2744 if (!bInGlobalSection && bGlobalOnly)
2745 return true;
2747 /* if we have a current service, tidy it up before moving on */
2748 bRetval = true;
2750 if (iServiceIndex >= 0)
2751 bRetval = service_ok(iServiceIndex);
2753 /* if all is still well, move to the next record in the services array */
2754 if (bRetval) {
2755 /* We put this here to avoid an odd message order if messages are */
2756 /* issued by the post-processing of a previous section. */
2757 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2759 iServiceIndex = add_a_service(&sDefault, pszSectionName);
2760 if (iServiceIndex < 0) {
2761 DEBUG(0, ("Failed to add a new service\n"));
2762 return false;
2764 /* Clean all parametric options for service */
2765 /* They will be added during parsing again */
2766 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
2769 return bRetval;
2773 /***************************************************************************
2774 Determine if a partcular base parameter is currentl set to the default value.
2775 ***************************************************************************/
2777 static bool is_default(int i)
2779 switch (parm_table[i].type) {
2780 case P_LIST:
2781 case P_CMDLIST:
2782 return str_list_equal((const char * const *)parm_table[i].def.lvalue,
2783 *(const char ***)lp_parm_ptr(NULL,
2784 &parm_table[i]));
2785 case P_STRING:
2786 case P_USTRING:
2787 return strequal(parm_table[i].def.svalue,
2788 *(char **)lp_parm_ptr(NULL,
2789 &parm_table[i]));
2790 case P_BOOL:
2791 case P_BOOLREV:
2792 return parm_table[i].def.bvalue ==
2793 *(bool *)lp_parm_ptr(NULL,
2794 &parm_table[i]);
2795 case P_CHAR:
2796 return parm_table[i].def.cvalue ==
2797 *(char *)lp_parm_ptr(NULL,
2798 &parm_table[i]);
2799 case P_INTEGER:
2800 case P_OCTAL:
2801 case P_ENUM:
2802 case P_BYTES:
2803 return parm_table[i].def.ivalue ==
2804 *(int *)lp_parm_ptr(NULL,
2805 &parm_table[i]);
2806 case P_SEP:
2807 break;
2809 return false;
2812 /***************************************************************************
2813 Display the contents of the global structure.
2814 ***************************************************************************/
2816 static void dump_globals(FILE *f, bool show_defaults)
2818 int i;
2819 struct parmlist_entry *data;
2821 fprintf(f, "[global]\n");
2823 for (i = 0; parm_table[i].label; i++)
2824 if (parm_table[i].p_class == P_GLOBAL &&
2825 !(parm_table[i].flags & FLAG_META) &&
2826 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
2827 if (show_defaults && is_default(i))
2828 continue;
2829 fprintf(f, "\t%s = ", parm_table[i].label);
2830 lpcfg_print_parameter(&parm_table[i], lp_parm_ptr(NULL,
2831 &parm_table[i]),
2833 fprintf(f, "\n");
2835 if (Globals.param_opt != NULL) {
2836 data = Globals.param_opt;
2837 while(data) {
2838 if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
2839 data = data->next;
2840 continue;
2842 fprintf(f, "\t%s = %s\n", data->key, data->value);
2843 data = data->next;
2849 /***************************************************************************
2850 Display the contents of a parameter of a single services record.
2851 ***************************************************************************/
2853 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
2855 bool result = false;
2857 struct loadparm_context *lp_ctx;
2859 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
2860 if (lp_ctx == NULL) {
2861 return false;
2864 if (isGlobal) {
2865 result = lpcfg_dump_a_parameter(lp_ctx, NULL, parm_name, f);
2866 } else {
2867 result = lpcfg_dump_a_parameter(lp_ctx, ServicePtrs[snum], parm_name, f);
2869 TALLOC_FREE(lp_ctx);
2870 return result;
2873 /***************************************************************************
2874 Return info about the requested parameter (given as a string).
2875 Return NULL when the string is not a valid parameter name.
2876 ***************************************************************************/
2878 struct parm_struct *lp_get_parameter(const char *param_name)
2880 int num = lpcfg_map_parameter(param_name);
2882 if (num < 0) {
2883 return NULL;
2886 return &parm_table[num];
2889 #if 0
2890 /***************************************************************************
2891 Display the contents of a single copy structure.
2892 ***************************************************************************/
2893 static void dump_copy_map(bool *pcopymap)
2895 int i;
2896 if (!pcopymap)
2897 return;
2899 printf("\n\tNon-Copied parameters:\n");
2901 for (i = 0; parm_table[i].label; i++)
2902 if (parm_table[i].p_class == P_LOCAL &&
2903 parm_table[i].ptr && !pcopymap[i] &&
2904 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
2906 printf("\t\t%s\n", parm_table[i].label);
2909 #endif
2911 /***************************************************************************
2912 Return TRUE if the passed service number is within range.
2913 ***************************************************************************/
2915 bool lp_snum_ok(int iService)
2917 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2920 /***************************************************************************
2921 Auto-load some home services.
2922 ***************************************************************************/
2924 static void lp_add_auto_services(char *str)
2926 char *s;
2927 char *p;
2928 int homes;
2929 char *saveptr;
2931 if (!str)
2932 return;
2934 s = talloc_strdup(talloc_tos(), str);
2935 if (!s) {
2936 smb_panic("talloc_strdup failed");
2937 return;
2940 homes = lp_servicenumber(HOMES_NAME);
2942 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
2943 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
2944 char *home;
2946 if (lp_servicenumber(p) >= 0)
2947 continue;
2949 home = get_user_home_dir(talloc_tos(), p);
2951 if (home && home[0] && homes >= 0)
2952 lp_add_home(p, homes, p, home);
2954 TALLOC_FREE(home);
2956 TALLOC_FREE(s);
2959 /***************************************************************************
2960 Auto-load one printer.
2961 ***************************************************************************/
2963 void lp_add_one_printer(const char *name, const char *comment,
2964 const char *location, void *pdata)
2966 int printers = lp_servicenumber(PRINTERS_NAME);
2967 int i;
2969 if (lp_servicenumber(name) < 0) {
2970 lp_add_printer(name, printers);
2971 if ((i = lp_servicenumber(name)) >= 0) {
2972 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
2973 ServicePtrs[i]->autoloaded = true;
2978 /***************************************************************************
2979 Have we loaded a services file yet?
2980 ***************************************************************************/
2982 bool lp_loaded(void)
2984 return (bLoaded);
2987 /***************************************************************************
2988 Unload unused services.
2989 ***************************************************************************/
2991 void lp_killunused(struct smbd_server_connection *sconn,
2992 bool (*snumused) (struct smbd_server_connection *, int))
2994 int i;
2995 for (i = 0; i < iNumServices; i++) {
2996 if (!VALID(i))
2997 continue;
2999 /* don't kill autoloaded or usershare services */
3000 if ( ServicePtrs[i]->autoloaded ||
3001 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3002 continue;
3005 if (!snumused || !snumused(sconn, i)) {
3006 free_service_byindex(i);
3012 * Kill all except autoloaded and usershare services - convenience wrapper
3014 void lp_kill_all_services(void)
3016 lp_killunused(NULL, NULL);
3019 /***************************************************************************
3020 Unload a service.
3021 ***************************************************************************/
3023 void lp_killservice(int iServiceIn)
3025 if (VALID(iServiceIn)) {
3026 free_service_byindex(iServiceIn);
3030 /***************************************************************************
3031 Save the curent values of all global and sDefault parameters into the
3032 defaults union. This allows testparm to show only the
3033 changed (ie. non-default) parameters.
3034 ***************************************************************************/
3036 static void lp_save_defaults(void)
3038 int i;
3039 struct parmlist_entry * parm;
3040 for (i = 0; parm_table[i].label; i++) {
3041 if (!(flags_list[i] & FLAG_CMDLINE)) {
3042 flags_list[i] |= FLAG_DEFAULT;
3045 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3046 && parm_table[i].p_class == parm_table[i - 1].p_class)
3047 continue;
3048 switch (parm_table[i].type) {
3049 case P_LIST:
3050 case P_CMDLIST:
3051 parm_table[i].def.lvalue = str_list_copy(
3052 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3053 break;
3054 case P_STRING:
3055 case P_USTRING:
3056 parm_table[i].def.svalue = talloc_strdup(Globals.ctx, *(char **)lp_parm_ptr(NULL, &parm_table[i]));
3057 if (parm_table[i].def.svalue == NULL) {
3058 smb_panic("talloc_strdup failed");
3060 break;
3061 case P_BOOL:
3062 case P_BOOLREV:
3063 parm_table[i].def.bvalue =
3064 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3065 break;
3066 case P_CHAR:
3067 parm_table[i].def.cvalue =
3068 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3069 break;
3070 case P_INTEGER:
3071 case P_OCTAL:
3072 case P_ENUM:
3073 case P_BYTES:
3074 parm_table[i].def.ivalue =
3075 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3076 break;
3077 case P_SEP:
3078 break;
3082 for (parm=Globals.param_opt; parm; parm=parm->next) {
3083 if (!(parm->priority & FLAG_CMDLINE)) {
3084 parm->priority |= FLAG_DEFAULT;
3088 for (parm=sDefault.param_opt; parm; parm=parm->next) {
3089 if (!(parm->priority & FLAG_CMDLINE)) {
3090 parm->priority |= FLAG_DEFAULT;
3094 defaults_saved = true;
3097 /***********************************************************
3098 If we should send plaintext/LANMAN passwords in the clinet
3099 ************************************************************/
3101 static void set_allowed_client_auth(void)
3103 if (Globals.client_ntlmv2_auth) {
3104 Globals.client_lanman_auth = false;
3106 if (!Globals.client_lanman_auth) {
3107 Globals.client_plaintext_auth = false;
3111 /***************************************************************************
3112 JRA.
3113 The following code allows smbd to read a user defined share file.
3114 Yes, this is my intent. Yes, I'm comfortable with that...
3116 THE FOLLOWING IS SECURITY CRITICAL CODE.
3118 It washes your clothes, it cleans your house, it guards you while you sleep...
3119 Do not f%^k with it....
3120 ***************************************************************************/
3122 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3124 /***************************************************************************
3125 Check allowed stat state of a usershare file.
3126 Ensure we print out who is dicking with us so the admin can
3127 get their sorry ass fired.
3128 ***************************************************************************/
3130 static bool check_usershare_stat(const char *fname,
3131 const SMB_STRUCT_STAT *psbuf)
3133 if (!S_ISREG(psbuf->st_ex_mode)) {
3134 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3135 "not a regular file\n",
3136 fname, (unsigned int)psbuf->st_ex_uid ));
3137 return false;
3140 /* Ensure this doesn't have the other write bit set. */
3141 if (psbuf->st_ex_mode & S_IWOTH) {
3142 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
3143 "public write. Refusing to allow as a usershare file.\n",
3144 fname, (unsigned int)psbuf->st_ex_uid ));
3145 return false;
3148 /* Should be 10k or less. */
3149 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
3150 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3151 "too large (%u) to be a user share file.\n",
3152 fname, (unsigned int)psbuf->st_ex_uid,
3153 (unsigned int)psbuf->st_ex_size ));
3154 return false;
3157 return true;
3160 /***************************************************************************
3161 Parse the contents of a usershare file.
3162 ***************************************************************************/
3164 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
3165 SMB_STRUCT_STAT *psbuf,
3166 const char *servicename,
3167 int snum,
3168 char **lines,
3169 int numlines,
3170 char **pp_sharepath,
3171 char **pp_comment,
3172 char **pp_cp_servicename,
3173 struct security_descriptor **ppsd,
3174 bool *pallow_guest)
3176 const char **prefixallowlist = lp_usershare_prefix_allow_list();
3177 const char **prefixdenylist = lp_usershare_prefix_deny_list();
3178 int us_vers;
3179 DIR *dp;
3180 SMB_STRUCT_STAT sbuf;
3181 char *sharepath = NULL;
3182 char *comment = NULL;
3184 *pp_sharepath = NULL;
3185 *pp_comment = NULL;
3187 *pallow_guest = false;
3189 if (numlines < 4) {
3190 return USERSHARE_MALFORMED_FILE;
3193 if (strcmp(lines[0], "#VERSION 1") == 0) {
3194 us_vers = 1;
3195 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
3196 us_vers = 2;
3197 if (numlines < 5) {
3198 return USERSHARE_MALFORMED_FILE;
3200 } else {
3201 return USERSHARE_BAD_VERSION;
3204 if (strncmp(lines[1], "path=", 5) != 0) {
3205 return USERSHARE_MALFORMED_PATH;
3208 sharepath = talloc_strdup(ctx, &lines[1][5]);
3209 if (!sharepath) {
3210 return USERSHARE_POSIX_ERR;
3212 trim_string(sharepath, " ", " ");
3214 if (strncmp(lines[2], "comment=", 8) != 0) {
3215 return USERSHARE_MALFORMED_COMMENT_DEF;
3218 comment = talloc_strdup(ctx, &lines[2][8]);
3219 if (!comment) {
3220 return USERSHARE_POSIX_ERR;
3222 trim_string(comment, " ", " ");
3223 trim_char(comment, '"', '"');
3225 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
3226 return USERSHARE_MALFORMED_ACL_DEF;
3229 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
3230 return USERSHARE_ACL_ERR;
3233 if (us_vers == 2) {
3234 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
3235 return USERSHARE_MALFORMED_ACL_DEF;
3237 if (lines[4][9] == 'y') {
3238 *pallow_guest = true;
3241 /* Backwards compatible extension to file version #2. */
3242 if (numlines > 5) {
3243 if (strncmp(lines[5], "sharename=", 10) != 0) {
3244 return USERSHARE_MALFORMED_SHARENAME_DEF;
3246 if (!strequal(&lines[5][10], servicename)) {
3247 return USERSHARE_BAD_SHARENAME;
3249 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
3250 if (!*pp_cp_servicename) {
3251 return USERSHARE_POSIX_ERR;
3256 if (*pp_cp_servicename == NULL) {
3257 *pp_cp_servicename = talloc_strdup(ctx, servicename);
3258 if (!*pp_cp_servicename) {
3259 return USERSHARE_POSIX_ERR;
3263 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->path) == 0)) {
3264 /* Path didn't change, no checks needed. */
3265 *pp_sharepath = sharepath;
3266 *pp_comment = comment;
3267 return USERSHARE_OK;
3270 /* The path *must* be absolute. */
3271 if (sharepath[0] != '/') {
3272 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
3273 servicename, sharepath));
3274 return USERSHARE_PATH_NOT_ABSOLUTE;
3277 /* If there is a usershare prefix deny list ensure one of these paths
3278 doesn't match the start of the user given path. */
3279 if (prefixdenylist) {
3280 int i;
3281 for ( i=0; prefixdenylist[i]; i++ ) {
3282 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
3283 servicename, i, prefixdenylist[i], sharepath ));
3284 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
3285 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
3286 "usershare prefix deny list entries.\n",
3287 servicename, sharepath));
3288 return USERSHARE_PATH_IS_DENIED;
3293 /* If there is a usershare prefix allow list ensure one of these paths
3294 does match the start of the user given path. */
3296 if (prefixallowlist) {
3297 int i;
3298 for ( i=0; prefixallowlist[i]; i++ ) {
3299 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
3300 servicename, i, prefixallowlist[i], sharepath ));
3301 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
3302 break;
3305 if (prefixallowlist[i] == NULL) {
3306 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
3307 "usershare prefix allow list entries.\n",
3308 servicename, sharepath));
3309 return USERSHARE_PATH_NOT_ALLOWED;
3313 /* Ensure this is pointing to a directory. */
3314 dp = opendir(sharepath);
3316 if (!dp) {
3317 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3318 servicename, sharepath));
3319 return USERSHARE_PATH_NOT_DIRECTORY;
3322 /* Ensure the owner of the usershare file has permission to share
3323 this directory. */
3325 if (sys_stat(sharepath, &sbuf, false) == -1) {
3326 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
3327 servicename, sharepath, strerror(errno) ));
3328 closedir(dp);
3329 return USERSHARE_POSIX_ERR;
3332 closedir(dp);
3334 if (!S_ISDIR(sbuf.st_ex_mode)) {
3335 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3336 servicename, sharepath ));
3337 return USERSHARE_PATH_NOT_DIRECTORY;
3340 /* Check if sharing is restricted to owner-only. */
3341 /* psbuf is the stat of the usershare definition file,
3342 sbuf is the stat of the target directory to be shared. */
3344 if (lp_usershare_owner_only()) {
3345 /* root can share anything. */
3346 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
3347 return USERSHARE_PATH_NOT_ALLOWED;
3351 *pp_sharepath = sharepath;
3352 *pp_comment = comment;
3353 return USERSHARE_OK;
3356 /***************************************************************************
3357 Deal with a usershare file.
3358 Returns:
3359 >= 0 - snum
3360 -1 - Bad name, invalid contents.
3361 - service name already existed and not a usershare, problem
3362 with permissions to share directory etc.
3363 ***************************************************************************/
3365 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
3367 SMB_STRUCT_STAT sbuf;
3368 SMB_STRUCT_STAT lsbuf;
3369 char *fname = NULL;
3370 char *sharepath = NULL;
3371 char *comment = NULL;
3372 char *cp_service_name = NULL;
3373 char **lines = NULL;
3374 int numlines = 0;
3375 int fd = -1;
3376 int iService = -1;
3377 TALLOC_CTX *ctx = talloc_stackframe();
3378 struct security_descriptor *psd = NULL;
3379 bool guest_ok = false;
3380 char *canon_name = NULL;
3381 bool added_service = false;
3382 int ret = -1;
3384 /* Ensure share name doesn't contain invalid characters. */
3385 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
3386 DEBUG(0,("process_usershare_file: share name %s contains "
3387 "invalid characters (any of %s)\n",
3388 file_name, INVALID_SHARENAME_CHARS ));
3389 goto out;
3392 canon_name = canonicalize_servicename(ctx, file_name);
3393 if (!canon_name) {
3394 goto out;
3397 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
3398 if (!fname) {
3399 goto out;
3402 /* Minimize the race condition by doing an lstat before we
3403 open and fstat. Ensure this isn't a symlink link. */
3405 if (sys_lstat(fname, &lsbuf, false) != 0) {
3406 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
3407 fname, strerror(errno) ));
3408 goto out;
3411 /* This must be a regular file, not a symlink, directory or
3412 other strange filetype. */
3413 if (!check_usershare_stat(fname, &lsbuf)) {
3414 goto out;
3418 TDB_DATA data;
3419 NTSTATUS status;
3421 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
3422 canon_name, &data);
3424 iService = -1;
3426 if (NT_STATUS_IS_OK(status) &&
3427 (data.dptr != NULL) &&
3428 (data.dsize == sizeof(iService))) {
3429 memcpy(&iService, data.dptr, sizeof(iService));
3433 if (iService != -1 &&
3434 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
3435 &lsbuf.st_ex_mtime) == 0) {
3436 /* Nothing changed - Mark valid and return. */
3437 DEBUG(10,("process_usershare_file: service %s not changed.\n",
3438 canon_name ));
3439 ServicePtrs[iService]->usershare = USERSHARE_VALID;
3440 ret = iService;
3441 goto out;
3444 /* Try and open the file read only - no symlinks allowed. */
3445 #ifdef O_NOFOLLOW
3446 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
3447 #else
3448 fd = open(fname, O_RDONLY, 0);
3449 #endif
3451 if (fd == -1) {
3452 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
3453 fname, strerror(errno) ));
3454 goto out;
3457 /* Now fstat to be *SURE* it's a regular file. */
3458 if (sys_fstat(fd, &sbuf, false) != 0) {
3459 close(fd);
3460 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
3461 fname, strerror(errno) ));
3462 goto out;
3465 /* Is it the same dev/inode as was lstated ? */
3466 if (!check_same_stat(&lsbuf, &sbuf)) {
3467 close(fd);
3468 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
3469 "Symlink spoofing going on ?\n", fname ));
3470 goto out;
3473 /* This must be a regular file, not a symlink, directory or
3474 other strange filetype. */
3475 if (!check_usershare_stat(fname, &sbuf)) {
3476 close(fd);
3477 goto out;
3480 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
3482 close(fd);
3483 if (lines == NULL) {
3484 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
3485 fname, (unsigned int)sbuf.st_ex_uid ));
3486 goto out;
3489 if (parse_usershare_file(ctx, &sbuf, file_name,
3490 iService, lines, numlines, &sharepath,
3491 &comment, &cp_service_name,
3492 &psd, &guest_ok) != USERSHARE_OK) {
3493 goto out;
3496 /* Everything ok - add the service possibly using a template. */
3497 if (iService < 0) {
3498 const struct loadparm_service *sp = &sDefault;
3499 if (snum_template != -1) {
3500 sp = ServicePtrs[snum_template];
3503 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
3504 DEBUG(0, ("process_usershare_file: Failed to add "
3505 "new service %s\n", cp_service_name));
3506 goto out;
3509 added_service = true;
3511 /* Read only is controlled by usershare ACL below. */
3512 ServicePtrs[iService]->read_only = false;
3515 /* Write the ACL of the new/modified share. */
3516 if (!set_share_security(canon_name, psd)) {
3517 DEBUG(0, ("process_usershare_file: Failed to set share "
3518 "security for user share %s\n",
3519 canon_name ));
3520 goto out;
3523 /* If from a template it may be marked invalid. */
3524 ServicePtrs[iService]->valid = true;
3526 /* Set the service as a valid usershare. */
3527 ServicePtrs[iService]->usershare = USERSHARE_VALID;
3529 /* Set guest access. */
3530 if (lp_usershare_allow_guests()) {
3531 ServicePtrs[iService]->guest_ok = guest_ok;
3534 /* And note when it was loaded. */
3535 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
3536 string_set(ServicePtrs[iService], &ServicePtrs[iService]->path, sharepath);
3537 string_set(ServicePtrs[iService], &ServicePtrs[iService]->comment, comment);
3539 ret = iService;
3541 out:
3543 if (ret == -1 && iService != -1 && added_service) {
3544 lp_remove_service(iService);
3547 TALLOC_FREE(lines);
3548 TALLOC_FREE(ctx);
3549 return ret;
3552 /***************************************************************************
3553 Checks if a usershare entry has been modified since last load.
3554 ***************************************************************************/
3556 static bool usershare_exists(int iService, struct timespec *last_mod)
3558 SMB_STRUCT_STAT lsbuf;
3559 const char *usersharepath = Globals.usershare_path;
3560 char *fname;
3562 fname = talloc_asprintf(talloc_tos(),
3563 "%s/%s",
3564 usersharepath,
3565 ServicePtrs[iService]->szService);
3566 if (fname == NULL) {
3567 return false;
3570 if (sys_lstat(fname, &lsbuf, false) != 0) {
3571 TALLOC_FREE(fname);
3572 return false;
3575 if (!S_ISREG(lsbuf.st_ex_mode)) {
3576 TALLOC_FREE(fname);
3577 return false;
3580 TALLOC_FREE(fname);
3581 *last_mod = lsbuf.st_ex_mtime;
3582 return true;
3585 /***************************************************************************
3586 Load a usershare service by name. Returns a valid servicenumber or -1.
3587 ***************************************************************************/
3589 int load_usershare_service(const char *servicename)
3591 SMB_STRUCT_STAT sbuf;
3592 const char *usersharepath = Globals.usershare_path;
3593 int max_user_shares = Globals.usershare_max_shares;
3594 int snum_template = -1;
3596 if (*usersharepath == 0 || max_user_shares == 0) {
3597 return -1;
3600 if (sys_stat(usersharepath, &sbuf, false) != 0) {
3601 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
3602 usersharepath, strerror(errno) ));
3603 return -1;
3606 if (!S_ISDIR(sbuf.st_ex_mode)) {
3607 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
3608 usersharepath ));
3609 return -1;
3613 * This directory must be owned by root, and have the 't' bit set.
3614 * It also must not be writable by "other".
3617 #ifdef S_ISVTX
3618 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
3619 #else
3620 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
3621 #endif
3622 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
3623 "or does not have the sticky bit 't' set or is writable by anyone.\n",
3624 usersharepath ));
3625 return -1;
3628 /* Ensure the template share exists if it's set. */
3629 if (Globals.usershare_template_share[0]) {
3630 /* We can't use lp_servicenumber here as we are recommending that
3631 template shares have -valid=false set. */
3632 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
3633 if (ServicePtrs[snum_template]->szService &&
3634 strequal(ServicePtrs[snum_template]->szService,
3635 Globals.usershare_template_share)) {
3636 break;
3640 if (snum_template == -1) {
3641 DEBUG(0,("load_usershare_service: usershare template share %s "
3642 "does not exist.\n",
3643 Globals.usershare_template_share ));
3644 return -1;
3648 return process_usershare_file(usersharepath, servicename, snum_template);
3651 /***************************************************************************
3652 Load all user defined shares from the user share directory.
3653 We only do this if we're enumerating the share list.
3654 This is the function that can delete usershares that have
3655 been removed.
3656 ***************************************************************************/
3658 int load_usershare_shares(struct smbd_server_connection *sconn,
3659 bool (*snumused) (struct smbd_server_connection *, int))
3661 DIR *dp;
3662 SMB_STRUCT_STAT sbuf;
3663 struct dirent *de;
3664 int num_usershares = 0;
3665 int max_user_shares = Globals.usershare_max_shares;
3666 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
3667 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
3668 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
3669 int iService;
3670 int snum_template = -1;
3671 const char *usersharepath = Globals.usershare_path;
3672 int ret = lp_numservices();
3673 TALLOC_CTX *tmp_ctx;
3675 if (max_user_shares == 0 || *usersharepath == '\0') {
3676 return lp_numservices();
3679 if (sys_stat(usersharepath, &sbuf, false) != 0) {
3680 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
3681 usersharepath, strerror(errno) ));
3682 return ret;
3686 * This directory must be owned by root, and have the 't' bit set.
3687 * It also must not be writable by "other".
3690 #ifdef S_ISVTX
3691 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
3692 #else
3693 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
3694 #endif
3695 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
3696 "or does not have the sticky bit 't' set or is writable by anyone.\n",
3697 usersharepath ));
3698 return ret;
3701 /* Ensure the template share exists if it's set. */
3702 if (Globals.usershare_template_share[0]) {
3703 /* We can't use lp_servicenumber here as we are recommending that
3704 template shares have -valid=false set. */
3705 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
3706 if (ServicePtrs[snum_template]->szService &&
3707 strequal(ServicePtrs[snum_template]->szService,
3708 Globals.usershare_template_share)) {
3709 break;
3713 if (snum_template == -1) {
3714 DEBUG(0,("load_usershare_shares: usershare template share %s "
3715 "does not exist.\n",
3716 Globals.usershare_template_share ));
3717 return ret;
3721 /* Mark all existing usershares as pending delete. */
3722 for (iService = iNumServices - 1; iService >= 0; iService--) {
3723 if (VALID(iService) && ServicePtrs[iService]->usershare) {
3724 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
3728 dp = opendir(usersharepath);
3729 if (!dp) {
3730 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
3731 usersharepath, strerror(errno) ));
3732 return ret;
3735 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
3736 (de = readdir(dp));
3737 num_dir_entries++ ) {
3738 int r;
3739 const char *n = de->d_name;
3741 /* Ignore . and .. */
3742 if (*n == '.') {
3743 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
3744 continue;
3748 if (n[0] == ':') {
3749 /* Temporary file used when creating a share. */
3750 num_tmp_dir_entries++;
3753 /* Allow 20% tmp entries. */
3754 if (num_tmp_dir_entries > allowed_tmp_entries) {
3755 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
3756 "in directory %s\n",
3757 num_tmp_dir_entries, usersharepath));
3758 break;
3761 r = process_usershare_file(usersharepath, n, snum_template);
3762 if (r == 0) {
3763 /* Update the services count. */
3764 num_usershares++;
3765 if (num_usershares >= max_user_shares) {
3766 DEBUG(0,("load_usershare_shares: max user shares reached "
3767 "on file %s in directory %s\n",
3768 n, usersharepath ));
3769 break;
3771 } else if (r == -1) {
3772 num_bad_dir_entries++;
3775 /* Allow 20% bad entries. */
3776 if (num_bad_dir_entries > allowed_bad_entries) {
3777 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
3778 "in directory %s\n",
3779 num_bad_dir_entries, usersharepath));
3780 break;
3783 /* Allow 20% bad entries. */
3784 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
3785 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
3786 "in directory %s\n",
3787 num_dir_entries, usersharepath));
3788 break;
3792 closedir(dp);
3794 /* Sweep through and delete any non-refreshed usershares that are
3795 not currently in use. */
3796 tmp_ctx = talloc_stackframe();
3797 for (iService = iNumServices - 1; iService >= 0; iService--) {
3798 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
3799 char *servname;
3801 if (snumused && snumused(sconn, iService)) {
3802 continue;
3805 servname = lp_servicename(tmp_ctx, iService);
3807 /* Remove from the share ACL db. */
3808 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
3809 servname ));
3810 delete_share_security(servname);
3811 free_service_byindex(iService);
3814 talloc_free(tmp_ctx);
3816 return lp_numservices();
3819 /********************************************************
3820 Destroy global resources allocated in this file
3821 ********************************************************/
3823 void gfree_loadparm(void)
3825 int i;
3827 free_file_list();
3829 /* Free resources allocated to services */
3831 for ( i = 0; i < iNumServices; i++ ) {
3832 if ( VALID(i) ) {
3833 free_service_byindex(i);
3837 TALLOC_FREE( ServicePtrs );
3838 iNumServices = 0;
3840 /* Now release all resources allocated to global
3841 parameters and the default service */
3843 free_global_parameters();
3847 /***************************************************************************
3848 Allow client apps to specify that they are a client
3849 ***************************************************************************/
3850 static void lp_set_in_client(bool b)
3852 in_client = b;
3856 /***************************************************************************
3857 Determine if we're running in a client app
3858 ***************************************************************************/
3859 static bool lp_is_in_client(void)
3861 return in_client;
3864 /***************************************************************************
3865 Load the services array from the services file. Return true on success,
3866 false on failure.
3867 ***************************************************************************/
3869 static bool lp_load_ex(const char *pszFname,
3870 bool global_only,
3871 bool save_defaults,
3872 bool add_ipc,
3873 bool initialize_globals,
3874 bool allow_include_registry,
3875 bool load_all_shares)
3877 char *n2 = NULL;
3878 bool bRetval;
3879 TALLOC_CTX *frame = talloc_stackframe();
3881 bRetval = false;
3883 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
3885 bInGlobalSection = true;
3886 bGlobalOnly = global_only;
3887 bAllowIncludeRegistry = allow_include_registry;
3889 init_globals(initialize_globals);
3891 free_file_list();
3893 if (save_defaults) {
3894 init_locals();
3895 lp_save_defaults();
3898 if (!initialize_globals) {
3899 free_param_opts(&Globals.param_opt);
3900 apply_lp_set_cmdline();
3903 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
3905 /* We get sections first, so have to start 'behind' to make up */
3906 iServiceIndex = -1;
3908 if (lp_config_backend_is_file()) {
3909 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
3910 current_user_info.domain,
3911 pszFname);
3912 if (!n2) {
3913 smb_panic("lp_load_ex: out of memory");
3916 add_to_file_list(NULL, &file_lists, pszFname, n2);
3918 bRetval = pm_process(n2, lp_do_section, do_parameter, NULL);
3919 TALLOC_FREE(n2);
3921 /* finish up the last section */
3922 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
3923 if (bRetval) {
3924 if (iServiceIndex >= 0) {
3925 bRetval = service_ok(iServiceIndex);
3929 if (lp_config_backend_is_registry()) {
3930 bool ok;
3931 /* config backend changed to registry in config file */
3933 * We need to use this extra global variable here to
3934 * survive restart: init_globals uses this as a default
3935 * for config_backend. Otherwise, init_globals would
3936 * send us into an endless loop here.
3938 config_backend = CONFIG_BACKEND_REGISTRY;
3939 /* start over */
3940 DEBUG(1, ("lp_load_ex: changing to config backend "
3941 "registry\n"));
3942 init_globals(true);
3943 lp_kill_all_services();
3944 ok = lp_load_ex(pszFname, global_only, save_defaults,
3945 add_ipc, initialize_globals,
3946 allow_include_registry,
3947 load_all_shares);
3948 TALLOC_FREE(frame);
3949 return ok;
3951 } else if (lp_config_backend_is_registry()) {
3952 bRetval = process_registry_globals();
3953 } else {
3954 DEBUG(0, ("Illegal config backend given: %d\n",
3955 lp_config_backend()));
3956 bRetval = false;
3959 if (bRetval && lp_registry_shares()) {
3960 if (load_all_shares) {
3961 bRetval = process_registry_shares();
3962 } else {
3963 bRetval = reload_registry_shares();
3968 char *serv = lp_auto_services(talloc_tos());
3969 lp_add_auto_services(serv);
3970 TALLOC_FREE(serv);
3973 if (add_ipc) {
3974 /* When 'restrict anonymous = 2' guest connections to ipc$
3975 are denied */
3976 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
3977 if ( lp_enable_asu_support() ) {
3978 lp_add_ipc("ADMIN$", false);
3982 set_allowed_client_auth();
3984 if (lp_security() == SEC_ADS && strchr(lp_password_server(), ':')) {
3985 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
3986 lp_password_server()));
3989 bLoaded = true;
3991 /* Now we check we_are_a_wins_server and set szWINSserver to 127.0.0.1 */
3992 /* if we_are_a_wins_server is true and we are in the client */
3993 if (lp_is_in_client() && Globals.we_are_a_wins_server) {
3994 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
3997 init_iconv();
3999 fault_configure(smb_panic_s3);
4002 * We run this check once the whole smb.conf is parsed, to
4003 * force some settings for the standard way a AD DC is
4004 * operated. We may changed these as our code evolves, which
4005 * is why we force these settings.
4007 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4008 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4010 lp_do_parameter(-1, "winbindd:use external pipes", "true");
4012 lp_do_parameter(-1, "rpc_server:default", "external");
4013 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4014 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4015 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4016 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4017 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4018 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4019 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4020 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4023 bAllowIncludeRegistry = true;
4025 TALLOC_FREE(frame);
4026 return (bRetval);
4029 bool lp_load(const char *pszFname,
4030 bool global_only,
4031 bool save_defaults,
4032 bool add_ipc,
4033 bool initialize_globals)
4035 return lp_load_ex(pszFname,
4036 global_only,
4037 save_defaults,
4038 add_ipc,
4039 initialize_globals,
4040 true, /* allow_include_registry */
4041 false); /* load_all_shares*/
4044 bool lp_load_initial_only(const char *pszFname)
4046 return lp_load_ex(pszFname,
4047 true, /* global only */
4048 false, /* save_defaults */
4049 false, /* add_ipc */
4050 true, /* initialize_globals */
4051 false, /* allow_include_registry */
4052 false); /* load_all_shares*/
4056 * most common lp_load wrapper, loading only the globals
4058 bool lp_load_global(const char *file_name)
4060 return lp_load_ex(file_name,
4061 true, /* global_only */
4062 false, /* save_defaults */
4063 false, /* add_ipc */
4064 true, /* initialize_globals */
4065 true, /* allow_include_registry */
4066 false); /* load_all_shares*/
4070 * lp_load wrapper, especially for clients
4072 bool lp_load_client(const char *file_name)
4074 lp_set_in_client(true);
4076 return lp_load_global(file_name);
4080 * lp_load wrapper, loading only globals, but intended
4081 * for subsequent calls, not reinitializing the globals
4082 * to default values
4084 bool lp_load_global_no_reinit(const char *file_name)
4086 return lp_load_ex(file_name,
4087 true, /* global_only */
4088 false, /* save_defaults */
4089 false, /* add_ipc */
4090 false, /* initialize_globals */
4091 true, /* allow_include_registry */
4092 false); /* load_all_shares*/
4096 * lp_load wrapper, especially for clients, no reinitialization
4098 bool lp_load_client_no_reinit(const char *file_name)
4100 lp_set_in_client(true);
4102 return lp_load_global_no_reinit(file_name);
4105 bool lp_load_with_registry_shares(const char *pszFname,
4106 bool global_only,
4107 bool save_defaults,
4108 bool add_ipc,
4109 bool initialize_globals)
4111 return lp_load_ex(pszFname,
4112 global_only,
4113 save_defaults,
4114 add_ipc,
4115 initialize_globals,
4116 true, /* allow_include_registry */
4117 true); /* load_all_shares*/
4120 /***************************************************************************
4121 Return the max number of services.
4122 ***************************************************************************/
4124 int lp_numservices(void)
4126 return (iNumServices);
4129 /***************************************************************************
4130 Display the contents of the services array in human-readable form.
4131 ***************************************************************************/
4133 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4135 int iService;
4137 if (show_defaults)
4138 defaults_saved = false;
4140 dump_globals(f, defaults_saved);
4142 lpcfg_dump_a_service(&sDefault, &sDefault, f, flags_list, show_defaults);
4144 for (iService = 0; iService < maxtoprint; iService++) {
4145 fprintf(f,"\n");
4146 lp_dump_one(f, show_defaults, iService);
4150 /***************************************************************************
4151 Display the contents of one service in human-readable form.
4152 ***************************************************************************/
4154 void lp_dump_one(FILE * f, bool show_defaults, int snum)
4156 if (VALID(snum)) {
4157 if (ServicePtrs[snum]->szService[0] == '\0')
4158 return;
4159 lpcfg_dump_a_service(ServicePtrs[snum], &sDefault, f,
4160 flags_list, show_defaults);
4164 /***************************************************************************
4165 Return the number of the service with the given name, or -1 if it doesn't
4166 exist. Note that this is a DIFFERENT ANIMAL from the internal function
4167 getservicebyname()! This works ONLY if all services have been loaded, and
4168 does not copy the found service.
4169 ***************************************************************************/
4171 int lp_servicenumber(const char *pszServiceName)
4173 int iService;
4174 fstring serviceName;
4176 if (!pszServiceName) {
4177 return GLOBAL_SECTION_SNUM;
4180 for (iService = iNumServices - 1; iService >= 0; iService--) {
4181 if (VALID(iService) && ServicePtrs[iService]->szService) {
4183 * The substitution here is used to support %U is
4184 * service names
4186 fstrcpy(serviceName, ServicePtrs[iService]->szService);
4187 standard_sub_basic(get_current_username(),
4188 current_user_info.domain,
4189 serviceName,sizeof(serviceName));
4190 if (strequal(serviceName, pszServiceName)) {
4191 break;
4196 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
4197 struct timespec last_mod;
4199 if (!usershare_exists(iService, &last_mod)) {
4200 /* Remove the share security tdb entry for it. */
4201 delete_share_security(lp_servicename(talloc_tos(), iService));
4202 /* Remove it from the array. */
4203 free_service_byindex(iService);
4204 /* Doesn't exist anymore. */
4205 return GLOBAL_SECTION_SNUM;
4208 /* Has it been modified ? If so delete and reload. */
4209 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4210 &last_mod) < 0) {
4211 /* Remove it from the array. */
4212 free_service_byindex(iService);
4213 /* and now reload it. */
4214 iService = load_usershare_service(pszServiceName);
4218 if (iService < 0) {
4219 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
4220 return GLOBAL_SECTION_SNUM;
4223 return (iService);
4226 /*******************************************************************
4227 A useful volume label function.
4228 ********************************************************************/
4230 const char *volume_label(TALLOC_CTX *ctx, int snum)
4232 char *ret;
4233 const char *label = lp_volume(ctx, snum);
4234 if (!*label) {
4235 label = lp_servicename(ctx, snum);
4238 /* This returns a 33 byte guarenteed null terminated string. */
4239 ret = talloc_strndup(ctx, label, 32);
4240 if (!ret) {
4241 return "";
4243 return ret;
4246 /*******************************************************************
4247 Get the default server type we will announce as via nmbd.
4248 ********************************************************************/
4250 int lp_default_server_announce(void)
4252 int default_server_announce = 0;
4253 default_server_announce |= SV_TYPE_WORKSTATION;
4254 default_server_announce |= SV_TYPE_SERVER;
4255 default_server_announce |= SV_TYPE_SERVER_UNIX;
4257 /* note that the flag should be set only if we have a
4258 printer service but nmbd doesn't actually load the
4259 services so we can't tell --jerry */
4261 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
4263 default_server_announce |= SV_TYPE_SERVER_NT;
4264 default_server_announce |= SV_TYPE_NT;
4266 switch (lp_server_role()) {
4267 case ROLE_DOMAIN_MEMBER:
4268 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
4269 break;
4270 case ROLE_DOMAIN_PDC:
4271 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
4272 break;
4273 case ROLE_DOMAIN_BDC:
4274 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
4275 break;
4276 case ROLE_STANDALONE:
4277 default:
4278 break;
4280 if (lp_time_server())
4281 default_server_announce |= SV_TYPE_TIME_SOURCE;
4283 if (lp_host_msdfs())
4284 default_server_announce |= SV_TYPE_DFS_SERVER;
4286 return default_server_announce;
4289 /***********************************************************
4290 If we are PDC then prefer us as DMB
4291 ************************************************************/
4293 bool lp_domain_master(void)
4295 if (Globals._domain_master == Auto)
4296 return (lp_server_role() == ROLE_DOMAIN_PDC);
4298 return (bool)Globals._domain_master;
4301 /***********************************************************
4302 If we are PDC then prefer us as DMB
4303 ************************************************************/
4305 static bool lp_domain_master_true_or_auto(void)
4307 if (Globals._domain_master) /* auto or yes */
4308 return true;
4310 return false;
4313 /***********************************************************
4314 If we are DMB then prefer us as LMB
4315 ************************************************************/
4317 bool lp_preferred_master(void)
4319 if (Globals.iPreferredMaster == Auto)
4320 return (lp_local_master() && lp_domain_master());
4322 return (bool)Globals.iPreferredMaster;
4325 /*******************************************************************
4326 Remove a service.
4327 ********************************************************************/
4329 void lp_remove_service(int snum)
4331 ServicePtrs[snum]->valid = false;
4334 const char *lp_printername(TALLOC_CTX *ctx, int snum)
4336 const char *ret = lp__printername(ctx, snum);
4337 if (ret == NULL || *ret == '\0') {
4338 ret = lp_const_servicename(snum);
4341 return ret;
4345 /***********************************************************
4346 Allow daemons such as winbindd to fix their logfile name.
4347 ************************************************************/
4349 void lp_set_logfile(const char *name)
4351 string_set(Globals.ctx, &Globals.logfile, name);
4352 debug_set_logfile(name);
4355 /*******************************************************************
4356 Return the max print jobs per queue.
4357 ********************************************************************/
4359 int lp_maxprintjobs(int snum)
4361 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
4362 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
4363 maxjobs = PRINT_MAX_JOBID - 1;
4365 return maxjobs;
4368 const char *lp_printcapname(void)
4370 if ((Globals.szPrintcapname != NULL) &&
4371 (Globals.szPrintcapname[0] != '\0'))
4372 return Globals.szPrintcapname;
4374 if (sDefault.printing == PRINT_CUPS) {
4375 return "cups";
4378 if (sDefault.printing == PRINT_BSD)
4379 return "/etc/printcap";
4381 return PRINTCAP_NAME;
4384 static uint32 spoolss_state;
4386 bool lp_disable_spoolss( void )
4388 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
4389 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
4391 return spoolss_state == SVCCTL_STOPPED ? true : false;
4394 void lp_set_spoolss_state( uint32 state )
4396 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
4398 spoolss_state = state;
4401 uint32 lp_get_spoolss_state( void )
4403 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
4406 /*******************************************************************
4407 Ensure we don't use sendfile if server smb signing is active.
4408 ********************************************************************/
4410 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
4412 bool sign_active = false;
4414 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
4415 if (get_Protocol() < PROTOCOL_NT1) {
4416 return false;
4418 if (signing_state) {
4419 sign_active = smb_signing_is_active(signing_state);
4421 return (lp__use_sendfile(snum) &&
4422 (get_remote_arch() != RA_WIN95) &&
4423 !sign_active);
4426 /*******************************************************************
4427 Turn off sendfile if we find the underlying OS doesn't support it.
4428 ********************************************************************/
4430 void set_use_sendfile(int snum, bool val)
4432 if (LP_SNUM_OK(snum))
4433 ServicePtrs[snum]->_use_sendfile = val;
4434 else
4435 sDefault._use_sendfile = val;
4438 /*******************************************************************
4439 Turn off storing DOS attributes if this share doesn't support it.
4440 ********************************************************************/
4442 void set_store_dos_attributes(int snum, bool val)
4444 if (!LP_SNUM_OK(snum))
4445 return;
4446 ServicePtrs[(snum)]->store_dos_attributes = val;
4449 void lp_set_mangling_method(const char *new_method)
4451 string_set(Globals.ctx, &Globals.mangling_method, new_method);
4454 /*******************************************************************
4455 Global state for POSIX pathname processing.
4456 ********************************************************************/
4458 static bool posix_pathnames;
4460 bool lp_posix_pathnames(void)
4462 return posix_pathnames;
4465 /*******************************************************************
4466 Change everything needed to ensure POSIX pathname processing (currently
4467 not much).
4468 ********************************************************************/
4470 void lp_set_posix_pathnames(void)
4472 posix_pathnames = true;
4475 /*******************************************************************
4476 Global state for POSIX lock processing - CIFS unix extensions.
4477 ********************************************************************/
4479 bool posix_default_lock_was_set;
4480 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
4482 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
4484 if (posix_default_lock_was_set) {
4485 return posix_cifsx_locktype;
4486 } else {
4487 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
4491 /*******************************************************************
4492 ********************************************************************/
4494 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
4496 posix_default_lock_was_set = true;
4497 posix_cifsx_locktype = val;
4500 int lp_min_receive_file_size(void)
4502 if (Globals.iminreceivefile < 0) {
4503 return 0;
4505 return Globals.iminreceivefile;
4508 /*******************************************************************
4509 Safe wide links checks.
4510 This helper function always verify the validity of wide links,
4511 even after a configuration file reload.
4512 ********************************************************************/
4514 static bool lp_widelinks_internal(int snum)
4516 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
4517 sDefault.bWidelinks);
4520 void widelinks_warning(int snum)
4522 if (lp_allow_insecure_wide_links()) {
4523 return;
4526 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
4527 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
4528 "These parameters are incompatible. "
4529 "Wide links will be disabled for this share.\n",
4530 lp_servicename(talloc_tos(), snum) ));
4534 bool lp_widelinks(int snum)
4536 /* wide links is always incompatible with unix extensions */
4537 if (lp_unix_extensions()) {
4539 * Unless we have "allow insecure widelinks"
4540 * turned on.
4542 if (!lp_allow_insecure_wide_links()) {
4543 return false;
4547 return lp_widelinks_internal(snum);
4550 int lp_server_role(void)
4552 return lp_find_server_role(lp__server_role(),
4553 lp__security(),
4554 lp__domain_logons(),
4555 lp_domain_master_true_or_auto());
4558 int lp_security(void)
4560 return lp_find_security(lp__server_role(),
4561 lp__security());
4564 struct loadparm_global * get_globals(void)
4566 return &Globals;
4569 unsigned int * get_flags(void)
4571 if (flags_list == NULL) {
4572 flags_list = talloc_zero_array(NULL, unsigned int, num_parameters());
4575 return flags_list;