param: duplicate the copy service in lib/param into source3 loadparm
[Samba.git] / source3 / param / loadparm.c
blobb2bef1d747bb1373690f7e336235fc074c3fa135
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_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
269 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
270 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
271 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
272 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
274 static void set_allowed_client_auth(void);
276 static void add_to_file_list(const char *fname, const char *subfname);
277 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
278 static void free_param_opts(struct parmlist_entry **popts);
280 #include "lib/param/param_table.c"
282 /* this is used to prevent lots of mallocs of size 1 */
283 static const char null_string[] = "";
286 Free a string value.
289 static void string_free(char **s)
291 if (!s || !(*s))
292 return;
293 if (*s == null_string)
294 *s = NULL;
295 TALLOC_FREE(*s);
299 Set a string value, deallocating any existing space, and allocing the space
300 for the string
303 static bool string_set(TALLOC_CTX *mem_ctx, char **dest,const char *src)
305 string_free(dest);
307 if (!src) {
308 src = "";
311 (*dest) = talloc_strdup(mem_ctx, src);
312 if ((*dest) == NULL) {
313 DEBUG(0,("Out of memory in string_init\n"));
314 return false;
317 return true;
320 bool lp_string_set(char **dest, const char *src) {
321 return string_set(Globals.ctx, dest, src);
324 /***************************************************************************
325 Initialise the sDefault parameter structure for the printer values.
326 ***************************************************************************/
328 static void init_printer_values(TALLOC_CTX *ctx, struct loadparm_service *pService)
330 /* choose defaults depending on the type of printing */
331 switch (pService->printing) {
332 case PRINT_BSD:
333 case PRINT_AIX:
334 case PRINT_LPRNT:
335 case PRINT_LPROS2:
336 string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
337 string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
338 string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
339 break;
341 case PRINT_LPRNG:
342 case PRINT_PLP:
343 string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
344 string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
345 string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
346 string_set(ctx, &pService->queuepause_command, "lpc stop '%p'");
347 string_set(ctx, &pService->queueresume_command, "lpc start '%p'");
348 string_set(ctx, &pService->lppause_command, "lpc hold '%p' %j");
349 string_set(ctx, &pService->lpresume_command, "lpc release '%p' %j");
350 break;
352 case PRINT_CUPS:
353 case PRINT_IPRINT:
354 /* set the lpq command to contain the destination printer
355 name only. This is used by cups_queue_get() */
356 string_set(ctx, &pService->lpq_command, "%p");
357 string_set(ctx, &pService->lprm_command, "");
358 string_set(ctx, &pService->print_command, "");
359 string_set(ctx, &pService->lppause_command, "");
360 string_set(ctx, &pService->lpresume_command, "");
361 string_set(ctx, &pService->queuepause_command, "");
362 string_set(ctx, &pService->queueresume_command, "");
363 break;
365 case PRINT_SYSV:
366 case PRINT_HPUX:
367 string_set(ctx, &pService->lpq_command, "lpstat -o%p");
368 string_set(ctx, &pService->lprm_command, "cancel %p-%j");
369 string_set(ctx, &pService->print_command, "lp -c -d%p %s; rm %s");
370 string_set(ctx, &pService->queuepause_command, "disable %p");
371 string_set(ctx, &pService->queueresume_command, "enable %p");
372 #ifndef HPUX
373 string_set(ctx, &pService->lppause_command, "lp -i %p-%j -H hold");
374 string_set(ctx, &pService->lpresume_command, "lp -i %p-%j -H resume");
375 #endif /* HPUX */
376 break;
378 case PRINT_QNX:
379 string_set(ctx, &pService->lpq_command, "lpq -P%p");
380 string_set(ctx, &pService->lprm_command, "lprm -P%p %j");
381 string_set(ctx, &pService->print_command, "lp -r -P%p %s");
382 break;
384 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
386 case PRINT_TEST:
387 case PRINT_VLP: {
388 const char *tdbfile;
389 TALLOC_CTX *tmp_ctx = talloc_stackframe();
390 char *tmp;
392 tdbfile = talloc_asprintf(
393 tmp_ctx, "tdbfile=%s",
394 lp_parm_const_string(-1, "vlp", "tdbfile",
395 "/tmp/vlp.tdb"));
396 if (tdbfile == NULL) {
397 tdbfile="tdbfile=/tmp/vlp.tdb";
400 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
401 tdbfile);
402 string_set(ctx, &pService->print_command,
403 tmp ? tmp : "vlp print %p %s");
405 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
406 tdbfile);
407 string_set(ctx, &pService->lpq_command,
408 tmp ? tmp : "vlp lpq %p");
410 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
411 tdbfile);
412 string_set(ctx, &pService->lprm_command,
413 tmp ? tmp : "vlp lprm %p %j");
415 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
416 tdbfile);
417 string_set(ctx, &pService->lppause_command,
418 tmp ? tmp : "vlp lppause %p %j");
420 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
421 tdbfile);
422 string_set(ctx, &pService->lpresume_command,
423 tmp ? tmp : "vlp lpresume %p %j");
425 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
426 tdbfile);
427 string_set(ctx, &pService->queuepause_command,
428 tmp ? tmp : "vlp queuepause %p");
430 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
431 tdbfile);
432 string_set(ctx, &pService->queueresume_command,
433 tmp ? tmp : "vlp queueresume %p");
434 TALLOC_FREE(tmp_ctx);
436 break;
438 #endif /* DEVELOPER */
443 * Function to return the default value for the maximum number of open
444 * file descriptors permitted. This function tries to consult the
445 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
446 * the smaller of those.
448 static int max_open_files(void)
450 int sysctl_max = MAX_OPEN_FILES;
451 int rlimit_max = MAX_OPEN_FILES;
453 #ifdef HAVE_SYSCTLBYNAME
455 size_t size = sizeof(sysctl_max);
456 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
459 #endif
461 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
463 struct rlimit rl;
465 ZERO_STRUCT(rl);
467 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
468 rlimit_max = rl.rlim_cur;
470 #if defined(RLIM_INFINITY)
471 if(rl.rlim_cur == RLIM_INFINITY)
472 rlimit_max = MAX_OPEN_FILES;
473 #endif
475 #endif
477 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
478 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
479 "minimum Windows limit (%d)\n",
480 sysctl_max,
481 MIN_OPEN_FILES_WINDOWS));
482 sysctl_max = MIN_OPEN_FILES_WINDOWS;
485 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
486 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
487 "minimum Windows limit (%d)\n",
488 rlimit_max,
489 MIN_OPEN_FILES_WINDOWS));
490 rlimit_max = MIN_OPEN_FILES_WINDOWS;
493 return MIN(sysctl_max, rlimit_max);
497 * Common part of freeing allocated data for one parameter.
499 static void free_one_parameter_common(void *parm_ptr,
500 struct parm_struct parm)
502 if ((parm.type == P_STRING) ||
503 (parm.type == P_USTRING))
505 string_free((char**)parm_ptr);
506 } else if (parm.type == P_LIST) {
507 TALLOC_FREE(*((char***)parm_ptr));
512 * Free the allocated data for one parameter for a share
513 * given as a service struct.
515 static void free_one_parameter(struct loadparm_service *service,
516 struct parm_struct parm)
518 void *parm_ptr;
520 if (parm.p_class != P_LOCAL) {
521 return;
524 parm_ptr = lp_parm_ptr(service, &parm);
526 free_one_parameter_common(parm_ptr, parm);
530 * Free the allocated parameter data of a share given
531 * as a service struct.
533 static void free_parameters(struct loadparm_service *service)
535 uint32_t i;
537 for (i=0; parm_table[i].label; i++) {
538 free_one_parameter(service, parm_table[i]);
543 * Free the allocated data for one parameter for a given share
544 * specified by an snum.
546 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
548 void *parm_ptr;
550 if (snum < 0) {
551 parm_ptr = lp_parm_ptr(NULL, &parm);
552 } else if (parm.p_class != P_LOCAL) {
553 return;
554 } else {
555 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
558 free_one_parameter_common(parm_ptr, parm);
562 * Free the allocated parameter data for a share specified
563 * by an snum.
565 static void free_parameters_by_snum(int snum)
567 uint32_t i;
569 for (i=0; parm_table[i].label; i++) {
570 free_one_parameter_by_snum(snum, parm_table[i]);
575 * Free the allocated global parameters.
577 static void free_global_parameters(void)
579 free_param_opts(&Globals.param_opt);
580 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
581 TALLOC_FREE(Globals.ctx);
584 struct lp_stored_option {
585 struct lp_stored_option *prev, *next;
586 const char *label;
587 const char *value;
590 static struct lp_stored_option *stored_options;
593 save options set by lp_set_cmdline() into a list. This list is
594 re-applied when we do a globals reset, so that cmdline set options
595 are sticky across reloads of smb.conf
597 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
599 struct lp_stored_option *entry, *entry_next;
600 for (entry = stored_options; entry != NULL; entry = entry_next) {
601 entry_next = entry->next;
602 if (strcmp(pszParmName, entry->label) == 0) {
603 DLIST_REMOVE(stored_options, entry);
604 talloc_free(entry);
605 break;
609 entry = talloc(NULL, struct lp_stored_option);
610 if (!entry) {
611 return false;
614 entry->label = talloc_strdup(entry, pszParmName);
615 if (!entry->label) {
616 talloc_free(entry);
617 return false;
620 entry->value = talloc_strdup(entry, pszParmValue);
621 if (!entry->value) {
622 talloc_free(entry);
623 return false;
626 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
628 return true;
631 static bool apply_lp_set_cmdline(void)
633 struct lp_stored_option *entry = NULL;
634 for (entry = stored_options; entry != NULL; entry = entry->next) {
635 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
636 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
637 entry->label, entry->value));
638 return false;
641 return true;
644 /***************************************************************************
645 Initialise the global parameter structure.
646 ***************************************************************************/
648 static void init_globals(bool reinit_globals)
650 static bool done_init = false;
651 char *s = NULL;
652 int i;
654 /* If requested to initialize only once and we've already done it... */
655 if (!reinit_globals && done_init) {
656 /* ... then we have nothing more to do */
657 return;
660 if (!done_init) {
661 /* The logfile can be set before this is invoked. Free it if so. */
662 if (Globals.logfile != NULL) {
663 string_free(&Globals.logfile);
664 Globals.logfile = NULL;
666 done_init = true;
667 } else {
668 free_global_parameters();
671 /* This memset and the free_global_parameters() above will
672 * wipe out smb.conf options set with lp_set_cmdline(). The
673 * apply_lp_set_cmdline() call puts these values back in the
674 * table once the defaults are set */
675 ZERO_STRUCT(Globals);
677 Globals.ctx = talloc_pooled_object(NULL, char, 272, 2048);
679 for (i = 0; parm_table[i].label; i++) {
680 if ((parm_table[i].type == P_STRING ||
681 parm_table[i].type == P_USTRING))
683 string_set(Globals.ctx, (char **)lp_parm_ptr(NULL, &parm_table[i]), "");
688 string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
689 string_set(Globals.ctx, &sDefault.printjob_username, "%U");
691 init_printer_values(Globals.ctx, &sDefault);
693 sDefault.ntvfs_handler = (const char **)str_list_make_v3(NULL, "unixuid default", NULL);
695 DEBUG(3, ("Initialising global parameters\n"));
697 /* Must manually force to upper case here, as this does not go via the handler */
698 string_set(Globals.ctx, &Globals.netbios_name, myhostname_upper());
700 string_set(Globals.ctx, &Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
701 string_set(Globals.ctx, &Globals.private_dir, get_dyn_PRIVATE_DIR());
703 /* use the new 'hash2' method by default, with a prefix of 1 */
704 string_set(Globals.ctx, &Globals.mangling_method, "hash2");
705 Globals.mangle_prefix = 1;
707 string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
709 /* using UTF8 by default allows us to support all chars */
710 string_set(Globals.ctx, &Globals.unix_charset, DEFAULT_UNIX_CHARSET);
712 /* Use codepage 850 as a default for the dos character set */
713 string_set(Globals.ctx, &Globals.dos_charset, DEFAULT_DOS_CHARSET);
716 * Allow the default PASSWD_CHAT to be overridden in local.h.
718 string_set(Globals.ctx, &Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
720 string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
722 string_set(Globals.ctx, &Globals.passwd_program, "");
723 string_set(Globals.ctx, &Globals.lock_directory, get_dyn_LOCKDIR());
724 string_set(Globals.ctx, &Globals.state_directory, get_dyn_STATEDIR());
725 string_set(Globals.ctx, &Globals.cache_directory, get_dyn_CACHEDIR());
726 string_set(Globals.ctx, &Globals.pid_directory, get_dyn_PIDDIR());
727 string_set(Globals.ctx, &Globals.nbt_client_socket_address, "0.0.0.0");
729 * By default support explicit binding to broadcast
730 * addresses.
732 Globals.nmbd_bind_explicit_broadcast = true;
734 s = talloc_asprintf(talloc_tos(), "Samba %s", samba_version_string());
735 if (s == NULL) {
736 smb_panic("init_globals: ENOMEM");
738 string_set(Globals.ctx, &Globals.server_string, s);
739 TALLOC_FREE(s);
740 #ifdef DEVELOPER
741 string_set(Globals.ctx, &Globals.panic_action, "/bin/sleep 999999999");
742 #endif
744 string_set(Globals.ctx, &Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
746 string_set(Globals.ctx, &Globals.logon_drive, "");
747 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
748 string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
749 string_set(Globals.ctx, &Globals.logon_path, "\\\\%N\\%U\\profile");
751 Globals.name_resolve_order = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
752 string_set(Globals.ctx, &Globals.password_server, "*");
754 Globals.algorithmic_rid_base = BASE_RID;
756 Globals.load_printers = true;
757 Globals.printcap_cache_time = 750; /* 12.5 minutes */
759 Globals.config_backend = config_backend;
760 Globals._server_role = ROLE_AUTO;
762 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
763 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
764 Globals.max_xmit = 0x4104;
765 Globals.max_mux = 50; /* This is *needed* for profile support. */
766 Globals.lpq_cache_time = 30; /* changed to handle large print servers better -- jerry */
767 Globals._disable_spoolss = false;
768 Globals.max_smbd_processes = 0;/* no limit specified */
769 Globals.username_level = 0;
770 Globals.deadtime = 0;
771 Globals.getwd_cache = true;
772 Globals.large_readwrite = true;
773 Globals.max_log_size = 5000;
774 Globals.max_open_files = max_open_files();
775 Globals.server_max_protocol = PROTOCOL_SMB3_00;
776 Globals.server_min_protocol = PROTOCOL_LANMAN1;
777 Globals.client_max_protocol = PROTOCOL_NT1;
778 Globals.client_min_protocol = PROTOCOL_CORE;
779 Globals._security = SEC_AUTO;
780 Globals.encrypt_passwords = true;
781 Globals.client_schannel = Auto;
782 Globals.winbind_sealed_pipes = true;
783 Globals.require_strong_key = true;
784 Globals.server_schannel = Auto;
785 Globals.read_raw = true;
786 Globals.write_raw = true;
787 Globals.null_passwords = false;
788 Globals.old_password_allowed_period = 60;
789 Globals.obey_pam_restrictions = false;
790 Globals.syslog = 1;
791 Globals.syslog_only = false;
792 Globals.timestamp_logs = true;
793 string_set(Globals.ctx, &Globals.log_level, "0");
794 Globals.debug_prefix_timestamp = false;
795 Globals.debug_hires_timestamp = true;
796 Globals.debug_pid = false;
797 Globals.debug_uid = false;
798 Globals.debug_class = false;
799 Globals.enable_core_files = true;
800 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
801 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
802 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
803 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
804 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
805 Globals.lm_interval = 60;
806 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
807 Globals.nis_homedir = false;
808 #ifdef WITH_NISPLUS_HOME
809 string_set(Globals.ctx, &Globals.homedir_map, "auto_home.org_dir");
810 #else
811 string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
812 #endif
813 #endif
814 Globals.time_server = false;
815 Globals.bind_interfaces_only = false;
816 Globals.unix_password_sync = false;
817 Globals.pam_password_change = false;
818 Globals.passwd_chat_debug = false;
819 Globals.passwd_chat_timeout = 2; /* 2 second default. */
820 Globals.nt_pipe_support = true; /* Do NT pipes by default. */
821 Globals.nt_status_support = true; /* Use NT status by default. */
822 Globals.stat_cache = true; /* use stat cache by default */
823 Globals.max_stat_cache_size = 256; /* 256k by default */
824 Globals.restrict_anonymous = 0;
825 Globals.client_lanman_auth = false; /* Do NOT use the LanMan hash if it is available */
826 Globals.client_plaintext_auth = false; /* Do NOT use a plaintext password even if is requested by the server */
827 Globals.lanman_auth = false; /* Do NOT use the LanMan hash, even if it is supplied */
828 Globals.ntlm_auth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
829 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 */
830 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
832 Globals.map_to_guest = 0; /* By Default, "Never" */
833 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
834 Globals.enhanced_browsing = true;
835 Globals.lock_spin_time = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
836 #ifdef MMAP_BLACKLIST
837 Globals.use_mmap = false;
838 #else
839 Globals.use_mmap = true;
840 #endif
841 Globals.unicode = true;
842 Globals.unix_extensions = true;
843 Globals.reset_on_zero_vc = false;
844 Globals.log_writeable_files_on_exit = false;
845 Globals.create_krb5_conf = true;
846 Globals.winbindMaxDomainConnections = 1;
848 /* hostname lookups can be very expensive and are broken on
849 a large number of sites (tridge) */
850 Globals.hostname_lookups = false;
852 string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
853 string_set(Globals.ctx, &Globals.ldap_suffix, "");
854 string_set(Globals.ctx, &Globals.szLdapMachineSuffix, "");
855 string_set(Globals.ctx, &Globals.szLdapUserSuffix, "");
856 string_set(Globals.ctx, &Globals.szLdapGroupSuffix, "");
857 string_set(Globals.ctx, &Globals.szLdapIdmapSuffix, "");
859 string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
860 Globals.ldap_ssl = LDAP_SSL_START_TLS;
861 Globals.ldap_ssl_ads = false;
862 Globals.ldap_deref = -1;
863 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
864 Globals.ldap_delete_dn = false;
865 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
866 Globals.ldap_follow_referral = Auto;
867 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
868 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
869 Globals.ldap_page_size = LDAP_PAGE_SIZE;
871 Globals.ldap_debug_level = 0;
872 Globals.ldap_debug_threshold = 10;
874 /* This is what we tell the afs client. in reality we set the token
875 * to never expire, though, when this runs out the afs client will
876 * forget the token. Set to 0 to get NEVERDATE.*/
877 Globals.afs_token_lifetime = 604800;
878 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
880 /* these parameters are set to defaults that are more appropriate
881 for the increasing samba install base:
883 as a member of the workgroup, that will possibly become a
884 _local_ master browser (lm = true). this is opposed to a forced
885 local master browser startup (pm = true).
887 doesn't provide WINS server service by default (wsupp = false),
888 and doesn't provide domain master browser services by default, either.
892 Globals.show_add_printer_wizard = true;
893 Globals.os_level = 20;
894 Globals.local_master = true;
895 Globals._domain_master = Auto; /* depending on _domain_logons */
896 Globals._domain_logons = false;
897 Globals.browse_list = true;
898 Globals.we_are_a_wins_server = false;
899 Globals.wins_proxy = false;
901 TALLOC_FREE(Globals.init_logon_delayed_hosts);
902 Globals.init_logon_delay = 100; /* 100 ms default delay */
904 Globals.wins_dns_proxy = true;
906 Globals.allow_trusted_domains = true;
907 string_set(Globals.ctx, &Globals.szIdmapBackend, "tdb");
909 string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
910 string_set(Globals.ctx, &Globals.template_homedir, "/home/%D/%U");
911 string_set(Globals.ctx, &Globals.winbind_separator, "\\");
912 string_set(Globals.ctx, &Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
914 string_set(Globals.ctx, &Globals.cups_server, "");
915 string_set(Globals.ctx, &Globals.iprint_server, "");
917 string_set(Globals.ctx, &Globals._ctdbd_socket, "");
919 Globals.cluster_addresses = NULL;
920 Globals.clustering = false;
921 Globals.ctdb_timeout = 0;
922 Globals.ctdb_locktime_warn_threshold = 0;
924 Globals.winbind_cache_time = 300; /* 5 minutes */
925 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
926 Globals.winbind_max_clients = 200;
927 Globals.winbind_enum_users = false;
928 Globals.winbind_enum_groups = false;
929 Globals.winbind_use_default_domain = false;
930 Globals.winbind_trusted_domains_only = false;
931 Globals.winbind_nested_groups = true;
932 Globals.winbind_expand_groups = 1;
933 Globals.winbind_nss_info = (const char **)str_list_make_v3(NULL, "template", NULL);
934 Globals.winbind_refresh_tickets = false;
935 Globals.winbind_offline_logon = false;
937 Globals.idmap_cache_time = 86400 * 7; /* a week by default */
938 Globals.idmap_negative_cache_time = 120; /* 2 minutes by default */
940 Globals.passdb_expand_explicit = false;
942 Globals.name_cache_timeout = 660; /* In seconds */
944 Globals.use_spnego = true;
945 Globals.client_use_spnego = true;
947 Globals.client_signing = SMB_SIGNING_DEFAULT;
948 Globals.server_signing = SMB_SIGNING_DEFAULT;
950 Globals.defer_sharing_violations = true;
951 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
953 Globals.enable_privileges = true;
954 Globals.host_msdfs = true;
955 Globals.enable_asu_support = false;
957 /* User defined shares. */
958 s = talloc_asprintf(talloc_tos(), "%s/usershares", get_dyn_STATEDIR());
959 if (s == NULL) {
960 smb_panic("init_globals: ENOMEM");
962 string_set(Globals.ctx, &Globals.usershare_path, s);
963 TALLOC_FREE(s);
964 string_set(Globals.ctx, &Globals.usershare_template_share, "");
965 Globals.usershare_max_shares = 0;
966 /* By default disallow sharing of directories not owned by the sharer. */
967 Globals.usershare_owner_only = true;
968 /* By default disallow guest access to usershares. */
969 Globals.usershare_allow_guests = false;
971 Globals.keepalive = DEFAULT_KEEPALIVE;
973 /* By default no shares out of the registry */
974 Globals.registry_shares = false;
976 Globals.iminreceivefile = 0;
978 Globals.map_untrusted_to_domain = false;
979 Globals.multicast_dns_register = true;
981 Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
982 Globals.smb2_max_write = DEFAULT_SMB2_MAX_WRITE;
983 Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
984 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
986 string_set(Globals.ctx, &Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
988 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);
990 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);
992 Globals.tls_enabled = true;
994 string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
995 string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
996 string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
998 string_set(Globals.ctx, &Globals.share_backend, "classic");
1000 Globals.iPreferredMaster = Auto;
1002 Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
1004 string_set(Globals.ctx, &Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
1006 string_set(Globals.ctx, &Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
1008 s = talloc_asprintf(talloc_tos(), "%s/samba_kcc", get_dyn_SCRIPTSBINDIR());
1009 if (s == NULL) {
1010 smb_panic("init_globals: ENOMEM");
1012 Globals.samba_kcc_command = (const char **)str_list_make_v3(NULL, s, NULL);
1013 TALLOC_FREE(s);
1015 s = talloc_asprintf(talloc_tos(), "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR());
1016 if (s == NULL) {
1017 smb_panic("init_globals: ENOMEM");
1019 Globals.dns_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1020 TALLOC_FREE(s);
1022 s = talloc_asprintf(talloc_tos(), "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR());
1023 if (s == NULL) {
1024 smb_panic("init_globals: ENOMEM");
1026 Globals.spn_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1027 TALLOC_FREE(s);
1029 Globals.nsupdate_command = (const char **)str_list_make_v3(NULL, "/usr/bin/nsupdate -g", NULL);
1031 Globals.rndc_command = (const char **)str_list_make_v3(NULL, "/usr/sbin/rndc", NULL);
1033 Globals.cldap_port = 389;
1035 Globals.dgram_port = 138;
1037 Globals.nbt_port = 137;
1039 Globals.krb5_port = 88;
1041 Globals.kpasswd_port = 464;
1043 Globals.web_port = 901;
1045 /* Now put back the settings that were set with lp_set_cmdline() */
1046 apply_lp_set_cmdline();
1049 /*******************************************************************
1050 Convenience routine to grab string parameters into talloced memory
1051 and run standard_sub_basic on them. The buffers can be written to by
1052 callers without affecting the source string.
1053 ********************************************************************/
1055 char *lp_string(TALLOC_CTX *ctx, const char *s)
1057 char *ret;
1059 /* The follow debug is useful for tracking down memory problems
1060 especially if you have an inner loop that is calling a lp_*()
1061 function that returns a string. Perhaps this debug should be
1062 present all the time? */
1064 #if 0
1065 DEBUG(10, ("lp_string(%s)\n", s));
1066 #endif
1067 if (!s) {
1068 return NULL;
1071 ret = talloc_sub_basic(ctx,
1072 get_current_username(),
1073 current_user_info.domain,
1075 if (trim_char(ret, '\"', '\"')) {
1076 if (strchr(ret,'\"') != NULL) {
1077 TALLOC_FREE(ret);
1078 ret = talloc_sub_basic(ctx,
1079 get_current_username(),
1080 current_user_info.domain,
1084 return ret;
1088 In this section all the functions that are used to access the
1089 parameters from the rest of the program are defined
1092 #define FN_GLOBAL_STRING(fn_name,ptr) \
1093 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1094 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1095 const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1096 #define FN_GLOBAL_LIST(fn_name,ptr) \
1097 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1098 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1099 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1100 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1101 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1102 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1103 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1105 #define FN_LOCAL_STRING(fn_name,val) \
1106 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));}
1107 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1108 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1109 #define FN_LOCAL_LIST(fn_name,val) \
1110 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1111 #define FN_LOCAL_BOOL(fn_name,val) \
1112 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1113 #define FN_LOCAL_INTEGER(fn_name,val) \
1114 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1116 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1117 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1118 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1119 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1120 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
1121 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1123 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1124 winbindMaxDomainConnections)
1126 int lp_winbind_max_domain_connections(void)
1128 if (lp_winbind_offline_logon() &&
1129 lp_winbind_max_domain_connections_int() > 1) {
1130 DEBUG(1, ("offline logons active, restricting max domain "
1131 "connections to 1\n"));
1132 return 1;
1134 return MAX(1, lp_winbind_max_domain_connections_int());
1137 int lp_smb2_max_credits(void)
1139 if (Globals.ismb2_max_credits == 0) {
1140 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1142 return Globals.ismb2_max_credits;
1144 int lp_cups_encrypt(void)
1146 int result = 0;
1147 #ifdef HAVE_HTTPCONNECTENCRYPT
1148 switch (Globals.CupsEncrypt) {
1149 case Auto:
1150 result = HTTP_ENCRYPT_REQUIRED;
1151 break;
1152 case true:
1153 result = HTTP_ENCRYPT_ALWAYS;
1154 break;
1155 case false:
1156 result = HTTP_ENCRYPT_NEVER;
1157 break;
1159 #endif
1160 return result;
1163 /* These functions remain in source3/param for now */
1165 #include "lib/param/param_functions.c"
1167 FN_LOCAL_STRING(servicename, szService)
1168 FN_LOCAL_CONST_STRING(const_servicename, szService)
1170 /* These functions cannot be auto-generated */
1171 FN_LOCAL_BOOL(autoloaded, autoloaded)
1173 /* local prototypes */
1175 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1176 static const char *get_boolean(bool bool_value);
1177 static int getservicebyname(const char *pszServiceName,
1178 struct loadparm_service *pserviceDest);
1179 static void copy_service(struct loadparm_service *pserviceDest,
1180 const struct loadparm_service *pserviceSource,
1181 struct bitmap *pcopymapDest);
1182 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1183 void *userdata);
1184 static bool do_section(const char *pszSectionName, void *userdata);
1185 static void init_copymap(struct loadparm_service *pservice);
1186 static bool hash_a_service(const char *name, int number);
1187 static void free_service_byindex(int iService);
1188 static void show_parameter(int parmIndex);
1189 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1192 * This is a helper function for parametrical options support. It returns a
1193 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1194 * parametrical functions are quite simple
1196 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1197 const char *option)
1199 bool global_section = false;
1200 char* param_key;
1201 struct parmlist_entry *data;
1202 TALLOC_CTX *mem_ctx = talloc_stackframe();
1204 if (service == NULL) {
1205 data = Globals.param_opt;
1206 global_section = true;
1207 } else {
1208 data = service->param_opt;
1211 param_key = talloc_asprintf(mem_ctx, "%s:%s", type, option);
1212 if (param_key == NULL) {
1213 DEBUG(0,("asprintf failed!\n"));
1214 TALLOC_FREE(mem_ctx);
1215 return NULL;
1218 while (data) {
1219 if (strwicmp(data->key, param_key) == 0) {
1220 TALLOC_FREE(mem_ctx);
1221 return data;
1223 data = data->next;
1226 if (!global_section) {
1227 /* Try to fetch the same option but from globals */
1228 /* but only if we are not already working with Globals */
1229 data = Globals.param_opt;
1230 while (data) {
1231 if (strwicmp(data->key, param_key) == 0) {
1232 TALLOC_FREE(mem_ctx);
1233 return data;
1235 data = data->next;
1239 TALLOC_FREE(mem_ctx);
1241 return NULL;
1245 * This is a helper function for parametrical options support. It returns a
1246 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1247 * parametrical functions are quite simple
1249 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1250 const char *option)
1252 if (snum >= iNumServices) return NULL;
1254 if (snum < 0) {
1255 return get_parametrics_by_service(NULL, type, option);
1256 } else {
1257 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1262 #define MISSING_PARAMETER(name) \
1263 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1265 /*******************************************************************
1266 convenience routine to return int parameters.
1267 ********************************************************************/
1268 static int lp_int(const char *s)
1271 if (!s || !*s) {
1272 MISSING_PARAMETER(lp_int);
1273 return (-1);
1276 return (int)strtol(s, NULL, 0);
1279 /*******************************************************************
1280 convenience routine to return unsigned long parameters.
1281 ********************************************************************/
1282 static unsigned long lp_ulong(const char *s)
1285 if (!s || !*s) {
1286 MISSING_PARAMETER(lp_ulong);
1287 return (0);
1290 return strtoul(s, NULL, 0);
1293 /*******************************************************************
1294 convenience routine to return boolean parameters.
1295 ********************************************************************/
1296 static bool lp_bool(const char *s)
1298 bool ret = false;
1300 if (!s || !*s) {
1301 MISSING_PARAMETER(lp_bool);
1302 return false;
1305 if (!set_boolean(s, &ret)) {
1306 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1307 return false;
1310 return ret;
1313 /*******************************************************************
1314 convenience routine to return enum parameters.
1315 ********************************************************************/
1316 static int lp_enum(const char *s,const struct enum_list *_enum)
1318 int i;
1320 if (!s || !*s || !_enum) {
1321 MISSING_PARAMETER(lp_enum);
1322 return (-1);
1325 for (i=0; _enum[i].name; i++) {
1326 if (strequal(_enum[i].name,s))
1327 return _enum[i].value;
1330 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1331 return (-1);
1334 #undef MISSING_PARAMETER
1336 /* Return parametric option from a given service. Type is a part of option before ':' */
1337 /* Parametric option has following syntax: 'Type: option = value' */
1338 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1340 struct parmlist_entry *data = get_parametrics(snum, type, option);
1342 if (data == NULL||data->value==NULL) {
1343 if (def) {
1344 return lp_string(ctx, def);
1345 } else {
1346 return NULL;
1350 return lp_string(ctx, data->value);
1353 /* Return parametric option from a given service. Type is a part of option before ':' */
1354 /* Parametric option has following syntax: 'Type: option = value' */
1355 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1357 struct parmlist_entry *data = get_parametrics(snum, type, option);
1359 if (data == NULL||data->value==NULL)
1360 return def;
1362 return data->value;
1365 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1367 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1369 if (data == NULL||data->value==NULL)
1370 return NULL;
1372 return data->value;
1376 /* Return parametric option from a given service. Type is a part of option before ':' */
1377 /* Parametric option has following syntax: 'Type: option = value' */
1379 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1381 struct parmlist_entry *data = get_parametrics(snum, type, option);
1383 if (data == NULL||data->value==NULL)
1384 return (const char **)def;
1386 if (data->list==NULL) {
1387 data->list = str_list_make_v3(NULL, data->value, NULL);
1390 return (const char **)data->list;
1393 /* Return parametric option from a given service. Type is a part of option before ':' */
1394 /* Parametric option has following syntax: 'Type: option = value' */
1396 int lp_parm_int(int snum, const char *type, const char *option, int def)
1398 struct parmlist_entry *data = get_parametrics(snum, type, option);
1400 if (data && data->value && *data->value)
1401 return lp_int(data->value);
1403 return def;
1406 /* Return parametric option from a given service. Type is a part of option before ':' */
1407 /* Parametric option has following syntax: 'Type: option = value' */
1409 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1411 struct parmlist_entry *data = get_parametrics(snum, type, option);
1413 if (data && data->value && *data->value)
1414 return lp_ulong(data->value);
1416 return def;
1419 /* Return parametric option from a given service. Type is a part of option before ':' */
1420 /* Parametric option has following syntax: 'Type: option = value' */
1422 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1424 struct parmlist_entry *data = get_parametrics(snum, type, option);
1426 if (data && data->value && *data->value)
1427 return lp_bool(data->value);
1429 return def;
1432 /* Return parametric option from a given service. Type is a part of option before ':' */
1433 /* Parametric option has following syntax: 'Type: option = value' */
1435 int lp_parm_enum(int snum, const char *type, const char *option,
1436 const struct enum_list *_enum, int def)
1438 struct parmlist_entry *data = get_parametrics(snum, type, option);
1440 if (data && data->value && *data->value && _enum)
1441 return lp_enum(data->value, _enum);
1443 return def;
1447 * free a param_opts structure.
1448 * param_opts handling should be moved to talloc;
1449 * then this whole functions reduces to a TALLOC_FREE().
1452 static void free_param_opts(struct parmlist_entry **popts)
1454 struct parmlist_entry *opt, *next_opt;
1456 if (*popts != NULL) {
1457 DEBUG(5, ("Freeing parametrics:\n"));
1459 opt = *popts;
1460 while (opt != NULL) {
1461 string_free(&opt->key);
1462 string_free(&opt->value);
1463 TALLOC_FREE(opt->list);
1464 next_opt = opt->next;
1465 TALLOC_FREE(opt);
1466 opt = next_opt;
1468 *popts = NULL;
1471 /***************************************************************************
1472 Free the dynamically allocated parts of a service struct.
1473 ***************************************************************************/
1475 static void free_service(struct loadparm_service *pservice)
1477 if (!pservice)
1478 return;
1480 if (pservice->szService)
1481 DEBUG(5, ("free_service: Freeing service %s\n",
1482 pservice->szService));
1484 free_parameters(pservice);
1486 string_free(&pservice->szService);
1487 TALLOC_FREE(pservice->copymap);
1489 free_param_opts(&pservice->param_opt);
1491 ZERO_STRUCTP(pservice);
1495 /***************************************************************************
1496 remove a service indexed in the ServicePtrs array from the ServiceHash
1497 and free the dynamically allocated parts
1498 ***************************************************************************/
1500 static void free_service_byindex(int idx)
1502 if ( !LP_SNUM_OK(idx) )
1503 return;
1505 ServicePtrs[idx]->valid = false;
1507 /* we have to cleanup the hash record */
1509 if (ServicePtrs[idx]->szService) {
1510 char *canon_name = canonicalize_servicename(
1511 talloc_tos(),
1512 ServicePtrs[idx]->szService );
1514 dbwrap_delete_bystring(ServiceHash, canon_name );
1515 TALLOC_FREE(canon_name);
1518 free_service(ServicePtrs[idx]);
1519 talloc_free_children(ServicePtrs[idx]);
1522 /***************************************************************************
1523 Add a new service to the services array initialising it with the given
1524 service.
1525 ***************************************************************************/
1527 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1529 int i;
1530 int num_to_alloc = iNumServices + 1;
1531 struct loadparm_service **tsp = NULL;
1533 /* it might already exist */
1534 if (name) {
1535 i = getservicebyname(name, NULL);
1536 if (i >= 0) {
1537 return (i);
1541 /* if not, then create one */
1542 i = iNumServices;
1543 tsp = talloc_realloc(NULL, ServicePtrs, struct loadparm_service *, num_to_alloc);
1544 if (tsp == NULL) {
1545 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1546 return (-1);
1548 ServicePtrs = tsp;
1549 ServicePtrs[iNumServices] = talloc_zero(NULL, struct loadparm_service);
1550 if (!ServicePtrs[iNumServices]) {
1551 DEBUG(0,("add_a_service: out of memory!\n"));
1552 return (-1);
1554 iNumServices++;
1556 ServicePtrs[i]->valid = true;
1558 copy_service(ServicePtrs[i], pservice, NULL);
1559 if (name)
1560 string_set(ServicePtrs[i], &ServicePtrs[i]->szService, name);
1562 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1563 i, ServicePtrs[i]->szService));
1565 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1566 return (-1);
1569 return (i);
1572 /***************************************************************************
1573 Convert a string to uppercase and remove whitespaces.
1574 ***************************************************************************/
1576 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1578 char *result;
1580 if ( !src ) {
1581 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1582 return NULL;
1585 result = talloc_strdup(ctx, src);
1586 SMB_ASSERT(result != NULL);
1588 if (!strlower_m(result)) {
1589 TALLOC_FREE(result);
1590 return NULL;
1592 return result;
1595 /***************************************************************************
1596 Add a name/index pair for the services array to the hash table.
1597 ***************************************************************************/
1599 static bool hash_a_service(const char *name, int idx)
1601 char *canon_name;
1603 if ( !ServiceHash ) {
1604 DEBUG(10,("hash_a_service: creating servicehash\n"));
1605 ServiceHash = db_open_rbt(NULL);
1606 if ( !ServiceHash ) {
1607 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1608 return false;
1612 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1613 idx, name));
1615 canon_name = canonicalize_servicename(talloc_tos(), name );
1617 dbwrap_store_bystring(ServiceHash, canon_name,
1618 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1619 TDB_REPLACE);
1621 TALLOC_FREE(canon_name);
1623 return true;
1626 /***************************************************************************
1627 Add a new home service, with the specified home directory, defaults coming
1628 from service ifrom.
1629 ***************************************************************************/
1631 bool lp_add_home(const char *pszHomename, int iDefaultService,
1632 const char *user, const char *pszHomedir)
1634 int i;
1636 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1637 pszHomedir[0] == '\0') {
1638 return false;
1641 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1643 if (i < 0)
1644 return false;
1646 if (!(*(ServicePtrs[iDefaultService]->path))
1647 || strequal(ServicePtrs[iDefaultService]->path,
1648 lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1649 string_set(ServicePtrs[i], &ServicePtrs[i]->path, pszHomedir);
1652 if (!(*(ServicePtrs[i]->comment))) {
1653 char *comment = talloc_asprintf(talloc_tos(), "Home directory of %s", user);
1654 if (comment == NULL) {
1655 return false;
1657 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1658 TALLOC_FREE(comment);
1661 /* set the browseable flag from the global default */
1663 ServicePtrs[i]->browseable = sDefault.browseable;
1664 ServicePtrs[i]->access_based_share_enum = sDefault.access_based_share_enum;
1666 ServicePtrs[i]->autoloaded = true;
1668 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1669 user, ServicePtrs[i]->path ));
1671 return true;
1674 /***************************************************************************
1675 Add a new service, based on an old one.
1676 ***************************************************************************/
1678 int lp_add_service(const char *pszService, int iDefaultService)
1680 if (iDefaultService < 0) {
1681 return add_a_service(&sDefault, pszService);
1684 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1687 /***************************************************************************
1688 Add the IPC service.
1689 ***************************************************************************/
1691 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1693 char *comment = NULL;
1694 int i = add_a_service(&sDefault, ipc_name);
1696 if (i < 0)
1697 return false;
1699 comment = talloc_asprintf(talloc_tos(), "IPC Service (%s)",
1700 Globals.server_string);
1701 if (comment == NULL) {
1702 return false;
1705 string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
1706 string_set(ServicePtrs[i], &ServicePtrs[i]->username, "");
1707 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1708 string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
1709 ServicePtrs[i]->max_connections = 0;
1710 ServicePtrs[i]->bAvailable = true;
1711 ServicePtrs[i]->read_only = true;
1712 ServicePtrs[i]->guest_only = false;
1713 ServicePtrs[i]->administrative_share = true;
1714 ServicePtrs[i]->guest_ok = guest_ok;
1715 ServicePtrs[i]->printable = false;
1716 ServicePtrs[i]->browseable = sDefault.browseable;
1718 DEBUG(3, ("adding IPC service\n"));
1720 TALLOC_FREE(comment);
1721 return true;
1724 /***************************************************************************
1725 Add a new printer service, with defaults coming from service iFrom.
1726 ***************************************************************************/
1728 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1730 const char *comment = "From Printcap";
1731 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1733 if (i < 0)
1734 return false;
1736 /* note that we do NOT default the availability flag to true - */
1737 /* we take it from the default service passed. This allows all */
1738 /* dynamic printers to be disabled by disabling the [printers] */
1739 /* entry (if/when the 'available' keyword is implemented!). */
1741 /* the printer name is set to the service name. */
1742 string_set(ServicePtrs[i], &ServicePtrs[i]->_printername, pszPrintername);
1743 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1745 /* set the browseable flag from the gloabl default */
1746 ServicePtrs[i]->browseable = sDefault.browseable;
1748 /* Printers cannot be read_only. */
1749 ServicePtrs[i]->read_only = false;
1750 /* No oplocks on printer services. */
1751 ServicePtrs[i]->oplocks = false;
1752 /* Printer services must be printable. */
1753 ServicePtrs[i]->printable = true;
1755 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1757 return true;
1761 /***************************************************************************
1762 Check whether the given parameter name is valid.
1763 Parametric options (names containing a colon) are considered valid.
1764 ***************************************************************************/
1766 bool lp_parameter_is_valid(const char *pszParmName)
1768 return ((lpcfg_map_parameter(pszParmName) != -1) ||
1769 (strchr(pszParmName, ':') != NULL));
1772 /***************************************************************************
1773 Check whether the given name is the name of a global parameter.
1774 Returns true for strings belonging to parameters of class
1775 P_GLOBAL, false for all other strings, also for parametric options
1776 and strings not belonging to any option.
1777 ***************************************************************************/
1779 bool lp_parameter_is_global(const char *pszParmName)
1781 int num = lpcfg_map_parameter(pszParmName);
1783 if (num >= 0) {
1784 return (parm_table[num].p_class == P_GLOBAL);
1787 return false;
1790 /**************************************************************************
1791 Check whether the given name is the canonical name of a parameter.
1792 Returns false if it is not a valid parameter Name.
1793 For parametric options, true is returned.
1794 **************************************************************************/
1796 bool lp_parameter_is_canonical(const char *parm_name)
1798 if (!lp_parameter_is_valid(parm_name)) {
1799 return false;
1802 return (lpcfg_map_parameter(parm_name) ==
1803 map_parameter_canonical(parm_name, NULL));
1806 /**************************************************************************
1807 Determine the canonical name for a parameter.
1808 Indicate when it is an inverse (boolean) synonym instead of a
1809 "usual" synonym.
1810 **************************************************************************/
1812 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1813 bool *inverse)
1815 int num;
1817 if (!lp_parameter_is_valid(parm_name)) {
1818 *canon_parm = NULL;
1819 return false;
1822 num = map_parameter_canonical(parm_name, inverse);
1823 if (num < 0) {
1824 /* parametric option */
1825 *canon_parm = parm_name;
1826 } else {
1827 *canon_parm = parm_table[num].label;
1830 return true;
1834 /**************************************************************************
1835 Determine the canonical name for a parameter.
1836 Turn the value given into the inverse boolean expression when
1837 the synonym is an invers boolean synonym.
1839 Return true if parm_name is a valid parameter name and
1840 in case it is an invers boolean synonym, if the val string could
1841 successfully be converted to the reverse bool.
1842 Return false in all other cases.
1843 **************************************************************************/
1845 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1846 const char *val,
1847 const char **canon_parm,
1848 const char **canon_val)
1850 int num;
1851 bool inverse;
1853 if (!lp_parameter_is_valid(parm_name)) {
1854 *canon_parm = NULL;
1855 *canon_val = NULL;
1856 return false;
1859 num = map_parameter_canonical(parm_name, &inverse);
1860 if (num < 0) {
1861 /* parametric option */
1862 *canon_parm = parm_name;
1863 *canon_val = val;
1864 } else {
1865 *canon_parm = parm_table[num].label;
1866 if (inverse) {
1867 if (!lp_invert_boolean(val, canon_val)) {
1868 *canon_val = NULL;
1869 return false;
1871 } else {
1872 *canon_val = val;
1876 return true;
1879 /***************************************************************************
1880 Map a parameter's string representation to the index of the canonical
1881 form of the parameter (it might be a synonym).
1882 Returns -1 if the parameter string is not recognised.
1883 ***************************************************************************/
1885 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1887 int parm_num, canon_num;
1888 bool loc_inverse = false;
1890 parm_num = lpcfg_map_parameter(pszParmName);
1891 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1892 /* invalid, parametric or no canidate for synonyms ... */
1893 goto done;
1896 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1897 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1898 parm_num = canon_num;
1899 goto done;
1903 done:
1904 if (inverse != NULL) {
1905 *inverse = loc_inverse;
1907 return parm_num;
1910 /***************************************************************************
1911 return true if parameter number parm1 is a synonym of parameter
1912 number parm2 (parm2 being the principal name).
1913 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1914 false otherwise.
1915 ***************************************************************************/
1917 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
1919 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
1920 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
1921 (parm_table[parm1].flags & FLAG_HIDE) &&
1922 !(parm_table[parm2].flags & FLAG_HIDE))
1924 if (inverse != NULL) {
1925 if ((parm_table[parm1].type == P_BOOLREV) &&
1926 (parm_table[parm2].type == P_BOOL))
1928 *inverse = true;
1929 } else {
1930 *inverse = false;
1933 return true;
1935 return false;
1938 /***************************************************************************
1939 Show one parameter's name, type, [values,] and flags.
1940 (helper functions for show_parameter_list)
1941 ***************************************************************************/
1943 static void show_parameter(int parmIndex)
1945 int enumIndex, flagIndex;
1946 int parmIndex2;
1947 bool hadFlag;
1948 bool hadSyn;
1949 bool inverse;
1950 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
1951 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
1952 "P_ENUM", "P_SEP"};
1953 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
1954 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
1955 FLAG_HIDE};
1956 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
1957 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
1958 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
1960 printf("%s=%s", parm_table[parmIndex].label,
1961 type[parm_table[parmIndex].type]);
1962 if (parm_table[parmIndex].type == P_ENUM) {
1963 printf(",");
1964 for (enumIndex=0;
1965 parm_table[parmIndex].enum_list[enumIndex].name;
1966 enumIndex++)
1968 printf("%s%s",
1969 enumIndex ? "|" : "",
1970 parm_table[parmIndex].enum_list[enumIndex].name);
1973 printf(",");
1974 hadFlag = false;
1975 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
1976 if (parm_table[parmIndex].flags & flags[flagIndex]) {
1977 printf("%s%s",
1978 hadFlag ? "|" : "",
1979 flag_names[flagIndex]);
1980 hadFlag = true;
1984 /* output synonyms */
1985 hadSyn = false;
1986 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
1987 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
1988 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
1989 parm_table[parmIndex2].label);
1990 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
1991 if (!hadSyn) {
1992 printf(" (synonyms: ");
1993 hadSyn = true;
1994 } else {
1995 printf(", ");
1997 printf("%s%s", parm_table[parmIndex2].label,
1998 inverse ? "[i]" : "");
2001 if (hadSyn) {
2002 printf(")");
2005 printf("\n");
2008 /***************************************************************************
2009 Show all parameter's name, type, [values,] and flags.
2010 ***************************************************************************/
2012 void show_parameter_list(void)
2014 int classIndex, parmIndex;
2015 const char *section_names[] = { "local", "global", NULL};
2017 for (classIndex=0; section_names[classIndex]; classIndex++) {
2018 printf("[%s]\n", section_names[classIndex]);
2019 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2020 if (parm_table[parmIndex].p_class == classIndex) {
2021 show_parameter(parmIndex);
2027 /***************************************************************************
2028 Get the standard string representation of a boolean value ("yes" or "no")
2029 ***************************************************************************/
2031 static const char *get_boolean(bool bool_value)
2033 static const char *yes_str = "yes";
2034 static const char *no_str = "no";
2036 return (bool_value ? yes_str : no_str);
2039 /***************************************************************************
2040 Provide the string of the negated boolean value associated to the boolean
2041 given as a string. Returns false if the passed string does not correctly
2042 represent a boolean.
2043 ***************************************************************************/
2045 bool lp_invert_boolean(const char *str, const char **inverse_str)
2047 bool val;
2049 if (!set_boolean(str, &val)) {
2050 return false;
2053 *inverse_str = get_boolean(!val);
2054 return true;
2057 /***************************************************************************
2058 Provide the canonical string representation of a boolean value given
2059 as a string. Return true on success, false if the string given does
2060 not correctly represent a boolean.
2061 ***************************************************************************/
2063 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2065 bool val;
2067 if (!set_boolean(str, &val)) {
2068 return false;
2071 *canon_str = get_boolean(val);
2072 return true;
2075 /***************************************************************************
2076 Find a service by name. Otherwise works like get_service.
2077 ***************************************************************************/
2079 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2081 int iService = -1;
2082 char *canon_name;
2083 TDB_DATA data;
2084 NTSTATUS status;
2086 if (ServiceHash == NULL) {
2087 return -1;
2090 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2092 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2093 &data);
2095 if (NT_STATUS_IS_OK(status) &&
2096 (data.dptr != NULL) &&
2097 (data.dsize == sizeof(iService)))
2099 iService = *(int *)data.dptr;
2102 TALLOC_FREE(canon_name);
2104 if ((iService != -1) && (LP_SNUM_OK(iService))
2105 && (pserviceDest != NULL)) {
2106 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2109 return (iService);
2112 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2113 struct loadparm_service *lp_service(const char *pszServiceName)
2115 int iService = getservicebyname(pszServiceName, NULL);
2116 if (iService == -1 || !LP_SNUM_OK(iService)) {
2117 return NULL;
2119 return ServicePtrs[iService];
2122 struct loadparm_service *lp_servicebynum(int snum)
2124 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2125 return NULL;
2127 return ServicePtrs[snum];
2130 struct loadparm_service *lp_default_loadparm_service()
2132 return &sDefault;
2136 /***************************************************************************
2137 Copy a service structure to another.
2138 If pcopymapDest is NULL then copy all fields
2139 ***************************************************************************/
2141 static void copy_service(struct loadparm_service *pserviceDest,
2142 const struct loadparm_service *pserviceSource,
2143 struct bitmap *pcopymapDest)
2145 int i;
2146 bool bcopyall = (pcopymapDest == NULL);
2147 struct parmlist_entry *data;
2149 for (i = 0; parm_table[i].label; i++)
2150 if (parm_table[i].p_class == P_LOCAL &&
2151 (bcopyall || bitmap_query(pcopymapDest, i))) {
2152 const void *src_ptr =
2153 ((const char *)pserviceSource) + parm_table[i].offset;
2154 void *dest_ptr =
2155 ((char *)pserviceDest) + parm_table[i].offset;
2157 switch (parm_table[i].type) {
2158 case P_BOOL:
2159 case P_BOOLREV:
2160 *(bool *)dest_ptr = *(const bool *)src_ptr;
2161 break;
2163 case P_INTEGER:
2164 case P_BYTES:
2165 case P_OCTAL:
2166 case P_ENUM:
2167 *(int *)dest_ptr = *(const int *)src_ptr;
2168 break;
2170 case P_CHAR:
2171 *(char *)dest_ptr = *(const char *)src_ptr;
2172 break;
2174 case P_STRING:
2175 lpcfg_string_set(pserviceDest,
2176 (char **)dest_ptr,
2177 *(const char * const *)src_ptr);
2178 break;
2180 case P_USTRING:
2181 lpcfg_string_set_upper(pserviceDest,
2182 (char **)dest_ptr,
2183 *(const char * const *)src_ptr);
2184 break;
2185 case P_LIST:
2186 TALLOC_FREE(*((char ***)dest_ptr));
2187 *(const char * const **)dest_ptr = (const char * const *)str_list_copy(pserviceDest,
2188 *(const char * * const *)src_ptr);
2189 break;
2190 default:
2191 break;
2195 if (bcopyall) {
2196 init_copymap(pserviceDest);
2197 if (pserviceSource->copymap)
2198 bitmap_copy(pserviceDest->copymap,
2199 pserviceSource->copymap);
2202 data = pserviceSource->param_opt;
2203 while (data) {
2204 set_param_opt(pserviceDest, &pserviceDest->param_opt, data->key, data->value, data->priority);
2205 data = data->next;
2209 /***************************************************************************
2210 Check a service for consistency. Return false if the service is in any way
2211 incomplete or faulty, else true.
2212 ***************************************************************************/
2214 bool service_ok(int iService)
2216 bool bRetval;
2218 bRetval = true;
2219 if (ServicePtrs[iService]->szService[0] == '\0') {
2220 DEBUG(0, ("The following message indicates an internal error:\n"));
2221 DEBUG(0, ("No service name in service entry.\n"));
2222 bRetval = false;
2225 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2226 /* I can't see why you'd want a non-printable printer service... */
2227 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2228 if (!ServicePtrs[iService]->printable) {
2229 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2230 ServicePtrs[iService]->szService));
2231 ServicePtrs[iService]->printable = true;
2233 /* [printers] service must also be non-browsable. */
2234 if (ServicePtrs[iService]->browseable)
2235 ServicePtrs[iService]->browseable = false;
2238 if (ServicePtrs[iService]->path[0] == '\0' &&
2239 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2240 ServicePtrs[iService]->msdfs_proxy[0] == '\0'
2242 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2243 ServicePtrs[iService]->szService));
2244 ServicePtrs[iService]->bAvailable = false;
2247 /* If a service is flagged unavailable, log the fact at level 1. */
2248 if (!ServicePtrs[iService]->bAvailable)
2249 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2250 ServicePtrs[iService]->szService));
2252 return (bRetval);
2255 static struct smbconf_ctx *lp_smbconf_ctx(void)
2257 sbcErr err;
2258 static struct smbconf_ctx *conf_ctx = NULL;
2260 if (conf_ctx == NULL) {
2261 err = smbconf_init(NULL, &conf_ctx, "registry:");
2262 if (!SBC_ERROR_IS_OK(err)) {
2263 DEBUG(1, ("error initializing registry configuration: "
2264 "%s\n", sbcErrorString(err)));
2265 conf_ctx = NULL;
2269 return conf_ctx;
2272 static bool process_smbconf_service(struct smbconf_service *service)
2274 uint32_t count;
2275 bool ret;
2277 if (service == NULL) {
2278 return false;
2281 ret = do_section(service->name, NULL);
2282 if (ret != true) {
2283 return false;
2285 for (count = 0; count < service->num_params; count++) {
2286 ret = do_parameter(service->param_names[count],
2287 service->param_values[count],
2288 NULL);
2289 if (ret != true) {
2290 return false;
2293 if (iServiceIndex >= 0) {
2294 return service_ok(iServiceIndex);
2296 return true;
2300 * load a service from registry and activate it
2302 bool process_registry_service(const char *service_name)
2304 sbcErr err;
2305 struct smbconf_service *service = NULL;
2306 TALLOC_CTX *mem_ctx = talloc_stackframe();
2307 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2308 bool ret = false;
2310 if (conf_ctx == NULL) {
2311 goto done;
2314 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2316 if (!smbconf_share_exists(conf_ctx, service_name)) {
2318 * Registry does not contain data for this service (yet),
2319 * but make sure lp_load doesn't return false.
2321 ret = true;
2322 goto done;
2325 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2326 if (!SBC_ERROR_IS_OK(err)) {
2327 goto done;
2330 ret = process_smbconf_service(service);
2331 if (!ret) {
2332 goto done;
2335 /* store the csn */
2336 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2338 done:
2339 TALLOC_FREE(mem_ctx);
2340 return ret;
2344 * process_registry_globals
2346 static bool process_registry_globals(void)
2348 bool ret;
2350 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2352 ret = do_parameter("registry shares", "yes", NULL);
2353 if (!ret) {
2354 return ret;
2357 return process_registry_service(GLOBAL_NAME);
2360 bool process_registry_shares(void)
2362 sbcErr err;
2363 uint32_t count;
2364 struct smbconf_service **service = NULL;
2365 uint32_t num_shares = 0;
2366 TALLOC_CTX *mem_ctx = talloc_stackframe();
2367 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2368 bool ret = false;
2370 if (conf_ctx == NULL) {
2371 goto done;
2374 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2375 if (!SBC_ERROR_IS_OK(err)) {
2376 goto done;
2379 ret = true;
2381 for (count = 0; count < num_shares; count++) {
2382 if (strequal(service[count]->name, GLOBAL_NAME)) {
2383 continue;
2385 ret = process_smbconf_service(service[count]);
2386 if (!ret) {
2387 goto done;
2391 /* store the csn */
2392 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2394 done:
2395 TALLOC_FREE(mem_ctx);
2396 return ret;
2400 * reload those shares from registry that are already
2401 * activated in the services array.
2403 static bool reload_registry_shares(void)
2405 int i;
2406 bool ret = true;
2408 for (i = 0; i < iNumServices; i++) {
2409 if (!VALID(i)) {
2410 continue;
2413 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2414 continue;
2417 ret = process_registry_service(ServicePtrs[i]->szService);
2418 if (!ret) {
2419 goto done;
2423 done:
2424 return ret;
2428 #define MAX_INCLUDE_DEPTH 100
2430 static uint8_t include_depth;
2432 static struct file_lists {
2433 struct file_lists *next;
2434 char *name;
2435 char *subfname;
2436 time_t modtime;
2437 } *file_lists = NULL;
2439 /*******************************************************************
2440 Keep a linked list of all config files so we know when one has changed
2441 it's date and needs to be reloaded.
2442 ********************************************************************/
2444 static void add_to_file_list(const char *fname, const char *subfname)
2446 struct file_lists *f = file_lists;
2448 while (f) {
2449 if (f->name && !strcmp(f->name, fname))
2450 break;
2451 f = f->next;
2454 if (!f) {
2455 f = talloc(NULL, struct file_lists);
2456 if (!f) {
2457 goto fail;
2459 f->next = file_lists;
2460 f->name = talloc_strdup(f, fname);
2461 if (!f->name) {
2462 TALLOC_FREE(f);
2463 goto fail;
2465 f->subfname = talloc_strdup(f, subfname);
2466 if (!f->subfname) {
2467 TALLOC_FREE(f);
2468 goto fail;
2470 file_lists = f;
2471 f->modtime = file_modtime(subfname);
2472 } else {
2473 time_t t = file_modtime(subfname);
2474 if (t)
2475 f->modtime = t;
2477 return;
2479 fail:
2480 DEBUG(0, ("Unable to add file to file list: %s\n", fname));
2485 * Free the file lists
2487 static void free_file_list(void)
2489 struct file_lists *f;
2490 struct file_lists *next;
2492 f = file_lists;
2493 while( f ) {
2494 next = f->next;
2495 TALLOC_FREE( f );
2496 f = next;
2498 file_lists = NULL;
2503 * Utility function for outsiders to check if we're running on registry.
2505 bool lp_config_backend_is_registry(void)
2507 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2511 * Utility function to check if the config backend is FILE.
2513 bool lp_config_backend_is_file(void)
2515 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2518 /*******************************************************************
2519 Check if a config file has changed date.
2520 ********************************************************************/
2522 bool lp_file_list_changed(void)
2524 struct file_lists *f = file_lists;
2526 DEBUG(6, ("lp_file_list_changed()\n"));
2528 while (f) {
2529 time_t mod_time;
2531 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2532 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2534 if (conf_ctx == NULL) {
2535 return false;
2537 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2538 NULL))
2540 DEBUGADD(6, ("registry config changed\n"));
2541 return true;
2543 } else {
2544 char *n2 = NULL;
2545 n2 = talloc_sub_basic(talloc_tos(),
2546 get_current_username(),
2547 current_user_info.domain,
2548 f->name);
2549 if (!n2) {
2550 return false;
2552 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2553 f->name, n2, ctime(&f->modtime)));
2555 mod_time = file_modtime(n2);
2557 if (mod_time &&
2558 ((f->modtime != mod_time) ||
2559 (f->subfname == NULL) ||
2560 (strcmp(n2, f->subfname) != 0)))
2562 DEBUGADD(6,
2563 ("file %s modified: %s\n", n2,
2564 ctime(&mod_time)));
2565 f->modtime = mod_time;
2566 TALLOC_FREE(f->subfname);
2567 f->subfname = talloc_strdup(f, n2);
2568 if (f->subfname == NULL) {
2569 smb_panic("talloc_strdup failed");
2571 TALLOC_FREE(n2);
2572 return true;
2574 TALLOC_FREE(n2);
2576 f = f->next;
2578 return false;
2583 * Initialize iconv conversion descriptors.
2585 * This is called the first time it is needed, and also called again
2586 * every time the configuration is reloaded, because the charset or
2587 * codepage might have changed.
2589 static void init_iconv(void)
2591 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2592 lp_unix_charset(),
2593 true, global_iconv_handle);
2596 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2598 if (strcmp(*ptr, pszParmValue) != 0) {
2599 string_set(Globals.ctx, ptr, pszParmValue);
2600 init_iconv();
2602 return true;
2605 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2607 bool is_utf8 = false;
2608 size_t len = strlen(pszParmValue);
2610 if (len == 4 || len == 5) {
2611 /* Don't use StrCaseCmp here as we don't want to
2612 initialize iconv. */
2613 if ((toupper_m(pszParmValue[0]) == 'U') &&
2614 (toupper_m(pszParmValue[1]) == 'T') &&
2615 (toupper_m(pszParmValue[2]) == 'F')) {
2616 if (len == 4) {
2617 if (pszParmValue[3] == '8') {
2618 is_utf8 = true;
2620 } else {
2621 if (pszParmValue[3] == '-' &&
2622 pszParmValue[4] == '8') {
2623 is_utf8 = true;
2629 if (strcmp(*ptr, pszParmValue) != 0) {
2630 if (is_utf8) {
2631 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2632 "be UTF8, using (default value) %s instead.\n",
2633 DEFAULT_DOS_CHARSET));
2634 pszParmValue = DEFAULT_DOS_CHARSET;
2636 string_set(Globals.ctx, ptr, pszParmValue);
2637 init_iconv();
2639 return true;
2642 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2644 TALLOC_FREE(Globals.netbios_aliases);
2645 Globals.netbios_aliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2646 return set_netbios_aliases(Globals.netbios_aliases);
2649 /***************************************************************************
2650 Handle the include operation.
2651 ***************************************************************************/
2652 static bool bAllowIncludeRegistry = true;
2654 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2656 char *fname;
2658 if (include_depth >= MAX_INCLUDE_DEPTH) {
2659 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2660 include_depth));
2661 return false;
2664 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2665 if (!bAllowIncludeRegistry) {
2666 return true;
2668 if (bInGlobalSection) {
2669 bool ret;
2670 include_depth++;
2671 ret = process_registry_globals();
2672 include_depth--;
2673 return ret;
2674 } else {
2675 DEBUG(1, ("\"include = registry\" only effective "
2676 "in %s section\n", GLOBAL_NAME));
2677 return false;
2681 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2682 current_user_info.domain,
2683 pszParmValue);
2685 add_to_file_list(pszParmValue, fname);
2687 if (snum < 0) {
2688 string_set(Globals.ctx, ptr, fname);
2689 } else {
2690 string_set(ServicePtrs[snum], ptr, fname);
2693 if (file_exist(fname)) {
2694 bool ret;
2695 include_depth++;
2696 ret = pm_process(fname, do_section, do_parameter, NULL);
2697 include_depth--;
2698 TALLOC_FREE(fname);
2699 return ret;
2702 DEBUG(2, ("Can't find include file %s\n", fname));
2703 TALLOC_FREE(fname);
2704 return true;
2707 /***************************************************************************
2708 Handle the interpretation of the copy parameter.
2709 ***************************************************************************/
2711 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2713 bool bRetval;
2714 int iTemp;
2716 bRetval = false;
2718 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2720 if ((iTemp = getservicebyname(pszParmValue, NULL)) >= 0) {
2721 if (iTemp == iServiceIndex) {
2722 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2723 } else {
2724 copy_service(ServicePtrs[iServiceIndex],
2725 ServicePtrs[iTemp],
2726 ServicePtrs[iServiceIndex]->copymap);
2727 string_set(ServicePtrs[iServiceIndex], ptr, pszParmValue);
2728 bRetval = true;
2730 } else {
2731 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2732 bRetval = false;
2735 return (bRetval);
2738 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2740 Globals.ldap_debug_level = lp_int(pszParmValue);
2741 init_ldap_debugging();
2742 return true;
2746 * idmap related parameters
2749 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2751 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2753 return true;
2756 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2758 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2760 return true;
2763 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2765 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2767 return true;
2770 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2772 char *config_option = NULL;
2773 const char *range = NULL;
2774 bool ret = false;
2776 SMB_ASSERT(low != NULL);
2777 SMB_ASSERT(high != NULL);
2779 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2780 domain_name = "*";
2783 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2784 domain_name);
2785 if (config_option == NULL) {
2786 DEBUG(0, ("out of memory\n"));
2787 return false;
2790 range = lp_parm_const_string(-1, config_option, "range", NULL);
2791 if (range == NULL) {
2792 DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2793 goto done;
2796 if (sscanf(range, "%u - %u", low, high) != 2) {
2797 DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2798 range, domain_name));
2799 goto done;
2802 ret = true;
2804 done:
2805 talloc_free(config_option);
2806 return ret;
2810 bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2812 return lp_idmap_range("*", low, high);
2815 const char *lp_idmap_backend(const char *domain_name)
2817 char *config_option = NULL;
2818 const char *backend = NULL;
2820 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2821 domain_name = "*";
2824 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2825 domain_name);
2826 if (config_option == NULL) {
2827 DEBUG(0, ("out of memory\n"));
2828 return false;
2831 backend = lp_parm_const_string(-1, config_option, "backend", NULL);
2832 if (backend == NULL) {
2833 DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
2834 goto done;
2837 done:
2838 talloc_free(config_option);
2839 return backend;
2842 const char *lp_idmap_default_backend(void)
2844 return lp_idmap_backend("*");
2847 /***************************************************************************
2848 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2849 ***************************************************************************/
2851 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2853 const char *suffix_string;
2855 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2856 Globals.ldap_suffix );
2857 if ( !suffix_string ) {
2858 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2859 return "";
2862 return suffix_string;
2865 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2867 if (Globals.szLdapMachineSuffix[0])
2868 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
2870 return lp_string(ctx, Globals.ldap_suffix);
2873 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
2875 if (Globals.szLdapUserSuffix[0])
2876 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
2878 return lp_string(ctx, Globals.ldap_suffix);
2881 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
2883 if (Globals.szLdapGroupSuffix[0])
2884 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
2886 return lp_string(ctx, Globals.ldap_suffix);
2889 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
2891 if (Globals.szLdapIdmapSuffix[0])
2892 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
2894 return lp_string(ctx, Globals.ldap_suffix);
2897 /****************************************************************************
2898 set the value for a P_ENUM
2899 ***************************************************************************/
2901 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
2902 int *ptr )
2904 int i;
2906 for (i = 0; parm->enum_list[i].name; i++) {
2907 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
2908 *ptr = parm->enum_list[i].value;
2909 return;
2912 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
2913 pszParmValue, parm->label));
2916 /***************************************************************************
2917 ***************************************************************************/
2919 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2921 static int parm_num = -1;
2922 struct loadparm_service *s;
2924 if ( parm_num == -1 )
2925 parm_num = lpcfg_map_parameter( "printing" );
2927 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
2929 if ( snum < 0 ) {
2930 s = &sDefault;
2931 init_printer_values(Globals.ctx, s);
2932 } else {
2933 s = ServicePtrs[snum];
2934 init_printer_values(s, s);
2937 return true;
2941 /***************************************************************************
2942 Initialise a copymap.
2943 ***************************************************************************/
2945 static void init_copymap(struct loadparm_service *pservice)
2947 int i;
2949 TALLOC_FREE(pservice->copymap);
2951 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
2952 if (!pservice->copymap)
2953 DEBUG(0,
2954 ("Couldn't allocate copymap!! (size %d)\n",
2955 (int)NUMPARAMETERS));
2956 else
2957 for (i = 0; i < NUMPARAMETERS; i++)
2958 bitmap_set(pservice->copymap, i);
2962 return the parameter pointer for a parameter
2964 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
2966 if (service == NULL) {
2967 if (parm->p_class == P_LOCAL)
2968 return (void *)(((char *)&sDefault)+parm->offset);
2969 else if (parm->p_class == P_GLOBAL)
2970 return (void *)(((char *)&Globals)+parm->offset);
2971 else return NULL;
2972 } else {
2973 return (void *)(((char *)service) + parm->offset);
2977 /***************************************************************************
2978 Return the local pointer to a parameter given the service number and parameter
2979 ***************************************************************************/
2981 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
2983 return lp_parm_ptr(ServicePtrs[snum], parm);
2986 /***************************************************************************
2987 Process a parameter for a particular service number. If snum < 0
2988 then assume we are in the globals.
2989 ***************************************************************************/
2991 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
2993 int parmnum, i;
2994 void *parm_ptr = NULL; /* where we are going to store the result */
2995 struct parmlist_entry **opt_list;
2996 TALLOC_CTX *mem_ctx;
2998 parmnum = lpcfg_map_parameter(pszParmName);
3000 if (parmnum < 0) {
3001 if (strchr(pszParmName, ':') == NULL) {
3002 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3003 pszParmName));
3004 return true;
3008 * We've got a parametric option
3011 if (snum < 0) {
3012 opt_list = &Globals.param_opt;
3013 set_param_opt(NULL, opt_list, pszParmName, pszParmValue, 0);
3014 } else {
3015 opt_list = &ServicePtrs[snum]->param_opt;
3016 set_param_opt(ServicePtrs[snum], opt_list, pszParmName, pszParmValue, 0);
3019 return true;
3022 /* if it's already been set by the command line, then we don't
3023 override here */
3024 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3025 return true;
3028 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3029 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3030 pszParmName));
3033 /* we might point at a service, the default service or a global */
3034 if (snum < 0) {
3035 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3036 } else {
3037 if (parm_table[parmnum].p_class == P_GLOBAL) {
3038 DEBUG(0,
3039 ("Global parameter %s found in service section!\n",
3040 pszParmName));
3041 return true;
3043 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3046 if (snum >= 0) {
3047 if (!ServicePtrs[snum]->copymap)
3048 init_copymap(ServicePtrs[snum]);
3050 /* this handles the aliases - set the copymap for other entries with
3051 the same data pointer */
3052 for (i = 0; parm_table[i].label; i++) {
3053 if ((parm_table[i].offset == parm_table[parmnum].offset)
3054 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3055 bitmap_clear(ServicePtrs[snum]->copymap, i);
3058 mem_ctx = ServicePtrs[snum];
3059 } else {
3060 mem_ctx = Globals.ctx;
3063 /* if it is a special case then go ahead */
3064 if (parm_table[parmnum].special) {
3065 bool ok;
3066 struct loadparm_context *lp_ctx = loadparm_init_s3(talloc_tos(),
3067 loadparm_s3_helpers());
3068 ok = parm_table[parmnum].special(lp_ctx, snum, pszParmValue,
3069 (char **)parm_ptr);
3070 TALLOC_FREE(lp_ctx);
3072 return ok;
3075 /* now switch on the type of variable it is */
3076 switch (parm_table[parmnum].type)
3078 case P_BOOL:
3079 *(bool *)parm_ptr = lp_bool(pszParmValue);
3080 break;
3082 case P_BOOLREV:
3083 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3084 break;
3086 case P_INTEGER:
3087 *(int *)parm_ptr = lp_int(pszParmValue);
3088 break;
3090 case P_CHAR:
3091 *(char *)parm_ptr = *pszParmValue;
3092 break;
3094 case P_OCTAL:
3095 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3096 if ( i != 1 ) {
3097 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3099 break;
3101 case P_BYTES:
3103 uint64_t val;
3104 if (conv_str_size_error(pszParmValue, &val)) {
3105 if (val <= INT_MAX) {
3106 *(int *)parm_ptr = (int)val;
3107 break;
3111 DEBUG(0,("lp_do_parameter(%s): value is not "
3112 "a valid size specifier!\n", pszParmValue));
3113 return false;
3116 case P_LIST:
3117 case P_CMDLIST:
3118 TALLOC_FREE(*((char ***)parm_ptr));
3119 *(char ***)parm_ptr = str_list_make_v3(
3120 NULL, pszParmValue, NULL);
3121 break;
3123 case P_STRING:
3124 string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
3125 break;
3127 case P_USTRING:
3129 char *upper_string = strupper_talloc(talloc_tos(),
3130 pszParmValue);
3131 string_set(mem_ctx, (char **)parm_ptr, upper_string);
3132 TALLOC_FREE(upper_string);
3133 break;
3135 case P_ENUM:
3136 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3137 break;
3138 case P_SEP:
3139 break;
3142 return true;
3145 /***************************************************************************
3146 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3147 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3148 ***************************************************************************/
3150 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3152 int parmnum, i;
3153 parmnum = lpcfg_map_parameter(pszParmName);
3154 if (parmnum >= 0) {
3155 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3156 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3157 return false;
3159 parm_table[parmnum].flags |= FLAG_CMDLINE;
3161 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3162 * be grouped in the table, so we don't have to search the
3163 * whole table */
3164 for (i=parmnum-1;
3165 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3166 && parm_table[i].p_class == parm_table[parmnum].p_class;
3167 i--) {
3168 parm_table[i].flags |= FLAG_CMDLINE;
3170 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3171 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3172 parm_table[i].flags |= FLAG_CMDLINE;
3175 if (store_values) {
3176 store_lp_set_cmdline(pszParmName, pszParmValue);
3178 return true;
3181 /* it might be parametric */
3182 if (strchr(pszParmName, ':') != NULL) {
3183 set_param_opt(NULL, &Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3184 if (store_values) {
3185 store_lp_set_cmdline(pszParmName, pszParmValue);
3187 return true;
3190 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3191 return true;
3194 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3196 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3199 /***************************************************************************
3200 Process a parameter.
3201 ***************************************************************************/
3203 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3204 void *userdata)
3206 if (!bInGlobalSection && bGlobalOnly)
3207 return true;
3209 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3211 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3212 pszParmName, pszParmValue));
3216 set a option from the commandline in 'a=b' format. Use to support --option
3218 bool lp_set_option(const char *option)
3220 char *p, *s;
3221 bool ret;
3223 s = talloc_strdup(NULL, option);
3224 if (!s) {
3225 return false;
3228 p = strchr(s, '=');
3229 if (!p) {
3230 talloc_free(s);
3231 return false;
3234 *p = 0;
3236 /* skip white spaces after the = sign */
3237 do {
3238 p++;
3239 } while (*p == ' ');
3241 ret = lp_set_cmdline(s, p);
3242 talloc_free(s);
3243 return ret;
3246 /***************************************************************************
3247 Initialize any local variables in the sDefault table, after parsing a
3248 [globals] section.
3249 ***************************************************************************/
3251 static void init_locals(void)
3254 * We run this check once the [globals] is parsed, to force
3255 * the VFS objects and other per-share settings we need for
3256 * the standard way a AD DC is operated. We may change these
3257 * as our code evolves, which is why we force these settings.
3259 * We can't do this at the end of lp_load_ex(), as by that
3260 * point the services have been loaded and they will already
3261 * have "" as their vfs objects.
3263 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
3264 const char **vfs_objects = lp_vfs_objects(-1);
3265 if (!vfs_objects || !vfs_objects[0]) {
3266 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
3267 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
3268 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
3269 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
3270 } else {
3271 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
3275 lp_do_parameter(-1, "map hidden", "no");
3276 lp_do_parameter(-1, "map system", "no");
3277 lp_do_parameter(-1, "map readonly", "no");
3278 lp_do_parameter(-1, "map archive", "no");
3279 lp_do_parameter(-1, "store dos attributes", "yes");
3283 /***************************************************************************
3284 Process a new section (service). At this stage all sections are services.
3285 Later we'll have special sections that permit server parameters to be set.
3286 Returns true on success, false on failure.
3287 ***************************************************************************/
3289 static bool do_section(const char *pszSectionName, void *userdata)
3291 bool bRetval;
3292 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3293 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3294 bRetval = false;
3296 /* if we were in a global section then do the local inits */
3297 if (bInGlobalSection && !isglobal)
3298 init_locals();
3300 /* if we've just struck a global section, note the fact. */
3301 bInGlobalSection = isglobal;
3303 /* check for multiple global sections */
3304 if (bInGlobalSection) {
3305 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3306 return true;
3309 if (!bInGlobalSection && bGlobalOnly)
3310 return true;
3312 /* if we have a current service, tidy it up before moving on */
3313 bRetval = true;
3315 if (iServiceIndex >= 0)
3316 bRetval = service_ok(iServiceIndex);
3318 /* if all is still well, move to the next record in the services array */
3319 if (bRetval) {
3320 /* We put this here to avoid an odd message order if messages are */
3321 /* issued by the post-processing of a previous section. */
3322 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3324 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3325 if (iServiceIndex < 0) {
3326 DEBUG(0, ("Failed to add a new service\n"));
3327 return false;
3329 /* Clean all parametric options for service */
3330 /* They will be added during parsing again */
3331 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3334 return bRetval;
3338 /***************************************************************************
3339 Determine if a partcular base parameter is currentl set to the default value.
3340 ***************************************************************************/
3342 static bool is_default(int i)
3344 switch (parm_table[i].type) {
3345 case P_LIST:
3346 case P_CMDLIST:
3347 return str_list_equal((const char * const *)parm_table[i].def.lvalue,
3348 *(const char ***)lp_parm_ptr(NULL,
3349 &parm_table[i]));
3350 case P_STRING:
3351 case P_USTRING:
3352 return strequal(parm_table[i].def.svalue,
3353 *(char **)lp_parm_ptr(NULL,
3354 &parm_table[i]));
3355 case P_BOOL:
3356 case P_BOOLREV:
3357 return parm_table[i].def.bvalue ==
3358 *(bool *)lp_parm_ptr(NULL,
3359 &parm_table[i]);
3360 case P_CHAR:
3361 return parm_table[i].def.cvalue ==
3362 *(char *)lp_parm_ptr(NULL,
3363 &parm_table[i]);
3364 case P_INTEGER:
3365 case P_OCTAL:
3366 case P_ENUM:
3367 case P_BYTES:
3368 return parm_table[i].def.ivalue ==
3369 *(int *)lp_parm_ptr(NULL,
3370 &parm_table[i]);
3371 case P_SEP:
3372 break;
3374 return false;
3377 /***************************************************************************
3378 Display the contents of the global structure.
3379 ***************************************************************************/
3381 static void dump_globals(FILE *f)
3383 int i;
3384 struct parmlist_entry *data;
3386 fprintf(f, "[global]\n");
3388 for (i = 0; parm_table[i].label; i++)
3389 if (parm_table[i].p_class == P_GLOBAL &&
3390 !(parm_table[i].flags & FLAG_META) &&
3391 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3392 if (defaults_saved && is_default(i))
3393 continue;
3394 fprintf(f, "\t%s = ", parm_table[i].label);
3395 lpcfg_print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3396 &parm_table[i]),
3398 fprintf(f, "\n");
3400 if (Globals.param_opt != NULL) {
3401 data = Globals.param_opt;
3402 while(data) {
3403 fprintf(f, "\t%s = %s\n", data->key, data->value);
3404 data = data->next;
3410 /***************************************************************************
3411 Display the contents of a single services record.
3412 ***************************************************************************/
3414 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3416 int i;
3417 struct parmlist_entry *data;
3419 if (pService != &sDefault)
3420 fprintf(f, "[%s]\n", pService->szService);
3422 for (i = 0; parm_table[i].label; i++) {
3424 if (parm_table[i].p_class == P_LOCAL &&
3425 !(parm_table[i].flags & FLAG_META) &&
3426 (*parm_table[i].label != '-') &&
3427 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3429 if (pService == &sDefault) {
3430 if (defaults_saved && is_default(i))
3431 continue;
3432 } else {
3433 if (lpcfg_equal_parameter(parm_table[i].type,
3434 lp_parm_ptr(pService, &parm_table[i]),
3435 lp_parm_ptr(NULL, &parm_table[i])))
3436 continue;
3439 fprintf(f, "\t%s = ", parm_table[i].label);
3440 lpcfg_print_parameter(&parm_table[i],
3441 lp_parm_ptr(pService, &parm_table[i]),
3443 fprintf(f, "\n");
3447 if (pService->param_opt != NULL) {
3448 data = pService->param_opt;
3449 while(data) {
3450 fprintf(f, "\t%s = %s\n", data->key, data->value);
3451 data = data->next;
3456 /***************************************************************************
3457 Display the contents of a parameter of a single services record.
3458 ***************************************************************************/
3460 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3462 bool result = false;
3463 fstring local_parm_name;
3464 char *parm_opt;
3465 const char *parm_opt_value;
3467 struct loadparm_context *lp_ctx;
3469 /* check for parametrical option */
3470 fstrcpy( local_parm_name, parm_name);
3471 parm_opt = strchr( local_parm_name, ':');
3473 if (parm_opt) {
3474 *parm_opt = '\0';
3475 parm_opt++;
3476 if (strlen(parm_opt)) {
3477 parm_opt_value = lp_parm_const_string( snum,
3478 local_parm_name, parm_opt, NULL);
3479 if (parm_opt_value) {
3480 printf( "%s\n", parm_opt_value);
3481 result = true;
3484 return result;
3487 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
3488 if (lp_ctx == NULL) {
3489 return false;
3492 if (isGlobal) {
3493 result = lpcfg_dump_a_parameter(lp_ctx, NULL, parm_name, f);
3494 } else {
3495 result = lpcfg_dump_a_parameter(lp_ctx, ServicePtrs[snum], parm_name, f);
3497 TALLOC_FREE(lp_ctx);
3498 return result;
3501 /***************************************************************************
3502 Return info about the requested parameter (given as a string).
3503 Return NULL when the string is not a valid parameter name.
3504 ***************************************************************************/
3506 struct parm_struct *lp_get_parameter(const char *param_name)
3508 int num = lpcfg_map_parameter(param_name);
3510 if (num < 0) {
3511 return NULL;
3514 return &parm_table[num];
3517 #if 0
3518 /***************************************************************************
3519 Display the contents of a single copy structure.
3520 ***************************************************************************/
3521 static void dump_copy_map(bool *pcopymap)
3523 int i;
3524 if (!pcopymap)
3525 return;
3527 printf("\n\tNon-Copied parameters:\n");
3529 for (i = 0; parm_table[i].label; i++)
3530 if (parm_table[i].p_class == P_LOCAL &&
3531 parm_table[i].ptr && !pcopymap[i] &&
3532 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3534 printf("\t\t%s\n", parm_table[i].label);
3537 #endif
3539 /***************************************************************************
3540 Return TRUE if the passed service number is within range.
3541 ***************************************************************************/
3543 bool lp_snum_ok(int iService)
3545 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3548 /***************************************************************************
3549 Auto-load some home services.
3550 ***************************************************************************/
3552 static void lp_add_auto_services(char *str)
3554 char *s;
3555 char *p;
3556 int homes;
3557 char *saveptr;
3559 if (!str)
3560 return;
3562 s = talloc_strdup(talloc_tos(), str);
3563 if (!s) {
3564 smb_panic("talloc_strdup failed");
3565 return;
3568 homes = lp_servicenumber(HOMES_NAME);
3570 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3571 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3572 char *home;
3574 if (lp_servicenumber(p) >= 0)
3575 continue;
3577 home = get_user_home_dir(talloc_tos(), p);
3579 if (home && home[0] && homes >= 0)
3580 lp_add_home(p, homes, p, home);
3582 TALLOC_FREE(home);
3584 TALLOC_FREE(s);
3587 /***************************************************************************
3588 Auto-load one printer.
3589 ***************************************************************************/
3591 void lp_add_one_printer(const char *name, const char *comment,
3592 const char *location, void *pdata)
3594 int printers = lp_servicenumber(PRINTERS_NAME);
3595 int i;
3597 if (lp_servicenumber(name) < 0) {
3598 lp_add_printer(name, printers);
3599 if ((i = lp_servicenumber(name)) >= 0) {
3600 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
3601 ServicePtrs[i]->autoloaded = true;
3606 /***************************************************************************
3607 Have we loaded a services file yet?
3608 ***************************************************************************/
3610 bool lp_loaded(void)
3612 return (bLoaded);
3615 /***************************************************************************
3616 Unload unused services.
3617 ***************************************************************************/
3619 void lp_killunused(struct smbd_server_connection *sconn,
3620 bool (*snumused) (struct smbd_server_connection *, int))
3622 int i;
3623 for (i = 0; i < iNumServices; i++) {
3624 if (!VALID(i))
3625 continue;
3627 /* don't kill autoloaded or usershare services */
3628 if ( ServicePtrs[i]->autoloaded ||
3629 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3630 continue;
3633 if (!snumused || !snumused(sconn, i)) {
3634 free_service_byindex(i);
3640 * Kill all except autoloaded and usershare services - convenience wrapper
3642 void lp_kill_all_services(void)
3644 lp_killunused(NULL, NULL);
3647 /***************************************************************************
3648 Unload a service.
3649 ***************************************************************************/
3651 void lp_killservice(int iServiceIn)
3653 if (VALID(iServiceIn)) {
3654 free_service_byindex(iServiceIn);
3658 /***************************************************************************
3659 Save the curent values of all global and sDefault parameters into the
3660 defaults union. This allows testparm to show only the
3661 changed (ie. non-default) parameters.
3662 ***************************************************************************/
3664 static void lp_save_defaults(void)
3666 int i;
3667 for (i = 0; parm_table[i].label; i++) {
3668 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3669 && parm_table[i].p_class == parm_table[i - 1].p_class)
3670 continue;
3671 switch (parm_table[i].type) {
3672 case P_LIST:
3673 case P_CMDLIST:
3674 parm_table[i].def.lvalue = str_list_copy(
3675 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3676 break;
3677 case P_STRING:
3678 case P_USTRING:
3679 parm_table[i].def.svalue = talloc_strdup(Globals.ctx, *(char **)lp_parm_ptr(NULL, &parm_table[i]));
3680 if (parm_table[i].def.svalue == NULL) {
3681 smb_panic("talloc_strdup failed");
3683 break;
3684 case P_BOOL:
3685 case P_BOOLREV:
3686 parm_table[i].def.bvalue =
3687 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3688 break;
3689 case P_CHAR:
3690 parm_table[i].def.cvalue =
3691 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3692 break;
3693 case P_INTEGER:
3694 case P_OCTAL:
3695 case P_ENUM:
3696 case P_BYTES:
3697 parm_table[i].def.ivalue =
3698 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3699 break;
3700 case P_SEP:
3701 break;
3704 defaults_saved = true;
3707 /***********************************************************
3708 If we should send plaintext/LANMAN passwords in the clinet
3709 ************************************************************/
3711 static void set_allowed_client_auth(void)
3713 if (Globals.client_ntlmv2_auth) {
3714 Globals.client_lanman_auth = false;
3716 if (!Globals.client_lanman_auth) {
3717 Globals.client_plaintext_auth = false;
3721 /***************************************************************************
3722 JRA.
3723 The following code allows smbd to read a user defined share file.
3724 Yes, this is my intent. Yes, I'm comfortable with that...
3726 THE FOLLOWING IS SECURITY CRITICAL CODE.
3728 It washes your clothes, it cleans your house, it guards you while you sleep...
3729 Do not f%^k with it....
3730 ***************************************************************************/
3732 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3734 /***************************************************************************
3735 Check allowed stat state of a usershare file.
3736 Ensure we print out who is dicking with us so the admin can
3737 get their sorry ass fired.
3738 ***************************************************************************/
3740 static bool check_usershare_stat(const char *fname,
3741 const SMB_STRUCT_STAT *psbuf)
3743 if (!S_ISREG(psbuf->st_ex_mode)) {
3744 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3745 "not a regular file\n",
3746 fname, (unsigned int)psbuf->st_ex_uid ));
3747 return false;
3750 /* Ensure this doesn't have the other write bit set. */
3751 if (psbuf->st_ex_mode & S_IWOTH) {
3752 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
3753 "public write. Refusing to allow as a usershare file.\n",
3754 fname, (unsigned int)psbuf->st_ex_uid ));
3755 return false;
3758 /* Should be 10k or less. */
3759 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
3760 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3761 "too large (%u) to be a user share file.\n",
3762 fname, (unsigned int)psbuf->st_ex_uid,
3763 (unsigned int)psbuf->st_ex_size ));
3764 return false;
3767 return true;
3770 /***************************************************************************
3771 Parse the contents of a usershare file.
3772 ***************************************************************************/
3774 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
3775 SMB_STRUCT_STAT *psbuf,
3776 const char *servicename,
3777 int snum,
3778 char **lines,
3779 int numlines,
3780 char **pp_sharepath,
3781 char **pp_comment,
3782 char **pp_cp_servicename,
3783 struct security_descriptor **ppsd,
3784 bool *pallow_guest)
3786 const char **prefixallowlist = lp_usershare_prefix_allow_list();
3787 const char **prefixdenylist = lp_usershare_prefix_deny_list();
3788 int us_vers;
3789 DIR *dp;
3790 SMB_STRUCT_STAT sbuf;
3791 char *sharepath = NULL;
3792 char *comment = NULL;
3794 *pp_sharepath = NULL;
3795 *pp_comment = NULL;
3797 *pallow_guest = false;
3799 if (numlines < 4) {
3800 return USERSHARE_MALFORMED_FILE;
3803 if (strcmp(lines[0], "#VERSION 1") == 0) {
3804 us_vers = 1;
3805 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
3806 us_vers = 2;
3807 if (numlines < 5) {
3808 return USERSHARE_MALFORMED_FILE;
3810 } else {
3811 return USERSHARE_BAD_VERSION;
3814 if (strncmp(lines[1], "path=", 5) != 0) {
3815 return USERSHARE_MALFORMED_PATH;
3818 sharepath = talloc_strdup(ctx, &lines[1][5]);
3819 if (!sharepath) {
3820 return USERSHARE_POSIX_ERR;
3822 trim_string(sharepath, " ", " ");
3824 if (strncmp(lines[2], "comment=", 8) != 0) {
3825 return USERSHARE_MALFORMED_COMMENT_DEF;
3828 comment = talloc_strdup(ctx, &lines[2][8]);
3829 if (!comment) {
3830 return USERSHARE_POSIX_ERR;
3832 trim_string(comment, " ", " ");
3833 trim_char(comment, '"', '"');
3835 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
3836 return USERSHARE_MALFORMED_ACL_DEF;
3839 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
3840 return USERSHARE_ACL_ERR;
3843 if (us_vers == 2) {
3844 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
3845 return USERSHARE_MALFORMED_ACL_DEF;
3847 if (lines[4][9] == 'y') {
3848 *pallow_guest = true;
3851 /* Backwards compatible extension to file version #2. */
3852 if (numlines > 5) {
3853 if (strncmp(lines[5], "sharename=", 10) != 0) {
3854 return USERSHARE_MALFORMED_SHARENAME_DEF;
3856 if (!strequal(&lines[5][10], servicename)) {
3857 return USERSHARE_BAD_SHARENAME;
3859 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
3860 if (!*pp_cp_servicename) {
3861 return USERSHARE_POSIX_ERR;
3866 if (*pp_cp_servicename == NULL) {
3867 *pp_cp_servicename = talloc_strdup(ctx, servicename);
3868 if (!*pp_cp_servicename) {
3869 return USERSHARE_POSIX_ERR;
3873 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->path) == 0)) {
3874 /* Path didn't change, no checks needed. */
3875 *pp_sharepath = sharepath;
3876 *pp_comment = comment;
3877 return USERSHARE_OK;
3880 /* The path *must* be absolute. */
3881 if (sharepath[0] != '/') {
3882 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
3883 servicename, sharepath));
3884 return USERSHARE_PATH_NOT_ABSOLUTE;
3887 /* If there is a usershare prefix deny list ensure one of these paths
3888 doesn't match the start of the user given path. */
3889 if (prefixdenylist) {
3890 int i;
3891 for ( i=0; prefixdenylist[i]; i++ ) {
3892 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
3893 servicename, i, prefixdenylist[i], sharepath ));
3894 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
3895 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
3896 "usershare prefix deny list entries.\n",
3897 servicename, sharepath));
3898 return USERSHARE_PATH_IS_DENIED;
3903 /* If there is a usershare prefix allow list ensure one of these paths
3904 does match the start of the user given path. */
3906 if (prefixallowlist) {
3907 int i;
3908 for ( i=0; prefixallowlist[i]; i++ ) {
3909 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
3910 servicename, i, prefixallowlist[i], sharepath ));
3911 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
3912 break;
3915 if (prefixallowlist[i] == NULL) {
3916 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
3917 "usershare prefix allow list entries.\n",
3918 servicename, sharepath));
3919 return USERSHARE_PATH_NOT_ALLOWED;
3923 /* Ensure this is pointing to a directory. */
3924 dp = opendir(sharepath);
3926 if (!dp) {
3927 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3928 servicename, sharepath));
3929 return USERSHARE_PATH_NOT_DIRECTORY;
3932 /* Ensure the owner of the usershare file has permission to share
3933 this directory. */
3935 if (sys_stat(sharepath, &sbuf, false) == -1) {
3936 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
3937 servicename, sharepath, strerror(errno) ));
3938 closedir(dp);
3939 return USERSHARE_POSIX_ERR;
3942 closedir(dp);
3944 if (!S_ISDIR(sbuf.st_ex_mode)) {
3945 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3946 servicename, sharepath ));
3947 return USERSHARE_PATH_NOT_DIRECTORY;
3950 /* Check if sharing is restricted to owner-only. */
3951 /* psbuf is the stat of the usershare definition file,
3952 sbuf is the stat of the target directory to be shared. */
3954 if (lp_usershare_owner_only()) {
3955 /* root can share anything. */
3956 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
3957 return USERSHARE_PATH_NOT_ALLOWED;
3961 *pp_sharepath = sharepath;
3962 *pp_comment = comment;
3963 return USERSHARE_OK;
3966 /***************************************************************************
3967 Deal with a usershare file.
3968 Returns:
3969 >= 0 - snum
3970 -1 - Bad name, invalid contents.
3971 - service name already existed and not a usershare, problem
3972 with permissions to share directory etc.
3973 ***************************************************************************/
3975 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
3977 SMB_STRUCT_STAT sbuf;
3978 SMB_STRUCT_STAT lsbuf;
3979 char *fname = NULL;
3980 char *sharepath = NULL;
3981 char *comment = NULL;
3982 char *cp_service_name = NULL;
3983 char **lines = NULL;
3984 int numlines = 0;
3985 int fd = -1;
3986 int iService = -1;
3987 TALLOC_CTX *ctx = talloc_stackframe();
3988 struct security_descriptor *psd = NULL;
3989 bool guest_ok = false;
3990 char *canon_name = NULL;
3991 bool added_service = false;
3992 int ret = -1;
3994 /* Ensure share name doesn't contain invalid characters. */
3995 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
3996 DEBUG(0,("process_usershare_file: share name %s contains "
3997 "invalid characters (any of %s)\n",
3998 file_name, INVALID_SHARENAME_CHARS ));
3999 goto out;
4002 canon_name = canonicalize_servicename(ctx, file_name);
4003 if (!canon_name) {
4004 goto out;
4007 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4008 if (!fname) {
4009 goto out;
4012 /* Minimize the race condition by doing an lstat before we
4013 open and fstat. Ensure this isn't a symlink link. */
4015 if (sys_lstat(fname, &lsbuf, false) != 0) {
4016 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4017 fname, strerror(errno) ));
4018 goto out;
4021 /* This must be a regular file, not a symlink, directory or
4022 other strange filetype. */
4023 if (!check_usershare_stat(fname, &lsbuf)) {
4024 goto out;
4028 TDB_DATA data;
4029 NTSTATUS status;
4031 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4032 canon_name, &data);
4034 iService = -1;
4036 if (NT_STATUS_IS_OK(status) &&
4037 (data.dptr != NULL) &&
4038 (data.dsize == sizeof(iService))) {
4039 memcpy(&iService, data.dptr, sizeof(iService));
4043 if (iService != -1 &&
4044 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4045 &lsbuf.st_ex_mtime) == 0) {
4046 /* Nothing changed - Mark valid and return. */
4047 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4048 canon_name ));
4049 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4050 ret = iService;
4051 goto out;
4054 /* Try and open the file read only - no symlinks allowed. */
4055 #ifdef O_NOFOLLOW
4056 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4057 #else
4058 fd = open(fname, O_RDONLY, 0);
4059 #endif
4061 if (fd == -1) {
4062 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4063 fname, strerror(errno) ));
4064 goto out;
4067 /* Now fstat to be *SURE* it's a regular file. */
4068 if (sys_fstat(fd, &sbuf, false) != 0) {
4069 close(fd);
4070 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4071 fname, strerror(errno) ));
4072 goto out;
4075 /* Is it the same dev/inode as was lstated ? */
4076 if (!check_same_stat(&lsbuf, &sbuf)) {
4077 close(fd);
4078 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4079 "Symlink spoofing going on ?\n", fname ));
4080 goto out;
4083 /* This must be a regular file, not a symlink, directory or
4084 other strange filetype. */
4085 if (!check_usershare_stat(fname, &sbuf)) {
4086 close(fd);
4087 goto out;
4090 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4092 close(fd);
4093 if (lines == NULL) {
4094 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4095 fname, (unsigned int)sbuf.st_ex_uid ));
4096 goto out;
4099 if (parse_usershare_file(ctx, &sbuf, file_name,
4100 iService, lines, numlines, &sharepath,
4101 &comment, &cp_service_name,
4102 &psd, &guest_ok) != USERSHARE_OK) {
4103 goto out;
4106 /* Everything ok - add the service possibly using a template. */
4107 if (iService < 0) {
4108 const struct loadparm_service *sp = &sDefault;
4109 if (snum_template != -1) {
4110 sp = ServicePtrs[snum_template];
4113 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4114 DEBUG(0, ("process_usershare_file: Failed to add "
4115 "new service %s\n", cp_service_name));
4116 goto out;
4119 added_service = true;
4121 /* Read only is controlled by usershare ACL below. */
4122 ServicePtrs[iService]->read_only = false;
4125 /* Write the ACL of the new/modified share. */
4126 if (!set_share_security(canon_name, psd)) {
4127 DEBUG(0, ("process_usershare_file: Failed to set share "
4128 "security for user share %s\n",
4129 canon_name ));
4130 goto out;
4133 /* If from a template it may be marked invalid. */
4134 ServicePtrs[iService]->valid = true;
4136 /* Set the service as a valid usershare. */
4137 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4139 /* Set guest access. */
4140 if (lp_usershare_allow_guests()) {
4141 ServicePtrs[iService]->guest_ok = guest_ok;
4144 /* And note when it was loaded. */
4145 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4146 string_set(ServicePtrs[iService], &ServicePtrs[iService]->path, sharepath);
4147 string_set(ServicePtrs[iService], &ServicePtrs[iService]->comment, comment);
4149 ret = iService;
4151 out:
4153 if (ret == -1 && iService != -1 && added_service) {
4154 lp_remove_service(iService);
4157 TALLOC_FREE(lines);
4158 TALLOC_FREE(ctx);
4159 return ret;
4162 /***************************************************************************
4163 Checks if a usershare entry has been modified since last load.
4164 ***************************************************************************/
4166 static bool usershare_exists(int iService, struct timespec *last_mod)
4168 SMB_STRUCT_STAT lsbuf;
4169 const char *usersharepath = Globals.usershare_path;
4170 char *fname;
4172 fname = talloc_asprintf(talloc_tos(),
4173 "%s/%s",
4174 usersharepath,
4175 ServicePtrs[iService]->szService);
4176 if (fname == NULL) {
4177 return false;
4180 if (sys_lstat(fname, &lsbuf, false) != 0) {
4181 TALLOC_FREE(fname);
4182 return false;
4185 if (!S_ISREG(lsbuf.st_ex_mode)) {
4186 TALLOC_FREE(fname);
4187 return false;
4190 TALLOC_FREE(fname);
4191 *last_mod = lsbuf.st_ex_mtime;
4192 return true;
4195 /***************************************************************************
4196 Load a usershare service by name. Returns a valid servicenumber or -1.
4197 ***************************************************************************/
4199 int load_usershare_service(const char *servicename)
4201 SMB_STRUCT_STAT sbuf;
4202 const char *usersharepath = Globals.usershare_path;
4203 int max_user_shares = Globals.usershare_max_shares;
4204 int snum_template = -1;
4206 if (*usersharepath == 0 || max_user_shares == 0) {
4207 return -1;
4210 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4211 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4212 usersharepath, strerror(errno) ));
4213 return -1;
4216 if (!S_ISDIR(sbuf.st_ex_mode)) {
4217 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4218 usersharepath ));
4219 return -1;
4223 * This directory must be owned by root, and have the 't' bit set.
4224 * It also must not be writable by "other".
4227 #ifdef S_ISVTX
4228 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4229 #else
4230 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4231 #endif
4232 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4233 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4234 usersharepath ));
4235 return -1;
4238 /* Ensure the template share exists if it's set. */
4239 if (Globals.usershare_template_share[0]) {
4240 /* We can't use lp_servicenumber here as we are recommending that
4241 template shares have -valid=false set. */
4242 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4243 if (ServicePtrs[snum_template]->szService &&
4244 strequal(ServicePtrs[snum_template]->szService,
4245 Globals.usershare_template_share)) {
4246 break;
4250 if (snum_template == -1) {
4251 DEBUG(0,("load_usershare_service: usershare template share %s "
4252 "does not exist.\n",
4253 Globals.usershare_template_share ));
4254 return -1;
4258 return process_usershare_file(usersharepath, servicename, snum_template);
4261 /***************************************************************************
4262 Load all user defined shares from the user share directory.
4263 We only do this if we're enumerating the share list.
4264 This is the function that can delete usershares that have
4265 been removed.
4266 ***************************************************************************/
4268 int load_usershare_shares(struct smbd_server_connection *sconn,
4269 bool (*snumused) (struct smbd_server_connection *, int))
4271 DIR *dp;
4272 SMB_STRUCT_STAT sbuf;
4273 struct dirent *de;
4274 int num_usershares = 0;
4275 int max_user_shares = Globals.usershare_max_shares;
4276 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4277 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4278 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4279 int iService;
4280 int snum_template = -1;
4281 const char *usersharepath = Globals.usershare_path;
4282 int ret = lp_numservices();
4283 TALLOC_CTX *tmp_ctx;
4285 if (max_user_shares == 0 || *usersharepath == '\0') {
4286 return lp_numservices();
4289 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4290 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4291 usersharepath, strerror(errno) ));
4292 return ret;
4296 * This directory must be owned by root, and have the 't' bit set.
4297 * It also must not be writable by "other".
4300 #ifdef S_ISVTX
4301 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4302 #else
4303 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4304 #endif
4305 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4306 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4307 usersharepath ));
4308 return ret;
4311 /* Ensure the template share exists if it's set. */
4312 if (Globals.usershare_template_share[0]) {
4313 /* We can't use lp_servicenumber here as we are recommending that
4314 template shares have -valid=false set. */
4315 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4316 if (ServicePtrs[snum_template]->szService &&
4317 strequal(ServicePtrs[snum_template]->szService,
4318 Globals.usershare_template_share)) {
4319 break;
4323 if (snum_template == -1) {
4324 DEBUG(0,("load_usershare_shares: usershare template share %s "
4325 "does not exist.\n",
4326 Globals.usershare_template_share ));
4327 return ret;
4331 /* Mark all existing usershares as pending delete. */
4332 for (iService = iNumServices - 1; iService >= 0; iService--) {
4333 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4334 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4338 dp = opendir(usersharepath);
4339 if (!dp) {
4340 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4341 usersharepath, strerror(errno) ));
4342 return ret;
4345 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4346 (de = readdir(dp));
4347 num_dir_entries++ ) {
4348 int r;
4349 const char *n = de->d_name;
4351 /* Ignore . and .. */
4352 if (*n == '.') {
4353 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4354 continue;
4358 if (n[0] == ':') {
4359 /* Temporary file used when creating a share. */
4360 num_tmp_dir_entries++;
4363 /* Allow 20% tmp entries. */
4364 if (num_tmp_dir_entries > allowed_tmp_entries) {
4365 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4366 "in directory %s\n",
4367 num_tmp_dir_entries, usersharepath));
4368 break;
4371 r = process_usershare_file(usersharepath, n, snum_template);
4372 if (r == 0) {
4373 /* Update the services count. */
4374 num_usershares++;
4375 if (num_usershares >= max_user_shares) {
4376 DEBUG(0,("load_usershare_shares: max user shares reached "
4377 "on file %s in directory %s\n",
4378 n, usersharepath ));
4379 break;
4381 } else if (r == -1) {
4382 num_bad_dir_entries++;
4385 /* Allow 20% bad entries. */
4386 if (num_bad_dir_entries > allowed_bad_entries) {
4387 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4388 "in directory %s\n",
4389 num_bad_dir_entries, usersharepath));
4390 break;
4393 /* Allow 20% bad entries. */
4394 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4395 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4396 "in directory %s\n",
4397 num_dir_entries, usersharepath));
4398 break;
4402 closedir(dp);
4404 /* Sweep through and delete any non-refreshed usershares that are
4405 not currently in use. */
4406 tmp_ctx = talloc_stackframe();
4407 for (iService = iNumServices - 1; iService >= 0; iService--) {
4408 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4409 char *servname;
4411 if (snumused && snumused(sconn, iService)) {
4412 continue;
4415 servname = lp_servicename(tmp_ctx, iService);
4417 /* Remove from the share ACL db. */
4418 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4419 servname ));
4420 delete_share_security(servname);
4421 free_service_byindex(iService);
4424 talloc_free(tmp_ctx);
4426 return lp_numservices();
4429 /********************************************************
4430 Destroy global resources allocated in this file
4431 ********************************************************/
4433 void gfree_loadparm(void)
4435 int i;
4437 free_file_list();
4439 /* Free resources allocated to services */
4441 for ( i = 0; i < iNumServices; i++ ) {
4442 if ( VALID(i) ) {
4443 free_service_byindex(i);
4447 TALLOC_FREE( ServicePtrs );
4448 iNumServices = 0;
4450 /* Now release all resources allocated to global
4451 parameters and the default service */
4453 free_global_parameters();
4457 /***************************************************************************
4458 Allow client apps to specify that they are a client
4459 ***************************************************************************/
4460 static void lp_set_in_client(bool b)
4462 in_client = b;
4466 /***************************************************************************
4467 Determine if we're running in a client app
4468 ***************************************************************************/
4469 static bool lp_is_in_client(void)
4471 return in_client;
4474 /***************************************************************************
4475 Load the services array from the services file. Return true on success,
4476 false on failure.
4477 ***************************************************************************/
4479 static bool lp_load_ex(const char *pszFname,
4480 bool global_only,
4481 bool save_defaults,
4482 bool add_ipc,
4483 bool initialize_globals,
4484 bool allow_include_registry,
4485 bool load_all_shares)
4487 char *n2 = NULL;
4488 bool bRetval;
4490 bRetval = false;
4492 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4494 bInGlobalSection = true;
4495 bGlobalOnly = global_only;
4496 bAllowIncludeRegistry = allow_include_registry;
4498 init_globals(initialize_globals);
4500 free_file_list();
4502 if (save_defaults) {
4503 init_locals();
4504 lp_save_defaults();
4507 if (!initialize_globals) {
4508 free_param_opts(&Globals.param_opt);
4509 apply_lp_set_cmdline();
4512 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4514 /* We get sections first, so have to start 'behind' to make up */
4515 iServiceIndex = -1;
4517 if (lp_config_backend_is_file()) {
4518 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4519 current_user_info.domain,
4520 pszFname);
4521 if (!n2) {
4522 smb_panic("lp_load_ex: out of memory");
4525 add_to_file_list(pszFname, n2);
4527 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4528 TALLOC_FREE(n2);
4530 /* finish up the last section */
4531 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4532 if (bRetval) {
4533 if (iServiceIndex >= 0) {
4534 bRetval = service_ok(iServiceIndex);
4538 if (lp_config_backend_is_registry()) {
4539 /* config backend changed to registry in config file */
4541 * We need to use this extra global variable here to
4542 * survive restart: init_globals uses this as a default
4543 * for config_backend. Otherwise, init_globals would
4544 * send us into an endless loop here.
4546 config_backend = CONFIG_BACKEND_REGISTRY;
4547 /* start over */
4548 DEBUG(1, ("lp_load_ex: changing to config backend "
4549 "registry\n"));
4550 init_globals(true);
4551 lp_kill_all_services();
4552 return lp_load_ex(pszFname, global_only, save_defaults,
4553 add_ipc, initialize_globals,
4554 allow_include_registry,
4555 load_all_shares);
4557 } else if (lp_config_backend_is_registry()) {
4558 bRetval = process_registry_globals();
4559 } else {
4560 DEBUG(0, ("Illegal config backend given: %d\n",
4561 lp_config_backend()));
4562 bRetval = false;
4565 if (bRetval && lp_registry_shares()) {
4566 if (load_all_shares) {
4567 bRetval = process_registry_shares();
4568 } else {
4569 bRetval = reload_registry_shares();
4574 char *serv = lp_auto_services(talloc_tos());
4575 lp_add_auto_services(serv);
4576 TALLOC_FREE(serv);
4579 if (add_ipc) {
4580 /* When 'restrict anonymous = 2' guest connections to ipc$
4581 are denied */
4582 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4583 if ( lp_enable_asu_support() ) {
4584 lp_add_ipc("ADMIN$", false);
4588 set_allowed_client_auth();
4590 if (lp_security() == SEC_ADS && strchr(lp_password_server(), ':')) {
4591 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4592 lp_password_server()));
4595 bLoaded = true;
4597 /* Now we check we_are_a_wins_server and set szWINSserver to 127.0.0.1 */
4598 /* if we_are_a_wins_server is true and we are in the client */
4599 if (lp_is_in_client() && Globals.we_are_a_wins_server) {
4600 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4603 init_iconv();
4605 fault_configure(smb_panic_s3);
4608 * We run this check once the whole smb.conf is parsed, to
4609 * force some settings for the standard way a AD DC is
4610 * operated. We may changed these as our code evolves, which
4611 * is why we force these settings.
4613 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4614 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4616 lp_do_parameter(-1, "rpc_server:default", "external");
4617 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4618 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4619 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4620 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4621 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4622 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4623 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4624 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4627 bAllowIncludeRegistry = true;
4629 return (bRetval);
4632 bool lp_load(const char *pszFname,
4633 bool global_only,
4634 bool save_defaults,
4635 bool add_ipc,
4636 bool initialize_globals)
4638 return lp_load_ex(pszFname,
4639 global_only,
4640 save_defaults,
4641 add_ipc,
4642 initialize_globals,
4643 true, /* allow_include_registry */
4644 false); /* load_all_shares*/
4647 bool lp_load_initial_only(const char *pszFname)
4649 return lp_load_ex(pszFname,
4650 true, /* global only */
4651 false, /* save_defaults */
4652 false, /* add_ipc */
4653 true, /* initialize_globals */
4654 false, /* allow_include_registry */
4655 false); /* load_all_shares*/
4659 * most common lp_load wrapper, loading only the globals
4661 bool lp_load_global(const char *file_name)
4663 return lp_load_ex(file_name,
4664 true, /* global_only */
4665 false, /* save_defaults */
4666 false, /* add_ipc */
4667 true, /* initialize_globals */
4668 true, /* allow_include_registry */
4669 false); /* load_all_shares*/
4673 * lp_load wrapper, especially for clients
4675 bool lp_load_client(const char *file_name)
4677 lp_set_in_client(true);
4679 return lp_load_global(file_name);
4683 * lp_load wrapper, loading only globals, but intended
4684 * for subsequent calls, not reinitializing the globals
4685 * to default values
4687 bool lp_load_global_no_reinit(const char *file_name)
4689 return lp_load_ex(file_name,
4690 true, /* global_only */
4691 false, /* save_defaults */
4692 false, /* add_ipc */
4693 false, /* initialize_globals */
4694 true, /* allow_include_registry */
4695 false); /* load_all_shares*/
4699 * lp_load wrapper, especially for clients, no reinitialization
4701 bool lp_load_client_no_reinit(const char *file_name)
4703 lp_set_in_client(true);
4705 return lp_load_global_no_reinit(file_name);
4708 bool lp_load_with_registry_shares(const char *pszFname,
4709 bool global_only,
4710 bool save_defaults,
4711 bool add_ipc,
4712 bool initialize_globals)
4714 return lp_load_ex(pszFname,
4715 global_only,
4716 save_defaults,
4717 add_ipc,
4718 initialize_globals,
4719 true, /* allow_include_registry */
4720 true); /* load_all_shares*/
4723 /***************************************************************************
4724 Return the max number of services.
4725 ***************************************************************************/
4727 int lp_numservices(void)
4729 return (iNumServices);
4732 /***************************************************************************
4733 Display the contents of the services array in human-readable form.
4734 ***************************************************************************/
4736 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4738 int iService;
4740 if (show_defaults)
4741 defaults_saved = false;
4743 dump_globals(f);
4745 dump_a_service(&sDefault, f);
4747 for (iService = 0; iService < maxtoprint; iService++) {
4748 fprintf(f,"\n");
4749 lp_dump_one(f, show_defaults, iService);
4753 /***************************************************************************
4754 Display the contents of one service in human-readable form.
4755 ***************************************************************************/
4757 void lp_dump_one(FILE * f, bool show_defaults, int snum)
4759 if (VALID(snum)) {
4760 if (ServicePtrs[snum]->szService[0] == '\0')
4761 return;
4762 dump_a_service(ServicePtrs[snum], f);
4766 /***************************************************************************
4767 Return the number of the service with the given name, or -1 if it doesn't
4768 exist. Note that this is a DIFFERENT ANIMAL from the internal function
4769 getservicebyname()! This works ONLY if all services have been loaded, and
4770 does not copy the found service.
4771 ***************************************************************************/
4773 int lp_servicenumber(const char *pszServiceName)
4775 int iService;
4776 fstring serviceName;
4778 if (!pszServiceName) {
4779 return GLOBAL_SECTION_SNUM;
4782 for (iService = iNumServices - 1; iService >= 0; iService--) {
4783 if (VALID(iService) && ServicePtrs[iService]->szService) {
4785 * The substitution here is used to support %U is
4786 * service names
4788 fstrcpy(serviceName, ServicePtrs[iService]->szService);
4789 standard_sub_basic(get_current_username(),
4790 current_user_info.domain,
4791 serviceName,sizeof(serviceName));
4792 if (strequal(serviceName, pszServiceName)) {
4793 break;
4798 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
4799 struct timespec last_mod;
4801 if (!usershare_exists(iService, &last_mod)) {
4802 /* Remove the share security tdb entry for it. */
4803 delete_share_security(lp_servicename(talloc_tos(), iService));
4804 /* Remove it from the array. */
4805 free_service_byindex(iService);
4806 /* Doesn't exist anymore. */
4807 return GLOBAL_SECTION_SNUM;
4810 /* Has it been modified ? If so delete and reload. */
4811 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4812 &last_mod) < 0) {
4813 /* Remove it from the array. */
4814 free_service_byindex(iService);
4815 /* and now reload it. */
4816 iService = load_usershare_service(pszServiceName);
4820 if (iService < 0) {
4821 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
4822 return GLOBAL_SECTION_SNUM;
4825 return (iService);
4828 /*******************************************************************
4829 A useful volume label function.
4830 ********************************************************************/
4832 const char *volume_label(TALLOC_CTX *ctx, int snum)
4834 char *ret;
4835 const char *label = lp_volume(ctx, snum);
4836 if (!*label) {
4837 label = lp_servicename(ctx, snum);
4840 /* This returns a 33 byte guarenteed null terminated string. */
4841 ret = talloc_strndup(ctx, label, 32);
4842 if (!ret) {
4843 return "";
4845 return ret;
4848 /*******************************************************************
4849 Get the default server type we will announce as via nmbd.
4850 ********************************************************************/
4852 int lp_default_server_announce(void)
4854 int default_server_announce = 0;
4855 default_server_announce |= SV_TYPE_WORKSTATION;
4856 default_server_announce |= SV_TYPE_SERVER;
4857 default_server_announce |= SV_TYPE_SERVER_UNIX;
4859 /* note that the flag should be set only if we have a
4860 printer service but nmbd doesn't actually load the
4861 services so we can't tell --jerry */
4863 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
4865 default_server_announce |= SV_TYPE_SERVER_NT;
4866 default_server_announce |= SV_TYPE_NT;
4868 switch (lp_server_role()) {
4869 case ROLE_DOMAIN_MEMBER:
4870 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
4871 break;
4872 case ROLE_DOMAIN_PDC:
4873 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
4874 break;
4875 case ROLE_DOMAIN_BDC:
4876 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
4877 break;
4878 case ROLE_STANDALONE:
4879 default:
4880 break;
4882 if (lp_time_server())
4883 default_server_announce |= SV_TYPE_TIME_SOURCE;
4885 if (lp_host_msdfs())
4886 default_server_announce |= SV_TYPE_DFS_SERVER;
4888 return default_server_announce;
4891 /***********************************************************
4892 If we are PDC then prefer us as DMB
4893 ************************************************************/
4895 bool lp_domain_master(void)
4897 if (Globals._domain_master == Auto)
4898 return (lp_server_role() == ROLE_DOMAIN_PDC);
4900 return (bool)Globals._domain_master;
4903 /***********************************************************
4904 If we are PDC then prefer us as DMB
4905 ************************************************************/
4907 static bool lp_domain_master_true_or_auto(void)
4909 if (Globals._domain_master) /* auto or yes */
4910 return true;
4912 return false;
4915 /***********************************************************
4916 If we are DMB then prefer us as LMB
4917 ************************************************************/
4919 bool lp_preferred_master(void)
4921 if (Globals.iPreferredMaster == Auto)
4922 return (lp_local_master() && lp_domain_master());
4924 return (bool)Globals.iPreferredMaster;
4927 /*******************************************************************
4928 Remove a service.
4929 ********************************************************************/
4931 void lp_remove_service(int snum)
4933 ServicePtrs[snum]->valid = false;
4936 /*******************************************************************
4937 Copy a service.
4938 ********************************************************************/
4940 void lp_copy_service(int snum, const char *new_name)
4942 do_section(new_name, NULL);
4943 if (snum >= 0) {
4944 snum = lp_servicenumber(new_name);
4945 if (snum >= 0) {
4946 char *name = lp_servicename(talloc_tos(), snum);
4947 lp_do_parameter(snum, "copy", name);
4952 const char *lp_printername(TALLOC_CTX *ctx, int snum)
4954 const char *ret = lp__printername(ctx, snum);
4955 if (ret == NULL || *ret == '\0') {
4956 ret = lp_const_servicename(snum);
4959 return ret;
4963 /***********************************************************
4964 Allow daemons such as winbindd to fix their logfile name.
4965 ************************************************************/
4967 void lp_set_logfile(const char *name)
4969 string_set(Globals.ctx, &Globals.logfile, name);
4970 debug_set_logfile(name);
4973 /*******************************************************************
4974 Return the max print jobs per queue.
4975 ********************************************************************/
4977 int lp_maxprintjobs(int snum)
4979 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
4980 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
4981 maxjobs = PRINT_MAX_JOBID - 1;
4983 return maxjobs;
4986 const char *lp_printcapname(void)
4988 if ((Globals.szPrintcapname != NULL) &&
4989 (Globals.szPrintcapname[0] != '\0'))
4990 return Globals.szPrintcapname;
4992 if (sDefault.printing == PRINT_CUPS) {
4993 return "cups";
4996 if (sDefault.printing == PRINT_BSD)
4997 return "/etc/printcap";
4999 return PRINTCAP_NAME;
5002 static uint32 spoolss_state;
5004 bool lp_disable_spoolss( void )
5006 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5007 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5009 return spoolss_state == SVCCTL_STOPPED ? true : false;
5012 void lp_set_spoolss_state( uint32 state )
5014 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5016 spoolss_state = state;
5019 uint32 lp_get_spoolss_state( void )
5021 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5024 /*******************************************************************
5025 Ensure we don't use sendfile if server smb signing is active.
5026 ********************************************************************/
5028 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5030 bool sign_active = false;
5032 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5033 if (get_Protocol() < PROTOCOL_NT1) {
5034 return false;
5036 if (signing_state) {
5037 sign_active = smb_signing_is_active(signing_state);
5039 return (lp__use_sendfile(snum) &&
5040 (get_remote_arch() != RA_WIN95) &&
5041 !sign_active);
5044 /*******************************************************************
5045 Turn off sendfile if we find the underlying OS doesn't support it.
5046 ********************************************************************/
5048 void set_use_sendfile(int snum, bool val)
5050 if (LP_SNUM_OK(snum))
5051 ServicePtrs[snum]->_use_sendfile = val;
5052 else
5053 sDefault._use_sendfile = val;
5056 /*******************************************************************
5057 Turn off storing DOS attributes if this share doesn't support it.
5058 ********************************************************************/
5060 void set_store_dos_attributes(int snum, bool val)
5062 if (!LP_SNUM_OK(snum))
5063 return;
5064 ServicePtrs[(snum)]->store_dos_attributes = val;
5067 void lp_set_mangling_method(const char *new_method)
5069 string_set(Globals.ctx, &Globals.mangling_method, new_method);
5072 /*******************************************************************
5073 Global state for POSIX pathname processing.
5074 ********************************************************************/
5076 static bool posix_pathnames;
5078 bool lp_posix_pathnames(void)
5080 return posix_pathnames;
5083 /*******************************************************************
5084 Change everything needed to ensure POSIX pathname processing (currently
5085 not much).
5086 ********************************************************************/
5088 void lp_set_posix_pathnames(void)
5090 posix_pathnames = true;
5093 /*******************************************************************
5094 Global state for POSIX lock processing - CIFS unix extensions.
5095 ********************************************************************/
5097 bool posix_default_lock_was_set;
5098 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5100 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5102 if (posix_default_lock_was_set) {
5103 return posix_cifsx_locktype;
5104 } else {
5105 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5109 /*******************************************************************
5110 ********************************************************************/
5112 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5114 posix_default_lock_was_set = true;
5115 posix_cifsx_locktype = val;
5118 int lp_min_receive_file_size(void)
5120 if (Globals.iminreceivefile < 0) {
5121 return 0;
5123 return Globals.iminreceivefile;
5126 /*******************************************************************
5127 Safe wide links checks.
5128 This helper function always verify the validity of wide links,
5129 even after a configuration file reload.
5130 ********************************************************************/
5132 static bool lp_widelinks_internal(int snum)
5134 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5135 sDefault.bWidelinks);
5138 void widelinks_warning(int snum)
5140 if (lp_allow_insecure_wide_links()) {
5141 return;
5144 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5145 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5146 "These parameters are incompatible. "
5147 "Wide links will be disabled for this share.\n",
5148 lp_servicename(talloc_tos(), snum) ));
5152 bool lp_widelinks(int snum)
5154 /* wide links is always incompatible with unix extensions */
5155 if (lp_unix_extensions()) {
5157 * Unless we have "allow insecure widelinks"
5158 * turned on.
5160 if (!lp_allow_insecure_wide_links()) {
5161 return false;
5165 return lp_widelinks_internal(snum);
5168 int lp_server_role(void)
5170 return lp_find_server_role(lp__server_role(),
5171 lp__security(),
5172 lp__domain_logons(),
5173 lp_domain_master_true_or_auto());
5176 int lp_security(void)
5178 return lp_find_security(lp__server_role(),
5179 lp__security());
5182 struct loadparm_global * get_globals(void)
5184 return &Globals;