lib/param: Add new parameter "old password allowed period"
[Samba.git] / source3 / param / loadparm.c
blob8006167fe519c4e9e01a2fd4e392633b6291c6b4
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;
260 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
262 /* prototypes for the special type handlers */
263 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
264 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
265 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
266 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
267 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
268 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
269 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
270 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
271 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
272 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
273 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
274 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
276 /* these are parameter handlers which are not needed in the
277 * source3 code
280 #define handle_logfile NULL
282 static void set_allowed_client_auth(void);
284 static void add_to_file_list(const char *fname, const char *subfname);
285 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
286 static void free_param_opts(struct parmlist_entry **popts);
288 #include "lib/param/param_table.c"
290 /* this is used to prevent lots of mallocs of size 1 */
291 static const char null_string[] = "";
294 Set a string value, allocing the space for the string
297 static bool string_init(char **dest,const char *src)
299 size_t l;
301 if (!src)
302 src = "";
304 l = strlen(src);
306 if (l == 0) {
307 *dest = discard_const_p(char, null_string);
308 } else {
309 (*dest) = SMB_STRDUP(src);
310 if ((*dest) == NULL) {
311 DEBUG(0,("Out of memory in string_init\n"));
312 return false;
315 return(true);
319 Free a string value.
322 static void string_free(char **s)
324 if (!s || !(*s))
325 return;
326 if (*s == null_string)
327 *s = NULL;
328 SAFE_FREE(*s);
332 Set a string value, deallocating any existing space, and allocing the space
333 for the string
336 static bool string_set(char **dest,const char *src)
338 string_free(dest);
339 return(string_init(dest,src));
342 /***************************************************************************
343 Initialise the sDefault parameter structure for the printer values.
344 ***************************************************************************/
346 static void init_printer_values(struct loadparm_service *pService)
348 /* choose defaults depending on the type of printing */
349 switch (pService->printing) {
350 case PRINT_BSD:
351 case PRINT_AIX:
352 case PRINT_LPRNT:
353 case PRINT_LPROS2:
354 string_set(&pService->lpq_command, "lpq -P'%p'");
355 string_set(&pService->lprm_command, "lprm -P'%p' %j");
356 string_set(&pService->print_command, "lpr -r -P'%p' %s");
357 break;
359 case PRINT_LPRNG:
360 case PRINT_PLP:
361 string_set(&pService->lpq_command, "lpq -P'%p'");
362 string_set(&pService->lprm_command, "lprm -P'%p' %j");
363 string_set(&pService->print_command, "lpr -r -P'%p' %s");
364 string_set(&pService->queuepause_command, "lpc stop '%p'");
365 string_set(&pService->queueresume_command, "lpc start '%p'");
366 string_set(&pService->lppause_command, "lpc hold '%p' %j");
367 string_set(&pService->lpresume_command, "lpc release '%p' %j");
368 break;
370 case PRINT_CUPS:
371 case PRINT_IPRINT:
372 /* set the lpq command to contain the destination printer
373 name only. This is used by cups_queue_get() */
374 string_set(&pService->lpq_command, "%p");
375 string_set(&pService->lprm_command, "");
376 string_set(&pService->print_command, "");
377 string_set(&pService->lppause_command, "");
378 string_set(&pService->lpresume_command, "");
379 string_set(&pService->queuepause_command, "");
380 string_set(&pService->queueresume_command, "");
381 break;
383 case PRINT_SYSV:
384 case PRINT_HPUX:
385 string_set(&pService->lpq_command, "lpstat -o%p");
386 string_set(&pService->lprm_command, "cancel %p-%j");
387 string_set(&pService->print_command, "lp -c -d%p %s; rm %s");
388 string_set(&pService->queuepause_command, "disable %p");
389 string_set(&pService->queueresume_command, "enable %p");
390 #ifndef HPUX
391 string_set(&pService->lppause_command, "lp -i %p-%j -H hold");
392 string_set(&pService->lpresume_command, "lp -i %p-%j -H resume");
393 #endif /* HPUX */
394 break;
396 case PRINT_QNX:
397 string_set(&pService->lpq_command, "lpq -P%p");
398 string_set(&pService->lprm_command, "lprm -P%p %j");
399 string_set(&pService->print_command, "lp -r -P%p %s");
400 break;
402 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
404 case PRINT_TEST:
405 case PRINT_VLP: {
406 const char *tdbfile;
407 TALLOC_CTX *tmp_ctx = talloc_stackframe();
408 char *tmp;
410 tdbfile = talloc_asprintf(
411 tmp_ctx, "tdbfile=%s",
412 lp_parm_const_string(-1, "vlp", "tdbfile",
413 "/tmp/vlp.tdb"));
414 if (tdbfile == NULL) {
415 tdbfile="tdbfile=/tmp/vlp.tdb";
418 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
419 tdbfile);
420 string_set(&pService->print_command,
421 tmp ? tmp : "vlp print %p %s");
423 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
424 tdbfile);
425 string_set(&pService->lpq_command,
426 tmp ? tmp : "vlp lpq %p");
428 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
429 tdbfile);
430 string_set(&pService->lprm_command,
431 tmp ? tmp : "vlp lprm %p %j");
433 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
434 tdbfile);
435 string_set(&pService->lppause_command,
436 tmp ? tmp : "vlp lppause %p %j");
438 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
439 tdbfile);
440 string_set(&pService->lpresume_command,
441 tmp ? tmp : "vlp lpresume %p %j");
443 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
444 tdbfile);
445 string_set(&pService->queuepause_command,
446 tmp ? tmp : "vlp queuepause %p");
448 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
449 tdbfile);
450 string_set(&pService->queueresume_command,
451 tmp ? tmp : "vlp queueresume %p");
452 TALLOC_FREE(tmp_ctx);
454 break;
456 #endif /* DEVELOPER */
461 * Function to return the default value for the maximum number of open
462 * file descriptors permitted. This function tries to consult the
463 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
464 * the smaller of those.
466 static int max_open_files(void)
468 int sysctl_max = MAX_OPEN_FILES;
469 int rlimit_max = MAX_OPEN_FILES;
471 #ifdef HAVE_SYSCTLBYNAME
473 size_t size = sizeof(sysctl_max);
474 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
477 #endif
479 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
481 struct rlimit rl;
483 ZERO_STRUCT(rl);
485 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
486 rlimit_max = rl.rlim_cur;
488 #if defined(RLIM_INFINITY)
489 if(rl.rlim_cur == RLIM_INFINITY)
490 rlimit_max = MAX_OPEN_FILES;
491 #endif
493 #endif
495 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
496 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
497 "minimum Windows limit (%d)\n",
498 sysctl_max,
499 MIN_OPEN_FILES_WINDOWS));
500 sysctl_max = MIN_OPEN_FILES_WINDOWS;
503 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
504 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
505 "minimum Windows limit (%d)\n",
506 rlimit_max,
507 MIN_OPEN_FILES_WINDOWS));
508 rlimit_max = MIN_OPEN_FILES_WINDOWS;
511 return MIN(sysctl_max, rlimit_max);
515 * Common part of freeing allocated data for one parameter.
517 static void free_one_parameter_common(void *parm_ptr,
518 struct parm_struct parm)
520 if ((parm.type == P_STRING) ||
521 (parm.type == P_USTRING))
523 string_free((char**)parm_ptr);
524 } else if (parm.type == P_LIST) {
525 TALLOC_FREE(*((char***)parm_ptr));
530 * Free the allocated data for one parameter for a share
531 * given as a service struct.
533 static void free_one_parameter(struct loadparm_service *service,
534 struct parm_struct parm)
536 void *parm_ptr;
538 if (parm.p_class != P_LOCAL) {
539 return;
542 parm_ptr = lp_parm_ptr(service, &parm);
544 free_one_parameter_common(parm_ptr, parm);
548 * Free the allocated parameter data of a share given
549 * as a service struct.
551 static void free_parameters(struct loadparm_service *service)
553 uint32_t i;
555 for (i=0; parm_table[i].label; i++) {
556 free_one_parameter(service, parm_table[i]);
561 * Free the allocated data for one parameter for a given share
562 * specified by an snum.
564 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
566 void *parm_ptr;
568 if (snum < 0) {
569 parm_ptr = lp_parm_ptr(NULL, &parm);
570 } else if (parm.p_class != P_LOCAL) {
571 return;
572 } else {
573 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
576 free_one_parameter_common(parm_ptr, parm);
580 * Free the allocated parameter data for a share specified
581 * by an snum.
583 static void free_parameters_by_snum(int snum)
585 uint32_t i;
587 for (i=0; parm_table[i].label; i++) {
588 free_one_parameter_by_snum(snum, parm_table[i]);
593 * Free the allocated global parameters.
595 static void free_global_parameters(void)
597 free_param_opts(&Globals.param_opt);
598 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
599 TALLOC_FREE(Globals.ctx);
602 struct lp_stored_option {
603 struct lp_stored_option *prev, *next;
604 const char *label;
605 const char *value;
608 static struct lp_stored_option *stored_options;
611 save options set by lp_set_cmdline() into a list. This list is
612 re-applied when we do a globals reset, so that cmdline set options
613 are sticky across reloads of smb.conf
615 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
617 struct lp_stored_option *entry, *entry_next;
618 for (entry = stored_options; entry != NULL; entry = entry_next) {
619 entry_next = entry->next;
620 if (strcmp(pszParmName, entry->label) == 0) {
621 DLIST_REMOVE(stored_options, entry);
622 talloc_free(entry);
623 break;
627 entry = talloc(NULL, struct lp_stored_option);
628 if (!entry) {
629 return false;
632 entry->label = talloc_strdup(entry, pszParmName);
633 if (!entry->label) {
634 talloc_free(entry);
635 return false;
638 entry->value = talloc_strdup(entry, pszParmValue);
639 if (!entry->value) {
640 talloc_free(entry);
641 return false;
644 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
646 return true;
649 static bool apply_lp_set_cmdline(void)
651 struct lp_stored_option *entry = NULL;
652 for (entry = stored_options; entry != NULL; entry = entry->next) {
653 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
654 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
655 entry->label, entry->value));
656 return false;
659 return true;
662 /***************************************************************************
663 Initialise the global parameter structure.
664 ***************************************************************************/
666 static void init_globals(bool reinit_globals)
668 static bool done_init = false;
669 char *s = NULL;
670 int i;
672 /* If requested to initialize only once and we've already done it... */
673 if (!reinit_globals && done_init) {
674 /* ... then we have nothing more to do */
675 return;
678 if (!done_init) {
679 /* The logfile can be set before this is invoked. Free it if so. */
680 if (Globals.logfile != NULL) {
681 string_free(&Globals.logfile);
682 Globals.logfile = NULL;
684 done_init = true;
685 } else {
686 free_global_parameters();
689 /* This memset and the free_global_parameters() above will
690 * wipe out smb.conf options set with lp_set_cmdline(). The
691 * apply_lp_set_cmdline() call puts these values back in the
692 * table once the defaults are set */
693 ZERO_STRUCT(Globals);
695 Globals.ctx = talloc_new(NULL);
697 for (i = 0; parm_table[i].label; i++) {
698 if ((parm_table[i].type == P_STRING ||
699 parm_table[i].type == P_USTRING))
701 string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
706 string_set(&sDefault.fstype, FSTYPE_STRING);
707 string_set(&sDefault.printjob_username, "%U");
709 init_printer_values(&sDefault);
711 sDefault.ntvfs_handler = (const char **)str_list_make_v3(NULL, "unixuid default", NULL);
713 DEBUG(3, ("Initialising global parameters\n"));
715 /* Must manually force to upper case here, as this does not go via the handler */
716 string_set(&Globals.netbios_name, myhostname_upper());
718 string_set(&Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
719 string_set(&Globals.private_dir, get_dyn_PRIVATE_DIR());
721 /* use the new 'hash2' method by default, with a prefix of 1 */
722 string_set(&Globals.mangling_method, "hash2");
723 Globals.mangle_prefix = 1;
725 string_set(&Globals.guest_account, GUEST_ACCOUNT);
727 /* using UTF8 by default allows us to support all chars */
728 string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
730 /* Use codepage 850 as a default for the dos character set */
731 string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
734 * Allow the default PASSWD_CHAT to be overridden in local.h.
736 string_set(&Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
738 string_set(&Globals.workgroup, DEFAULT_WORKGROUP);
740 string_set(&Globals.passwd_program, "");
741 string_set(&Globals.lock_directory, get_dyn_LOCKDIR());
742 string_set(&Globals.state_directory, get_dyn_STATEDIR());
743 string_set(&Globals.cache_directory, get_dyn_CACHEDIR());
744 string_set(&Globals.pid_directory, get_dyn_PIDDIR());
745 string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
747 * By default support explicit binding to broadcast
748 * addresses.
750 Globals.nmbd_bind_explicit_broadcast = true;
752 if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
753 smb_panic("init_globals: ENOMEM");
755 string_set(&Globals.server_string, s);
756 SAFE_FREE(s);
757 #ifdef DEVELOPER
758 string_set(&Globals.panic_action, "/bin/sleep 999999999");
759 #endif
761 string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
763 string_set(&Globals.logon_drive, "");
764 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
765 string_set(&Globals.logon_home, "\\\\%N\\%U");
766 string_set(&Globals.logon_path, "\\\\%N\\%U\\profile");
768 Globals.name_resolve_order = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
769 string_set(&Globals.password_server, "*");
771 Globals.algorithmic_rid_base = BASE_RID;
773 Globals.load_printers = true;
774 Globals.printcap_cache_time = 750; /* 12.5 minutes */
776 Globals.config_backend = config_backend;
777 Globals._server_role = ROLE_AUTO;
779 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
780 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
781 Globals.max_xmit = 0x4104;
782 Globals.max_mux = 50; /* This is *needed* for profile support. */
783 Globals.lpq_cache_time = 30; /* changed to handle large print servers better -- jerry */
784 Globals._disable_spoolss = false;
785 Globals.max_smbd_processes = 0;/* no limit specified */
786 Globals.username_level = 0;
787 Globals.deadtime = 0;
788 Globals.getwd_cache = true;
789 Globals.large_readwrite = true;
790 Globals.max_log_size = 5000;
791 Globals.max_open_files = max_open_files();
792 Globals.server_max_protocol = PROTOCOL_SMB3_00;
793 Globals.server_min_protocol = PROTOCOL_LANMAN1;
794 Globals.client_max_protocol = PROTOCOL_NT1;
795 Globals.client_min_protocol = PROTOCOL_CORE;
796 Globals._security = SEC_AUTO;
797 Globals.encrypt_passwords = true;
798 Globals.client_schannel = Auto;
799 Globals.winbind_sealed_pipes = true;
800 Globals.require_strong_key = true;
801 Globals.server_schannel = Auto;
802 Globals.read_raw = true;
803 Globals.write_raw = true;
804 Globals.null_passwords = false;
805 Globals.old_password_allowed_period = 60;
806 Globals.obey_pam_restrictions = false;
807 Globals.syslog = 1;
808 Globals.syslog_only = false;
809 Globals.timestamp_logs = true;
810 string_set(&Globals.log_level, "0");
811 Globals.debug_prefix_timestamp = false;
812 Globals.debug_hires_timestamp = true;
813 Globals.debug_pid = false;
814 Globals.debug_uid = false;
815 Globals.debug_class = false;
816 Globals.enable_core_files = true;
817 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
818 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
819 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
820 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
821 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
822 Globals.lm_interval = 60;
823 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
824 Globals.nis_homedir = false;
825 #ifdef WITH_NISPLUS_HOME
826 string_set(&Globals.homedir_map, "auto_home.org_dir");
827 #else
828 string_set(&Globals.homedir_map, "auto.home");
829 #endif
830 #endif
831 Globals.time_server = false;
832 Globals.bind_interfaces_only = false;
833 Globals.unix_password_sync = false;
834 Globals.pam_password_change = false;
835 Globals.passwd_chat_debug = false;
836 Globals.passwd_chat_timeout = 2; /* 2 second default. */
837 Globals.nt_pipe_support = true; /* Do NT pipes by default. */
838 Globals.nt_status_support = true; /* Use NT status by default. */
839 Globals.stat_cache = true; /* use stat cache by default */
840 Globals.max_stat_cache_size = 256; /* 256k by default */
841 Globals.restrict_anonymous = 0;
842 Globals.client_lanman_auth = false; /* Do NOT use the LanMan hash if it is available */
843 Globals.client_plaintext_auth = false; /* Do NOT use a plaintext password even if is requested by the server */
844 Globals.lanman_auth = false; /* Do NOT use the LanMan hash, even if it is supplied */
845 Globals.ntlm_auth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
846 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 */
847 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
849 Globals.map_to_guest = 0; /* By Default, "Never" */
850 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
851 Globals.enhanced_browsing = true;
852 Globals.lock_spin_time = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
853 #ifdef MMAP_BLACKLIST
854 Globals.use_mmap = false;
855 #else
856 Globals.use_mmap = true;
857 #endif
858 Globals.unicode = true;
859 Globals.unix_extensions = true;
860 Globals.reset_on_zero_vc = false;
861 Globals.log_writeable_files_on_exit = false;
862 Globals.create_krb5_conf = true;
863 Globals.winbindMaxDomainConnections = 1;
865 /* hostname lookups can be very expensive and are broken on
866 a large number of sites (tridge) */
867 Globals.hostname_lookups = false;
869 string_set(&Globals.passdb_backend, "tdbsam");
870 string_set(&Globals.ldap_suffix, "");
871 string_set(&Globals.szLdapMachineSuffix, "");
872 string_set(&Globals.szLdapUserSuffix, "");
873 string_set(&Globals.szLdapGroupSuffix, "");
874 string_set(&Globals.szLdapIdmapSuffix, "");
876 string_set(&Globals.ldap_admin_dn, "");
877 Globals.ldap_ssl = LDAP_SSL_START_TLS;
878 Globals.ldap_ssl_ads = false;
879 Globals.ldap_deref = -1;
880 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
881 Globals.ldap_delete_dn = false;
882 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
883 Globals.ldap_follow_referral = Auto;
884 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
885 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
886 Globals.ldap_page_size = LDAP_PAGE_SIZE;
888 Globals.ldap_debug_level = 0;
889 Globals.ldap_debug_threshold = 10;
891 /* This is what we tell the afs client. in reality we set the token
892 * to never expire, though, when this runs out the afs client will
893 * forget the token. Set to 0 to get NEVERDATE.*/
894 Globals.afs_token_lifetime = 604800;
895 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
897 /* these parameters are set to defaults that are more appropriate
898 for the increasing samba install base:
900 as a member of the workgroup, that will possibly become a
901 _local_ master browser (lm = true). this is opposed to a forced
902 local master browser startup (pm = true).
904 doesn't provide WINS server service by default (wsupp = false),
905 and doesn't provide domain master browser services by default, either.
909 Globals.show_add_printer_wizard = true;
910 Globals.os_level = 20;
911 Globals.local_master = true;
912 Globals._domain_master = Auto; /* depending on _domain_logons */
913 Globals._domain_logons = false;
914 Globals.browse_list = true;
915 Globals.we_are_a_wins_server = false;
916 Globals.wins_proxy = false;
918 TALLOC_FREE(Globals.init_logon_delayed_hosts);
919 Globals.init_logon_delay = 100; /* 100 ms default delay */
921 Globals.wins_dns_proxy = true;
923 Globals.allow_trusted_domains = true;
924 string_set(&Globals.szIdmapBackend, "tdb");
926 string_set(&Globals.template_shell, "/bin/false");
927 string_set(&Globals.template_homedir, "/home/%D/%U");
928 string_set(&Globals.winbind_separator, "\\");
929 string_set(&Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
931 string_set(&Globals.cups_server, "");
932 string_set(&Globals.iprint_server, "");
934 string_set(&Globals._ctdbd_socket, "");
936 Globals.cluster_addresses = NULL;
937 Globals.clustering = false;
938 Globals.ctdb_timeout = 0;
939 Globals.ctdb_locktime_warn_threshold = 0;
941 Globals.winbind_cache_time = 300; /* 5 minutes */
942 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
943 Globals.winbind_max_clients = 200;
944 Globals.winbind_enum_users = false;
945 Globals.winbind_enum_groups = false;
946 Globals.winbind_use_default_domain = false;
947 Globals.winbind_trusted_domains_only = false;
948 Globals.winbind_nested_groups = true;
949 Globals.winbind_expand_groups = 1;
950 Globals.winbind_nss_info = (const char **)str_list_make_v3(NULL, "template", NULL);
951 Globals.winbind_refresh_tickets = false;
952 Globals.winbind_offline_logon = false;
954 Globals.idmap_cache_time = 86400 * 7; /* a week by default */
955 Globals.idmap_negative_cache_time = 120; /* 2 minutes by default */
957 Globals.passdb_expand_explicit = false;
959 Globals.name_cache_timeout = 660; /* In seconds */
961 Globals.use_spnego = true;
962 Globals.client_use_spnego = true;
964 Globals.client_signing = SMB_SIGNING_DEFAULT;
965 Globals.server_signing = SMB_SIGNING_DEFAULT;
967 Globals.defer_sharing_violations = true;
968 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
970 Globals.enable_privileges = true;
971 Globals.host_msdfs = true;
972 Globals.enable_asu_support = false;
974 /* User defined shares. */
975 if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
976 smb_panic("init_globals: ENOMEM");
978 string_set(&Globals.usershare_path, s);
979 SAFE_FREE(s);
980 string_set(&Globals.usershare_template_share, "");
981 Globals.usershare_max_shares = 0;
982 /* By default disallow sharing of directories not owned by the sharer. */
983 Globals.usershare_owner_only = true;
984 /* By default disallow guest access to usershares. */
985 Globals.usershare_allow_guests = false;
987 Globals.keepalive = DEFAULT_KEEPALIVE;
989 /* By default no shares out of the registry */
990 Globals.registry_shares = false;
992 Globals.iminreceivefile = 0;
994 Globals.map_untrusted_to_domain = false;
995 Globals.multicast_dns_register = true;
997 Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
998 Globals.smb2_max_write = DEFAULT_SMB2_MAX_WRITE;
999 Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
1000 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1002 string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1004 Globals.server_services = (const char **)str_list_make_v3(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate dns", NULL);
1006 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);
1008 Globals.tls_enabled = true;
1010 string_set(&Globals._tls_keyfile, "tls/key.pem");
1011 string_set(&Globals._tls_certfile, "tls/cert.pem");
1012 string_set(&Globals._tls_cafile, "tls/ca.pem");
1014 string_set(&Globals.share_backend, "classic");
1016 Globals.iPreferredMaster = Auto;
1018 Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
1020 string_set(&Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
1022 string_set(&Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
1024 if (asprintf(&s, "%s/samba_kcc", get_dyn_SCRIPTSBINDIR()) < 0) {
1025 smb_panic("init_globals: ENOMEM");
1027 Globals.samba_kcc_command = (const char **)str_list_make_v3(NULL, s, NULL);
1028 SAFE_FREE(s);
1030 if (asprintf(&s, "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR()) < 0) {
1031 smb_panic("init_globals: ENOMEM");
1033 Globals.dns_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1034 SAFE_FREE(s);
1036 if (asprintf(&s, "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR()) < 0) {
1037 smb_panic("init_globals: ENOMEM");
1039 Globals.spn_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1040 SAFE_FREE(s);
1042 Globals.nsupdate_command = (const char **)str_list_make_v3(NULL, "/usr/bin/nsupdate -g", NULL);
1044 Globals.rndc_command = (const char **)str_list_make_v3(NULL, "/usr/sbin/rndc", NULL);
1046 Globals.cldap_port = 389;
1048 Globals.dgram_port = 138;
1050 Globals.nbt_port = 137;
1052 Globals.krb5_port = 88;
1054 Globals.kpasswd_port = 464;
1056 Globals.web_port = 901;
1058 /* Now put back the settings that were set with lp_set_cmdline() */
1059 apply_lp_set_cmdline();
1062 /*******************************************************************
1063 Convenience routine to grab string parameters into talloced memory
1064 and run standard_sub_basic on them. The buffers can be written to by
1065 callers without affecting the source string.
1066 ********************************************************************/
1068 char *lp_string(TALLOC_CTX *ctx, const char *s)
1070 char *ret;
1072 /* The follow debug is useful for tracking down memory problems
1073 especially if you have an inner loop that is calling a lp_*()
1074 function that returns a string. Perhaps this debug should be
1075 present all the time? */
1077 #if 0
1078 DEBUG(10, ("lp_string(%s)\n", s));
1079 #endif
1080 if (!s) {
1081 return NULL;
1084 ret = talloc_sub_basic(ctx,
1085 get_current_username(),
1086 current_user_info.domain,
1088 if (trim_char(ret, '\"', '\"')) {
1089 if (strchr(ret,'\"') != NULL) {
1090 TALLOC_FREE(ret);
1091 ret = talloc_sub_basic(ctx,
1092 get_current_username(),
1093 current_user_info.domain,
1097 return ret;
1101 In this section all the functions that are used to access the
1102 parameters from the rest of the program are defined
1105 #define FN_GLOBAL_STRING(fn_name,ptr) \
1106 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1107 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1108 const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1109 #define FN_GLOBAL_LIST(fn_name,ptr) \
1110 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1111 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1112 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1113 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1114 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1115 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1116 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1118 #define FN_LOCAL_STRING(fn_name,val) \
1119 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));}
1120 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1121 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1122 #define FN_LOCAL_LIST(fn_name,val) \
1123 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1124 #define FN_LOCAL_BOOL(fn_name,val) \
1125 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1126 #define FN_LOCAL_INTEGER(fn_name,val) \
1127 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1129 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1130 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1131 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1132 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1133 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
1134 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1136 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1137 winbindMaxDomainConnections)
1139 int lp_winbind_max_domain_connections(void)
1141 if (lp_winbind_offline_logon() &&
1142 lp_winbind_max_domain_connections_int() > 1) {
1143 DEBUG(1, ("offline logons active, restricting max domain "
1144 "connections to 1\n"));
1145 return 1;
1147 return MAX(1, lp_winbind_max_domain_connections_int());
1150 int lp_smb2_max_credits(void)
1152 if (Globals.ismb2_max_credits == 0) {
1153 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1155 return Globals.ismb2_max_credits;
1157 int lp_cups_encrypt(void)
1159 int result = 0;
1160 #ifdef HAVE_HTTPCONNECTENCRYPT
1161 switch (Globals.CupsEncrypt) {
1162 case Auto:
1163 result = HTTP_ENCRYPT_REQUIRED;
1164 break;
1165 case true:
1166 result = HTTP_ENCRYPT_ALWAYS;
1167 break;
1168 case false:
1169 result = HTTP_ENCRYPT_NEVER;
1170 break;
1172 #endif
1173 return result;
1176 /* These functions remain in source3/param for now */
1178 #include "lib/param/param_functions.c"
1180 FN_LOCAL_STRING(servicename, szService)
1181 FN_LOCAL_CONST_STRING(const_servicename, szService)
1183 /* These functions cannot be auto-generated */
1184 FN_LOCAL_BOOL(autoloaded, autoloaded)
1186 /* local prototypes */
1188 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1189 static const char *get_boolean(bool bool_value);
1190 static int getservicebyname(const char *pszServiceName,
1191 struct loadparm_service *pserviceDest);
1192 static void copy_service(struct loadparm_service *pserviceDest,
1193 struct loadparm_service *pserviceSource,
1194 struct bitmap *pcopymapDest);
1195 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1196 void *userdata);
1197 static bool do_section(const char *pszSectionName, void *userdata);
1198 static void init_copymap(struct loadparm_service *pservice);
1199 static bool hash_a_service(const char *name, int number);
1200 static void free_service_byindex(int iService);
1201 static void show_parameter(int parmIndex);
1202 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1205 * This is a helper function for parametrical options support. It returns a
1206 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1207 * parametrical functions are quite simple
1209 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1210 const char *option)
1212 bool global_section = false;
1213 char* param_key;
1214 struct parmlist_entry *data;
1216 if (service == NULL) {
1217 data = Globals.param_opt;
1218 global_section = true;
1219 } else {
1220 data = service->param_opt;
1223 if (asprintf(&param_key, "%s:%s", type, option) == -1) {
1224 DEBUG(0,("asprintf failed!\n"));
1225 return NULL;
1228 while (data) {
1229 if (strwicmp(data->key, param_key) == 0) {
1230 string_free(&param_key);
1231 return data;
1233 data = data->next;
1236 if (!global_section) {
1237 /* Try to fetch the same option but from globals */
1238 /* but only if we are not already working with Globals */
1239 data = Globals.param_opt;
1240 while (data) {
1241 if (strwicmp(data->key, param_key) == 0) {
1242 string_free(&param_key);
1243 return data;
1245 data = data->next;
1249 string_free(&param_key);
1251 return NULL;
1255 * This is a helper function for parametrical options support. It returns a
1256 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1257 * parametrical functions are quite simple
1259 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1260 const char *option)
1262 if (snum >= iNumServices) return NULL;
1264 if (snum < 0) {
1265 return get_parametrics_by_service(NULL, type, option);
1266 } else {
1267 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1272 #define MISSING_PARAMETER(name) \
1273 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1275 /*******************************************************************
1276 convenience routine to return int parameters.
1277 ********************************************************************/
1278 static int lp_int(const char *s)
1281 if (!s || !*s) {
1282 MISSING_PARAMETER(lp_int);
1283 return (-1);
1286 return (int)strtol(s, NULL, 0);
1289 /*******************************************************************
1290 convenience routine to return unsigned long parameters.
1291 ********************************************************************/
1292 static unsigned long lp_ulong(const char *s)
1295 if (!s || !*s) {
1296 MISSING_PARAMETER(lp_ulong);
1297 return (0);
1300 return strtoul(s, NULL, 0);
1303 /*******************************************************************
1304 convenience routine to return boolean parameters.
1305 ********************************************************************/
1306 static bool lp_bool(const char *s)
1308 bool ret = false;
1310 if (!s || !*s) {
1311 MISSING_PARAMETER(lp_bool);
1312 return false;
1315 if (!set_boolean(s, &ret)) {
1316 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1317 return false;
1320 return ret;
1323 /*******************************************************************
1324 convenience routine to return enum parameters.
1325 ********************************************************************/
1326 static int lp_enum(const char *s,const struct enum_list *_enum)
1328 int i;
1330 if (!s || !*s || !_enum) {
1331 MISSING_PARAMETER(lp_enum);
1332 return (-1);
1335 for (i=0; _enum[i].name; i++) {
1336 if (strequal(_enum[i].name,s))
1337 return _enum[i].value;
1340 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1341 return (-1);
1344 #undef MISSING_PARAMETER
1346 /* Return parametric option from a given service. Type is a part of option before ':' */
1347 /* Parametric option has following syntax: 'Type: option = value' */
1348 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1350 struct parmlist_entry *data = get_parametrics(snum, type, option);
1352 if (data == NULL||data->value==NULL) {
1353 if (def) {
1354 return lp_string(ctx, def);
1355 } else {
1356 return NULL;
1360 return lp_string(ctx, data->value);
1363 /* Return parametric option from a given service. Type is a part of option before ':' */
1364 /* Parametric option has following syntax: 'Type: option = value' */
1365 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1367 struct parmlist_entry *data = get_parametrics(snum, type, option);
1369 if (data == NULL||data->value==NULL)
1370 return def;
1372 return data->value;
1375 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1377 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1379 if (data == NULL||data->value==NULL)
1380 return NULL;
1382 return data->value;
1386 /* Return parametric option from a given service. Type is a part of option before ':' */
1387 /* Parametric option has following syntax: 'Type: option = value' */
1389 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1391 struct parmlist_entry *data = get_parametrics(snum, type, option);
1393 if (data == NULL||data->value==NULL)
1394 return (const char **)def;
1396 if (data->list==NULL) {
1397 data->list = str_list_make_v3(NULL, data->value, NULL);
1400 return (const char **)data->list;
1403 /* Return parametric option from a given service. Type is a part of option before ':' */
1404 /* Parametric option has following syntax: 'Type: option = value' */
1406 int lp_parm_int(int snum, const char *type, const char *option, int def)
1408 struct parmlist_entry *data = get_parametrics(snum, type, option);
1410 if (data && data->value && *data->value)
1411 return lp_int(data->value);
1413 return def;
1416 /* Return parametric option from a given service. Type is a part of option before ':' */
1417 /* Parametric option has following syntax: 'Type: option = value' */
1419 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1421 struct parmlist_entry *data = get_parametrics(snum, type, option);
1423 if (data && data->value && *data->value)
1424 return lp_ulong(data->value);
1426 return def;
1429 /* Return parametric option from a given service. Type is a part of option before ':' */
1430 /* Parametric option has following syntax: 'Type: option = value' */
1432 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1434 struct parmlist_entry *data = get_parametrics(snum, type, option);
1436 if (data && data->value && *data->value)
1437 return lp_bool(data->value);
1439 return def;
1442 /* Return parametric option from a given service. Type is a part of option before ':' */
1443 /* Parametric option has following syntax: 'Type: option = value' */
1445 int lp_parm_enum(int snum, const char *type, const char *option,
1446 const struct enum_list *_enum, int def)
1448 struct parmlist_entry *data = get_parametrics(snum, type, option);
1450 if (data && data->value && *data->value && _enum)
1451 return lp_enum(data->value, _enum);
1453 return def;
1457 /***************************************************************************
1458 Initialise a service to the defaults.
1459 ***************************************************************************/
1461 static void init_service(struct loadparm_service *pservice)
1463 memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1464 copy_service(pservice, &sDefault, NULL);
1469 * free a param_opts structure.
1470 * param_opts handling should be moved to talloc;
1471 * then this whole functions reduces to a TALLOC_FREE().
1474 static void free_param_opts(struct parmlist_entry **popts)
1476 struct parmlist_entry *opt, *next_opt;
1478 if (*popts != NULL) {
1479 DEBUG(5, ("Freeing parametrics:\n"));
1481 opt = *popts;
1482 while (opt != NULL) {
1483 string_free(&opt->key);
1484 string_free(&opt->value);
1485 TALLOC_FREE(opt->list);
1486 next_opt = opt->next;
1487 SAFE_FREE(opt);
1488 opt = next_opt;
1490 *popts = NULL;
1493 /***************************************************************************
1494 Free the dynamically allocated parts of a service struct.
1495 ***************************************************************************/
1497 static void free_service(struct loadparm_service *pservice)
1499 if (!pservice)
1500 return;
1502 if (pservice->szService)
1503 DEBUG(5, ("free_service: Freeing service %s\n",
1504 pservice->szService));
1506 free_parameters(pservice);
1508 string_free(&pservice->szService);
1509 TALLOC_FREE(pservice->copymap);
1511 free_param_opts(&pservice->param_opt);
1513 ZERO_STRUCTP(pservice);
1517 /***************************************************************************
1518 remove a service indexed in the ServicePtrs array from the ServiceHash
1519 and free the dynamically allocated parts
1520 ***************************************************************************/
1522 static void free_service_byindex(int idx)
1524 if ( !LP_SNUM_OK(idx) )
1525 return;
1527 ServicePtrs[idx]->valid = false;
1529 /* we have to cleanup the hash record */
1531 if (ServicePtrs[idx]->szService) {
1532 char *canon_name = canonicalize_servicename(
1533 talloc_tos(),
1534 ServicePtrs[idx]->szService );
1536 dbwrap_delete_bystring(ServiceHash, canon_name );
1537 TALLOC_FREE(canon_name);
1540 free_service(ServicePtrs[idx]);
1541 talloc_free_children(ServicePtrs[idx]);
1544 /***************************************************************************
1545 Add a new service to the services array initialising it with the given
1546 service.
1547 ***************************************************************************/
1549 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1551 int i;
1552 struct loadparm_service tservice;
1553 int num_to_alloc = iNumServices + 1;
1554 struct loadparm_service **tsp = NULL;
1556 tservice = *pservice;
1558 /* it might already exist */
1559 if (name) {
1560 i = getservicebyname(name, NULL);
1561 if (i >= 0) {
1562 return (i);
1566 /* if not, then create one */
1567 i = iNumServices;
1568 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1569 if (tsp == NULL) {
1570 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1571 return (-1);
1573 ServicePtrs = tsp;
1574 ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1575 if (!ServicePtrs[iNumServices]) {
1576 DEBUG(0,("add_a_service: out of memory!\n"));
1577 return (-1);
1579 iNumServices++;
1581 ServicePtrs[i]->valid = true;
1583 init_service(ServicePtrs[i]);
1584 copy_service(ServicePtrs[i], &tservice, NULL);
1585 if (name)
1586 string_set(&ServicePtrs[i]->szService, name);
1588 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1589 i, ServicePtrs[i]->szService));
1591 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1592 return (-1);
1595 return (i);
1598 /***************************************************************************
1599 Convert a string to uppercase and remove whitespaces.
1600 ***************************************************************************/
1602 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1604 char *result;
1606 if ( !src ) {
1607 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1608 return NULL;
1611 result = talloc_strdup(ctx, src);
1612 SMB_ASSERT(result != NULL);
1614 if (!strlower_m(result)) {
1615 TALLOC_FREE(result);
1616 return NULL;
1618 return result;
1621 /***************************************************************************
1622 Add a name/index pair for the services array to the hash table.
1623 ***************************************************************************/
1625 static bool hash_a_service(const char *name, int idx)
1627 char *canon_name;
1629 if ( !ServiceHash ) {
1630 DEBUG(10,("hash_a_service: creating servicehash\n"));
1631 ServiceHash = db_open_rbt(NULL);
1632 if ( !ServiceHash ) {
1633 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1634 return false;
1638 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1639 idx, name));
1641 canon_name = canonicalize_servicename(talloc_tos(), name );
1643 dbwrap_store_bystring(ServiceHash, canon_name,
1644 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1645 TDB_REPLACE);
1647 TALLOC_FREE(canon_name);
1649 return true;
1652 /***************************************************************************
1653 Add a new home service, with the specified home directory, defaults coming
1654 from service ifrom.
1655 ***************************************************************************/
1657 bool lp_add_home(const char *pszHomename, int iDefaultService,
1658 const char *user, const char *pszHomedir)
1660 int i;
1662 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1663 pszHomedir[0] == '\0') {
1664 return false;
1667 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1669 if (i < 0)
1670 return false;
1672 if (!(*(ServicePtrs[iDefaultService]->path))
1673 || strequal(ServicePtrs[iDefaultService]->path,
1674 lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1675 string_set(&ServicePtrs[i]->path, pszHomedir);
1678 if (!(*(ServicePtrs[i]->comment))) {
1679 char *comment = NULL;
1680 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1681 return false;
1683 string_set(&ServicePtrs[i]->comment, comment);
1684 SAFE_FREE(comment);
1687 /* set the browseable flag from the global default */
1689 ServicePtrs[i]->browseable = sDefault.browseable;
1690 ServicePtrs[i]->access_based_share_enum = sDefault.access_based_share_enum;
1692 ServicePtrs[i]->autoloaded = true;
1694 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1695 user, ServicePtrs[i]->path ));
1697 return true;
1700 /***************************************************************************
1701 Add a new service, based on an old one.
1702 ***************************************************************************/
1704 int lp_add_service(const char *pszService, int iDefaultService)
1706 if (iDefaultService < 0) {
1707 return add_a_service(&sDefault, pszService);
1710 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1713 /***************************************************************************
1714 Add the IPC service.
1715 ***************************************************************************/
1717 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1719 char *comment = NULL;
1720 int i = add_a_service(&sDefault, ipc_name);
1722 if (i < 0)
1723 return false;
1725 if (asprintf(&comment, "IPC Service (%s)",
1726 Globals.server_string) < 0) {
1727 return false;
1730 string_set(&ServicePtrs[i]->path, tmpdir());
1731 string_set(&ServicePtrs[i]->username, "");
1732 string_set(&ServicePtrs[i]->comment, comment);
1733 string_set(&ServicePtrs[i]->fstype, "IPC");
1734 ServicePtrs[i]->max_connections = 0;
1735 ServicePtrs[i]->bAvailable = true;
1736 ServicePtrs[i]->read_only = true;
1737 ServicePtrs[i]->guest_only = false;
1738 ServicePtrs[i]->administrative_share = true;
1739 ServicePtrs[i]->guest_ok = guest_ok;
1740 ServicePtrs[i]->printable = false;
1741 ServicePtrs[i]->browseable = sDefault.browseable;
1743 DEBUG(3, ("adding IPC service\n"));
1745 SAFE_FREE(comment);
1746 return true;
1749 /***************************************************************************
1750 Add a new printer service, with defaults coming from service iFrom.
1751 ***************************************************************************/
1753 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1755 const char *comment = "From Printcap";
1756 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1758 if (i < 0)
1759 return false;
1761 /* note that we do NOT default the availability flag to true - */
1762 /* we take it from the default service passed. This allows all */
1763 /* dynamic printers to be disabled by disabling the [printers] */
1764 /* entry (if/when the 'available' keyword is implemented!). */
1766 /* the printer name is set to the service name. */
1767 string_set(&ServicePtrs[i]->_printername, pszPrintername);
1768 string_set(&ServicePtrs[i]->comment, comment);
1770 /* set the browseable flag from the gloabl default */
1771 ServicePtrs[i]->browseable = sDefault.browseable;
1773 /* Printers cannot be read_only. */
1774 ServicePtrs[i]->read_only = false;
1775 /* No oplocks on printer services. */
1776 ServicePtrs[i]->oplocks = false;
1777 /* Printer services must be printable. */
1778 ServicePtrs[i]->printable = true;
1780 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1782 return true;
1786 /***************************************************************************
1787 Check whether the given parameter name is valid.
1788 Parametric options (names containing a colon) are considered valid.
1789 ***************************************************************************/
1791 bool lp_parameter_is_valid(const char *pszParmName)
1793 return ((lpcfg_map_parameter(pszParmName) != -1) ||
1794 (strchr(pszParmName, ':') != NULL));
1797 /***************************************************************************
1798 Check whether the given name is the name of a global parameter.
1799 Returns true for strings belonging to parameters of class
1800 P_GLOBAL, false for all other strings, also for parametric options
1801 and strings not belonging to any option.
1802 ***************************************************************************/
1804 bool lp_parameter_is_global(const char *pszParmName)
1806 int num = lpcfg_map_parameter(pszParmName);
1808 if (num >= 0) {
1809 return (parm_table[num].p_class == P_GLOBAL);
1812 return false;
1815 /**************************************************************************
1816 Check whether the given name is the canonical name of a parameter.
1817 Returns false if it is not a valid parameter Name.
1818 For parametric options, true is returned.
1819 **************************************************************************/
1821 bool lp_parameter_is_canonical(const char *parm_name)
1823 if (!lp_parameter_is_valid(parm_name)) {
1824 return false;
1827 return (lpcfg_map_parameter(parm_name) ==
1828 map_parameter_canonical(parm_name, NULL));
1831 /**************************************************************************
1832 Determine the canonical name for a parameter.
1833 Indicate when it is an inverse (boolean) synonym instead of a
1834 "usual" synonym.
1835 **************************************************************************/
1837 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1838 bool *inverse)
1840 int num;
1842 if (!lp_parameter_is_valid(parm_name)) {
1843 *canon_parm = NULL;
1844 return false;
1847 num = map_parameter_canonical(parm_name, inverse);
1848 if (num < 0) {
1849 /* parametric option */
1850 *canon_parm = parm_name;
1851 } else {
1852 *canon_parm = parm_table[num].label;
1855 return true;
1859 /**************************************************************************
1860 Determine the canonical name for a parameter.
1861 Turn the value given into the inverse boolean expression when
1862 the synonym is an invers boolean synonym.
1864 Return true if parm_name is a valid parameter name and
1865 in case it is an invers boolean synonym, if the val string could
1866 successfully be converted to the reverse bool.
1867 Return false in all other cases.
1868 **************************************************************************/
1870 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1871 const char *val,
1872 const char **canon_parm,
1873 const char **canon_val)
1875 int num;
1876 bool inverse;
1878 if (!lp_parameter_is_valid(parm_name)) {
1879 *canon_parm = NULL;
1880 *canon_val = NULL;
1881 return false;
1884 num = map_parameter_canonical(parm_name, &inverse);
1885 if (num < 0) {
1886 /* parametric option */
1887 *canon_parm = parm_name;
1888 *canon_val = val;
1889 } else {
1890 *canon_parm = parm_table[num].label;
1891 if (inverse) {
1892 if (!lp_invert_boolean(val, canon_val)) {
1893 *canon_val = NULL;
1894 return false;
1896 } else {
1897 *canon_val = val;
1901 return true;
1904 /***************************************************************************
1905 Map a parameter's string representation to the index of the canonical
1906 form of the parameter (it might be a synonym).
1907 Returns -1 if the parameter string is not recognised.
1908 ***************************************************************************/
1910 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1912 int parm_num, canon_num;
1913 bool loc_inverse = false;
1915 parm_num = lpcfg_map_parameter(pszParmName);
1916 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1917 /* invalid, parametric or no canidate for synonyms ... */
1918 goto done;
1921 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1922 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1923 parm_num = canon_num;
1924 goto done;
1928 done:
1929 if (inverse != NULL) {
1930 *inverse = loc_inverse;
1932 return parm_num;
1935 /***************************************************************************
1936 return true if parameter number parm1 is a synonym of parameter
1937 number parm2 (parm2 being the principal name).
1938 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1939 false otherwise.
1940 ***************************************************************************/
1942 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
1944 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
1945 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
1946 (parm_table[parm1].flags & FLAG_HIDE) &&
1947 !(parm_table[parm2].flags & FLAG_HIDE))
1949 if (inverse != NULL) {
1950 if ((parm_table[parm1].type == P_BOOLREV) &&
1951 (parm_table[parm2].type == P_BOOL))
1953 *inverse = true;
1954 } else {
1955 *inverse = false;
1958 return true;
1960 return false;
1963 /***************************************************************************
1964 Show one parameter's name, type, [values,] and flags.
1965 (helper functions for show_parameter_list)
1966 ***************************************************************************/
1968 static void show_parameter(int parmIndex)
1970 int enumIndex, flagIndex;
1971 int parmIndex2;
1972 bool hadFlag;
1973 bool hadSyn;
1974 bool inverse;
1975 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
1976 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
1977 "P_ENUM", "P_SEP"};
1978 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
1979 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
1980 FLAG_HIDE};
1981 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
1982 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
1983 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
1985 printf("%s=%s", parm_table[parmIndex].label,
1986 type[parm_table[parmIndex].type]);
1987 if (parm_table[parmIndex].type == P_ENUM) {
1988 printf(",");
1989 for (enumIndex=0;
1990 parm_table[parmIndex].enum_list[enumIndex].name;
1991 enumIndex++)
1993 printf("%s%s",
1994 enumIndex ? "|" : "",
1995 parm_table[parmIndex].enum_list[enumIndex].name);
1998 printf(",");
1999 hadFlag = false;
2000 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2001 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2002 printf("%s%s",
2003 hadFlag ? "|" : "",
2004 flag_names[flagIndex]);
2005 hadFlag = true;
2009 /* output synonyms */
2010 hadSyn = false;
2011 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2012 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2013 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2014 parm_table[parmIndex2].label);
2015 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2016 if (!hadSyn) {
2017 printf(" (synonyms: ");
2018 hadSyn = true;
2019 } else {
2020 printf(", ");
2022 printf("%s%s", parm_table[parmIndex2].label,
2023 inverse ? "[i]" : "");
2026 if (hadSyn) {
2027 printf(")");
2030 printf("\n");
2033 /***************************************************************************
2034 Show all parameter's name, type, [values,] and flags.
2035 ***************************************************************************/
2037 void show_parameter_list(void)
2039 int classIndex, parmIndex;
2040 const char *section_names[] = { "local", "global", NULL};
2042 for (classIndex=0; section_names[classIndex]; classIndex++) {
2043 printf("[%s]\n", section_names[classIndex]);
2044 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2045 if (parm_table[parmIndex].p_class == classIndex) {
2046 show_parameter(parmIndex);
2052 /***************************************************************************
2053 Check if a given string correctly represents a boolean value.
2054 ***************************************************************************/
2056 bool lp_string_is_valid_boolean(const char *parm_value)
2058 return set_boolean(parm_value, NULL);
2061 /***************************************************************************
2062 Get the standard string representation of a boolean value ("yes" or "no")
2063 ***************************************************************************/
2065 static const char *get_boolean(bool bool_value)
2067 static const char *yes_str = "yes";
2068 static const char *no_str = "no";
2070 return (bool_value ? yes_str : no_str);
2073 /***************************************************************************
2074 Provide the string of the negated boolean value associated to the boolean
2075 given as a string. Returns false if the passed string does not correctly
2076 represent a boolean.
2077 ***************************************************************************/
2079 bool lp_invert_boolean(const char *str, const char **inverse_str)
2081 bool val;
2083 if (!set_boolean(str, &val)) {
2084 return false;
2087 *inverse_str = get_boolean(!val);
2088 return true;
2091 /***************************************************************************
2092 Provide the canonical string representation of a boolean value given
2093 as a string. Return true on success, false if the string given does
2094 not correctly represent a boolean.
2095 ***************************************************************************/
2097 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2099 bool val;
2101 if (!set_boolean(str, &val)) {
2102 return false;
2105 *canon_str = get_boolean(val);
2106 return true;
2109 /***************************************************************************
2110 Find a service by name. Otherwise works like get_service.
2111 ***************************************************************************/
2113 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2115 int iService = -1;
2116 char *canon_name;
2117 TDB_DATA data;
2118 NTSTATUS status;
2120 if (ServiceHash == NULL) {
2121 return -1;
2124 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2126 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2127 &data);
2129 if (NT_STATUS_IS_OK(status) &&
2130 (data.dptr != NULL) &&
2131 (data.dsize == sizeof(iService)))
2133 iService = *(int *)data.dptr;
2136 TALLOC_FREE(canon_name);
2138 if ((iService != -1) && (LP_SNUM_OK(iService))
2139 && (pserviceDest != NULL)) {
2140 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2143 return (iService);
2146 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2147 struct loadparm_service *lp_service(const char *pszServiceName)
2149 int iService = getservicebyname(pszServiceName, NULL);
2150 if (iService == -1 || !LP_SNUM_OK(iService)) {
2151 return NULL;
2153 return ServicePtrs[iService];
2156 struct loadparm_service *lp_servicebynum(int snum)
2158 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2159 return NULL;
2161 return ServicePtrs[snum];
2164 struct loadparm_service *lp_default_loadparm_service()
2166 return &sDefault;
2170 /***************************************************************************
2171 Copy a service structure to another.
2172 If pcopymapDest is NULL then copy all fields
2173 ***************************************************************************/
2176 * Add a parametric option to a parmlist_entry,
2177 * replacing old value, if already present.
2179 static void set_param_opt(struct parmlist_entry **opt_list,
2180 const char *opt_name,
2181 const char *opt_value,
2182 unsigned priority)
2184 struct parmlist_entry *new_opt, *opt;
2185 bool not_added;
2187 opt = *opt_list;
2188 not_added = true;
2190 /* Traverse destination */
2191 while (opt) {
2192 /* If we already have same option, override it */
2193 if (strwicmp(opt->key, opt_name) == 0) {
2194 if ((opt->priority & FLAG_CMDLINE) &&
2195 !(priority & FLAG_CMDLINE)) {
2196 /* it's been marked as not to be
2197 overridden */
2198 return;
2200 string_free(&opt->value);
2201 TALLOC_FREE(opt->list);
2202 opt->value = SMB_STRDUP(opt_value);
2203 opt->priority = priority;
2204 not_added = false;
2205 break;
2207 opt = opt->next;
2209 if (not_added) {
2210 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2211 new_opt->key = SMB_STRDUP(opt_name);
2212 new_opt->value = SMB_STRDUP(opt_value);
2213 new_opt->list = NULL;
2214 new_opt->priority = priority;
2215 DLIST_ADD(*opt_list, new_opt);
2219 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2220 struct bitmap *pcopymapDest)
2222 int i;
2223 bool bcopyall = (pcopymapDest == NULL);
2224 struct parmlist_entry *data;
2226 for (i = 0; parm_table[i].label; i++)
2227 if (parm_table[i].p_class == P_LOCAL &&
2228 (bcopyall || bitmap_query(pcopymapDest,i))) {
2229 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2230 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2232 switch (parm_table[i].type) {
2233 case P_BOOL:
2234 case P_BOOLREV:
2235 *(bool *)dest_ptr = *(bool *)src_ptr;
2236 break;
2238 case P_INTEGER:
2239 case P_ENUM:
2240 case P_OCTAL:
2241 case P_BYTES:
2242 *(int *)dest_ptr = *(int *)src_ptr;
2243 break;
2245 case P_CHAR:
2246 *(char *)dest_ptr = *(char *)src_ptr;
2247 break;
2249 case P_STRING:
2250 string_set((char **)dest_ptr,
2251 *(char **)src_ptr);
2252 break;
2254 case P_USTRING:
2256 char *upper_string = strupper_talloc(talloc_tos(),
2257 *(char **)src_ptr);
2258 string_set((char **)dest_ptr,
2259 upper_string);
2260 TALLOC_FREE(upper_string);
2261 break;
2263 case P_LIST:
2264 TALLOC_FREE(*((char ***)dest_ptr));
2265 *((char ***)dest_ptr) = str_list_copy(NULL,
2266 *(const char ***)src_ptr);
2267 break;
2268 default:
2269 break;
2273 if (bcopyall) {
2274 init_copymap(pserviceDest);
2275 if (pserviceSource->copymap)
2276 bitmap_copy(pserviceDest->copymap,
2277 pserviceSource->copymap);
2280 data = pserviceSource->param_opt;
2281 while (data) {
2282 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2283 data = data->next;
2287 /***************************************************************************
2288 Check a service for consistency. Return false if the service is in any way
2289 incomplete or faulty, else true.
2290 ***************************************************************************/
2292 bool service_ok(int iService)
2294 bool bRetval;
2296 bRetval = true;
2297 if (ServicePtrs[iService]->szService[0] == '\0') {
2298 DEBUG(0, ("The following message indicates an internal error:\n"));
2299 DEBUG(0, ("No service name in service entry.\n"));
2300 bRetval = false;
2303 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2304 /* I can't see why you'd want a non-printable printer service... */
2305 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2306 if (!ServicePtrs[iService]->printable) {
2307 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2308 ServicePtrs[iService]->szService));
2309 ServicePtrs[iService]->printable = true;
2311 /* [printers] service must also be non-browsable. */
2312 if (ServicePtrs[iService]->browseable)
2313 ServicePtrs[iService]->browseable = false;
2316 if (ServicePtrs[iService]->path[0] == '\0' &&
2317 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2318 ServicePtrs[iService]->msdfs_proxy[0] == '\0'
2320 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2321 ServicePtrs[iService]->szService));
2322 ServicePtrs[iService]->bAvailable = false;
2325 /* If a service is flagged unavailable, log the fact at level 1. */
2326 if (!ServicePtrs[iService]->bAvailable)
2327 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2328 ServicePtrs[iService]->szService));
2330 return (bRetval);
2333 static struct smbconf_ctx *lp_smbconf_ctx(void)
2335 sbcErr err;
2336 static struct smbconf_ctx *conf_ctx = NULL;
2338 if (conf_ctx == NULL) {
2339 err = smbconf_init(NULL, &conf_ctx, "registry:");
2340 if (!SBC_ERROR_IS_OK(err)) {
2341 DEBUG(1, ("error initializing registry configuration: "
2342 "%s\n", sbcErrorString(err)));
2343 conf_ctx = NULL;
2347 return conf_ctx;
2350 static bool process_smbconf_service(struct smbconf_service *service)
2352 uint32_t count;
2353 bool ret;
2355 if (service == NULL) {
2356 return false;
2359 ret = do_section(service->name, NULL);
2360 if (ret != true) {
2361 return false;
2363 for (count = 0; count < service->num_params; count++) {
2364 ret = do_parameter(service->param_names[count],
2365 service->param_values[count],
2366 NULL);
2367 if (ret != true) {
2368 return false;
2371 if (iServiceIndex >= 0) {
2372 return service_ok(iServiceIndex);
2374 return true;
2378 * load a service from registry and activate it
2380 bool process_registry_service(const char *service_name)
2382 sbcErr err;
2383 struct smbconf_service *service = NULL;
2384 TALLOC_CTX *mem_ctx = talloc_stackframe();
2385 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2386 bool ret = false;
2388 if (conf_ctx == NULL) {
2389 goto done;
2392 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2394 if (!smbconf_share_exists(conf_ctx, service_name)) {
2396 * Registry does not contain data for this service (yet),
2397 * but make sure lp_load doesn't return false.
2399 ret = true;
2400 goto done;
2403 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2404 if (!SBC_ERROR_IS_OK(err)) {
2405 goto done;
2408 ret = process_smbconf_service(service);
2409 if (!ret) {
2410 goto done;
2413 /* store the csn */
2414 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2416 done:
2417 TALLOC_FREE(mem_ctx);
2418 return ret;
2422 * process_registry_globals
2424 static bool process_registry_globals(void)
2426 bool ret;
2428 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2430 ret = do_parameter("registry shares", "yes", NULL);
2431 if (!ret) {
2432 return ret;
2435 return process_registry_service(GLOBAL_NAME);
2438 bool process_registry_shares(void)
2440 sbcErr err;
2441 uint32_t count;
2442 struct smbconf_service **service = NULL;
2443 uint32_t num_shares = 0;
2444 TALLOC_CTX *mem_ctx = talloc_stackframe();
2445 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2446 bool ret = false;
2448 if (conf_ctx == NULL) {
2449 goto done;
2452 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2453 if (!SBC_ERROR_IS_OK(err)) {
2454 goto done;
2457 ret = true;
2459 for (count = 0; count < num_shares; count++) {
2460 if (strequal(service[count]->name, GLOBAL_NAME)) {
2461 continue;
2463 ret = process_smbconf_service(service[count]);
2464 if (!ret) {
2465 goto done;
2469 /* store the csn */
2470 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2472 done:
2473 TALLOC_FREE(mem_ctx);
2474 return ret;
2478 * reload those shares from registry that are already
2479 * activated in the services array.
2481 static bool reload_registry_shares(void)
2483 int i;
2484 bool ret = true;
2486 for (i = 0; i < iNumServices; i++) {
2487 if (!VALID(i)) {
2488 continue;
2491 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2492 continue;
2495 ret = process_registry_service(ServicePtrs[i]->szService);
2496 if (!ret) {
2497 goto done;
2501 done:
2502 return ret;
2506 #define MAX_INCLUDE_DEPTH 100
2508 static uint8_t include_depth;
2510 static struct file_lists {
2511 struct file_lists *next;
2512 char *name;
2513 char *subfname;
2514 time_t modtime;
2515 } *file_lists = NULL;
2517 /*******************************************************************
2518 Keep a linked list of all config files so we know when one has changed
2519 it's date and needs to be reloaded.
2520 ********************************************************************/
2522 static void add_to_file_list(const char *fname, const char *subfname)
2524 struct file_lists *f = file_lists;
2526 while (f) {
2527 if (f->name && !strcmp(f->name, fname))
2528 break;
2529 f = f->next;
2532 if (!f) {
2533 f = SMB_MALLOC_P(struct file_lists);
2534 if (!f)
2535 return;
2536 f->next = file_lists;
2537 f->name = SMB_STRDUP(fname);
2538 if (!f->name) {
2539 SAFE_FREE(f);
2540 return;
2542 f->subfname = SMB_STRDUP(subfname);
2543 if (!f->subfname) {
2544 SAFE_FREE(f->name);
2545 SAFE_FREE(f);
2546 return;
2548 file_lists = f;
2549 f->modtime = file_modtime(subfname);
2550 } else {
2551 time_t t = file_modtime(subfname);
2552 if (t)
2553 f->modtime = t;
2555 return;
2559 * Free the file lists
2561 static void free_file_list(void)
2563 struct file_lists *f;
2564 struct file_lists *next;
2566 f = file_lists;
2567 while( f ) {
2568 next = f->next;
2569 SAFE_FREE( f->name );
2570 SAFE_FREE( f->subfname );
2571 SAFE_FREE( f );
2572 f = next;
2574 file_lists = NULL;
2579 * Utility function for outsiders to check if we're running on registry.
2581 bool lp_config_backend_is_registry(void)
2583 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2587 * Utility function to check if the config backend is FILE.
2589 bool lp_config_backend_is_file(void)
2591 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2594 /*******************************************************************
2595 Check if a config file has changed date.
2596 ********************************************************************/
2598 bool lp_file_list_changed(void)
2600 struct file_lists *f = file_lists;
2602 DEBUG(6, ("lp_file_list_changed()\n"));
2604 while (f) {
2605 time_t mod_time;
2607 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2608 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2610 if (conf_ctx == NULL) {
2611 return false;
2613 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2614 NULL))
2616 DEBUGADD(6, ("registry config changed\n"));
2617 return true;
2619 } else {
2620 char *n2 = NULL;
2621 n2 = talloc_sub_basic(talloc_tos(),
2622 get_current_username(),
2623 current_user_info.domain,
2624 f->name);
2625 if (!n2) {
2626 return false;
2628 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2629 f->name, n2, ctime(&f->modtime)));
2631 mod_time = file_modtime(n2);
2633 if (mod_time &&
2634 ((f->modtime != mod_time) ||
2635 (f->subfname == NULL) ||
2636 (strcmp(n2, f->subfname) != 0)))
2638 DEBUGADD(6,
2639 ("file %s modified: %s\n", n2,
2640 ctime(&mod_time)));
2641 f->modtime = mod_time;
2642 SAFE_FREE(f->subfname);
2643 f->subfname = SMB_STRDUP(n2);
2644 TALLOC_FREE(n2);
2645 return true;
2647 TALLOC_FREE(n2);
2649 f = f->next;
2651 return false;
2656 * Initialize iconv conversion descriptors.
2658 * This is called the first time it is needed, and also called again
2659 * every time the configuration is reloaded, because the charset or
2660 * codepage might have changed.
2662 static void init_iconv(void)
2664 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2665 lp_unix_charset(),
2666 true, global_iconv_handle);
2669 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2671 if (strcmp(*ptr, pszParmValue) != 0) {
2672 string_set(ptr, pszParmValue);
2673 init_iconv();
2675 return true;
2678 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2680 bool is_utf8 = false;
2681 size_t len = strlen(pszParmValue);
2683 if (len == 4 || len == 5) {
2684 /* Don't use StrCaseCmp here as we don't want to
2685 initialize iconv. */
2686 if ((toupper_m(pszParmValue[0]) == 'U') &&
2687 (toupper_m(pszParmValue[1]) == 'T') &&
2688 (toupper_m(pszParmValue[2]) == 'F')) {
2689 if (len == 4) {
2690 if (pszParmValue[3] == '8') {
2691 is_utf8 = true;
2693 } else {
2694 if (pszParmValue[3] == '-' &&
2695 pszParmValue[4] == '8') {
2696 is_utf8 = true;
2702 if (strcmp(*ptr, pszParmValue) != 0) {
2703 if (is_utf8) {
2704 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2705 "be UTF8, using (default value) %s instead.\n",
2706 DEFAULT_DOS_CHARSET));
2707 pszParmValue = DEFAULT_DOS_CHARSET;
2709 string_set(ptr, pszParmValue);
2710 init_iconv();
2712 return true;
2715 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2717 bool ret = true;
2718 TALLOC_CTX *frame = talloc_stackframe();
2719 char *realm = strupper_talloc(frame, pszParmValue);
2720 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2722 ret &= string_set(&Globals.realm_original, pszParmValue);
2723 ret &= string_set(&Globals.realm, realm);
2724 ret &= string_set(&Globals.dnsdomain, dnsdomain);
2725 TALLOC_FREE(frame);
2727 return ret;
2730 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2732 TALLOC_FREE(Globals.netbios_aliases);
2733 Globals.netbios_aliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2734 return set_netbios_aliases(Globals.netbios_aliases);
2737 /***************************************************************************
2738 Handle the include operation.
2739 ***************************************************************************/
2740 static bool bAllowIncludeRegistry = true;
2742 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2744 char *fname;
2746 if (include_depth >= MAX_INCLUDE_DEPTH) {
2747 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2748 include_depth));
2749 return false;
2752 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2753 if (!bAllowIncludeRegistry) {
2754 return true;
2756 if (bInGlobalSection) {
2757 bool ret;
2758 include_depth++;
2759 ret = process_registry_globals();
2760 include_depth--;
2761 return ret;
2762 } else {
2763 DEBUG(1, ("\"include = registry\" only effective "
2764 "in %s section\n", GLOBAL_NAME));
2765 return false;
2769 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2770 current_user_info.domain,
2771 pszParmValue);
2773 add_to_file_list(pszParmValue, fname);
2775 string_set(ptr, fname);
2777 if (file_exist(fname)) {
2778 bool ret;
2779 include_depth++;
2780 ret = pm_process(fname, do_section, do_parameter, NULL);
2781 include_depth--;
2782 TALLOC_FREE(fname);
2783 return ret;
2786 DEBUG(2, ("Can't find include file %s\n", fname));
2787 TALLOC_FREE(fname);
2788 return true;
2791 /***************************************************************************
2792 Handle the interpretation of the copy parameter.
2793 ***************************************************************************/
2795 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2797 bool bRetval;
2798 int iTemp;
2799 struct loadparm_service serviceTemp;
2801 string_set(ptr, pszParmValue);
2803 init_service(&serviceTemp);
2805 bRetval = false;
2807 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2809 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2810 if (iTemp == iServiceIndex) {
2811 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2812 } else {
2813 copy_service(ServicePtrs[iServiceIndex],
2814 &serviceTemp,
2815 ServicePtrs[iServiceIndex]->copymap);
2816 bRetval = true;
2818 } else {
2819 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2820 bRetval = false;
2823 free_service(&serviceTemp);
2824 return (bRetval);
2827 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2829 Globals.ldap_debug_level = lp_int(pszParmValue);
2830 init_ldap_debugging();
2831 return true;
2835 * idmap related parameters
2838 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2840 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2842 return true;
2845 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2847 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2849 return true;
2852 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2854 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2856 return true;
2859 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2861 char *config_option = NULL;
2862 const char *range = NULL;
2863 bool ret = false;
2865 SMB_ASSERT(low != NULL);
2866 SMB_ASSERT(high != NULL);
2868 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2869 domain_name = "*";
2872 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2873 domain_name);
2874 if (config_option == NULL) {
2875 DEBUG(0, ("out of memory\n"));
2876 return false;
2879 range = lp_parm_const_string(-1, config_option, "range", NULL);
2880 if (range == NULL) {
2881 DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2882 goto done;
2885 if (sscanf(range, "%u - %u", low, high) != 2) {
2886 DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2887 range, domain_name));
2888 goto done;
2891 ret = true;
2893 done:
2894 talloc_free(config_option);
2895 return ret;
2899 bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2901 return lp_idmap_range("*", low, high);
2904 const char *lp_idmap_backend(const char *domain_name)
2906 char *config_option = NULL;
2907 const char *backend = NULL;
2909 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2910 domain_name = "*";
2913 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2914 domain_name);
2915 if (config_option == NULL) {
2916 DEBUG(0, ("out of memory\n"));
2917 return false;
2920 backend = lp_parm_const_string(-1, config_option, "backend", NULL);
2921 if (backend == NULL) {
2922 DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
2923 goto done;
2926 done:
2927 talloc_free(config_option);
2928 return backend;
2931 const char *lp_idmap_default_backend(void)
2933 return lp_idmap_backend("*");
2936 /***************************************************************************
2937 Handle the DEBUG level list.
2938 ***************************************************************************/
2940 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2942 string_set(ptr, pszParmValueIn);
2943 return debug_parse_levels(pszParmValueIn);
2946 /***************************************************************************
2947 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2948 ***************************************************************************/
2950 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2952 const char *suffix_string;
2954 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2955 Globals.ldap_suffix );
2956 if ( !suffix_string ) {
2957 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2958 return "";
2961 return suffix_string;
2964 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2966 if (Globals.szLdapMachineSuffix[0])
2967 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
2969 return lp_string(ctx, Globals.ldap_suffix);
2972 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
2974 if (Globals.szLdapUserSuffix[0])
2975 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
2977 return lp_string(ctx, Globals.ldap_suffix);
2980 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
2982 if (Globals.szLdapGroupSuffix[0])
2983 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
2985 return lp_string(ctx, Globals.ldap_suffix);
2988 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
2990 if (Globals.szLdapIdmapSuffix[0])
2991 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
2993 return lp_string(ctx, Globals.ldap_suffix);
2996 /****************************************************************************
2997 set the value for a P_ENUM
2998 ***************************************************************************/
3000 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3001 int *ptr )
3003 int i;
3005 for (i = 0; parm->enum_list[i].name; i++) {
3006 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3007 *ptr = parm->enum_list[i].value;
3008 return;
3011 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3012 pszParmValue, parm->label));
3015 /***************************************************************************
3016 ***************************************************************************/
3018 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3020 static int parm_num = -1;
3021 struct loadparm_service *s;
3023 if ( parm_num == -1 )
3024 parm_num = lpcfg_map_parameter( "printing" );
3026 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3028 if ( snum < 0 )
3029 s = &sDefault;
3030 else
3031 s = ServicePtrs[snum];
3033 init_printer_values( s );
3035 return true;
3039 /***************************************************************************
3040 Initialise a copymap.
3041 ***************************************************************************/
3043 static void init_copymap(struct loadparm_service *pservice)
3045 int i;
3047 TALLOC_FREE(pservice->copymap);
3049 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3050 if (!pservice->copymap)
3051 DEBUG(0,
3052 ("Couldn't allocate copymap!! (size %d)\n",
3053 (int)NUMPARAMETERS));
3054 else
3055 for (i = 0; i < NUMPARAMETERS; i++)
3056 bitmap_set(pservice->copymap, i);
3060 return the parameter pointer for a parameter
3062 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3064 if (service == NULL) {
3065 if (parm->p_class == P_LOCAL)
3066 return (void *)(((char *)&sDefault)+parm->offset);
3067 else if (parm->p_class == P_GLOBAL)
3068 return (void *)(((char *)&Globals)+parm->offset);
3069 else return NULL;
3070 } else {
3071 return (void *)(((char *)service) + parm->offset);
3075 /***************************************************************************
3076 Return the local pointer to a parameter given the service number and parameter
3077 ***************************************************************************/
3079 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3081 return lp_parm_ptr(ServicePtrs[snum], parm);
3084 /***************************************************************************
3085 Process a parameter for a particular service number. If snum < 0
3086 then assume we are in the globals.
3087 ***************************************************************************/
3089 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3091 int parmnum, i;
3092 void *parm_ptr = NULL; /* where we are going to store the result */
3093 struct parmlist_entry **opt_list;
3095 parmnum = lpcfg_map_parameter(pszParmName);
3097 if (parmnum < 0) {
3098 if (strchr(pszParmName, ':') == NULL) {
3099 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3100 pszParmName));
3101 return true;
3105 * We've got a parametric option
3108 opt_list = (snum < 0)
3109 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3110 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3112 return true;
3115 /* if it's already been set by the command line, then we don't
3116 override here */
3117 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3118 return true;
3121 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3122 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3123 pszParmName));
3126 /* we might point at a service, the default service or a global */
3127 if (snum < 0) {
3128 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3129 } else {
3130 if (parm_table[parmnum].p_class == P_GLOBAL) {
3131 DEBUG(0,
3132 ("Global parameter %s found in service section!\n",
3133 pszParmName));
3134 return true;
3136 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3139 if (snum >= 0) {
3140 if (!ServicePtrs[snum]->copymap)
3141 init_copymap(ServicePtrs[snum]);
3143 /* this handles the aliases - set the copymap for other entries with
3144 the same data pointer */
3145 for (i = 0; parm_table[i].label; i++) {
3146 if ((parm_table[i].offset == parm_table[parmnum].offset)
3147 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3148 bitmap_clear(ServicePtrs[snum]->copymap, i);
3153 /* if it is a special case then go ahead */
3154 if (parm_table[parmnum].special) {
3155 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3156 (char **)parm_ptr);
3159 /* now switch on the type of variable it is */
3160 switch (parm_table[parmnum].type)
3162 case P_BOOL:
3163 *(bool *)parm_ptr = lp_bool(pszParmValue);
3164 break;
3166 case P_BOOLREV:
3167 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3168 break;
3170 case P_INTEGER:
3171 *(int *)parm_ptr = lp_int(pszParmValue);
3172 break;
3174 case P_CHAR:
3175 *(char *)parm_ptr = *pszParmValue;
3176 break;
3178 case P_OCTAL:
3179 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3180 if ( i != 1 ) {
3181 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3183 break;
3185 case P_BYTES:
3187 uint64_t val;
3188 if (conv_str_size_error(pszParmValue, &val)) {
3189 if (val <= INT_MAX) {
3190 *(int *)parm_ptr = (int)val;
3191 break;
3195 DEBUG(0,("lp_do_parameter(%s): value is not "
3196 "a valid size specifier!\n", pszParmValue));
3197 return false;
3200 case P_LIST:
3201 case P_CMDLIST:
3202 TALLOC_FREE(*((char ***)parm_ptr));
3203 *(char ***)parm_ptr = str_list_make_v3(
3204 NULL, pszParmValue, NULL);
3205 break;
3207 case P_STRING:
3208 string_set((char **)parm_ptr, pszParmValue);
3209 break;
3211 case P_USTRING:
3213 char *upper_string = strupper_talloc(talloc_tos(),
3214 pszParmValue);
3215 string_set((char **)parm_ptr, upper_string);
3216 TALLOC_FREE(upper_string);
3217 break;
3219 case P_ENUM:
3220 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3221 break;
3222 case P_SEP:
3223 break;
3226 return true;
3229 /***************************************************************************
3230 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3231 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3232 ***************************************************************************/
3234 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3236 int parmnum, i;
3237 parmnum = lpcfg_map_parameter(pszParmName);
3238 if (parmnum >= 0) {
3239 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3240 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3241 return false;
3243 parm_table[parmnum].flags |= FLAG_CMDLINE;
3245 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3246 * be grouped in the table, so we don't have to search the
3247 * whole table */
3248 for (i=parmnum-1;
3249 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3250 && parm_table[i].p_class == parm_table[parmnum].p_class;
3251 i--) {
3252 parm_table[i].flags |= FLAG_CMDLINE;
3254 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3255 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3256 parm_table[i].flags |= FLAG_CMDLINE;
3259 if (store_values) {
3260 store_lp_set_cmdline(pszParmName, pszParmValue);
3262 return true;
3265 /* it might be parametric */
3266 if (strchr(pszParmName, ':') != NULL) {
3267 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3268 if (store_values) {
3269 store_lp_set_cmdline(pszParmName, pszParmValue);
3271 return true;
3274 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3275 return true;
3278 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3280 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3283 /***************************************************************************
3284 Process a parameter.
3285 ***************************************************************************/
3287 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3288 void *userdata)
3290 if (!bInGlobalSection && bGlobalOnly)
3291 return true;
3293 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3295 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3296 pszParmName, pszParmValue));
3300 set a option from the commandline in 'a=b' format. Use to support --option
3302 bool lp_set_option(const char *option)
3304 char *p, *s;
3305 bool ret;
3307 s = talloc_strdup(NULL, option);
3308 if (!s) {
3309 return false;
3312 p = strchr(s, '=');
3313 if (!p) {
3314 talloc_free(s);
3315 return false;
3318 *p = 0;
3320 /* skip white spaces after the = sign */
3321 do {
3322 p++;
3323 } while (*p == ' ');
3325 ret = lp_set_cmdline(s, p);
3326 talloc_free(s);
3327 return ret;
3330 /***************************************************************************
3331 Initialize any local variables in the sDefault table, after parsing a
3332 [globals] section.
3333 ***************************************************************************/
3335 static void init_locals(void)
3338 * We run this check once the [globals] is parsed, to force
3339 * the VFS objects and other per-share settings we need for
3340 * the standard way a AD DC is operated. We may change these
3341 * as our code evolves, which is why we force these settings.
3343 * We can't do this at the end of lp_load_ex(), as by that
3344 * point the services have been loaded and they will already
3345 * have "" as their vfs objects.
3347 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
3348 const char **vfs_objects = lp_vfs_objects(-1);
3349 if (!vfs_objects || !vfs_objects[0]) {
3350 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
3351 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
3352 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
3353 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
3354 } else {
3355 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
3359 lp_do_parameter(-1, "map hidden", "no");
3360 lp_do_parameter(-1, "map system", "no");
3361 lp_do_parameter(-1, "map readonly", "no");
3362 lp_do_parameter(-1, "map archive", "no");
3363 lp_do_parameter(-1, "store dos attributes", "yes");
3367 /***************************************************************************
3368 Process a new section (service). At this stage all sections are services.
3369 Later we'll have special sections that permit server parameters to be set.
3370 Returns true on success, false on failure.
3371 ***************************************************************************/
3373 static bool do_section(const char *pszSectionName, void *userdata)
3375 bool bRetval;
3376 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3377 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3378 bRetval = false;
3380 /* if we were in a global section then do the local inits */
3381 if (bInGlobalSection && !isglobal)
3382 init_locals();
3384 /* if we've just struck a global section, note the fact. */
3385 bInGlobalSection = isglobal;
3387 /* check for multiple global sections */
3388 if (bInGlobalSection) {
3389 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3390 return true;
3393 if (!bInGlobalSection && bGlobalOnly)
3394 return true;
3396 /* if we have a current service, tidy it up before moving on */
3397 bRetval = true;
3399 if (iServiceIndex >= 0)
3400 bRetval = service_ok(iServiceIndex);
3402 /* if all is still well, move to the next record in the services array */
3403 if (bRetval) {
3404 /* We put this here to avoid an odd message order if messages are */
3405 /* issued by the post-processing of a previous section. */
3406 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3408 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3409 if (iServiceIndex < 0) {
3410 DEBUG(0, ("Failed to add a new service\n"));
3411 return false;
3413 /* Clean all parametric options for service */
3414 /* They will be added during parsing again */
3415 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3418 return bRetval;
3422 /***************************************************************************
3423 Determine if a partcular base parameter is currentl set to the default value.
3424 ***************************************************************************/
3426 static bool is_default(int i)
3428 switch (parm_table[i].type) {
3429 case P_LIST:
3430 case P_CMDLIST:
3431 return str_list_equal((const char **)parm_table[i].def.lvalue,
3432 *(const char ***)lp_parm_ptr(NULL,
3433 &parm_table[i]));
3434 case P_STRING:
3435 case P_USTRING:
3436 return strequal(parm_table[i].def.svalue,
3437 *(char **)lp_parm_ptr(NULL,
3438 &parm_table[i]));
3439 case P_BOOL:
3440 case P_BOOLREV:
3441 return parm_table[i].def.bvalue ==
3442 *(bool *)lp_parm_ptr(NULL,
3443 &parm_table[i]);
3444 case P_CHAR:
3445 return parm_table[i].def.cvalue ==
3446 *(char *)lp_parm_ptr(NULL,
3447 &parm_table[i]);
3448 case P_INTEGER:
3449 case P_OCTAL:
3450 case P_ENUM:
3451 case P_BYTES:
3452 return parm_table[i].def.ivalue ==
3453 *(int *)lp_parm_ptr(NULL,
3454 &parm_table[i]);
3455 case P_SEP:
3456 break;
3458 return false;
3461 /***************************************************************************
3462 Display the contents of the global structure.
3463 ***************************************************************************/
3465 static void dump_globals(FILE *f)
3467 int i;
3468 struct parmlist_entry *data;
3470 fprintf(f, "[global]\n");
3472 for (i = 0; parm_table[i].label; i++)
3473 if (parm_table[i].p_class == P_GLOBAL &&
3474 !(parm_table[i].flags & FLAG_META) &&
3475 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3476 if (defaults_saved && is_default(i))
3477 continue;
3478 fprintf(f, "\t%s = ", parm_table[i].label);
3479 lpcfg_print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3480 &parm_table[i]),
3482 fprintf(f, "\n");
3484 if (Globals.param_opt != NULL) {
3485 data = Globals.param_opt;
3486 while(data) {
3487 fprintf(f, "\t%s = %s\n", data->key, data->value);
3488 data = data->next;
3494 /***************************************************************************
3495 Display the contents of a single services record.
3496 ***************************************************************************/
3498 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3500 int i;
3501 struct parmlist_entry *data;
3503 if (pService != &sDefault)
3504 fprintf(f, "[%s]\n", pService->szService);
3506 for (i = 0; parm_table[i].label; i++) {
3508 if (parm_table[i].p_class == P_LOCAL &&
3509 !(parm_table[i].flags & FLAG_META) &&
3510 (*parm_table[i].label != '-') &&
3511 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3513 if (pService == &sDefault) {
3514 if (defaults_saved && is_default(i))
3515 continue;
3516 } else {
3517 if (lpcfg_equal_parameter(parm_table[i].type,
3518 lp_parm_ptr(pService, &parm_table[i]),
3519 lp_parm_ptr(NULL, &parm_table[i])))
3520 continue;
3523 fprintf(f, "\t%s = ", parm_table[i].label);
3524 lpcfg_print_parameter(&parm_table[i],
3525 lp_parm_ptr(pService, &parm_table[i]),
3527 fprintf(f, "\n");
3531 if (pService->param_opt != NULL) {
3532 data = pService->param_opt;
3533 while(data) {
3534 fprintf(f, "\t%s = %s\n", data->key, data->value);
3535 data = data->next;
3540 /***************************************************************************
3541 Display the contents of a parameter of a single services record.
3542 ***************************************************************************/
3544 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3546 bool result = false;
3547 fstring local_parm_name;
3548 char *parm_opt;
3549 const char *parm_opt_value;
3551 struct loadparm_context *lp_ctx;
3553 /* check for parametrical option */
3554 fstrcpy( local_parm_name, parm_name);
3555 parm_opt = strchr( local_parm_name, ':');
3557 if (parm_opt) {
3558 *parm_opt = '\0';
3559 parm_opt++;
3560 if (strlen(parm_opt)) {
3561 parm_opt_value = lp_parm_const_string( snum,
3562 local_parm_name, parm_opt, NULL);
3563 if (parm_opt_value) {
3564 printf( "%s\n", parm_opt_value);
3565 result = true;
3568 return result;
3571 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
3572 if (lp_ctx == NULL) {
3573 return false;
3576 if (isGlobal) {
3577 result = lpcfg_dump_a_parameter(lp_ctx, NULL, parm_name, f);
3578 } else {
3579 result = lpcfg_dump_a_parameter(lp_ctx, ServicePtrs[snum], parm_name, f);
3581 TALLOC_FREE(lp_ctx);
3582 return result;
3585 /***************************************************************************
3586 Return info about the requested parameter (given as a string).
3587 Return NULL when the string is not a valid parameter name.
3588 ***************************************************************************/
3590 struct parm_struct *lp_get_parameter(const char *param_name)
3592 int num = lpcfg_map_parameter(param_name);
3594 if (num < 0) {
3595 return NULL;
3598 return &parm_table[num];
3601 #if 0
3602 /***************************************************************************
3603 Display the contents of a single copy structure.
3604 ***************************************************************************/
3605 static void dump_copy_map(bool *pcopymap)
3607 int i;
3608 if (!pcopymap)
3609 return;
3611 printf("\n\tNon-Copied parameters:\n");
3613 for (i = 0; parm_table[i].label; i++)
3614 if (parm_table[i].p_class == P_LOCAL &&
3615 parm_table[i].ptr && !pcopymap[i] &&
3616 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3618 printf("\t\t%s\n", parm_table[i].label);
3621 #endif
3623 /***************************************************************************
3624 Return TRUE if the passed service number is within range.
3625 ***************************************************************************/
3627 bool lp_snum_ok(int iService)
3629 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3632 /***************************************************************************
3633 Auto-load some home services.
3634 ***************************************************************************/
3636 static void lp_add_auto_services(char *str)
3638 char *s;
3639 char *p;
3640 int homes;
3641 char *saveptr;
3643 if (!str)
3644 return;
3646 s = SMB_STRDUP(str);
3647 if (!s)
3648 return;
3650 homes = lp_servicenumber(HOMES_NAME);
3652 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3653 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3654 char *home;
3656 if (lp_servicenumber(p) >= 0)
3657 continue;
3659 home = get_user_home_dir(talloc_tos(), p);
3661 if (home && home[0] && homes >= 0)
3662 lp_add_home(p, homes, p, home);
3664 TALLOC_FREE(home);
3666 SAFE_FREE(s);
3669 /***************************************************************************
3670 Auto-load one printer.
3671 ***************************************************************************/
3673 void lp_add_one_printer(const char *name, const char *comment,
3674 const char *location, void *pdata)
3676 int printers = lp_servicenumber(PRINTERS_NAME);
3677 int i;
3679 if (lp_servicenumber(name) < 0) {
3680 lp_add_printer(name, printers);
3681 if ((i = lp_servicenumber(name)) >= 0) {
3682 string_set(&ServicePtrs[i]->comment, comment);
3683 ServicePtrs[i]->autoloaded = true;
3688 /***************************************************************************
3689 Have we loaded a services file yet?
3690 ***************************************************************************/
3692 bool lp_loaded(void)
3694 return (bLoaded);
3697 /***************************************************************************
3698 Unload unused services.
3699 ***************************************************************************/
3701 void lp_killunused(struct smbd_server_connection *sconn,
3702 bool (*snumused) (struct smbd_server_connection *, int))
3704 int i;
3705 for (i = 0; i < iNumServices; i++) {
3706 if (!VALID(i))
3707 continue;
3709 /* don't kill autoloaded or usershare services */
3710 if ( ServicePtrs[i]->autoloaded ||
3711 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3712 continue;
3715 if (!snumused || !snumused(sconn, i)) {
3716 free_service_byindex(i);
3722 * Kill all except autoloaded and usershare services - convenience wrapper
3724 void lp_kill_all_services(void)
3726 lp_killunused(NULL, NULL);
3729 /***************************************************************************
3730 Unload a service.
3731 ***************************************************************************/
3733 void lp_killservice(int iServiceIn)
3735 if (VALID(iServiceIn)) {
3736 free_service_byindex(iServiceIn);
3740 /***************************************************************************
3741 Save the curent values of all global and sDefault parameters into the
3742 defaults union. This allows testparm to show only the
3743 changed (ie. non-default) parameters.
3744 ***************************************************************************/
3746 static void lp_save_defaults(void)
3748 int i;
3749 for (i = 0; parm_table[i].label; i++) {
3750 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3751 && parm_table[i].p_class == parm_table[i - 1].p_class)
3752 continue;
3753 switch (parm_table[i].type) {
3754 case P_LIST:
3755 case P_CMDLIST:
3756 parm_table[i].def.lvalue = str_list_copy(
3757 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3758 break;
3759 case P_STRING:
3760 case P_USTRING:
3761 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3762 break;
3763 case P_BOOL:
3764 case P_BOOLREV:
3765 parm_table[i].def.bvalue =
3766 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3767 break;
3768 case P_CHAR:
3769 parm_table[i].def.cvalue =
3770 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3771 break;
3772 case P_INTEGER:
3773 case P_OCTAL:
3774 case P_ENUM:
3775 case P_BYTES:
3776 parm_table[i].def.ivalue =
3777 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3778 break;
3779 case P_SEP:
3780 break;
3783 defaults_saved = true;
3786 /***********************************************************
3787 If we should send plaintext/LANMAN passwords in the clinet
3788 ************************************************************/
3790 static void set_allowed_client_auth(void)
3792 if (Globals.client_ntlmv2_auth) {
3793 Globals.client_lanman_auth = false;
3795 if (!Globals.client_lanman_auth) {
3796 Globals.client_plaintext_auth = false;
3800 /***************************************************************************
3801 JRA.
3802 The following code allows smbd to read a user defined share file.
3803 Yes, this is my intent. Yes, I'm comfortable with that...
3805 THE FOLLOWING IS SECURITY CRITICAL CODE.
3807 It washes your clothes, it cleans your house, it guards you while you sleep...
3808 Do not f%^k with it....
3809 ***************************************************************************/
3811 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3813 /***************************************************************************
3814 Check allowed stat state of a usershare file.
3815 Ensure we print out who is dicking with us so the admin can
3816 get their sorry ass fired.
3817 ***************************************************************************/
3819 static bool check_usershare_stat(const char *fname,
3820 const SMB_STRUCT_STAT *psbuf)
3822 if (!S_ISREG(psbuf->st_ex_mode)) {
3823 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3824 "not a regular file\n",
3825 fname, (unsigned int)psbuf->st_ex_uid ));
3826 return false;
3829 /* Ensure this doesn't have the other write bit set. */
3830 if (psbuf->st_ex_mode & S_IWOTH) {
3831 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
3832 "public write. Refusing to allow as a usershare file.\n",
3833 fname, (unsigned int)psbuf->st_ex_uid ));
3834 return false;
3837 /* Should be 10k or less. */
3838 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
3839 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3840 "too large (%u) to be a user share file.\n",
3841 fname, (unsigned int)psbuf->st_ex_uid,
3842 (unsigned int)psbuf->st_ex_size ));
3843 return false;
3846 return true;
3849 /***************************************************************************
3850 Parse the contents of a usershare file.
3851 ***************************************************************************/
3853 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
3854 SMB_STRUCT_STAT *psbuf,
3855 const char *servicename,
3856 int snum,
3857 char **lines,
3858 int numlines,
3859 char **pp_sharepath,
3860 char **pp_comment,
3861 char **pp_cp_servicename,
3862 struct security_descriptor **ppsd,
3863 bool *pallow_guest)
3865 const char **prefixallowlist = lp_usershare_prefix_allow_list();
3866 const char **prefixdenylist = lp_usershare_prefix_deny_list();
3867 int us_vers;
3868 DIR *dp;
3869 SMB_STRUCT_STAT sbuf;
3870 char *sharepath = NULL;
3871 char *comment = NULL;
3873 *pp_sharepath = NULL;
3874 *pp_comment = NULL;
3876 *pallow_guest = false;
3878 if (numlines < 4) {
3879 return USERSHARE_MALFORMED_FILE;
3882 if (strcmp(lines[0], "#VERSION 1") == 0) {
3883 us_vers = 1;
3884 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
3885 us_vers = 2;
3886 if (numlines < 5) {
3887 return USERSHARE_MALFORMED_FILE;
3889 } else {
3890 return USERSHARE_BAD_VERSION;
3893 if (strncmp(lines[1], "path=", 5) != 0) {
3894 return USERSHARE_MALFORMED_PATH;
3897 sharepath = talloc_strdup(ctx, &lines[1][5]);
3898 if (!sharepath) {
3899 return USERSHARE_POSIX_ERR;
3901 trim_string(sharepath, " ", " ");
3903 if (strncmp(lines[2], "comment=", 8) != 0) {
3904 return USERSHARE_MALFORMED_COMMENT_DEF;
3907 comment = talloc_strdup(ctx, &lines[2][8]);
3908 if (!comment) {
3909 return USERSHARE_POSIX_ERR;
3911 trim_string(comment, " ", " ");
3912 trim_char(comment, '"', '"');
3914 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
3915 return USERSHARE_MALFORMED_ACL_DEF;
3918 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
3919 return USERSHARE_ACL_ERR;
3922 if (us_vers == 2) {
3923 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
3924 return USERSHARE_MALFORMED_ACL_DEF;
3926 if (lines[4][9] == 'y') {
3927 *pallow_guest = true;
3930 /* Backwards compatible extension to file version #2. */
3931 if (numlines > 5) {
3932 if (strncmp(lines[5], "sharename=", 10) != 0) {
3933 return USERSHARE_MALFORMED_SHARENAME_DEF;
3935 if (!strequal(&lines[5][10], servicename)) {
3936 return USERSHARE_BAD_SHARENAME;
3938 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
3939 if (!*pp_cp_servicename) {
3940 return USERSHARE_POSIX_ERR;
3945 if (*pp_cp_servicename == NULL) {
3946 *pp_cp_servicename = talloc_strdup(ctx, servicename);
3947 if (!*pp_cp_servicename) {
3948 return USERSHARE_POSIX_ERR;
3952 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->path) == 0)) {
3953 /* Path didn't change, no checks needed. */
3954 *pp_sharepath = sharepath;
3955 *pp_comment = comment;
3956 return USERSHARE_OK;
3959 /* The path *must* be absolute. */
3960 if (sharepath[0] != '/') {
3961 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
3962 servicename, sharepath));
3963 return USERSHARE_PATH_NOT_ABSOLUTE;
3966 /* If there is a usershare prefix deny list ensure one of these paths
3967 doesn't match the start of the user given path. */
3968 if (prefixdenylist) {
3969 int i;
3970 for ( i=0; prefixdenylist[i]; i++ ) {
3971 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
3972 servicename, i, prefixdenylist[i], sharepath ));
3973 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
3974 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
3975 "usershare prefix deny list entries.\n",
3976 servicename, sharepath));
3977 return USERSHARE_PATH_IS_DENIED;
3982 /* If there is a usershare prefix allow list ensure one of these paths
3983 does match the start of the user given path. */
3985 if (prefixallowlist) {
3986 int i;
3987 for ( i=0; prefixallowlist[i]; i++ ) {
3988 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
3989 servicename, i, prefixallowlist[i], sharepath ));
3990 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
3991 break;
3994 if (prefixallowlist[i] == NULL) {
3995 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
3996 "usershare prefix allow list entries.\n",
3997 servicename, sharepath));
3998 return USERSHARE_PATH_NOT_ALLOWED;
4002 /* Ensure this is pointing to a directory. */
4003 dp = opendir(sharepath);
4005 if (!dp) {
4006 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4007 servicename, sharepath));
4008 return USERSHARE_PATH_NOT_DIRECTORY;
4011 /* Ensure the owner of the usershare file has permission to share
4012 this directory. */
4014 if (sys_stat(sharepath, &sbuf, false) == -1) {
4015 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4016 servicename, sharepath, strerror(errno) ));
4017 closedir(dp);
4018 return USERSHARE_POSIX_ERR;
4021 closedir(dp);
4023 if (!S_ISDIR(sbuf.st_ex_mode)) {
4024 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4025 servicename, sharepath ));
4026 return USERSHARE_PATH_NOT_DIRECTORY;
4029 /* Check if sharing is restricted to owner-only. */
4030 /* psbuf is the stat of the usershare definition file,
4031 sbuf is the stat of the target directory to be shared. */
4033 if (lp_usershare_owner_only()) {
4034 /* root can share anything. */
4035 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4036 return USERSHARE_PATH_NOT_ALLOWED;
4040 *pp_sharepath = sharepath;
4041 *pp_comment = comment;
4042 return USERSHARE_OK;
4045 /***************************************************************************
4046 Deal with a usershare file.
4047 Returns:
4048 >= 0 - snum
4049 -1 - Bad name, invalid contents.
4050 - service name already existed and not a usershare, problem
4051 with permissions to share directory etc.
4052 ***************************************************************************/
4054 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4056 SMB_STRUCT_STAT sbuf;
4057 SMB_STRUCT_STAT lsbuf;
4058 char *fname = NULL;
4059 char *sharepath = NULL;
4060 char *comment = NULL;
4061 char *cp_service_name = NULL;
4062 char **lines = NULL;
4063 int numlines = 0;
4064 int fd = -1;
4065 int iService = -1;
4066 TALLOC_CTX *ctx = talloc_stackframe();
4067 struct security_descriptor *psd = NULL;
4068 bool guest_ok = false;
4069 char *canon_name = NULL;
4070 bool added_service = false;
4071 int ret = -1;
4073 /* Ensure share name doesn't contain invalid characters. */
4074 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4075 DEBUG(0,("process_usershare_file: share name %s contains "
4076 "invalid characters (any of %s)\n",
4077 file_name, INVALID_SHARENAME_CHARS ));
4078 goto out;
4081 canon_name = canonicalize_servicename(ctx, file_name);
4082 if (!canon_name) {
4083 goto out;
4086 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4087 if (!fname) {
4088 goto out;
4091 /* Minimize the race condition by doing an lstat before we
4092 open and fstat. Ensure this isn't a symlink link. */
4094 if (sys_lstat(fname, &lsbuf, false) != 0) {
4095 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4096 fname, strerror(errno) ));
4097 goto out;
4100 /* This must be a regular file, not a symlink, directory or
4101 other strange filetype. */
4102 if (!check_usershare_stat(fname, &lsbuf)) {
4103 goto out;
4107 TDB_DATA data;
4108 NTSTATUS status;
4110 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4111 canon_name, &data);
4113 iService = -1;
4115 if (NT_STATUS_IS_OK(status) &&
4116 (data.dptr != NULL) &&
4117 (data.dsize == sizeof(iService))) {
4118 memcpy(&iService, data.dptr, sizeof(iService));
4122 if (iService != -1 &&
4123 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4124 &lsbuf.st_ex_mtime) == 0) {
4125 /* Nothing changed - Mark valid and return. */
4126 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4127 canon_name ));
4128 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4129 ret = iService;
4130 goto out;
4133 /* Try and open the file read only - no symlinks allowed. */
4134 #ifdef O_NOFOLLOW
4135 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4136 #else
4137 fd = open(fname, O_RDONLY, 0);
4138 #endif
4140 if (fd == -1) {
4141 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4142 fname, strerror(errno) ));
4143 goto out;
4146 /* Now fstat to be *SURE* it's a regular file. */
4147 if (sys_fstat(fd, &sbuf, false) != 0) {
4148 close(fd);
4149 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4150 fname, strerror(errno) ));
4151 goto out;
4154 /* Is it the same dev/inode as was lstated ? */
4155 if (!check_same_stat(&lsbuf, &sbuf)) {
4156 close(fd);
4157 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4158 "Symlink spoofing going on ?\n", fname ));
4159 goto out;
4162 /* This must be a regular file, not a symlink, directory or
4163 other strange filetype. */
4164 if (!check_usershare_stat(fname, &sbuf)) {
4165 close(fd);
4166 goto out;
4169 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4171 close(fd);
4172 if (lines == NULL) {
4173 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4174 fname, (unsigned int)sbuf.st_ex_uid ));
4175 goto out;
4178 if (parse_usershare_file(ctx, &sbuf, file_name,
4179 iService, lines, numlines, &sharepath,
4180 &comment, &cp_service_name,
4181 &psd, &guest_ok) != USERSHARE_OK) {
4182 goto out;
4185 /* Everything ok - add the service possibly using a template. */
4186 if (iService < 0) {
4187 const struct loadparm_service *sp = &sDefault;
4188 if (snum_template != -1) {
4189 sp = ServicePtrs[snum_template];
4192 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4193 DEBUG(0, ("process_usershare_file: Failed to add "
4194 "new service %s\n", cp_service_name));
4195 goto out;
4198 added_service = true;
4200 /* Read only is controlled by usershare ACL below. */
4201 ServicePtrs[iService]->read_only = false;
4204 /* Write the ACL of the new/modified share. */
4205 if (!set_share_security(canon_name, psd)) {
4206 DEBUG(0, ("process_usershare_file: Failed to set share "
4207 "security for user share %s\n",
4208 canon_name ));
4209 goto out;
4212 /* If from a template it may be marked invalid. */
4213 ServicePtrs[iService]->valid = true;
4215 /* Set the service as a valid usershare. */
4216 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4218 /* Set guest access. */
4219 if (lp_usershare_allow_guests()) {
4220 ServicePtrs[iService]->guest_ok = guest_ok;
4223 /* And note when it was loaded. */
4224 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4225 string_set(&ServicePtrs[iService]->path, sharepath);
4226 string_set(&ServicePtrs[iService]->comment, comment);
4228 ret = iService;
4230 out:
4232 if (ret == -1 && iService != -1 && added_service) {
4233 lp_remove_service(iService);
4236 TALLOC_FREE(lines);
4237 TALLOC_FREE(ctx);
4238 return ret;
4241 /***************************************************************************
4242 Checks if a usershare entry has been modified since last load.
4243 ***************************************************************************/
4245 static bool usershare_exists(int iService, struct timespec *last_mod)
4247 SMB_STRUCT_STAT lsbuf;
4248 const char *usersharepath = Globals.usershare_path;
4249 char *fname;
4251 if (asprintf(&fname, "%s/%s",
4252 usersharepath,
4253 ServicePtrs[iService]->szService) < 0) {
4254 return false;
4257 if (sys_lstat(fname, &lsbuf, false) != 0) {
4258 SAFE_FREE(fname);
4259 return false;
4262 if (!S_ISREG(lsbuf.st_ex_mode)) {
4263 SAFE_FREE(fname);
4264 return false;
4267 SAFE_FREE(fname);
4268 *last_mod = lsbuf.st_ex_mtime;
4269 return true;
4272 /***************************************************************************
4273 Load a usershare service by name. Returns a valid servicenumber or -1.
4274 ***************************************************************************/
4276 int load_usershare_service(const char *servicename)
4278 SMB_STRUCT_STAT sbuf;
4279 const char *usersharepath = Globals.usershare_path;
4280 int max_user_shares = Globals.usershare_max_shares;
4281 int snum_template = -1;
4283 if (*usersharepath == 0 || max_user_shares == 0) {
4284 return -1;
4287 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4288 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4289 usersharepath, strerror(errno) ));
4290 return -1;
4293 if (!S_ISDIR(sbuf.st_ex_mode)) {
4294 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4295 usersharepath ));
4296 return -1;
4300 * This directory must be owned by root, and have the 't' bit set.
4301 * It also must not be writable by "other".
4304 #ifdef S_ISVTX
4305 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4306 #else
4307 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4308 #endif
4309 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4310 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4311 usersharepath ));
4312 return -1;
4315 /* Ensure the template share exists if it's set. */
4316 if (Globals.usershare_template_share[0]) {
4317 /* We can't use lp_servicenumber here as we are recommending that
4318 template shares have -valid=false set. */
4319 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4320 if (ServicePtrs[snum_template]->szService &&
4321 strequal(ServicePtrs[snum_template]->szService,
4322 Globals.usershare_template_share)) {
4323 break;
4327 if (snum_template == -1) {
4328 DEBUG(0,("load_usershare_service: usershare template share %s "
4329 "does not exist.\n",
4330 Globals.usershare_template_share ));
4331 return -1;
4335 return process_usershare_file(usersharepath, servicename, snum_template);
4338 /***************************************************************************
4339 Load all user defined shares from the user share directory.
4340 We only do this if we're enumerating the share list.
4341 This is the function that can delete usershares that have
4342 been removed.
4343 ***************************************************************************/
4345 int load_usershare_shares(struct smbd_server_connection *sconn,
4346 bool (*snumused) (struct smbd_server_connection *, int))
4348 DIR *dp;
4349 SMB_STRUCT_STAT sbuf;
4350 struct dirent *de;
4351 int num_usershares = 0;
4352 int max_user_shares = Globals.usershare_max_shares;
4353 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4354 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4355 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4356 int iService;
4357 int snum_template = -1;
4358 const char *usersharepath = Globals.usershare_path;
4359 int ret = lp_numservices();
4360 TALLOC_CTX *tmp_ctx;
4362 if (max_user_shares == 0 || *usersharepath == '\0') {
4363 return lp_numservices();
4366 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4367 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4368 usersharepath, strerror(errno) ));
4369 return ret;
4373 * This directory must be owned by root, and have the 't' bit set.
4374 * It also must not be writable by "other".
4377 #ifdef S_ISVTX
4378 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4379 #else
4380 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4381 #endif
4382 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4383 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4384 usersharepath ));
4385 return ret;
4388 /* Ensure the template share exists if it's set. */
4389 if (Globals.usershare_template_share[0]) {
4390 /* We can't use lp_servicenumber here as we are recommending that
4391 template shares have -valid=false set. */
4392 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4393 if (ServicePtrs[snum_template]->szService &&
4394 strequal(ServicePtrs[snum_template]->szService,
4395 Globals.usershare_template_share)) {
4396 break;
4400 if (snum_template == -1) {
4401 DEBUG(0,("load_usershare_shares: usershare template share %s "
4402 "does not exist.\n",
4403 Globals.usershare_template_share ));
4404 return ret;
4408 /* Mark all existing usershares as pending delete. */
4409 for (iService = iNumServices - 1; iService >= 0; iService--) {
4410 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4411 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4415 dp = opendir(usersharepath);
4416 if (!dp) {
4417 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4418 usersharepath, strerror(errno) ));
4419 return ret;
4422 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4423 (de = readdir(dp));
4424 num_dir_entries++ ) {
4425 int r;
4426 const char *n = de->d_name;
4428 /* Ignore . and .. */
4429 if (*n == '.') {
4430 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4431 continue;
4435 if (n[0] == ':') {
4436 /* Temporary file used when creating a share. */
4437 num_tmp_dir_entries++;
4440 /* Allow 20% tmp entries. */
4441 if (num_tmp_dir_entries > allowed_tmp_entries) {
4442 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4443 "in directory %s\n",
4444 num_tmp_dir_entries, usersharepath));
4445 break;
4448 r = process_usershare_file(usersharepath, n, snum_template);
4449 if (r == 0) {
4450 /* Update the services count. */
4451 num_usershares++;
4452 if (num_usershares >= max_user_shares) {
4453 DEBUG(0,("load_usershare_shares: max user shares reached "
4454 "on file %s in directory %s\n",
4455 n, usersharepath ));
4456 break;
4458 } else if (r == -1) {
4459 num_bad_dir_entries++;
4462 /* Allow 20% bad entries. */
4463 if (num_bad_dir_entries > allowed_bad_entries) {
4464 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4465 "in directory %s\n",
4466 num_bad_dir_entries, usersharepath));
4467 break;
4470 /* Allow 20% bad entries. */
4471 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4472 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4473 "in directory %s\n",
4474 num_dir_entries, usersharepath));
4475 break;
4479 closedir(dp);
4481 /* Sweep through and delete any non-refreshed usershares that are
4482 not currently in use. */
4483 tmp_ctx = talloc_stackframe();
4484 for (iService = iNumServices - 1; iService >= 0; iService--) {
4485 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4486 char *servname;
4488 if (snumused && snumused(sconn, iService)) {
4489 continue;
4492 servname = lp_servicename(tmp_ctx, iService);
4494 /* Remove from the share ACL db. */
4495 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4496 servname ));
4497 delete_share_security(servname);
4498 free_service_byindex(iService);
4501 talloc_free(tmp_ctx);
4503 return lp_numservices();
4506 /********************************************************
4507 Destroy global resources allocated in this file
4508 ********************************************************/
4510 void gfree_loadparm(void)
4512 int i;
4514 free_file_list();
4516 /* Free resources allocated to services */
4518 for ( i = 0; i < iNumServices; i++ ) {
4519 if ( VALID(i) ) {
4520 free_service_byindex(i);
4524 SAFE_FREE( ServicePtrs );
4525 iNumServices = 0;
4527 /* Now release all resources allocated to global
4528 parameters and the default service */
4530 free_global_parameters();
4534 /***************************************************************************
4535 Allow client apps to specify that they are a client
4536 ***************************************************************************/
4537 static void lp_set_in_client(bool b)
4539 in_client = b;
4543 /***************************************************************************
4544 Determine if we're running in a client app
4545 ***************************************************************************/
4546 static bool lp_is_in_client(void)
4548 return in_client;
4551 /***************************************************************************
4552 Load the services array from the services file. Return true on success,
4553 false on failure.
4554 ***************************************************************************/
4556 static bool lp_load_ex(const char *pszFname,
4557 bool global_only,
4558 bool save_defaults,
4559 bool add_ipc,
4560 bool initialize_globals,
4561 bool allow_include_registry,
4562 bool load_all_shares)
4564 char *n2 = NULL;
4565 bool bRetval;
4567 bRetval = false;
4569 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4571 bInGlobalSection = true;
4572 bGlobalOnly = global_only;
4573 bAllowIncludeRegistry = allow_include_registry;
4575 init_globals(initialize_globals);
4577 free_file_list();
4579 if (save_defaults) {
4580 init_locals();
4581 lp_save_defaults();
4584 if (!initialize_globals) {
4585 free_param_opts(&Globals.param_opt);
4586 apply_lp_set_cmdline();
4589 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4591 /* We get sections first, so have to start 'behind' to make up */
4592 iServiceIndex = -1;
4594 if (lp_config_backend_is_file()) {
4595 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4596 current_user_info.domain,
4597 pszFname);
4598 if (!n2) {
4599 smb_panic("lp_load_ex: out of memory");
4602 add_to_file_list(pszFname, n2);
4604 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4605 TALLOC_FREE(n2);
4607 /* finish up the last section */
4608 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4609 if (bRetval) {
4610 if (iServiceIndex >= 0) {
4611 bRetval = service_ok(iServiceIndex);
4615 if (lp_config_backend_is_registry()) {
4616 /* config backend changed to registry in config file */
4618 * We need to use this extra global variable here to
4619 * survive restart: init_globals uses this as a default
4620 * for config_backend. Otherwise, init_globals would
4621 * send us into an endless loop here.
4623 config_backend = CONFIG_BACKEND_REGISTRY;
4624 /* start over */
4625 DEBUG(1, ("lp_load_ex: changing to config backend "
4626 "registry\n"));
4627 init_globals(true);
4628 lp_kill_all_services();
4629 return lp_load_ex(pszFname, global_only, save_defaults,
4630 add_ipc, initialize_globals,
4631 allow_include_registry,
4632 load_all_shares);
4634 } else if (lp_config_backend_is_registry()) {
4635 bRetval = process_registry_globals();
4636 } else {
4637 DEBUG(0, ("Illegal config backend given: %d\n",
4638 lp_config_backend()));
4639 bRetval = false;
4642 if (bRetval && lp_registry_shares()) {
4643 if (load_all_shares) {
4644 bRetval = process_registry_shares();
4645 } else {
4646 bRetval = reload_registry_shares();
4651 char *serv = lp_auto_services(talloc_tos());
4652 lp_add_auto_services(serv);
4653 TALLOC_FREE(serv);
4656 if (add_ipc) {
4657 /* When 'restrict anonymous = 2' guest connections to ipc$
4658 are denied */
4659 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4660 if ( lp_enable_asu_support() ) {
4661 lp_add_ipc("ADMIN$", false);
4665 set_allowed_client_auth();
4667 if (lp_security() == SEC_ADS && strchr(lp_password_server(), ':')) {
4668 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4669 lp_password_server()));
4672 bLoaded = true;
4674 /* Now we check we_are_a_wins_server and set szWINSserver to 127.0.0.1 */
4675 /* if we_are_a_wins_server is true and we are in the client */
4676 if (lp_is_in_client() && Globals.we_are_a_wins_server) {
4677 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4680 init_iconv();
4682 fault_configure(smb_panic_s3);
4685 * We run this check once the whole smb.conf is parsed, to
4686 * force some settings for the standard way a AD DC is
4687 * operated. We may changed these as our code evolves, which
4688 * is why we force these settings.
4690 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4691 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4693 lp_do_parameter(-1, "rpc_server:default", "external");
4694 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4695 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4696 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4697 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4698 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4699 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4700 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4701 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4704 bAllowIncludeRegistry = true;
4706 return (bRetval);
4709 bool lp_load(const char *pszFname,
4710 bool global_only,
4711 bool save_defaults,
4712 bool add_ipc,
4713 bool initialize_globals)
4715 return lp_load_ex(pszFname,
4716 global_only,
4717 save_defaults,
4718 add_ipc,
4719 initialize_globals,
4720 true, /* allow_include_registry */
4721 false); /* load_all_shares*/
4724 bool lp_load_initial_only(const char *pszFname)
4726 return lp_load_ex(pszFname,
4727 true, /* global only */
4728 false, /* save_defaults */
4729 false, /* add_ipc */
4730 true, /* initialize_globals */
4731 false, /* allow_include_registry */
4732 false); /* load_all_shares*/
4736 * most common lp_load wrapper, loading only the globals
4738 bool lp_load_global(const char *file_name)
4740 return lp_load_ex(file_name,
4741 true, /* global_only */
4742 false, /* save_defaults */
4743 false, /* add_ipc */
4744 true, /* initialize_globals */
4745 true, /* allow_include_registry */
4746 false); /* load_all_shares*/
4750 * lp_load wrapper, especially for clients
4752 bool lp_load_client(const char *file_name)
4754 lp_set_in_client(true);
4756 return lp_load_global(file_name);
4760 * lp_load wrapper, loading only globals, but intended
4761 * for subsequent calls, not reinitializing the globals
4762 * to default values
4764 bool lp_load_global_no_reinit(const char *file_name)
4766 return lp_load_ex(file_name,
4767 true, /* global_only */
4768 false, /* save_defaults */
4769 false, /* add_ipc */
4770 false, /* initialize_globals */
4771 true, /* allow_include_registry */
4772 false); /* load_all_shares*/
4776 * lp_load wrapper, especially for clients, no reinitialization
4778 bool lp_load_client_no_reinit(const char *file_name)
4780 lp_set_in_client(true);
4782 return lp_load_global_no_reinit(file_name);
4785 bool lp_load_with_registry_shares(const char *pszFname,
4786 bool global_only,
4787 bool save_defaults,
4788 bool add_ipc,
4789 bool initialize_globals)
4791 return lp_load_ex(pszFname,
4792 global_only,
4793 save_defaults,
4794 add_ipc,
4795 initialize_globals,
4796 true, /* allow_include_registry */
4797 true); /* load_all_shares*/
4800 /***************************************************************************
4801 Return the max number of services.
4802 ***************************************************************************/
4804 int lp_numservices(void)
4806 return (iNumServices);
4809 /***************************************************************************
4810 Display the contents of the services array in human-readable form.
4811 ***************************************************************************/
4813 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4815 int iService;
4817 if (show_defaults)
4818 defaults_saved = false;
4820 dump_globals(f);
4822 dump_a_service(&sDefault, f);
4824 for (iService = 0; iService < maxtoprint; iService++) {
4825 fprintf(f,"\n");
4826 lp_dump_one(f, show_defaults, iService);
4830 /***************************************************************************
4831 Display the contents of one service in human-readable form.
4832 ***************************************************************************/
4834 void lp_dump_one(FILE * f, bool show_defaults, int snum)
4836 if (VALID(snum)) {
4837 if (ServicePtrs[snum]->szService[0] == '\0')
4838 return;
4839 dump_a_service(ServicePtrs[snum], f);
4843 /***************************************************************************
4844 Return the number of the service with the given name, or -1 if it doesn't
4845 exist. Note that this is a DIFFERENT ANIMAL from the internal function
4846 getservicebyname()! This works ONLY if all services have been loaded, and
4847 does not copy the found service.
4848 ***************************************************************************/
4850 int lp_servicenumber(const char *pszServiceName)
4852 int iService;
4853 fstring serviceName;
4855 if (!pszServiceName) {
4856 return GLOBAL_SECTION_SNUM;
4859 for (iService = iNumServices - 1; iService >= 0; iService--) {
4860 if (VALID(iService) && ServicePtrs[iService]->szService) {
4862 * The substitution here is used to support %U is
4863 * service names
4865 fstrcpy(serviceName, ServicePtrs[iService]->szService);
4866 standard_sub_basic(get_current_username(),
4867 current_user_info.domain,
4868 serviceName,sizeof(serviceName));
4869 if (strequal(serviceName, pszServiceName)) {
4870 break;
4875 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
4876 struct timespec last_mod;
4878 if (!usershare_exists(iService, &last_mod)) {
4879 /* Remove the share security tdb entry for it. */
4880 delete_share_security(lp_servicename(talloc_tos(), iService));
4881 /* Remove it from the array. */
4882 free_service_byindex(iService);
4883 /* Doesn't exist anymore. */
4884 return GLOBAL_SECTION_SNUM;
4887 /* Has it been modified ? If so delete and reload. */
4888 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4889 &last_mod) < 0) {
4890 /* Remove it from the array. */
4891 free_service_byindex(iService);
4892 /* and now reload it. */
4893 iService = load_usershare_service(pszServiceName);
4897 if (iService < 0) {
4898 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
4899 return GLOBAL_SECTION_SNUM;
4902 return (iService);
4905 /*******************************************************************
4906 A useful volume label function.
4907 ********************************************************************/
4909 const char *volume_label(TALLOC_CTX *ctx, int snum)
4911 char *ret;
4912 const char *label = lp_volume(ctx, snum);
4913 if (!*label) {
4914 label = lp_servicename(ctx, snum);
4917 /* This returns a 33 byte guarenteed null terminated string. */
4918 ret = talloc_strndup(ctx, label, 32);
4919 if (!ret) {
4920 return "";
4922 return ret;
4925 /*******************************************************************
4926 Get the default server type we will announce as via nmbd.
4927 ********************************************************************/
4929 int lp_default_server_announce(void)
4931 int default_server_announce = 0;
4932 default_server_announce |= SV_TYPE_WORKSTATION;
4933 default_server_announce |= SV_TYPE_SERVER;
4934 default_server_announce |= SV_TYPE_SERVER_UNIX;
4936 /* note that the flag should be set only if we have a
4937 printer service but nmbd doesn't actually load the
4938 services so we can't tell --jerry */
4940 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
4942 default_server_announce |= SV_TYPE_SERVER_NT;
4943 default_server_announce |= SV_TYPE_NT;
4945 switch (lp_server_role()) {
4946 case ROLE_DOMAIN_MEMBER:
4947 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
4948 break;
4949 case ROLE_DOMAIN_PDC:
4950 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
4951 break;
4952 case ROLE_DOMAIN_BDC:
4953 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
4954 break;
4955 case ROLE_STANDALONE:
4956 default:
4957 break;
4959 if (lp_time_server())
4960 default_server_announce |= SV_TYPE_TIME_SOURCE;
4962 if (lp_host_msdfs())
4963 default_server_announce |= SV_TYPE_DFS_SERVER;
4965 return default_server_announce;
4968 /***********************************************************
4969 If we are PDC then prefer us as DMB
4970 ************************************************************/
4972 bool lp_domain_master(void)
4974 if (Globals._domain_master == Auto)
4975 return (lp_server_role() == ROLE_DOMAIN_PDC);
4977 return (bool)Globals._domain_master;
4980 /***********************************************************
4981 If we are PDC then prefer us as DMB
4982 ************************************************************/
4984 static bool lp_domain_master_true_or_auto(void)
4986 if (Globals._domain_master) /* auto or yes */
4987 return true;
4989 return false;
4992 /***********************************************************
4993 If we are DMB then prefer us as LMB
4994 ************************************************************/
4996 bool lp_preferred_master(void)
4998 if (Globals.iPreferredMaster == Auto)
4999 return (lp_local_master() && lp_domain_master());
5001 return (bool)Globals.iPreferredMaster;
5004 /*******************************************************************
5005 Remove a service.
5006 ********************************************************************/
5008 void lp_remove_service(int snum)
5010 ServicePtrs[snum]->valid = false;
5013 /*******************************************************************
5014 Copy a service.
5015 ********************************************************************/
5017 void lp_copy_service(int snum, const char *new_name)
5019 do_section(new_name, NULL);
5020 if (snum >= 0) {
5021 snum = lp_servicenumber(new_name);
5022 if (snum >= 0) {
5023 char *name = lp_servicename(talloc_tos(), snum);
5024 lp_do_parameter(snum, "copy", name);
5029 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5031 const char *ret = lp__printername(ctx, snum);
5032 if (ret == NULL || *ret == '\0') {
5033 ret = lp_const_servicename(snum);
5036 return ret;
5040 /***********************************************************
5041 Allow daemons such as winbindd to fix their logfile name.
5042 ************************************************************/
5044 void lp_set_logfile(const char *name)
5046 string_set(&Globals.logfile, name);
5047 debug_set_logfile(name);
5050 /*******************************************************************
5051 Return the max print jobs per queue.
5052 ********************************************************************/
5054 int lp_maxprintjobs(int snum)
5056 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5057 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5058 maxjobs = PRINT_MAX_JOBID - 1;
5060 return maxjobs;
5063 const char *lp_printcapname(void)
5065 if ((Globals.szPrintcapname != NULL) &&
5066 (Globals.szPrintcapname[0] != '\0'))
5067 return Globals.szPrintcapname;
5069 if (sDefault.printing == PRINT_CUPS) {
5070 return "cups";
5073 if (sDefault.printing == PRINT_BSD)
5074 return "/etc/printcap";
5076 return PRINTCAP_NAME;
5079 static uint32 spoolss_state;
5081 bool lp_disable_spoolss( void )
5083 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5084 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5086 return spoolss_state == SVCCTL_STOPPED ? true : false;
5089 void lp_set_spoolss_state( uint32 state )
5091 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5093 spoolss_state = state;
5096 uint32 lp_get_spoolss_state( void )
5098 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5101 /*******************************************************************
5102 Ensure we don't use sendfile if server smb signing is active.
5103 ********************************************************************/
5105 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5107 bool sign_active = false;
5109 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5110 if (get_Protocol() < PROTOCOL_NT1) {
5111 return false;
5113 if (signing_state) {
5114 sign_active = smb_signing_is_active(signing_state);
5116 return (lp__use_sendfile(snum) &&
5117 (get_remote_arch() != RA_WIN95) &&
5118 !sign_active);
5121 /*******************************************************************
5122 Turn off sendfile if we find the underlying OS doesn't support it.
5123 ********************************************************************/
5125 void set_use_sendfile(int snum, bool val)
5127 if (LP_SNUM_OK(snum))
5128 ServicePtrs[snum]->_use_sendfile = val;
5129 else
5130 sDefault._use_sendfile = val;
5133 /*******************************************************************
5134 Turn off storing DOS attributes if this share doesn't support it.
5135 ********************************************************************/
5137 void set_store_dos_attributes(int snum, bool val)
5139 if (!LP_SNUM_OK(snum))
5140 return;
5141 ServicePtrs[(snum)]->store_dos_attributes = val;
5144 void lp_set_mangling_method(const char *new_method)
5146 string_set(&Globals.mangling_method, new_method);
5149 /*******************************************************************
5150 Global state for POSIX pathname processing.
5151 ********************************************************************/
5153 static bool posix_pathnames;
5155 bool lp_posix_pathnames(void)
5157 return posix_pathnames;
5160 /*******************************************************************
5161 Change everything needed to ensure POSIX pathname processing (currently
5162 not much).
5163 ********************************************************************/
5165 void lp_set_posix_pathnames(void)
5167 posix_pathnames = true;
5170 /*******************************************************************
5171 Global state for POSIX lock processing - CIFS unix extensions.
5172 ********************************************************************/
5174 bool posix_default_lock_was_set;
5175 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5177 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5179 if (posix_default_lock_was_set) {
5180 return posix_cifsx_locktype;
5181 } else {
5182 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5186 /*******************************************************************
5187 ********************************************************************/
5189 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5191 posix_default_lock_was_set = true;
5192 posix_cifsx_locktype = val;
5195 int lp_min_receive_file_size(void)
5197 if (Globals.iminreceivefile < 0) {
5198 return 0;
5200 return Globals.iminreceivefile;
5203 /*******************************************************************
5204 Safe wide links checks.
5205 This helper function always verify the validity of wide links,
5206 even after a configuration file reload.
5207 ********************************************************************/
5209 static bool lp_widelinks_internal(int snum)
5211 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5212 sDefault.bWidelinks);
5215 void widelinks_warning(int snum)
5217 if (lp_allow_insecure_wide_links()) {
5218 return;
5221 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5222 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5223 "These parameters are incompatible. "
5224 "Wide links will be disabled for this share.\n",
5225 lp_servicename(talloc_tos(), snum) ));
5229 bool lp_widelinks(int snum)
5231 /* wide links is always incompatible with unix extensions */
5232 if (lp_unix_extensions()) {
5234 * Unless we have "allow insecure widelinks"
5235 * turned on.
5237 if (!lp_allow_insecure_wide_links()) {
5238 return false;
5242 return lp_widelinks_internal(snum);
5245 int lp_server_role(void)
5247 return lp_find_server_role(lp__server_role(),
5248 lp__security(),
5249 lp__domain_logons(),
5250 lp_domain_master_true_or_auto());
5253 int lp_security(void)
5255 return lp_find_security(lp__server_role(),
5256 lp__security());
5259 struct loadparm_global * get_globals(void)
5261 return &Globals;