param: consolidate handle_copy method between the two loadparms
[Samba.git] / source3 / param / loadparm.c
blob2964544ce4df572b6ba68f37bd0d6f93e0aff352
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_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
265 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
266 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
267 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
268 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
269 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
270 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
271 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
273 static void set_allowed_client_auth(void);
275 static void add_to_file_list(const char *fname, const char *subfname);
276 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
277 static void free_param_opts(struct parmlist_entry **popts);
279 #include "lib/param/param_table.c"
281 /* this is used to prevent lots of mallocs of size 1 */
282 static const char null_string[] = "";
285 Free a string value.
288 static void string_free(char **s)
290 if (!s || !(*s))
291 return;
292 if (*s == null_string)
293 *s = NULL;
294 TALLOC_FREE(*s);
298 Set a string value, deallocating any existing space, and allocing the space
299 for the string
302 static bool string_set(TALLOC_CTX *mem_ctx, char **dest,const char *src)
304 string_free(dest);
306 if (!src) {
307 src = "";
310 (*dest) = talloc_strdup(mem_ctx, src);
311 if ((*dest) == NULL) {
312 DEBUG(0,("Out of memory in string_init\n"));
313 return false;
316 return true;
319 bool lp_string_set(char **dest, const char *src) {
320 return string_set(Globals.ctx, dest, src);
323 /***************************************************************************
324 Initialise the sDefault parameter structure for the printer values.
325 ***************************************************************************/
327 static void init_printer_values(TALLOC_CTX *ctx, struct loadparm_service *pService)
329 /* choose defaults depending on the type of printing */
330 switch (pService->printing) {
331 case PRINT_BSD:
332 case PRINT_AIX:
333 case PRINT_LPRNT:
334 case PRINT_LPROS2:
335 string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
336 string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
337 string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
338 break;
340 case PRINT_LPRNG:
341 case PRINT_PLP:
342 string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
343 string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
344 string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
345 string_set(ctx, &pService->queuepause_command, "lpc stop '%p'");
346 string_set(ctx, &pService->queueresume_command, "lpc start '%p'");
347 string_set(ctx, &pService->lppause_command, "lpc hold '%p' %j");
348 string_set(ctx, &pService->lpresume_command, "lpc release '%p' %j");
349 break;
351 case PRINT_CUPS:
352 case PRINT_IPRINT:
353 /* set the lpq command to contain the destination printer
354 name only. This is used by cups_queue_get() */
355 string_set(ctx, &pService->lpq_command, "%p");
356 string_set(ctx, &pService->lprm_command, "");
357 string_set(ctx, &pService->print_command, "");
358 string_set(ctx, &pService->lppause_command, "");
359 string_set(ctx, &pService->lpresume_command, "");
360 string_set(ctx, &pService->queuepause_command, "");
361 string_set(ctx, &pService->queueresume_command, "");
362 break;
364 case PRINT_SYSV:
365 case PRINT_HPUX:
366 string_set(ctx, &pService->lpq_command, "lpstat -o%p");
367 string_set(ctx, &pService->lprm_command, "cancel %p-%j");
368 string_set(ctx, &pService->print_command, "lp -c -d%p %s; rm %s");
369 string_set(ctx, &pService->queuepause_command, "disable %p");
370 string_set(ctx, &pService->queueresume_command, "enable %p");
371 #ifndef HPUX
372 string_set(ctx, &pService->lppause_command, "lp -i %p-%j -H hold");
373 string_set(ctx, &pService->lpresume_command, "lp -i %p-%j -H resume");
374 #endif /* HPUX */
375 break;
377 case PRINT_QNX:
378 string_set(ctx, &pService->lpq_command, "lpq -P%p");
379 string_set(ctx, &pService->lprm_command, "lprm -P%p %j");
380 string_set(ctx, &pService->print_command, "lp -r -P%p %s");
381 break;
383 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
385 case PRINT_TEST:
386 case PRINT_VLP: {
387 const char *tdbfile;
388 TALLOC_CTX *tmp_ctx = talloc_stackframe();
389 char *tmp;
391 tdbfile = talloc_asprintf(
392 tmp_ctx, "tdbfile=%s",
393 lp_parm_const_string(-1, "vlp", "tdbfile",
394 "/tmp/vlp.tdb"));
395 if (tdbfile == NULL) {
396 tdbfile="tdbfile=/tmp/vlp.tdb";
399 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
400 tdbfile);
401 string_set(ctx, &pService->print_command,
402 tmp ? tmp : "vlp print %p %s");
404 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
405 tdbfile);
406 string_set(ctx, &pService->lpq_command,
407 tmp ? tmp : "vlp lpq %p");
409 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
410 tdbfile);
411 string_set(ctx, &pService->lprm_command,
412 tmp ? tmp : "vlp lprm %p %j");
414 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
415 tdbfile);
416 string_set(ctx, &pService->lppause_command,
417 tmp ? tmp : "vlp lppause %p %j");
419 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
420 tdbfile);
421 string_set(ctx, &pService->lpresume_command,
422 tmp ? tmp : "vlp lpresume %p %j");
424 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
425 tdbfile);
426 string_set(ctx, &pService->queuepause_command,
427 tmp ? tmp : "vlp queuepause %p");
429 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
430 tdbfile);
431 string_set(ctx, &pService->queueresume_command,
432 tmp ? tmp : "vlp queueresume %p");
433 TALLOC_FREE(tmp_ctx);
435 break;
437 #endif /* DEVELOPER */
442 * Function to return the default value for the maximum number of open
443 * file descriptors permitted. This function tries to consult the
444 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
445 * the smaller of those.
447 static int max_open_files(void)
449 int sysctl_max = MAX_OPEN_FILES;
450 int rlimit_max = MAX_OPEN_FILES;
452 #ifdef HAVE_SYSCTLBYNAME
454 size_t size = sizeof(sysctl_max);
455 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
458 #endif
460 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
462 struct rlimit rl;
464 ZERO_STRUCT(rl);
466 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
467 rlimit_max = rl.rlim_cur;
469 #if defined(RLIM_INFINITY)
470 if(rl.rlim_cur == RLIM_INFINITY)
471 rlimit_max = MAX_OPEN_FILES;
472 #endif
474 #endif
476 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
477 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
478 "minimum Windows limit (%d)\n",
479 sysctl_max,
480 MIN_OPEN_FILES_WINDOWS));
481 sysctl_max = MIN_OPEN_FILES_WINDOWS;
484 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
485 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
486 "minimum Windows limit (%d)\n",
487 rlimit_max,
488 MIN_OPEN_FILES_WINDOWS));
489 rlimit_max = MIN_OPEN_FILES_WINDOWS;
492 return MIN(sysctl_max, rlimit_max);
496 * Common part of freeing allocated data for one parameter.
498 static void free_one_parameter_common(void *parm_ptr,
499 struct parm_struct parm)
501 if ((parm.type == P_STRING) ||
502 (parm.type == P_USTRING))
504 string_free((char**)parm_ptr);
505 } else if (parm.type == P_LIST) {
506 TALLOC_FREE(*((char***)parm_ptr));
511 * Free the allocated data for one parameter for a share
512 * given as a service struct.
514 static void free_one_parameter(struct loadparm_service *service,
515 struct parm_struct parm)
517 void *parm_ptr;
519 if (parm.p_class != P_LOCAL) {
520 return;
523 parm_ptr = lp_parm_ptr(service, &parm);
525 free_one_parameter_common(parm_ptr, parm);
529 * Free the allocated parameter data of a share given
530 * as a service struct.
532 static void free_parameters(struct loadparm_service *service)
534 uint32_t i;
536 for (i=0; parm_table[i].label; i++) {
537 free_one_parameter(service, parm_table[i]);
542 * Free the allocated data for one parameter for a given share
543 * specified by an snum.
545 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
547 void *parm_ptr;
549 if (snum < 0) {
550 parm_ptr = lp_parm_ptr(NULL, &parm);
551 } else if (parm.p_class != P_LOCAL) {
552 return;
553 } else {
554 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
557 free_one_parameter_common(parm_ptr, parm);
561 * Free the allocated parameter data for a share specified
562 * by an snum.
564 static void free_parameters_by_snum(int snum)
566 uint32_t i;
568 for (i=0; parm_table[i].label; i++) {
569 free_one_parameter_by_snum(snum, parm_table[i]);
574 * Free the allocated global parameters.
576 static void free_global_parameters(void)
578 free_param_opts(&Globals.param_opt);
579 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
580 TALLOC_FREE(Globals.ctx);
583 struct lp_stored_option {
584 struct lp_stored_option *prev, *next;
585 const char *label;
586 const char *value;
589 static struct lp_stored_option *stored_options;
592 save options set by lp_set_cmdline() into a list. This list is
593 re-applied when we do a globals reset, so that cmdline set options
594 are sticky across reloads of smb.conf
596 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
598 struct lp_stored_option *entry, *entry_next;
599 for (entry = stored_options; entry != NULL; entry = entry_next) {
600 entry_next = entry->next;
601 if (strcmp(pszParmName, entry->label) == 0) {
602 DLIST_REMOVE(stored_options, entry);
603 talloc_free(entry);
604 break;
608 entry = talloc(NULL, struct lp_stored_option);
609 if (!entry) {
610 return false;
613 entry->label = talloc_strdup(entry, pszParmName);
614 if (!entry->label) {
615 talloc_free(entry);
616 return false;
619 entry->value = talloc_strdup(entry, pszParmValue);
620 if (!entry->value) {
621 talloc_free(entry);
622 return false;
625 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
627 return true;
630 static bool apply_lp_set_cmdline(void)
632 struct lp_stored_option *entry = NULL;
633 for (entry = stored_options; entry != NULL; entry = entry->next) {
634 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
635 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
636 entry->label, entry->value));
637 return false;
640 return true;
643 /***************************************************************************
644 Initialise the global parameter structure.
645 ***************************************************************************/
647 static void init_globals(bool reinit_globals)
649 static bool done_init = false;
650 char *s = NULL;
651 int i;
653 /* If requested to initialize only once and we've already done it... */
654 if (!reinit_globals && done_init) {
655 /* ... then we have nothing more to do */
656 return;
659 if (!done_init) {
660 /* The logfile can be set before this is invoked. Free it if so. */
661 if (Globals.logfile != NULL) {
662 string_free(&Globals.logfile);
663 Globals.logfile = NULL;
665 done_init = true;
666 } else {
667 free_global_parameters();
670 /* This memset and the free_global_parameters() above will
671 * wipe out smb.conf options set with lp_set_cmdline(). The
672 * apply_lp_set_cmdline() call puts these values back in the
673 * table once the defaults are set */
674 ZERO_STRUCT(Globals);
676 Globals.ctx = talloc_pooled_object(NULL, char, 272, 2048);
678 for (i = 0; parm_table[i].label; i++) {
679 if ((parm_table[i].type == P_STRING ||
680 parm_table[i].type == P_USTRING))
682 string_set(Globals.ctx, (char **)lp_parm_ptr(NULL, &parm_table[i]), "");
687 string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
688 string_set(Globals.ctx, &sDefault.printjob_username, "%U");
690 init_printer_values(Globals.ctx, &sDefault);
692 sDefault.ntvfs_handler = (const char **)str_list_make_v3(NULL, "unixuid default", NULL);
694 DEBUG(3, ("Initialising global parameters\n"));
696 /* Must manually force to upper case here, as this does not go via the handler */
697 string_set(Globals.ctx, &Globals.netbios_name, myhostname_upper());
699 string_set(Globals.ctx, &Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
700 string_set(Globals.ctx, &Globals.private_dir, get_dyn_PRIVATE_DIR());
702 /* use the new 'hash2' method by default, with a prefix of 1 */
703 string_set(Globals.ctx, &Globals.mangling_method, "hash2");
704 Globals.mangle_prefix = 1;
706 string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
708 /* using UTF8 by default allows us to support all chars */
709 string_set(Globals.ctx, &Globals.unix_charset, DEFAULT_UNIX_CHARSET);
711 /* Use codepage 850 as a default for the dos character set */
712 string_set(Globals.ctx, &Globals.dos_charset, DEFAULT_DOS_CHARSET);
715 * Allow the default PASSWD_CHAT to be overridden in local.h.
717 string_set(Globals.ctx, &Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
719 string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
721 string_set(Globals.ctx, &Globals.passwd_program, "");
722 string_set(Globals.ctx, &Globals.lock_directory, get_dyn_LOCKDIR());
723 string_set(Globals.ctx, &Globals.state_directory, get_dyn_STATEDIR());
724 string_set(Globals.ctx, &Globals.cache_directory, get_dyn_CACHEDIR());
725 string_set(Globals.ctx, &Globals.pid_directory, get_dyn_PIDDIR());
726 string_set(Globals.ctx, &Globals.nbt_client_socket_address, "0.0.0.0");
728 * By default support explicit binding to broadcast
729 * addresses.
731 Globals.nmbd_bind_explicit_broadcast = true;
733 s = talloc_asprintf(talloc_tos(), "Samba %s", samba_version_string());
734 if (s == NULL) {
735 smb_panic("init_globals: ENOMEM");
737 string_set(Globals.ctx, &Globals.server_string, s);
738 TALLOC_FREE(s);
739 #ifdef DEVELOPER
740 string_set(Globals.ctx, &Globals.panic_action, "/bin/sleep 999999999");
741 #endif
743 string_set(Globals.ctx, &Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
745 string_set(Globals.ctx, &Globals.logon_drive, "");
746 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
747 string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
748 string_set(Globals.ctx, &Globals.logon_path, "\\\\%N\\%U\\profile");
750 Globals.name_resolve_order = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
751 string_set(Globals.ctx, &Globals.password_server, "*");
753 Globals.algorithmic_rid_base = BASE_RID;
755 Globals.load_printers = true;
756 Globals.printcap_cache_time = 750; /* 12.5 minutes */
758 Globals.config_backend = config_backend;
759 Globals._server_role = ROLE_AUTO;
761 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
762 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
763 Globals.max_xmit = 0x4104;
764 Globals.max_mux = 50; /* This is *needed* for profile support. */
765 Globals.lpq_cache_time = 30; /* changed to handle large print servers better -- jerry */
766 Globals._disable_spoolss = false;
767 Globals.max_smbd_processes = 0;/* no limit specified */
768 Globals.username_level = 0;
769 Globals.deadtime = 0;
770 Globals.getwd_cache = true;
771 Globals.large_readwrite = true;
772 Globals.max_log_size = 5000;
773 Globals.max_open_files = max_open_files();
774 Globals.server_max_protocol = PROTOCOL_SMB3_00;
775 Globals.server_min_protocol = PROTOCOL_LANMAN1;
776 Globals.client_max_protocol = PROTOCOL_NT1;
777 Globals.client_min_protocol = PROTOCOL_CORE;
778 Globals._security = SEC_AUTO;
779 Globals.encrypt_passwords = true;
780 Globals.client_schannel = Auto;
781 Globals.winbind_sealed_pipes = true;
782 Globals.require_strong_key = true;
783 Globals.server_schannel = Auto;
784 Globals.read_raw = true;
785 Globals.write_raw = true;
786 Globals.null_passwords = false;
787 Globals.old_password_allowed_period = 60;
788 Globals.obey_pam_restrictions = false;
789 Globals.syslog = 1;
790 Globals.syslog_only = false;
791 Globals.timestamp_logs = true;
792 string_set(Globals.ctx, &Globals.log_level, "0");
793 Globals.debug_prefix_timestamp = false;
794 Globals.debug_hires_timestamp = true;
795 Globals.debug_pid = false;
796 Globals.debug_uid = false;
797 Globals.debug_class = false;
798 Globals.enable_core_files = true;
799 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
800 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
801 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
802 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
803 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
804 Globals.lm_interval = 60;
805 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
806 Globals.nis_homedir = false;
807 #ifdef WITH_NISPLUS_HOME
808 string_set(Globals.ctx, &Globals.homedir_map, "auto_home.org_dir");
809 #else
810 string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
811 #endif
812 #endif
813 Globals.time_server = false;
814 Globals.bind_interfaces_only = false;
815 Globals.unix_password_sync = false;
816 Globals.pam_password_change = false;
817 Globals.passwd_chat_debug = false;
818 Globals.passwd_chat_timeout = 2; /* 2 second default. */
819 Globals.nt_pipe_support = true; /* Do NT pipes by default. */
820 Globals.nt_status_support = true; /* Use NT status by default. */
821 Globals.stat_cache = true; /* use stat cache by default */
822 Globals.max_stat_cache_size = 256; /* 256k by default */
823 Globals.restrict_anonymous = 0;
824 Globals.client_lanman_auth = false; /* Do NOT use the LanMan hash if it is available */
825 Globals.client_plaintext_auth = false; /* Do NOT use a plaintext password even if is requested by the server */
826 Globals.lanman_auth = false; /* Do NOT use the LanMan hash, even if it is supplied */
827 Globals.ntlm_auth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
828 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 */
829 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
831 Globals.map_to_guest = 0; /* By Default, "Never" */
832 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
833 Globals.enhanced_browsing = true;
834 Globals.lock_spin_time = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
835 #ifdef MMAP_BLACKLIST
836 Globals.use_mmap = false;
837 #else
838 Globals.use_mmap = true;
839 #endif
840 Globals.unicode = true;
841 Globals.unix_extensions = true;
842 Globals.reset_on_zero_vc = false;
843 Globals.log_writeable_files_on_exit = false;
844 Globals.create_krb5_conf = true;
845 Globals.winbindMaxDomainConnections = 1;
847 /* hostname lookups can be very expensive and are broken on
848 a large number of sites (tridge) */
849 Globals.hostname_lookups = false;
851 string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
852 string_set(Globals.ctx, &Globals.ldap_suffix, "");
853 string_set(Globals.ctx, &Globals.szLdapMachineSuffix, "");
854 string_set(Globals.ctx, &Globals.szLdapUserSuffix, "");
855 string_set(Globals.ctx, &Globals.szLdapGroupSuffix, "");
856 string_set(Globals.ctx, &Globals.szLdapIdmapSuffix, "");
858 string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
859 Globals.ldap_ssl = LDAP_SSL_START_TLS;
860 Globals.ldap_ssl_ads = false;
861 Globals.ldap_deref = -1;
862 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
863 Globals.ldap_delete_dn = false;
864 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
865 Globals.ldap_follow_referral = Auto;
866 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
867 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
868 Globals.ldap_page_size = LDAP_PAGE_SIZE;
870 Globals.ldap_debug_level = 0;
871 Globals.ldap_debug_threshold = 10;
873 /* This is what we tell the afs client. in reality we set the token
874 * to never expire, though, when this runs out the afs client will
875 * forget the token. Set to 0 to get NEVERDATE.*/
876 Globals.afs_token_lifetime = 604800;
877 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
879 /* these parameters are set to defaults that are more appropriate
880 for the increasing samba install base:
882 as a member of the workgroup, that will possibly become a
883 _local_ master browser (lm = true). this is opposed to a forced
884 local master browser startup (pm = true).
886 doesn't provide WINS server service by default (wsupp = false),
887 and doesn't provide domain master browser services by default, either.
891 Globals.show_add_printer_wizard = true;
892 Globals.os_level = 20;
893 Globals.local_master = true;
894 Globals._domain_master = Auto; /* depending on _domain_logons */
895 Globals._domain_logons = false;
896 Globals.browse_list = true;
897 Globals.we_are_a_wins_server = false;
898 Globals.wins_proxy = false;
900 TALLOC_FREE(Globals.init_logon_delayed_hosts);
901 Globals.init_logon_delay = 100; /* 100 ms default delay */
903 Globals.wins_dns_proxy = true;
905 Globals.allow_trusted_domains = true;
906 string_set(Globals.ctx, &Globals.szIdmapBackend, "tdb");
908 string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
909 string_set(Globals.ctx, &Globals.template_homedir, "/home/%D/%U");
910 string_set(Globals.ctx, &Globals.winbind_separator, "\\");
911 string_set(Globals.ctx, &Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
913 string_set(Globals.ctx, &Globals.cups_server, "");
914 string_set(Globals.ctx, &Globals.iprint_server, "");
916 string_set(Globals.ctx, &Globals._ctdbd_socket, "");
918 Globals.cluster_addresses = NULL;
919 Globals.clustering = false;
920 Globals.ctdb_timeout = 0;
921 Globals.ctdb_locktime_warn_threshold = 0;
923 Globals.winbind_cache_time = 300; /* 5 minutes */
924 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
925 Globals.winbind_max_clients = 200;
926 Globals.winbind_enum_users = false;
927 Globals.winbind_enum_groups = false;
928 Globals.winbind_use_default_domain = false;
929 Globals.winbind_trusted_domains_only = false;
930 Globals.winbind_nested_groups = true;
931 Globals.winbind_expand_groups = 1;
932 Globals.winbind_nss_info = (const char **)str_list_make_v3(NULL, "template", NULL);
933 Globals.winbind_refresh_tickets = false;
934 Globals.winbind_offline_logon = false;
936 Globals.idmap_cache_time = 86400 * 7; /* a week by default */
937 Globals.idmap_negative_cache_time = 120; /* 2 minutes by default */
939 Globals.passdb_expand_explicit = false;
941 Globals.name_cache_timeout = 660; /* In seconds */
943 Globals.use_spnego = true;
944 Globals.client_use_spnego = true;
946 Globals.client_signing = SMB_SIGNING_DEFAULT;
947 Globals.server_signing = SMB_SIGNING_DEFAULT;
949 Globals.defer_sharing_violations = true;
950 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
952 Globals.enable_privileges = true;
953 Globals.host_msdfs = true;
954 Globals.enable_asu_support = false;
956 /* User defined shares. */
957 s = talloc_asprintf(talloc_tos(), "%s/usershares", get_dyn_STATEDIR());
958 if (s == NULL) {
959 smb_panic("init_globals: ENOMEM");
961 string_set(Globals.ctx, &Globals.usershare_path, s);
962 TALLOC_FREE(s);
963 string_set(Globals.ctx, &Globals.usershare_template_share, "");
964 Globals.usershare_max_shares = 0;
965 /* By default disallow sharing of directories not owned by the sharer. */
966 Globals.usershare_owner_only = true;
967 /* By default disallow guest access to usershares. */
968 Globals.usershare_allow_guests = false;
970 Globals.keepalive = DEFAULT_KEEPALIVE;
972 /* By default no shares out of the registry */
973 Globals.registry_shares = false;
975 Globals.iminreceivefile = 0;
977 Globals.map_untrusted_to_domain = false;
978 Globals.multicast_dns_register = true;
980 Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
981 Globals.smb2_max_write = DEFAULT_SMB2_MAX_WRITE;
982 Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
983 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
985 string_set(Globals.ctx, &Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
987 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);
989 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);
991 Globals.tls_enabled = true;
993 string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
994 string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
995 string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
997 string_set(Globals.ctx, &Globals.share_backend, "classic");
999 Globals.iPreferredMaster = Auto;
1001 Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
1003 string_set(Globals.ctx, &Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
1005 string_set(Globals.ctx, &Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
1007 s = talloc_asprintf(talloc_tos(), "%s/samba_kcc", get_dyn_SCRIPTSBINDIR());
1008 if (s == NULL) {
1009 smb_panic("init_globals: ENOMEM");
1011 Globals.samba_kcc_command = (const char **)str_list_make_v3(NULL, s, NULL);
1012 TALLOC_FREE(s);
1014 s = talloc_asprintf(talloc_tos(), "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR());
1015 if (s == NULL) {
1016 smb_panic("init_globals: ENOMEM");
1018 Globals.dns_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1019 TALLOC_FREE(s);
1021 s = talloc_asprintf(talloc_tos(), "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR());
1022 if (s == NULL) {
1023 smb_panic("init_globals: ENOMEM");
1025 Globals.spn_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1026 TALLOC_FREE(s);
1028 Globals.nsupdate_command = (const char **)str_list_make_v3(NULL, "/usr/bin/nsupdate -g", NULL);
1030 Globals.rndc_command = (const char **)str_list_make_v3(NULL, "/usr/sbin/rndc", NULL);
1032 Globals.cldap_port = 389;
1034 Globals.dgram_port = 138;
1036 Globals.nbt_port = 137;
1038 Globals.krb5_port = 88;
1040 Globals.kpasswd_port = 464;
1042 Globals.web_port = 901;
1044 /* Now put back the settings that were set with lp_set_cmdline() */
1045 apply_lp_set_cmdline();
1048 /*******************************************************************
1049 Convenience routine to grab string parameters into talloced memory
1050 and run standard_sub_basic on them. The buffers can be written to by
1051 callers without affecting the source string.
1052 ********************************************************************/
1054 char *lp_string(TALLOC_CTX *ctx, const char *s)
1056 char *ret;
1058 /* The follow debug is useful for tracking down memory problems
1059 especially if you have an inner loop that is calling a lp_*()
1060 function that returns a string. Perhaps this debug should be
1061 present all the time? */
1063 #if 0
1064 DEBUG(10, ("lp_string(%s)\n", s));
1065 #endif
1066 if (!s) {
1067 return NULL;
1070 ret = talloc_sub_basic(ctx,
1071 get_current_username(),
1072 current_user_info.domain,
1074 if (trim_char(ret, '\"', '\"')) {
1075 if (strchr(ret,'\"') != NULL) {
1076 TALLOC_FREE(ret);
1077 ret = talloc_sub_basic(ctx,
1078 get_current_username(),
1079 current_user_info.domain,
1083 return ret;
1087 In this section all the functions that are used to access the
1088 parameters from the rest of the program are defined
1091 #define FN_GLOBAL_STRING(fn_name,ptr) \
1092 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1093 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1094 const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1095 #define FN_GLOBAL_LIST(fn_name,ptr) \
1096 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1097 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1098 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1099 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1100 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1101 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1102 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1104 #define FN_LOCAL_STRING(fn_name,val) \
1105 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));}
1106 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1107 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1108 #define FN_LOCAL_LIST(fn_name,val) \
1109 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1110 #define FN_LOCAL_BOOL(fn_name,val) \
1111 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1112 #define FN_LOCAL_INTEGER(fn_name,val) \
1113 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1115 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1116 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1117 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1118 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1119 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
1120 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1122 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1123 winbindMaxDomainConnections)
1125 int lp_winbind_max_domain_connections(void)
1127 if (lp_winbind_offline_logon() &&
1128 lp_winbind_max_domain_connections_int() > 1) {
1129 DEBUG(1, ("offline logons active, restricting max domain "
1130 "connections to 1\n"));
1131 return 1;
1133 return MAX(1, lp_winbind_max_domain_connections_int());
1136 int lp_smb2_max_credits(void)
1138 if (Globals.ismb2_max_credits == 0) {
1139 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1141 return Globals.ismb2_max_credits;
1143 int lp_cups_encrypt(void)
1145 int result = 0;
1146 #ifdef HAVE_HTTPCONNECTENCRYPT
1147 switch (Globals.CupsEncrypt) {
1148 case Auto:
1149 result = HTTP_ENCRYPT_REQUIRED;
1150 break;
1151 case true:
1152 result = HTTP_ENCRYPT_ALWAYS;
1153 break;
1154 case false:
1155 result = HTTP_ENCRYPT_NEVER;
1156 break;
1158 #endif
1159 return result;
1162 /* These functions remain in source3/param for now */
1164 #include "lib/param/param_functions.c"
1166 FN_LOCAL_STRING(servicename, szService)
1167 FN_LOCAL_CONST_STRING(const_servicename, szService)
1169 /* These functions cannot be auto-generated */
1170 FN_LOCAL_BOOL(autoloaded, autoloaded)
1172 /* local prototypes */
1174 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1175 static const char *get_boolean(bool bool_value);
1176 static int getservicebyname(const char *pszServiceName,
1177 struct loadparm_service *pserviceDest);
1178 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1179 void *userdata);
1180 static bool do_section(const char *pszSectionName, void *userdata);
1181 static void init_copymap(struct loadparm_service *pservice);
1182 static bool hash_a_service(const char *name, int number);
1183 static void free_service_byindex(int iService);
1184 static void show_parameter(int parmIndex);
1185 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1188 * This is a helper function for parametrical options support. It returns a
1189 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1190 * parametrical functions are quite simple
1192 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1193 const char *option)
1195 bool global_section = false;
1196 char* param_key;
1197 struct parmlist_entry *data;
1198 TALLOC_CTX *mem_ctx = talloc_stackframe();
1200 if (service == NULL) {
1201 data = Globals.param_opt;
1202 global_section = true;
1203 } else {
1204 data = service->param_opt;
1207 param_key = talloc_asprintf(mem_ctx, "%s:%s", type, option);
1208 if (param_key == NULL) {
1209 DEBUG(0,("asprintf failed!\n"));
1210 TALLOC_FREE(mem_ctx);
1211 return NULL;
1214 while (data) {
1215 if (strwicmp(data->key, param_key) == 0) {
1216 TALLOC_FREE(mem_ctx);
1217 return data;
1219 data = data->next;
1222 if (!global_section) {
1223 /* Try to fetch the same option but from globals */
1224 /* but only if we are not already working with Globals */
1225 data = Globals.param_opt;
1226 while (data) {
1227 if (strwicmp(data->key, param_key) == 0) {
1228 TALLOC_FREE(mem_ctx);
1229 return data;
1231 data = data->next;
1235 TALLOC_FREE(mem_ctx);
1237 return NULL;
1241 * This is a helper function for parametrical options support. It returns a
1242 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1243 * parametrical functions are quite simple
1245 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1246 const char *option)
1248 if (snum >= iNumServices) return NULL;
1250 if (snum < 0) {
1251 return get_parametrics_by_service(NULL, type, option);
1252 } else {
1253 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1258 #define MISSING_PARAMETER(name) \
1259 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1261 /*******************************************************************
1262 convenience routine to return int parameters.
1263 ********************************************************************/
1264 static int lp_int(const char *s)
1267 if (!s || !*s) {
1268 MISSING_PARAMETER(lp_int);
1269 return (-1);
1272 return (int)strtol(s, NULL, 0);
1275 /*******************************************************************
1276 convenience routine to return unsigned long parameters.
1277 ********************************************************************/
1278 static unsigned long lp_ulong(const char *s)
1281 if (!s || !*s) {
1282 MISSING_PARAMETER(lp_ulong);
1283 return (0);
1286 return strtoul(s, NULL, 0);
1289 /*******************************************************************
1290 convenience routine to return boolean parameters.
1291 ********************************************************************/
1292 static bool lp_bool(const char *s)
1294 bool ret = false;
1296 if (!s || !*s) {
1297 MISSING_PARAMETER(lp_bool);
1298 return false;
1301 if (!set_boolean(s, &ret)) {
1302 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1303 return false;
1306 return ret;
1309 /*******************************************************************
1310 convenience routine to return enum parameters.
1311 ********************************************************************/
1312 static int lp_enum(const char *s,const struct enum_list *_enum)
1314 int i;
1316 if (!s || !*s || !_enum) {
1317 MISSING_PARAMETER(lp_enum);
1318 return (-1);
1321 for (i=0; _enum[i].name; i++) {
1322 if (strequal(_enum[i].name,s))
1323 return _enum[i].value;
1326 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1327 return (-1);
1330 #undef MISSING_PARAMETER
1332 /* Return parametric option from a given service. Type is a part of option before ':' */
1333 /* Parametric option has following syntax: 'Type: option = value' */
1334 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1336 struct parmlist_entry *data = get_parametrics(snum, type, option);
1338 if (data == NULL||data->value==NULL) {
1339 if (def) {
1340 return lp_string(ctx, def);
1341 } else {
1342 return NULL;
1346 return lp_string(ctx, data->value);
1349 /* Return parametric option from a given service. Type is a part of option before ':' */
1350 /* Parametric option has following syntax: 'Type: option = value' */
1351 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1353 struct parmlist_entry *data = get_parametrics(snum, type, option);
1355 if (data == NULL||data->value==NULL)
1356 return def;
1358 return data->value;
1361 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1363 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1365 if (data == NULL||data->value==NULL)
1366 return NULL;
1368 return data->value;
1372 /* Return parametric option from a given service. Type is a part of option before ':' */
1373 /* Parametric option has following syntax: 'Type: option = value' */
1375 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1377 struct parmlist_entry *data = get_parametrics(snum, type, option);
1379 if (data == NULL||data->value==NULL)
1380 return (const char **)def;
1382 if (data->list==NULL) {
1383 data->list = str_list_make_v3(NULL, data->value, NULL);
1386 return (const char **)data->list;
1389 /* Return parametric option from a given service. Type is a part of option before ':' */
1390 /* Parametric option has following syntax: 'Type: option = value' */
1392 int lp_parm_int(int snum, const char *type, const char *option, int def)
1394 struct parmlist_entry *data = get_parametrics(snum, type, option);
1396 if (data && data->value && *data->value)
1397 return lp_int(data->value);
1399 return def;
1402 /* Return parametric option from a given service. Type is a part of option before ':' */
1403 /* Parametric option has following syntax: 'Type: option = value' */
1405 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1407 struct parmlist_entry *data = get_parametrics(snum, type, option);
1409 if (data && data->value && *data->value)
1410 return lp_ulong(data->value);
1412 return def;
1415 /* Return parametric option from a given service. Type is a part of option before ':' */
1416 /* Parametric option has following syntax: 'Type: option = value' */
1418 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1420 struct parmlist_entry *data = get_parametrics(snum, type, option);
1422 if (data && data->value && *data->value)
1423 return lp_bool(data->value);
1425 return def;
1428 /* Return parametric option from a given service. Type is a part of option before ':' */
1429 /* Parametric option has following syntax: 'Type: option = value' */
1431 int lp_parm_enum(int snum, const char *type, const char *option,
1432 const struct enum_list *_enum, int def)
1434 struct parmlist_entry *data = get_parametrics(snum, type, option);
1436 if (data && data->value && *data->value && _enum)
1437 return lp_enum(data->value, _enum);
1439 return def;
1443 * free a param_opts structure.
1444 * param_opts handling should be moved to talloc;
1445 * then this whole functions reduces to a TALLOC_FREE().
1448 static void free_param_opts(struct parmlist_entry **popts)
1450 struct parmlist_entry *opt, *next_opt;
1452 if (*popts != NULL) {
1453 DEBUG(5, ("Freeing parametrics:\n"));
1455 opt = *popts;
1456 while (opt != NULL) {
1457 string_free(&opt->key);
1458 string_free(&opt->value);
1459 TALLOC_FREE(opt->list);
1460 next_opt = opt->next;
1461 TALLOC_FREE(opt);
1462 opt = next_opt;
1464 *popts = NULL;
1467 /***************************************************************************
1468 Free the dynamically allocated parts of a service struct.
1469 ***************************************************************************/
1471 static void free_service(struct loadparm_service *pservice)
1473 if (!pservice)
1474 return;
1476 if (pservice->szService)
1477 DEBUG(5, ("free_service: Freeing service %s\n",
1478 pservice->szService));
1480 free_parameters(pservice);
1482 string_free(&pservice->szService);
1483 TALLOC_FREE(pservice->copymap);
1485 free_param_opts(&pservice->param_opt);
1487 ZERO_STRUCTP(pservice);
1491 /***************************************************************************
1492 remove a service indexed in the ServicePtrs array from the ServiceHash
1493 and free the dynamically allocated parts
1494 ***************************************************************************/
1496 static void free_service_byindex(int idx)
1498 if ( !LP_SNUM_OK(idx) )
1499 return;
1501 ServicePtrs[idx]->valid = false;
1503 /* we have to cleanup the hash record */
1505 if (ServicePtrs[idx]->szService) {
1506 char *canon_name = canonicalize_servicename(
1507 talloc_tos(),
1508 ServicePtrs[idx]->szService );
1510 dbwrap_delete_bystring(ServiceHash, canon_name );
1511 TALLOC_FREE(canon_name);
1514 free_service(ServicePtrs[idx]);
1515 talloc_free_children(ServicePtrs[idx]);
1518 /***************************************************************************
1519 Add a new service to the services array initialising it with the given
1520 service.
1521 ***************************************************************************/
1523 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1525 int i;
1526 int num_to_alloc = iNumServices + 1;
1527 struct loadparm_service **tsp = NULL;
1529 /* it might already exist */
1530 if (name) {
1531 i = getservicebyname(name, NULL);
1532 if (i >= 0) {
1533 return (i);
1537 /* if not, then create one */
1538 i = iNumServices;
1539 tsp = talloc_realloc(NULL, ServicePtrs, struct loadparm_service *, num_to_alloc);
1540 if (tsp == NULL) {
1541 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1542 return (-1);
1544 ServicePtrs = tsp;
1545 ServicePtrs[iNumServices] = talloc_zero(NULL, struct loadparm_service);
1546 if (!ServicePtrs[iNumServices]) {
1547 DEBUG(0,("add_a_service: out of memory!\n"));
1548 return (-1);
1550 iNumServices++;
1552 ServicePtrs[i]->valid = true;
1554 copy_service(ServicePtrs[i], pservice, NULL);
1555 if (name)
1556 string_set(ServicePtrs[i], &ServicePtrs[i]->szService, name);
1558 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1559 i, ServicePtrs[i]->szService));
1561 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1562 return (-1);
1565 return (i);
1568 /***************************************************************************
1569 Convert a string to uppercase and remove whitespaces.
1570 ***************************************************************************/
1572 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1574 char *result;
1576 if ( !src ) {
1577 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1578 return NULL;
1581 result = talloc_strdup(ctx, src);
1582 SMB_ASSERT(result != NULL);
1584 if (!strlower_m(result)) {
1585 TALLOC_FREE(result);
1586 return NULL;
1588 return result;
1591 /***************************************************************************
1592 Add a name/index pair for the services array to the hash table.
1593 ***************************************************************************/
1595 static bool hash_a_service(const char *name, int idx)
1597 char *canon_name;
1599 if ( !ServiceHash ) {
1600 DEBUG(10,("hash_a_service: creating servicehash\n"));
1601 ServiceHash = db_open_rbt(NULL);
1602 if ( !ServiceHash ) {
1603 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1604 return false;
1608 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1609 idx, name));
1611 canon_name = canonicalize_servicename(talloc_tos(), name );
1613 dbwrap_store_bystring(ServiceHash, canon_name,
1614 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1615 TDB_REPLACE);
1617 TALLOC_FREE(canon_name);
1619 return true;
1622 /***************************************************************************
1623 Add a new home service, with the specified home directory, defaults coming
1624 from service ifrom.
1625 ***************************************************************************/
1627 bool lp_add_home(const char *pszHomename, int iDefaultService,
1628 const char *user, const char *pszHomedir)
1630 int i;
1632 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1633 pszHomedir[0] == '\0') {
1634 return false;
1637 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1639 if (i < 0)
1640 return false;
1642 if (!(*(ServicePtrs[iDefaultService]->path))
1643 || strequal(ServicePtrs[iDefaultService]->path,
1644 lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1645 string_set(ServicePtrs[i], &ServicePtrs[i]->path, pszHomedir);
1648 if (!(*(ServicePtrs[i]->comment))) {
1649 char *comment = talloc_asprintf(talloc_tos(), "Home directory of %s", user);
1650 if (comment == NULL) {
1651 return false;
1653 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1654 TALLOC_FREE(comment);
1657 /* set the browseable flag from the global default */
1659 ServicePtrs[i]->browseable = sDefault.browseable;
1660 ServicePtrs[i]->access_based_share_enum = sDefault.access_based_share_enum;
1662 ServicePtrs[i]->autoloaded = true;
1664 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1665 user, ServicePtrs[i]->path ));
1667 return true;
1670 /***************************************************************************
1671 Add a new service, based on an old one.
1672 ***************************************************************************/
1674 int lp_add_service(const char *pszService, int iDefaultService)
1676 if (iDefaultService < 0) {
1677 return add_a_service(&sDefault, pszService);
1680 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1683 /***************************************************************************
1684 Add the IPC service.
1685 ***************************************************************************/
1687 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1689 char *comment = NULL;
1690 int i = add_a_service(&sDefault, ipc_name);
1692 if (i < 0)
1693 return false;
1695 comment = talloc_asprintf(talloc_tos(), "IPC Service (%s)",
1696 Globals.server_string);
1697 if (comment == NULL) {
1698 return false;
1701 string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
1702 string_set(ServicePtrs[i], &ServicePtrs[i]->username, "");
1703 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1704 string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
1705 ServicePtrs[i]->max_connections = 0;
1706 ServicePtrs[i]->bAvailable = true;
1707 ServicePtrs[i]->read_only = true;
1708 ServicePtrs[i]->guest_only = false;
1709 ServicePtrs[i]->administrative_share = true;
1710 ServicePtrs[i]->guest_ok = guest_ok;
1711 ServicePtrs[i]->printable = false;
1712 ServicePtrs[i]->browseable = sDefault.browseable;
1714 DEBUG(3, ("adding IPC service\n"));
1716 TALLOC_FREE(comment);
1717 return true;
1720 /***************************************************************************
1721 Add a new printer service, with defaults coming from service iFrom.
1722 ***************************************************************************/
1724 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1726 const char *comment = "From Printcap";
1727 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1729 if (i < 0)
1730 return false;
1732 /* note that we do NOT default the availability flag to true - */
1733 /* we take it from the default service passed. This allows all */
1734 /* dynamic printers to be disabled by disabling the [printers] */
1735 /* entry (if/when the 'available' keyword is implemented!). */
1737 /* the printer name is set to the service name. */
1738 string_set(ServicePtrs[i], &ServicePtrs[i]->_printername, pszPrintername);
1739 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1741 /* set the browseable flag from the gloabl default */
1742 ServicePtrs[i]->browseable = sDefault.browseable;
1744 /* Printers cannot be read_only. */
1745 ServicePtrs[i]->read_only = false;
1746 /* No oplocks on printer services. */
1747 ServicePtrs[i]->oplocks = false;
1748 /* Printer services must be printable. */
1749 ServicePtrs[i]->printable = true;
1751 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1753 return true;
1757 /***************************************************************************
1758 Check whether the given parameter name is valid.
1759 Parametric options (names containing a colon) are considered valid.
1760 ***************************************************************************/
1762 bool lp_parameter_is_valid(const char *pszParmName)
1764 return ((lpcfg_map_parameter(pszParmName) != -1) ||
1765 (strchr(pszParmName, ':') != NULL));
1768 /***************************************************************************
1769 Check whether the given name is the name of a global parameter.
1770 Returns true for strings belonging to parameters of class
1771 P_GLOBAL, false for all other strings, also for parametric options
1772 and strings not belonging to any option.
1773 ***************************************************************************/
1775 bool lp_parameter_is_global(const char *pszParmName)
1777 int num = lpcfg_map_parameter(pszParmName);
1779 if (num >= 0) {
1780 return (parm_table[num].p_class == P_GLOBAL);
1783 return false;
1786 /**************************************************************************
1787 Check whether the given name is the canonical name of a parameter.
1788 Returns false if it is not a valid parameter Name.
1789 For parametric options, true is returned.
1790 **************************************************************************/
1792 bool lp_parameter_is_canonical(const char *parm_name)
1794 if (!lp_parameter_is_valid(parm_name)) {
1795 return false;
1798 return (lpcfg_map_parameter(parm_name) ==
1799 map_parameter_canonical(parm_name, NULL));
1802 /**************************************************************************
1803 Determine the canonical name for a parameter.
1804 Indicate when it is an inverse (boolean) synonym instead of a
1805 "usual" synonym.
1806 **************************************************************************/
1808 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1809 bool *inverse)
1811 int num;
1813 if (!lp_parameter_is_valid(parm_name)) {
1814 *canon_parm = NULL;
1815 return false;
1818 num = map_parameter_canonical(parm_name, inverse);
1819 if (num < 0) {
1820 /* parametric option */
1821 *canon_parm = parm_name;
1822 } else {
1823 *canon_parm = parm_table[num].label;
1826 return true;
1830 /**************************************************************************
1831 Determine the canonical name for a parameter.
1832 Turn the value given into the inverse boolean expression when
1833 the synonym is an invers boolean synonym.
1835 Return true if parm_name is a valid parameter name and
1836 in case it is an invers boolean synonym, if the val string could
1837 successfully be converted to the reverse bool.
1838 Return false in all other cases.
1839 **************************************************************************/
1841 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1842 const char *val,
1843 const char **canon_parm,
1844 const char **canon_val)
1846 int num;
1847 bool inverse;
1849 if (!lp_parameter_is_valid(parm_name)) {
1850 *canon_parm = NULL;
1851 *canon_val = NULL;
1852 return false;
1855 num = map_parameter_canonical(parm_name, &inverse);
1856 if (num < 0) {
1857 /* parametric option */
1858 *canon_parm = parm_name;
1859 *canon_val = val;
1860 } else {
1861 *canon_parm = parm_table[num].label;
1862 if (inverse) {
1863 if (!lp_invert_boolean(val, canon_val)) {
1864 *canon_val = NULL;
1865 return false;
1867 } else {
1868 *canon_val = val;
1872 return true;
1875 /***************************************************************************
1876 Map a parameter's string representation to the index of the canonical
1877 form of the parameter (it might be a synonym).
1878 Returns -1 if the parameter string is not recognised.
1879 ***************************************************************************/
1881 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1883 int parm_num, canon_num;
1884 bool loc_inverse = false;
1886 parm_num = lpcfg_map_parameter(pszParmName);
1887 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1888 /* invalid, parametric or no canidate for synonyms ... */
1889 goto done;
1892 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1893 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1894 parm_num = canon_num;
1895 goto done;
1899 done:
1900 if (inverse != NULL) {
1901 *inverse = loc_inverse;
1903 return parm_num;
1906 /***************************************************************************
1907 return true if parameter number parm1 is a synonym of parameter
1908 number parm2 (parm2 being the principal name).
1909 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1910 false otherwise.
1911 ***************************************************************************/
1913 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
1915 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
1916 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
1917 (parm_table[parm1].flags & FLAG_HIDE) &&
1918 !(parm_table[parm2].flags & FLAG_HIDE))
1920 if (inverse != NULL) {
1921 if ((parm_table[parm1].type == P_BOOLREV) &&
1922 (parm_table[parm2].type == P_BOOL))
1924 *inverse = true;
1925 } else {
1926 *inverse = false;
1929 return true;
1931 return false;
1934 /***************************************************************************
1935 Show one parameter's name, type, [values,] and flags.
1936 (helper functions for show_parameter_list)
1937 ***************************************************************************/
1939 static void show_parameter(int parmIndex)
1941 int enumIndex, flagIndex;
1942 int parmIndex2;
1943 bool hadFlag;
1944 bool hadSyn;
1945 bool inverse;
1946 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
1947 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
1948 "P_ENUM", "P_SEP"};
1949 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
1950 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
1951 FLAG_HIDE};
1952 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
1953 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
1954 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
1956 printf("%s=%s", parm_table[parmIndex].label,
1957 type[parm_table[parmIndex].type]);
1958 if (parm_table[parmIndex].type == P_ENUM) {
1959 printf(",");
1960 for (enumIndex=0;
1961 parm_table[parmIndex].enum_list[enumIndex].name;
1962 enumIndex++)
1964 printf("%s%s",
1965 enumIndex ? "|" : "",
1966 parm_table[parmIndex].enum_list[enumIndex].name);
1969 printf(",");
1970 hadFlag = false;
1971 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
1972 if (parm_table[parmIndex].flags & flags[flagIndex]) {
1973 printf("%s%s",
1974 hadFlag ? "|" : "",
1975 flag_names[flagIndex]);
1976 hadFlag = true;
1980 /* output synonyms */
1981 hadSyn = false;
1982 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
1983 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
1984 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
1985 parm_table[parmIndex2].label);
1986 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
1987 if (!hadSyn) {
1988 printf(" (synonyms: ");
1989 hadSyn = true;
1990 } else {
1991 printf(", ");
1993 printf("%s%s", parm_table[parmIndex2].label,
1994 inverse ? "[i]" : "");
1997 if (hadSyn) {
1998 printf(")");
2001 printf("\n");
2004 /***************************************************************************
2005 Show all parameter's name, type, [values,] and flags.
2006 ***************************************************************************/
2008 void show_parameter_list(void)
2010 int classIndex, parmIndex;
2011 const char *section_names[] = { "local", "global", NULL};
2013 for (classIndex=0; section_names[classIndex]; classIndex++) {
2014 printf("[%s]\n", section_names[classIndex]);
2015 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2016 if (parm_table[parmIndex].p_class == classIndex) {
2017 show_parameter(parmIndex);
2023 /***************************************************************************
2024 Get the standard string representation of a boolean value ("yes" or "no")
2025 ***************************************************************************/
2027 static const char *get_boolean(bool bool_value)
2029 static const char *yes_str = "yes";
2030 static const char *no_str = "no";
2032 return (bool_value ? yes_str : no_str);
2035 /***************************************************************************
2036 Provide the string of the negated boolean value associated to the boolean
2037 given as a string. Returns false if the passed string does not correctly
2038 represent a boolean.
2039 ***************************************************************************/
2041 bool lp_invert_boolean(const char *str, const char **inverse_str)
2043 bool val;
2045 if (!set_boolean(str, &val)) {
2046 return false;
2049 *inverse_str = get_boolean(!val);
2050 return true;
2053 /***************************************************************************
2054 Provide the canonical string representation of a boolean value given
2055 as a string. Return true on success, false if the string given does
2056 not correctly represent a boolean.
2057 ***************************************************************************/
2059 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2061 bool val;
2063 if (!set_boolean(str, &val)) {
2064 return false;
2067 *canon_str = get_boolean(val);
2068 return true;
2071 /***************************************************************************
2072 Find a service by name. Otherwise works like get_service.
2073 ***************************************************************************/
2075 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2077 int iService = -1;
2078 char *canon_name;
2079 TDB_DATA data;
2080 NTSTATUS status;
2082 if (ServiceHash == NULL) {
2083 return -1;
2086 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2088 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2089 &data);
2091 if (NT_STATUS_IS_OK(status) &&
2092 (data.dptr != NULL) &&
2093 (data.dsize == sizeof(iService)))
2095 iService = *(int *)data.dptr;
2098 TALLOC_FREE(canon_name);
2100 if ((iService != -1) && (LP_SNUM_OK(iService))
2101 && (pserviceDest != NULL)) {
2102 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2105 return (iService);
2108 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2109 struct loadparm_service *lp_service(const char *pszServiceName)
2111 int iService = getservicebyname(pszServiceName, NULL);
2112 if (iService == -1 || !LP_SNUM_OK(iService)) {
2113 return NULL;
2115 return ServicePtrs[iService];
2118 struct loadparm_service *lp_servicebynum(int snum)
2120 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2121 return NULL;
2123 return ServicePtrs[snum];
2126 struct loadparm_service *lp_default_loadparm_service()
2128 return &sDefault;
2131 /***************************************************************************
2132 Check a service for consistency. Return false if the service is in any way
2133 incomplete or faulty, else true.
2134 ***************************************************************************/
2136 bool service_ok(int iService)
2138 bool bRetval;
2140 bRetval = true;
2141 if (ServicePtrs[iService]->szService[0] == '\0') {
2142 DEBUG(0, ("The following message indicates an internal error:\n"));
2143 DEBUG(0, ("No service name in service entry.\n"));
2144 bRetval = false;
2147 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2148 /* I can't see why you'd want a non-printable printer service... */
2149 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2150 if (!ServicePtrs[iService]->printable) {
2151 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2152 ServicePtrs[iService]->szService));
2153 ServicePtrs[iService]->printable = true;
2155 /* [printers] service must also be non-browsable. */
2156 if (ServicePtrs[iService]->browseable)
2157 ServicePtrs[iService]->browseable = false;
2160 if (ServicePtrs[iService]->path[0] == '\0' &&
2161 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2162 ServicePtrs[iService]->msdfs_proxy[0] == '\0'
2164 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2165 ServicePtrs[iService]->szService));
2166 ServicePtrs[iService]->bAvailable = false;
2169 /* If a service is flagged unavailable, log the fact at level 1. */
2170 if (!ServicePtrs[iService]->bAvailable)
2171 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2172 ServicePtrs[iService]->szService));
2174 return (bRetval);
2177 static struct smbconf_ctx *lp_smbconf_ctx(void)
2179 sbcErr err;
2180 static struct smbconf_ctx *conf_ctx = NULL;
2182 if (conf_ctx == NULL) {
2183 err = smbconf_init(NULL, &conf_ctx, "registry:");
2184 if (!SBC_ERROR_IS_OK(err)) {
2185 DEBUG(1, ("error initializing registry configuration: "
2186 "%s\n", sbcErrorString(err)));
2187 conf_ctx = NULL;
2191 return conf_ctx;
2194 static bool process_smbconf_service(struct smbconf_service *service)
2196 uint32_t count;
2197 bool ret;
2199 if (service == NULL) {
2200 return false;
2203 ret = do_section(service->name, NULL);
2204 if (ret != true) {
2205 return false;
2207 for (count = 0; count < service->num_params; count++) {
2208 ret = do_parameter(service->param_names[count],
2209 service->param_values[count],
2210 NULL);
2211 if (ret != true) {
2212 return false;
2215 if (iServiceIndex >= 0) {
2216 return service_ok(iServiceIndex);
2218 return true;
2222 * load a service from registry and activate it
2224 bool process_registry_service(const char *service_name)
2226 sbcErr err;
2227 struct smbconf_service *service = NULL;
2228 TALLOC_CTX *mem_ctx = talloc_stackframe();
2229 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2230 bool ret = false;
2232 if (conf_ctx == NULL) {
2233 goto done;
2236 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2238 if (!smbconf_share_exists(conf_ctx, service_name)) {
2240 * Registry does not contain data for this service (yet),
2241 * but make sure lp_load doesn't return false.
2243 ret = true;
2244 goto done;
2247 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2248 if (!SBC_ERROR_IS_OK(err)) {
2249 goto done;
2252 ret = process_smbconf_service(service);
2253 if (!ret) {
2254 goto done;
2257 /* store the csn */
2258 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2260 done:
2261 TALLOC_FREE(mem_ctx);
2262 return ret;
2266 * process_registry_globals
2268 static bool process_registry_globals(void)
2270 bool ret;
2272 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2274 ret = do_parameter("registry shares", "yes", NULL);
2275 if (!ret) {
2276 return ret;
2279 return process_registry_service(GLOBAL_NAME);
2282 bool process_registry_shares(void)
2284 sbcErr err;
2285 uint32_t count;
2286 struct smbconf_service **service = NULL;
2287 uint32_t num_shares = 0;
2288 TALLOC_CTX *mem_ctx = talloc_stackframe();
2289 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2290 bool ret = false;
2292 if (conf_ctx == NULL) {
2293 goto done;
2296 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2297 if (!SBC_ERROR_IS_OK(err)) {
2298 goto done;
2301 ret = true;
2303 for (count = 0; count < num_shares; count++) {
2304 if (strequal(service[count]->name, GLOBAL_NAME)) {
2305 continue;
2307 ret = process_smbconf_service(service[count]);
2308 if (!ret) {
2309 goto done;
2313 /* store the csn */
2314 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2316 done:
2317 TALLOC_FREE(mem_ctx);
2318 return ret;
2322 * reload those shares from registry that are already
2323 * activated in the services array.
2325 static bool reload_registry_shares(void)
2327 int i;
2328 bool ret = true;
2330 for (i = 0; i < iNumServices; i++) {
2331 if (!VALID(i)) {
2332 continue;
2335 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2336 continue;
2339 ret = process_registry_service(ServicePtrs[i]->szService);
2340 if (!ret) {
2341 goto done;
2345 done:
2346 return ret;
2350 #define MAX_INCLUDE_DEPTH 100
2352 static uint8_t include_depth;
2354 static struct file_lists {
2355 struct file_lists *next;
2356 char *name;
2357 char *subfname;
2358 time_t modtime;
2359 } *file_lists = NULL;
2361 /*******************************************************************
2362 Keep a linked list of all config files so we know when one has changed
2363 it's date and needs to be reloaded.
2364 ********************************************************************/
2366 static void add_to_file_list(const char *fname, const char *subfname)
2368 struct file_lists *f = file_lists;
2370 while (f) {
2371 if (f->name && !strcmp(f->name, fname))
2372 break;
2373 f = f->next;
2376 if (!f) {
2377 f = talloc(NULL, struct file_lists);
2378 if (!f) {
2379 goto fail;
2381 f->next = file_lists;
2382 f->name = talloc_strdup(f, fname);
2383 if (!f->name) {
2384 TALLOC_FREE(f);
2385 goto fail;
2387 f->subfname = talloc_strdup(f, subfname);
2388 if (!f->subfname) {
2389 TALLOC_FREE(f);
2390 goto fail;
2392 file_lists = f;
2393 f->modtime = file_modtime(subfname);
2394 } else {
2395 time_t t = file_modtime(subfname);
2396 if (t)
2397 f->modtime = t;
2399 return;
2401 fail:
2402 DEBUG(0, ("Unable to add file to file list: %s\n", fname));
2407 * Free the file lists
2409 static void free_file_list(void)
2411 struct file_lists *f;
2412 struct file_lists *next;
2414 f = file_lists;
2415 while( f ) {
2416 next = f->next;
2417 TALLOC_FREE( f );
2418 f = next;
2420 file_lists = NULL;
2425 * Utility function for outsiders to check if we're running on registry.
2427 bool lp_config_backend_is_registry(void)
2429 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2433 * Utility function to check if the config backend is FILE.
2435 bool lp_config_backend_is_file(void)
2437 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2440 /*******************************************************************
2441 Check if a config file has changed date.
2442 ********************************************************************/
2444 bool lp_file_list_changed(void)
2446 struct file_lists *f = file_lists;
2448 DEBUG(6, ("lp_file_list_changed()\n"));
2450 while (f) {
2451 time_t mod_time;
2453 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2454 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2456 if (conf_ctx == NULL) {
2457 return false;
2459 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2460 NULL))
2462 DEBUGADD(6, ("registry config changed\n"));
2463 return true;
2465 } else {
2466 char *n2 = NULL;
2467 n2 = talloc_sub_basic(talloc_tos(),
2468 get_current_username(),
2469 current_user_info.domain,
2470 f->name);
2471 if (!n2) {
2472 return false;
2474 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2475 f->name, n2, ctime(&f->modtime)));
2477 mod_time = file_modtime(n2);
2479 if (mod_time &&
2480 ((f->modtime != mod_time) ||
2481 (f->subfname == NULL) ||
2482 (strcmp(n2, f->subfname) != 0)))
2484 DEBUGADD(6,
2485 ("file %s modified: %s\n", n2,
2486 ctime(&mod_time)));
2487 f->modtime = mod_time;
2488 TALLOC_FREE(f->subfname);
2489 f->subfname = talloc_strdup(f, n2);
2490 if (f->subfname == NULL) {
2491 smb_panic("talloc_strdup failed");
2493 TALLOC_FREE(n2);
2494 return true;
2496 TALLOC_FREE(n2);
2498 f = f->next;
2500 return false;
2505 * Initialize iconv conversion descriptors.
2507 * This is called the first time it is needed, and also called again
2508 * every time the configuration is reloaded, because the charset or
2509 * codepage might have changed.
2511 static void init_iconv(void)
2513 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2514 lp_unix_charset(),
2515 true, global_iconv_handle);
2518 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2520 if (strcmp(*ptr, pszParmValue) != 0) {
2521 string_set(Globals.ctx, ptr, pszParmValue);
2522 init_iconv();
2524 return true;
2527 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2529 bool is_utf8 = false;
2530 size_t len = strlen(pszParmValue);
2532 if (len == 4 || len == 5) {
2533 /* Don't use StrCaseCmp here as we don't want to
2534 initialize iconv. */
2535 if ((toupper_m(pszParmValue[0]) == 'U') &&
2536 (toupper_m(pszParmValue[1]) == 'T') &&
2537 (toupper_m(pszParmValue[2]) == 'F')) {
2538 if (len == 4) {
2539 if (pszParmValue[3] == '8') {
2540 is_utf8 = true;
2542 } else {
2543 if (pszParmValue[3] == '-' &&
2544 pszParmValue[4] == '8') {
2545 is_utf8 = true;
2551 if (strcmp(*ptr, pszParmValue) != 0) {
2552 if (is_utf8) {
2553 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2554 "be UTF8, using (default value) %s instead.\n",
2555 DEFAULT_DOS_CHARSET));
2556 pszParmValue = DEFAULT_DOS_CHARSET;
2558 string_set(Globals.ctx, ptr, pszParmValue);
2559 init_iconv();
2561 return true;
2564 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2566 TALLOC_FREE(Globals.netbios_aliases);
2567 Globals.netbios_aliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2568 return set_netbios_aliases(Globals.netbios_aliases);
2571 /***************************************************************************
2572 Handle the include operation.
2573 ***************************************************************************/
2574 static bool bAllowIncludeRegistry = true;
2576 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2578 char *fname;
2580 if (include_depth >= MAX_INCLUDE_DEPTH) {
2581 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2582 include_depth));
2583 return false;
2586 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2587 if (!bAllowIncludeRegistry) {
2588 return true;
2590 if (bInGlobalSection) {
2591 bool ret;
2592 include_depth++;
2593 ret = process_registry_globals();
2594 include_depth--;
2595 return ret;
2596 } else {
2597 DEBUG(1, ("\"include = registry\" only effective "
2598 "in %s section\n", GLOBAL_NAME));
2599 return false;
2603 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2604 current_user_info.domain,
2605 pszParmValue);
2607 add_to_file_list(pszParmValue, fname);
2609 if (snum < 0) {
2610 string_set(Globals.ctx, ptr, fname);
2611 } else {
2612 string_set(ServicePtrs[snum], ptr, fname);
2615 if (file_exist(fname)) {
2616 bool ret;
2617 include_depth++;
2618 ret = pm_process(fname, do_section, do_parameter, NULL);
2619 include_depth--;
2620 TALLOC_FREE(fname);
2621 return ret;
2624 DEBUG(2, ("Can't find include file %s\n", fname));
2625 TALLOC_FREE(fname);
2626 return true;
2629 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2631 Globals.ldap_debug_level = lp_int(pszParmValue);
2632 init_ldap_debugging();
2633 return true;
2637 * idmap related parameters
2640 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2642 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2644 return true;
2647 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2649 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2651 return true;
2654 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2656 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2658 return true;
2661 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2663 char *config_option = NULL;
2664 const char *range = NULL;
2665 bool ret = false;
2667 SMB_ASSERT(low != NULL);
2668 SMB_ASSERT(high != NULL);
2670 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2671 domain_name = "*";
2674 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2675 domain_name);
2676 if (config_option == NULL) {
2677 DEBUG(0, ("out of memory\n"));
2678 return false;
2681 range = lp_parm_const_string(-1, config_option, "range", NULL);
2682 if (range == NULL) {
2683 DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2684 goto done;
2687 if (sscanf(range, "%u - %u", low, high) != 2) {
2688 DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2689 range, domain_name));
2690 goto done;
2693 ret = true;
2695 done:
2696 talloc_free(config_option);
2697 return ret;
2701 bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2703 return lp_idmap_range("*", low, high);
2706 const char *lp_idmap_backend(const char *domain_name)
2708 char *config_option = NULL;
2709 const char *backend = NULL;
2711 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2712 domain_name = "*";
2715 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2716 domain_name);
2717 if (config_option == NULL) {
2718 DEBUG(0, ("out of memory\n"));
2719 return false;
2722 backend = lp_parm_const_string(-1, config_option, "backend", NULL);
2723 if (backend == NULL) {
2724 DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
2725 goto done;
2728 done:
2729 talloc_free(config_option);
2730 return backend;
2733 const char *lp_idmap_default_backend(void)
2735 return lp_idmap_backend("*");
2738 /***************************************************************************
2739 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2740 ***************************************************************************/
2742 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2744 const char *suffix_string;
2746 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2747 Globals.ldap_suffix );
2748 if ( !suffix_string ) {
2749 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2750 return "";
2753 return suffix_string;
2756 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2758 if (Globals.szLdapMachineSuffix[0])
2759 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
2761 return lp_string(ctx, Globals.ldap_suffix);
2764 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
2766 if (Globals.szLdapUserSuffix[0])
2767 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
2769 return lp_string(ctx, Globals.ldap_suffix);
2772 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
2774 if (Globals.szLdapGroupSuffix[0])
2775 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
2777 return lp_string(ctx, Globals.ldap_suffix);
2780 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
2782 if (Globals.szLdapIdmapSuffix[0])
2783 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
2785 return lp_string(ctx, Globals.ldap_suffix);
2788 /****************************************************************************
2789 set the value for a P_ENUM
2790 ***************************************************************************/
2792 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
2793 int *ptr )
2795 int i;
2797 for (i = 0; parm->enum_list[i].name; i++) {
2798 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
2799 *ptr = parm->enum_list[i].value;
2800 return;
2803 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
2804 pszParmValue, parm->label));
2807 /***************************************************************************
2808 ***************************************************************************/
2810 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2812 static int parm_num = -1;
2813 struct loadparm_service *s;
2815 if ( parm_num == -1 )
2816 parm_num = lpcfg_map_parameter( "printing" );
2818 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
2820 if ( snum < 0 ) {
2821 s = &sDefault;
2822 init_printer_values(Globals.ctx, s);
2823 } else {
2824 s = ServicePtrs[snum];
2825 init_printer_values(s, s);
2828 return true;
2832 /***************************************************************************
2833 Initialise a copymap.
2834 ***************************************************************************/
2836 static void init_copymap(struct loadparm_service *pservice)
2838 int i;
2840 TALLOC_FREE(pservice->copymap);
2842 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
2843 if (!pservice->copymap)
2844 DEBUG(0,
2845 ("Couldn't allocate copymap!! (size %d)\n",
2846 (int)NUMPARAMETERS));
2847 else
2848 for (i = 0; i < NUMPARAMETERS; i++)
2849 bitmap_set(pservice->copymap, i);
2853 return the parameter pointer for a parameter
2855 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
2857 if (service == NULL) {
2858 if (parm->p_class == P_LOCAL)
2859 return (void *)(((char *)&sDefault)+parm->offset);
2860 else if (parm->p_class == P_GLOBAL)
2861 return (void *)(((char *)&Globals)+parm->offset);
2862 else return NULL;
2863 } else {
2864 return (void *)(((char *)service) + parm->offset);
2868 /***************************************************************************
2869 Return the local pointer to a parameter given the service number and parameter
2870 ***************************************************************************/
2872 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
2874 return lp_parm_ptr(ServicePtrs[snum], parm);
2877 /***************************************************************************
2878 Process a parameter for a particular service number. If snum < 0
2879 then assume we are in the globals.
2880 ***************************************************************************/
2882 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
2884 int parmnum, i;
2885 void *parm_ptr = NULL; /* where we are going to store the result */
2886 struct parmlist_entry **opt_list;
2887 TALLOC_CTX *mem_ctx;
2889 parmnum = lpcfg_map_parameter(pszParmName);
2891 if (parmnum < 0) {
2892 if (strchr(pszParmName, ':') == NULL) {
2893 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
2894 pszParmName));
2895 return true;
2899 * We've got a parametric option
2902 if (snum < 0) {
2903 opt_list = &Globals.param_opt;
2904 set_param_opt(NULL, opt_list, pszParmName, pszParmValue, 0);
2905 } else {
2906 opt_list = &ServicePtrs[snum]->param_opt;
2907 set_param_opt(ServicePtrs[snum], opt_list, pszParmName, pszParmValue, 0);
2910 return true;
2913 /* if it's already been set by the command line, then we don't
2914 override here */
2915 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
2916 return true;
2919 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
2920 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
2921 pszParmName));
2924 /* we might point at a service, the default service or a global */
2925 if (snum < 0) {
2926 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
2927 } else {
2928 if (parm_table[parmnum].p_class == P_GLOBAL) {
2929 DEBUG(0,
2930 ("Global parameter %s found in service section!\n",
2931 pszParmName));
2932 return true;
2934 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
2937 if (snum >= 0) {
2938 if (!ServicePtrs[snum]->copymap)
2939 init_copymap(ServicePtrs[snum]);
2941 /* this handles the aliases - set the copymap for other entries with
2942 the same data pointer */
2943 for (i = 0; parm_table[i].label; i++) {
2944 if ((parm_table[i].offset == parm_table[parmnum].offset)
2945 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
2946 bitmap_clear(ServicePtrs[snum]->copymap, i);
2949 mem_ctx = ServicePtrs[snum];
2950 } else {
2951 mem_ctx = Globals.ctx;
2954 /* if it is a special case then go ahead */
2955 if (parm_table[parmnum].special) {
2956 bool ok;
2957 struct loadparm_context *lp_ctx = loadparm_init_s3(talloc_tos(),
2958 loadparm_s3_helpers());
2959 ok = parm_table[parmnum].special(lp_ctx, snum, pszParmValue,
2960 (char **)parm_ptr);
2961 TALLOC_FREE(lp_ctx);
2963 return ok;
2966 /* now switch on the type of variable it is */
2967 switch (parm_table[parmnum].type)
2969 case P_BOOL:
2970 *(bool *)parm_ptr = lp_bool(pszParmValue);
2971 break;
2973 case P_BOOLREV:
2974 *(bool *)parm_ptr = !lp_bool(pszParmValue);
2975 break;
2977 case P_INTEGER:
2978 *(int *)parm_ptr = lp_int(pszParmValue);
2979 break;
2981 case P_CHAR:
2982 *(char *)parm_ptr = *pszParmValue;
2983 break;
2985 case P_OCTAL:
2986 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
2987 if ( i != 1 ) {
2988 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
2990 break;
2992 case P_BYTES:
2994 uint64_t val;
2995 if (conv_str_size_error(pszParmValue, &val)) {
2996 if (val <= INT_MAX) {
2997 *(int *)parm_ptr = (int)val;
2998 break;
3002 DEBUG(0,("lp_do_parameter(%s): value is not "
3003 "a valid size specifier!\n", pszParmValue));
3004 return false;
3007 case P_LIST:
3008 case P_CMDLIST:
3009 TALLOC_FREE(*((char ***)parm_ptr));
3010 *(char ***)parm_ptr = str_list_make_v3(
3011 NULL, pszParmValue, NULL);
3012 break;
3014 case P_STRING:
3015 string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
3016 break;
3018 case P_USTRING:
3020 char *upper_string = strupper_talloc(talloc_tos(),
3021 pszParmValue);
3022 string_set(mem_ctx, (char **)parm_ptr, upper_string);
3023 TALLOC_FREE(upper_string);
3024 break;
3026 case P_ENUM:
3027 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3028 break;
3029 case P_SEP:
3030 break;
3033 return true;
3036 /***************************************************************************
3037 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3038 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3039 ***************************************************************************/
3041 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3043 int parmnum, i;
3044 parmnum = lpcfg_map_parameter(pszParmName);
3045 if (parmnum >= 0) {
3046 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3047 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3048 return false;
3050 parm_table[parmnum].flags |= FLAG_CMDLINE;
3052 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3053 * be grouped in the table, so we don't have to search the
3054 * whole table */
3055 for (i=parmnum-1;
3056 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3057 && parm_table[i].p_class == parm_table[parmnum].p_class;
3058 i--) {
3059 parm_table[i].flags |= FLAG_CMDLINE;
3061 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3062 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3063 parm_table[i].flags |= FLAG_CMDLINE;
3066 if (store_values) {
3067 store_lp_set_cmdline(pszParmName, pszParmValue);
3069 return true;
3072 /* it might be parametric */
3073 if (strchr(pszParmName, ':') != NULL) {
3074 set_param_opt(NULL, &Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3075 if (store_values) {
3076 store_lp_set_cmdline(pszParmName, pszParmValue);
3078 return true;
3081 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3082 return true;
3085 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3087 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3090 /***************************************************************************
3091 Process a parameter.
3092 ***************************************************************************/
3094 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3095 void *userdata)
3097 if (!bInGlobalSection && bGlobalOnly)
3098 return true;
3100 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3102 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3103 pszParmName, pszParmValue));
3107 set a option from the commandline in 'a=b' format. Use to support --option
3109 bool lp_set_option(const char *option)
3111 char *p, *s;
3112 bool ret;
3114 s = talloc_strdup(NULL, option);
3115 if (!s) {
3116 return false;
3119 p = strchr(s, '=');
3120 if (!p) {
3121 talloc_free(s);
3122 return false;
3125 *p = 0;
3127 /* skip white spaces after the = sign */
3128 do {
3129 p++;
3130 } while (*p == ' ');
3132 ret = lp_set_cmdline(s, p);
3133 talloc_free(s);
3134 return ret;
3137 /***************************************************************************
3138 Initialize any local variables in the sDefault table, after parsing a
3139 [globals] section.
3140 ***************************************************************************/
3142 static void init_locals(void)
3145 * We run this check once the [globals] is parsed, to force
3146 * the VFS objects and other per-share settings we need for
3147 * the standard way a AD DC is operated. We may change these
3148 * as our code evolves, which is why we force these settings.
3150 * We can't do this at the end of lp_load_ex(), as by that
3151 * point the services have been loaded and they will already
3152 * have "" as their vfs objects.
3154 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
3155 const char **vfs_objects = lp_vfs_objects(-1);
3156 if (!vfs_objects || !vfs_objects[0]) {
3157 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
3158 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
3159 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
3160 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
3161 } else {
3162 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
3166 lp_do_parameter(-1, "map hidden", "no");
3167 lp_do_parameter(-1, "map system", "no");
3168 lp_do_parameter(-1, "map readonly", "no");
3169 lp_do_parameter(-1, "map archive", "no");
3170 lp_do_parameter(-1, "store dos attributes", "yes");
3174 /***************************************************************************
3175 Process a new section (service). At this stage all sections are services.
3176 Later we'll have special sections that permit server parameters to be set.
3177 Returns true on success, false on failure.
3178 ***************************************************************************/
3180 static bool do_section(const char *pszSectionName, void *userdata)
3182 bool bRetval;
3183 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3184 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3185 bRetval = false;
3187 /* if we were in a global section then do the local inits */
3188 if (bInGlobalSection && !isglobal)
3189 init_locals();
3191 /* if we've just struck a global section, note the fact. */
3192 bInGlobalSection = isglobal;
3194 /* check for multiple global sections */
3195 if (bInGlobalSection) {
3196 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3197 return true;
3200 if (!bInGlobalSection && bGlobalOnly)
3201 return true;
3203 /* if we have a current service, tidy it up before moving on */
3204 bRetval = true;
3206 if (iServiceIndex >= 0)
3207 bRetval = service_ok(iServiceIndex);
3209 /* if all is still well, move to the next record in the services array */
3210 if (bRetval) {
3211 /* We put this here to avoid an odd message order if messages are */
3212 /* issued by the post-processing of a previous section. */
3213 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3215 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3216 if (iServiceIndex < 0) {
3217 DEBUG(0, ("Failed to add a new service\n"));
3218 return false;
3220 /* Clean all parametric options for service */
3221 /* They will be added during parsing again */
3222 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3225 return bRetval;
3229 /***************************************************************************
3230 Determine if a partcular base parameter is currentl set to the default value.
3231 ***************************************************************************/
3233 static bool is_default(int i)
3235 switch (parm_table[i].type) {
3236 case P_LIST:
3237 case P_CMDLIST:
3238 return str_list_equal((const char * const *)parm_table[i].def.lvalue,
3239 *(const char ***)lp_parm_ptr(NULL,
3240 &parm_table[i]));
3241 case P_STRING:
3242 case P_USTRING:
3243 return strequal(parm_table[i].def.svalue,
3244 *(char **)lp_parm_ptr(NULL,
3245 &parm_table[i]));
3246 case P_BOOL:
3247 case P_BOOLREV:
3248 return parm_table[i].def.bvalue ==
3249 *(bool *)lp_parm_ptr(NULL,
3250 &parm_table[i]);
3251 case P_CHAR:
3252 return parm_table[i].def.cvalue ==
3253 *(char *)lp_parm_ptr(NULL,
3254 &parm_table[i]);
3255 case P_INTEGER:
3256 case P_OCTAL:
3257 case P_ENUM:
3258 case P_BYTES:
3259 return parm_table[i].def.ivalue ==
3260 *(int *)lp_parm_ptr(NULL,
3261 &parm_table[i]);
3262 case P_SEP:
3263 break;
3265 return false;
3268 /***************************************************************************
3269 Display the contents of the global structure.
3270 ***************************************************************************/
3272 static void dump_globals(FILE *f)
3274 int i;
3275 struct parmlist_entry *data;
3277 fprintf(f, "[global]\n");
3279 for (i = 0; parm_table[i].label; i++)
3280 if (parm_table[i].p_class == P_GLOBAL &&
3281 !(parm_table[i].flags & FLAG_META) &&
3282 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3283 if (defaults_saved && is_default(i))
3284 continue;
3285 fprintf(f, "\t%s = ", parm_table[i].label);
3286 lpcfg_print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3287 &parm_table[i]),
3289 fprintf(f, "\n");
3291 if (Globals.param_opt != NULL) {
3292 data = Globals.param_opt;
3293 while(data) {
3294 fprintf(f, "\t%s = %s\n", data->key, data->value);
3295 data = data->next;
3301 /***************************************************************************
3302 Display the contents of a single services record.
3303 ***************************************************************************/
3305 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3307 int i;
3308 struct parmlist_entry *data;
3310 if (pService != &sDefault)
3311 fprintf(f, "[%s]\n", pService->szService);
3313 for (i = 0; parm_table[i].label; i++) {
3315 if (parm_table[i].p_class == P_LOCAL &&
3316 !(parm_table[i].flags & FLAG_META) &&
3317 (*parm_table[i].label != '-') &&
3318 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3320 if (pService == &sDefault) {
3321 if (defaults_saved && is_default(i))
3322 continue;
3323 } else {
3324 if (lpcfg_equal_parameter(parm_table[i].type,
3325 lp_parm_ptr(pService, &parm_table[i]),
3326 lp_parm_ptr(NULL, &parm_table[i])))
3327 continue;
3330 fprintf(f, "\t%s = ", parm_table[i].label);
3331 lpcfg_print_parameter(&parm_table[i],
3332 lp_parm_ptr(pService, &parm_table[i]),
3334 fprintf(f, "\n");
3338 if (pService->param_opt != NULL) {
3339 data = pService->param_opt;
3340 while(data) {
3341 fprintf(f, "\t%s = %s\n", data->key, data->value);
3342 data = data->next;
3347 /***************************************************************************
3348 Display the contents of a parameter of a single services record.
3349 ***************************************************************************/
3351 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3353 bool result = false;
3354 fstring local_parm_name;
3355 char *parm_opt;
3356 const char *parm_opt_value;
3358 struct loadparm_context *lp_ctx;
3360 /* check for parametrical option */
3361 fstrcpy( local_parm_name, parm_name);
3362 parm_opt = strchr( local_parm_name, ':');
3364 if (parm_opt) {
3365 *parm_opt = '\0';
3366 parm_opt++;
3367 if (strlen(parm_opt)) {
3368 parm_opt_value = lp_parm_const_string( snum,
3369 local_parm_name, parm_opt, NULL);
3370 if (parm_opt_value) {
3371 printf( "%s\n", parm_opt_value);
3372 result = true;
3375 return result;
3378 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
3379 if (lp_ctx == NULL) {
3380 return false;
3383 if (isGlobal) {
3384 result = lpcfg_dump_a_parameter(lp_ctx, NULL, parm_name, f);
3385 } else {
3386 result = lpcfg_dump_a_parameter(lp_ctx, ServicePtrs[snum], parm_name, f);
3388 TALLOC_FREE(lp_ctx);
3389 return result;
3392 /***************************************************************************
3393 Return info about the requested parameter (given as a string).
3394 Return NULL when the string is not a valid parameter name.
3395 ***************************************************************************/
3397 struct parm_struct *lp_get_parameter(const char *param_name)
3399 int num = lpcfg_map_parameter(param_name);
3401 if (num < 0) {
3402 return NULL;
3405 return &parm_table[num];
3408 #if 0
3409 /***************************************************************************
3410 Display the contents of a single copy structure.
3411 ***************************************************************************/
3412 static void dump_copy_map(bool *pcopymap)
3414 int i;
3415 if (!pcopymap)
3416 return;
3418 printf("\n\tNon-Copied parameters:\n");
3420 for (i = 0; parm_table[i].label; i++)
3421 if (parm_table[i].p_class == P_LOCAL &&
3422 parm_table[i].ptr && !pcopymap[i] &&
3423 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3425 printf("\t\t%s\n", parm_table[i].label);
3428 #endif
3430 /***************************************************************************
3431 Return TRUE if the passed service number is within range.
3432 ***************************************************************************/
3434 bool lp_snum_ok(int iService)
3436 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3439 /***************************************************************************
3440 Auto-load some home services.
3441 ***************************************************************************/
3443 static void lp_add_auto_services(char *str)
3445 char *s;
3446 char *p;
3447 int homes;
3448 char *saveptr;
3450 if (!str)
3451 return;
3453 s = talloc_strdup(talloc_tos(), str);
3454 if (!s) {
3455 smb_panic("talloc_strdup failed");
3456 return;
3459 homes = lp_servicenumber(HOMES_NAME);
3461 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3462 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3463 char *home;
3465 if (lp_servicenumber(p) >= 0)
3466 continue;
3468 home = get_user_home_dir(talloc_tos(), p);
3470 if (home && home[0] && homes >= 0)
3471 lp_add_home(p, homes, p, home);
3473 TALLOC_FREE(home);
3475 TALLOC_FREE(s);
3478 /***************************************************************************
3479 Auto-load one printer.
3480 ***************************************************************************/
3482 void lp_add_one_printer(const char *name, const char *comment,
3483 const char *location, void *pdata)
3485 int printers = lp_servicenumber(PRINTERS_NAME);
3486 int i;
3488 if (lp_servicenumber(name) < 0) {
3489 lp_add_printer(name, printers);
3490 if ((i = lp_servicenumber(name)) >= 0) {
3491 string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
3492 ServicePtrs[i]->autoloaded = true;
3497 /***************************************************************************
3498 Have we loaded a services file yet?
3499 ***************************************************************************/
3501 bool lp_loaded(void)
3503 return (bLoaded);
3506 /***************************************************************************
3507 Unload unused services.
3508 ***************************************************************************/
3510 void lp_killunused(struct smbd_server_connection *sconn,
3511 bool (*snumused) (struct smbd_server_connection *, int))
3513 int i;
3514 for (i = 0; i < iNumServices; i++) {
3515 if (!VALID(i))
3516 continue;
3518 /* don't kill autoloaded or usershare services */
3519 if ( ServicePtrs[i]->autoloaded ||
3520 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3521 continue;
3524 if (!snumused || !snumused(sconn, i)) {
3525 free_service_byindex(i);
3531 * Kill all except autoloaded and usershare services - convenience wrapper
3533 void lp_kill_all_services(void)
3535 lp_killunused(NULL, NULL);
3538 /***************************************************************************
3539 Unload a service.
3540 ***************************************************************************/
3542 void lp_killservice(int iServiceIn)
3544 if (VALID(iServiceIn)) {
3545 free_service_byindex(iServiceIn);
3549 /***************************************************************************
3550 Save the curent values of all global and sDefault parameters into the
3551 defaults union. This allows testparm to show only the
3552 changed (ie. non-default) parameters.
3553 ***************************************************************************/
3555 static void lp_save_defaults(void)
3557 int i;
3558 for (i = 0; parm_table[i].label; i++) {
3559 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3560 && parm_table[i].p_class == parm_table[i - 1].p_class)
3561 continue;
3562 switch (parm_table[i].type) {
3563 case P_LIST:
3564 case P_CMDLIST:
3565 parm_table[i].def.lvalue = str_list_copy(
3566 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3567 break;
3568 case P_STRING:
3569 case P_USTRING:
3570 parm_table[i].def.svalue = talloc_strdup(Globals.ctx, *(char **)lp_parm_ptr(NULL, &parm_table[i]));
3571 if (parm_table[i].def.svalue == NULL) {
3572 smb_panic("talloc_strdup failed");
3574 break;
3575 case P_BOOL:
3576 case P_BOOLREV:
3577 parm_table[i].def.bvalue =
3578 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3579 break;
3580 case P_CHAR:
3581 parm_table[i].def.cvalue =
3582 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3583 break;
3584 case P_INTEGER:
3585 case P_OCTAL:
3586 case P_ENUM:
3587 case P_BYTES:
3588 parm_table[i].def.ivalue =
3589 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3590 break;
3591 case P_SEP:
3592 break;
3595 defaults_saved = true;
3598 /***********************************************************
3599 If we should send plaintext/LANMAN passwords in the clinet
3600 ************************************************************/
3602 static void set_allowed_client_auth(void)
3604 if (Globals.client_ntlmv2_auth) {
3605 Globals.client_lanman_auth = false;
3607 if (!Globals.client_lanman_auth) {
3608 Globals.client_plaintext_auth = false;
3612 /***************************************************************************
3613 JRA.
3614 The following code allows smbd to read a user defined share file.
3615 Yes, this is my intent. Yes, I'm comfortable with that...
3617 THE FOLLOWING IS SECURITY CRITICAL CODE.
3619 It washes your clothes, it cleans your house, it guards you while you sleep...
3620 Do not f%^k with it....
3621 ***************************************************************************/
3623 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3625 /***************************************************************************
3626 Check allowed stat state of a usershare file.
3627 Ensure we print out who is dicking with us so the admin can
3628 get their sorry ass fired.
3629 ***************************************************************************/
3631 static bool check_usershare_stat(const char *fname,
3632 const SMB_STRUCT_STAT *psbuf)
3634 if (!S_ISREG(psbuf->st_ex_mode)) {
3635 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3636 "not a regular file\n",
3637 fname, (unsigned int)psbuf->st_ex_uid ));
3638 return false;
3641 /* Ensure this doesn't have the other write bit set. */
3642 if (psbuf->st_ex_mode & S_IWOTH) {
3643 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
3644 "public write. Refusing to allow as a usershare file.\n",
3645 fname, (unsigned int)psbuf->st_ex_uid ));
3646 return false;
3649 /* Should be 10k or less. */
3650 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
3651 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3652 "too large (%u) to be a user share file.\n",
3653 fname, (unsigned int)psbuf->st_ex_uid,
3654 (unsigned int)psbuf->st_ex_size ));
3655 return false;
3658 return true;
3661 /***************************************************************************
3662 Parse the contents of a usershare file.
3663 ***************************************************************************/
3665 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
3666 SMB_STRUCT_STAT *psbuf,
3667 const char *servicename,
3668 int snum,
3669 char **lines,
3670 int numlines,
3671 char **pp_sharepath,
3672 char **pp_comment,
3673 char **pp_cp_servicename,
3674 struct security_descriptor **ppsd,
3675 bool *pallow_guest)
3677 const char **prefixallowlist = lp_usershare_prefix_allow_list();
3678 const char **prefixdenylist = lp_usershare_prefix_deny_list();
3679 int us_vers;
3680 DIR *dp;
3681 SMB_STRUCT_STAT sbuf;
3682 char *sharepath = NULL;
3683 char *comment = NULL;
3685 *pp_sharepath = NULL;
3686 *pp_comment = NULL;
3688 *pallow_guest = false;
3690 if (numlines < 4) {
3691 return USERSHARE_MALFORMED_FILE;
3694 if (strcmp(lines[0], "#VERSION 1") == 0) {
3695 us_vers = 1;
3696 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
3697 us_vers = 2;
3698 if (numlines < 5) {
3699 return USERSHARE_MALFORMED_FILE;
3701 } else {
3702 return USERSHARE_BAD_VERSION;
3705 if (strncmp(lines[1], "path=", 5) != 0) {
3706 return USERSHARE_MALFORMED_PATH;
3709 sharepath = talloc_strdup(ctx, &lines[1][5]);
3710 if (!sharepath) {
3711 return USERSHARE_POSIX_ERR;
3713 trim_string(sharepath, " ", " ");
3715 if (strncmp(lines[2], "comment=", 8) != 0) {
3716 return USERSHARE_MALFORMED_COMMENT_DEF;
3719 comment = talloc_strdup(ctx, &lines[2][8]);
3720 if (!comment) {
3721 return USERSHARE_POSIX_ERR;
3723 trim_string(comment, " ", " ");
3724 trim_char(comment, '"', '"');
3726 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
3727 return USERSHARE_MALFORMED_ACL_DEF;
3730 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
3731 return USERSHARE_ACL_ERR;
3734 if (us_vers == 2) {
3735 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
3736 return USERSHARE_MALFORMED_ACL_DEF;
3738 if (lines[4][9] == 'y') {
3739 *pallow_guest = true;
3742 /* Backwards compatible extension to file version #2. */
3743 if (numlines > 5) {
3744 if (strncmp(lines[5], "sharename=", 10) != 0) {
3745 return USERSHARE_MALFORMED_SHARENAME_DEF;
3747 if (!strequal(&lines[5][10], servicename)) {
3748 return USERSHARE_BAD_SHARENAME;
3750 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
3751 if (!*pp_cp_servicename) {
3752 return USERSHARE_POSIX_ERR;
3757 if (*pp_cp_servicename == NULL) {
3758 *pp_cp_servicename = talloc_strdup(ctx, servicename);
3759 if (!*pp_cp_servicename) {
3760 return USERSHARE_POSIX_ERR;
3764 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->path) == 0)) {
3765 /* Path didn't change, no checks needed. */
3766 *pp_sharepath = sharepath;
3767 *pp_comment = comment;
3768 return USERSHARE_OK;
3771 /* The path *must* be absolute. */
3772 if (sharepath[0] != '/') {
3773 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
3774 servicename, sharepath));
3775 return USERSHARE_PATH_NOT_ABSOLUTE;
3778 /* If there is a usershare prefix deny list ensure one of these paths
3779 doesn't match the start of the user given path. */
3780 if (prefixdenylist) {
3781 int i;
3782 for ( i=0; prefixdenylist[i]; i++ ) {
3783 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
3784 servicename, i, prefixdenylist[i], sharepath ));
3785 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
3786 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
3787 "usershare prefix deny list entries.\n",
3788 servicename, sharepath));
3789 return USERSHARE_PATH_IS_DENIED;
3794 /* If there is a usershare prefix allow list ensure one of these paths
3795 does match the start of the user given path. */
3797 if (prefixallowlist) {
3798 int i;
3799 for ( i=0; prefixallowlist[i]; i++ ) {
3800 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
3801 servicename, i, prefixallowlist[i], sharepath ));
3802 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
3803 break;
3806 if (prefixallowlist[i] == NULL) {
3807 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
3808 "usershare prefix allow list entries.\n",
3809 servicename, sharepath));
3810 return USERSHARE_PATH_NOT_ALLOWED;
3814 /* Ensure this is pointing to a directory. */
3815 dp = opendir(sharepath);
3817 if (!dp) {
3818 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3819 servicename, sharepath));
3820 return USERSHARE_PATH_NOT_DIRECTORY;
3823 /* Ensure the owner of the usershare file has permission to share
3824 this directory. */
3826 if (sys_stat(sharepath, &sbuf, false) == -1) {
3827 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
3828 servicename, sharepath, strerror(errno) ));
3829 closedir(dp);
3830 return USERSHARE_POSIX_ERR;
3833 closedir(dp);
3835 if (!S_ISDIR(sbuf.st_ex_mode)) {
3836 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3837 servicename, sharepath ));
3838 return USERSHARE_PATH_NOT_DIRECTORY;
3841 /* Check if sharing is restricted to owner-only. */
3842 /* psbuf is the stat of the usershare definition file,
3843 sbuf is the stat of the target directory to be shared. */
3845 if (lp_usershare_owner_only()) {
3846 /* root can share anything. */
3847 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
3848 return USERSHARE_PATH_NOT_ALLOWED;
3852 *pp_sharepath = sharepath;
3853 *pp_comment = comment;
3854 return USERSHARE_OK;
3857 /***************************************************************************
3858 Deal with a usershare file.
3859 Returns:
3860 >= 0 - snum
3861 -1 - Bad name, invalid contents.
3862 - service name already existed and not a usershare, problem
3863 with permissions to share directory etc.
3864 ***************************************************************************/
3866 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
3868 SMB_STRUCT_STAT sbuf;
3869 SMB_STRUCT_STAT lsbuf;
3870 char *fname = NULL;
3871 char *sharepath = NULL;
3872 char *comment = NULL;
3873 char *cp_service_name = NULL;
3874 char **lines = NULL;
3875 int numlines = 0;
3876 int fd = -1;
3877 int iService = -1;
3878 TALLOC_CTX *ctx = talloc_stackframe();
3879 struct security_descriptor *psd = NULL;
3880 bool guest_ok = false;
3881 char *canon_name = NULL;
3882 bool added_service = false;
3883 int ret = -1;
3885 /* Ensure share name doesn't contain invalid characters. */
3886 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
3887 DEBUG(0,("process_usershare_file: share name %s contains "
3888 "invalid characters (any of %s)\n",
3889 file_name, INVALID_SHARENAME_CHARS ));
3890 goto out;
3893 canon_name = canonicalize_servicename(ctx, file_name);
3894 if (!canon_name) {
3895 goto out;
3898 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
3899 if (!fname) {
3900 goto out;
3903 /* Minimize the race condition by doing an lstat before we
3904 open and fstat. Ensure this isn't a symlink link. */
3906 if (sys_lstat(fname, &lsbuf, false) != 0) {
3907 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
3908 fname, strerror(errno) ));
3909 goto out;
3912 /* This must be a regular file, not a symlink, directory or
3913 other strange filetype. */
3914 if (!check_usershare_stat(fname, &lsbuf)) {
3915 goto out;
3919 TDB_DATA data;
3920 NTSTATUS status;
3922 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
3923 canon_name, &data);
3925 iService = -1;
3927 if (NT_STATUS_IS_OK(status) &&
3928 (data.dptr != NULL) &&
3929 (data.dsize == sizeof(iService))) {
3930 memcpy(&iService, data.dptr, sizeof(iService));
3934 if (iService != -1 &&
3935 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
3936 &lsbuf.st_ex_mtime) == 0) {
3937 /* Nothing changed - Mark valid and return. */
3938 DEBUG(10,("process_usershare_file: service %s not changed.\n",
3939 canon_name ));
3940 ServicePtrs[iService]->usershare = USERSHARE_VALID;
3941 ret = iService;
3942 goto out;
3945 /* Try and open the file read only - no symlinks allowed. */
3946 #ifdef O_NOFOLLOW
3947 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
3948 #else
3949 fd = open(fname, O_RDONLY, 0);
3950 #endif
3952 if (fd == -1) {
3953 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
3954 fname, strerror(errno) ));
3955 goto out;
3958 /* Now fstat to be *SURE* it's a regular file. */
3959 if (sys_fstat(fd, &sbuf, false) != 0) {
3960 close(fd);
3961 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
3962 fname, strerror(errno) ));
3963 goto out;
3966 /* Is it the same dev/inode as was lstated ? */
3967 if (!check_same_stat(&lsbuf, &sbuf)) {
3968 close(fd);
3969 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
3970 "Symlink spoofing going on ?\n", fname ));
3971 goto out;
3974 /* This must be a regular file, not a symlink, directory or
3975 other strange filetype. */
3976 if (!check_usershare_stat(fname, &sbuf)) {
3977 close(fd);
3978 goto out;
3981 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
3983 close(fd);
3984 if (lines == NULL) {
3985 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
3986 fname, (unsigned int)sbuf.st_ex_uid ));
3987 goto out;
3990 if (parse_usershare_file(ctx, &sbuf, file_name,
3991 iService, lines, numlines, &sharepath,
3992 &comment, &cp_service_name,
3993 &psd, &guest_ok) != USERSHARE_OK) {
3994 goto out;
3997 /* Everything ok - add the service possibly using a template. */
3998 if (iService < 0) {
3999 const struct loadparm_service *sp = &sDefault;
4000 if (snum_template != -1) {
4001 sp = ServicePtrs[snum_template];
4004 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4005 DEBUG(0, ("process_usershare_file: Failed to add "
4006 "new service %s\n", cp_service_name));
4007 goto out;
4010 added_service = true;
4012 /* Read only is controlled by usershare ACL below. */
4013 ServicePtrs[iService]->read_only = false;
4016 /* Write the ACL of the new/modified share. */
4017 if (!set_share_security(canon_name, psd)) {
4018 DEBUG(0, ("process_usershare_file: Failed to set share "
4019 "security for user share %s\n",
4020 canon_name ));
4021 goto out;
4024 /* If from a template it may be marked invalid. */
4025 ServicePtrs[iService]->valid = true;
4027 /* Set the service as a valid usershare. */
4028 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4030 /* Set guest access. */
4031 if (lp_usershare_allow_guests()) {
4032 ServicePtrs[iService]->guest_ok = guest_ok;
4035 /* And note when it was loaded. */
4036 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4037 string_set(ServicePtrs[iService], &ServicePtrs[iService]->path, sharepath);
4038 string_set(ServicePtrs[iService], &ServicePtrs[iService]->comment, comment);
4040 ret = iService;
4042 out:
4044 if (ret == -1 && iService != -1 && added_service) {
4045 lp_remove_service(iService);
4048 TALLOC_FREE(lines);
4049 TALLOC_FREE(ctx);
4050 return ret;
4053 /***************************************************************************
4054 Checks if a usershare entry has been modified since last load.
4055 ***************************************************************************/
4057 static bool usershare_exists(int iService, struct timespec *last_mod)
4059 SMB_STRUCT_STAT lsbuf;
4060 const char *usersharepath = Globals.usershare_path;
4061 char *fname;
4063 fname = talloc_asprintf(talloc_tos(),
4064 "%s/%s",
4065 usersharepath,
4066 ServicePtrs[iService]->szService);
4067 if (fname == NULL) {
4068 return false;
4071 if (sys_lstat(fname, &lsbuf, false) != 0) {
4072 TALLOC_FREE(fname);
4073 return false;
4076 if (!S_ISREG(lsbuf.st_ex_mode)) {
4077 TALLOC_FREE(fname);
4078 return false;
4081 TALLOC_FREE(fname);
4082 *last_mod = lsbuf.st_ex_mtime;
4083 return true;
4086 /***************************************************************************
4087 Load a usershare service by name. Returns a valid servicenumber or -1.
4088 ***************************************************************************/
4090 int load_usershare_service(const char *servicename)
4092 SMB_STRUCT_STAT sbuf;
4093 const char *usersharepath = Globals.usershare_path;
4094 int max_user_shares = Globals.usershare_max_shares;
4095 int snum_template = -1;
4097 if (*usersharepath == 0 || max_user_shares == 0) {
4098 return -1;
4101 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4102 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4103 usersharepath, strerror(errno) ));
4104 return -1;
4107 if (!S_ISDIR(sbuf.st_ex_mode)) {
4108 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4109 usersharepath ));
4110 return -1;
4114 * This directory must be owned by root, and have the 't' bit set.
4115 * It also must not be writable by "other".
4118 #ifdef S_ISVTX
4119 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4120 #else
4121 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4122 #endif
4123 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4124 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4125 usersharepath ));
4126 return -1;
4129 /* Ensure the template share exists if it's set. */
4130 if (Globals.usershare_template_share[0]) {
4131 /* We can't use lp_servicenumber here as we are recommending that
4132 template shares have -valid=false set. */
4133 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4134 if (ServicePtrs[snum_template]->szService &&
4135 strequal(ServicePtrs[snum_template]->szService,
4136 Globals.usershare_template_share)) {
4137 break;
4141 if (snum_template == -1) {
4142 DEBUG(0,("load_usershare_service: usershare template share %s "
4143 "does not exist.\n",
4144 Globals.usershare_template_share ));
4145 return -1;
4149 return process_usershare_file(usersharepath, servicename, snum_template);
4152 /***************************************************************************
4153 Load all user defined shares from the user share directory.
4154 We only do this if we're enumerating the share list.
4155 This is the function that can delete usershares that have
4156 been removed.
4157 ***************************************************************************/
4159 int load_usershare_shares(struct smbd_server_connection *sconn,
4160 bool (*snumused) (struct smbd_server_connection *, int))
4162 DIR *dp;
4163 SMB_STRUCT_STAT sbuf;
4164 struct dirent *de;
4165 int num_usershares = 0;
4166 int max_user_shares = Globals.usershare_max_shares;
4167 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4168 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4169 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4170 int iService;
4171 int snum_template = -1;
4172 const char *usersharepath = Globals.usershare_path;
4173 int ret = lp_numservices();
4174 TALLOC_CTX *tmp_ctx;
4176 if (max_user_shares == 0 || *usersharepath == '\0') {
4177 return lp_numservices();
4180 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4181 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4182 usersharepath, strerror(errno) ));
4183 return ret;
4187 * This directory must be owned by root, and have the 't' bit set.
4188 * It also must not be writable by "other".
4191 #ifdef S_ISVTX
4192 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4193 #else
4194 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4195 #endif
4196 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4197 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4198 usersharepath ));
4199 return ret;
4202 /* Ensure the template share exists if it's set. */
4203 if (Globals.usershare_template_share[0]) {
4204 /* We can't use lp_servicenumber here as we are recommending that
4205 template shares have -valid=false set. */
4206 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4207 if (ServicePtrs[snum_template]->szService &&
4208 strequal(ServicePtrs[snum_template]->szService,
4209 Globals.usershare_template_share)) {
4210 break;
4214 if (snum_template == -1) {
4215 DEBUG(0,("load_usershare_shares: usershare template share %s "
4216 "does not exist.\n",
4217 Globals.usershare_template_share ));
4218 return ret;
4222 /* Mark all existing usershares as pending delete. */
4223 for (iService = iNumServices - 1; iService >= 0; iService--) {
4224 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4225 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4229 dp = opendir(usersharepath);
4230 if (!dp) {
4231 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4232 usersharepath, strerror(errno) ));
4233 return ret;
4236 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4237 (de = readdir(dp));
4238 num_dir_entries++ ) {
4239 int r;
4240 const char *n = de->d_name;
4242 /* Ignore . and .. */
4243 if (*n == '.') {
4244 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4245 continue;
4249 if (n[0] == ':') {
4250 /* Temporary file used when creating a share. */
4251 num_tmp_dir_entries++;
4254 /* Allow 20% tmp entries. */
4255 if (num_tmp_dir_entries > allowed_tmp_entries) {
4256 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4257 "in directory %s\n",
4258 num_tmp_dir_entries, usersharepath));
4259 break;
4262 r = process_usershare_file(usersharepath, n, snum_template);
4263 if (r == 0) {
4264 /* Update the services count. */
4265 num_usershares++;
4266 if (num_usershares >= max_user_shares) {
4267 DEBUG(0,("load_usershare_shares: max user shares reached "
4268 "on file %s in directory %s\n",
4269 n, usersharepath ));
4270 break;
4272 } else if (r == -1) {
4273 num_bad_dir_entries++;
4276 /* Allow 20% bad entries. */
4277 if (num_bad_dir_entries > allowed_bad_entries) {
4278 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4279 "in directory %s\n",
4280 num_bad_dir_entries, usersharepath));
4281 break;
4284 /* Allow 20% bad entries. */
4285 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4286 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4287 "in directory %s\n",
4288 num_dir_entries, usersharepath));
4289 break;
4293 closedir(dp);
4295 /* Sweep through and delete any non-refreshed usershares that are
4296 not currently in use. */
4297 tmp_ctx = talloc_stackframe();
4298 for (iService = iNumServices - 1; iService >= 0; iService--) {
4299 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4300 char *servname;
4302 if (snumused && snumused(sconn, iService)) {
4303 continue;
4306 servname = lp_servicename(tmp_ctx, iService);
4308 /* Remove from the share ACL db. */
4309 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4310 servname ));
4311 delete_share_security(servname);
4312 free_service_byindex(iService);
4315 talloc_free(tmp_ctx);
4317 return lp_numservices();
4320 /********************************************************
4321 Destroy global resources allocated in this file
4322 ********************************************************/
4324 void gfree_loadparm(void)
4326 int i;
4328 free_file_list();
4330 /* Free resources allocated to services */
4332 for ( i = 0; i < iNumServices; i++ ) {
4333 if ( VALID(i) ) {
4334 free_service_byindex(i);
4338 TALLOC_FREE( ServicePtrs );
4339 iNumServices = 0;
4341 /* Now release all resources allocated to global
4342 parameters and the default service */
4344 free_global_parameters();
4348 /***************************************************************************
4349 Allow client apps to specify that they are a client
4350 ***************************************************************************/
4351 static void lp_set_in_client(bool b)
4353 in_client = b;
4357 /***************************************************************************
4358 Determine if we're running in a client app
4359 ***************************************************************************/
4360 static bool lp_is_in_client(void)
4362 return in_client;
4365 /***************************************************************************
4366 Load the services array from the services file. Return true on success,
4367 false on failure.
4368 ***************************************************************************/
4370 static bool lp_load_ex(const char *pszFname,
4371 bool global_only,
4372 bool save_defaults,
4373 bool add_ipc,
4374 bool initialize_globals,
4375 bool allow_include_registry,
4376 bool load_all_shares)
4378 char *n2 = NULL;
4379 bool bRetval;
4381 bRetval = false;
4383 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4385 bInGlobalSection = true;
4386 bGlobalOnly = global_only;
4387 bAllowIncludeRegistry = allow_include_registry;
4389 init_globals(initialize_globals);
4391 free_file_list();
4393 if (save_defaults) {
4394 init_locals();
4395 lp_save_defaults();
4398 if (!initialize_globals) {
4399 free_param_opts(&Globals.param_opt);
4400 apply_lp_set_cmdline();
4403 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4405 /* We get sections first, so have to start 'behind' to make up */
4406 iServiceIndex = -1;
4408 if (lp_config_backend_is_file()) {
4409 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4410 current_user_info.domain,
4411 pszFname);
4412 if (!n2) {
4413 smb_panic("lp_load_ex: out of memory");
4416 add_to_file_list(pszFname, n2);
4418 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4419 TALLOC_FREE(n2);
4421 /* finish up the last section */
4422 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4423 if (bRetval) {
4424 if (iServiceIndex >= 0) {
4425 bRetval = service_ok(iServiceIndex);
4429 if (lp_config_backend_is_registry()) {
4430 /* config backend changed to registry in config file */
4432 * We need to use this extra global variable here to
4433 * survive restart: init_globals uses this as a default
4434 * for config_backend. Otherwise, init_globals would
4435 * send us into an endless loop here.
4437 config_backend = CONFIG_BACKEND_REGISTRY;
4438 /* start over */
4439 DEBUG(1, ("lp_load_ex: changing to config backend "
4440 "registry\n"));
4441 init_globals(true);
4442 lp_kill_all_services();
4443 return lp_load_ex(pszFname, global_only, save_defaults,
4444 add_ipc, initialize_globals,
4445 allow_include_registry,
4446 load_all_shares);
4448 } else if (lp_config_backend_is_registry()) {
4449 bRetval = process_registry_globals();
4450 } else {
4451 DEBUG(0, ("Illegal config backend given: %d\n",
4452 lp_config_backend()));
4453 bRetval = false;
4456 if (bRetval && lp_registry_shares()) {
4457 if (load_all_shares) {
4458 bRetval = process_registry_shares();
4459 } else {
4460 bRetval = reload_registry_shares();
4465 char *serv = lp_auto_services(talloc_tos());
4466 lp_add_auto_services(serv);
4467 TALLOC_FREE(serv);
4470 if (add_ipc) {
4471 /* When 'restrict anonymous = 2' guest connections to ipc$
4472 are denied */
4473 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4474 if ( lp_enable_asu_support() ) {
4475 lp_add_ipc("ADMIN$", false);
4479 set_allowed_client_auth();
4481 if (lp_security() == SEC_ADS && strchr(lp_password_server(), ':')) {
4482 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4483 lp_password_server()));
4486 bLoaded = true;
4488 /* Now we check we_are_a_wins_server and set szWINSserver to 127.0.0.1 */
4489 /* if we_are_a_wins_server is true and we are in the client */
4490 if (lp_is_in_client() && Globals.we_are_a_wins_server) {
4491 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4494 init_iconv();
4496 fault_configure(smb_panic_s3);
4499 * We run this check once the whole smb.conf is parsed, to
4500 * force some settings for the standard way a AD DC is
4501 * operated. We may changed these as our code evolves, which
4502 * is why we force these settings.
4504 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4505 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4507 lp_do_parameter(-1, "rpc_server:default", "external");
4508 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4509 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4510 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4511 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4512 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4513 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4514 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4515 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4518 bAllowIncludeRegistry = true;
4520 return (bRetval);
4523 bool lp_load(const char *pszFname,
4524 bool global_only,
4525 bool save_defaults,
4526 bool add_ipc,
4527 bool initialize_globals)
4529 return lp_load_ex(pszFname,
4530 global_only,
4531 save_defaults,
4532 add_ipc,
4533 initialize_globals,
4534 true, /* allow_include_registry */
4535 false); /* load_all_shares*/
4538 bool lp_load_initial_only(const char *pszFname)
4540 return lp_load_ex(pszFname,
4541 true, /* global only */
4542 false, /* save_defaults */
4543 false, /* add_ipc */
4544 true, /* initialize_globals */
4545 false, /* allow_include_registry */
4546 false); /* load_all_shares*/
4550 * most common lp_load wrapper, loading only the globals
4552 bool lp_load_global(const char *file_name)
4554 return lp_load_ex(file_name,
4555 true, /* global_only */
4556 false, /* save_defaults */
4557 false, /* add_ipc */
4558 true, /* initialize_globals */
4559 true, /* allow_include_registry */
4560 false); /* load_all_shares*/
4564 * lp_load wrapper, especially for clients
4566 bool lp_load_client(const char *file_name)
4568 lp_set_in_client(true);
4570 return lp_load_global(file_name);
4574 * lp_load wrapper, loading only globals, but intended
4575 * for subsequent calls, not reinitializing the globals
4576 * to default values
4578 bool lp_load_global_no_reinit(const char *file_name)
4580 return lp_load_ex(file_name,
4581 true, /* global_only */
4582 false, /* save_defaults */
4583 false, /* add_ipc */
4584 false, /* initialize_globals */
4585 true, /* allow_include_registry */
4586 false); /* load_all_shares*/
4590 * lp_load wrapper, especially for clients, no reinitialization
4592 bool lp_load_client_no_reinit(const char *file_name)
4594 lp_set_in_client(true);
4596 return lp_load_global_no_reinit(file_name);
4599 bool lp_load_with_registry_shares(const char *pszFname,
4600 bool global_only,
4601 bool save_defaults,
4602 bool add_ipc,
4603 bool initialize_globals)
4605 return lp_load_ex(pszFname,
4606 global_only,
4607 save_defaults,
4608 add_ipc,
4609 initialize_globals,
4610 true, /* allow_include_registry */
4611 true); /* load_all_shares*/
4614 /***************************************************************************
4615 Return the max number of services.
4616 ***************************************************************************/
4618 int lp_numservices(void)
4620 return (iNumServices);
4623 /***************************************************************************
4624 Display the contents of the services array in human-readable form.
4625 ***************************************************************************/
4627 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4629 int iService;
4631 if (show_defaults)
4632 defaults_saved = false;
4634 dump_globals(f);
4636 dump_a_service(&sDefault, f);
4638 for (iService = 0; iService < maxtoprint; iService++) {
4639 fprintf(f,"\n");
4640 lp_dump_one(f, show_defaults, iService);
4644 /***************************************************************************
4645 Display the contents of one service in human-readable form.
4646 ***************************************************************************/
4648 void lp_dump_one(FILE * f, bool show_defaults, int snum)
4650 if (VALID(snum)) {
4651 if (ServicePtrs[snum]->szService[0] == '\0')
4652 return;
4653 dump_a_service(ServicePtrs[snum], f);
4657 /***************************************************************************
4658 Return the number of the service with the given name, or -1 if it doesn't
4659 exist. Note that this is a DIFFERENT ANIMAL from the internal function
4660 getservicebyname()! This works ONLY if all services have been loaded, and
4661 does not copy the found service.
4662 ***************************************************************************/
4664 int lp_servicenumber(const char *pszServiceName)
4666 int iService;
4667 fstring serviceName;
4669 if (!pszServiceName) {
4670 return GLOBAL_SECTION_SNUM;
4673 for (iService = iNumServices - 1; iService >= 0; iService--) {
4674 if (VALID(iService) && ServicePtrs[iService]->szService) {
4676 * The substitution here is used to support %U is
4677 * service names
4679 fstrcpy(serviceName, ServicePtrs[iService]->szService);
4680 standard_sub_basic(get_current_username(),
4681 current_user_info.domain,
4682 serviceName,sizeof(serviceName));
4683 if (strequal(serviceName, pszServiceName)) {
4684 break;
4689 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
4690 struct timespec last_mod;
4692 if (!usershare_exists(iService, &last_mod)) {
4693 /* Remove the share security tdb entry for it. */
4694 delete_share_security(lp_servicename(talloc_tos(), iService));
4695 /* Remove it from the array. */
4696 free_service_byindex(iService);
4697 /* Doesn't exist anymore. */
4698 return GLOBAL_SECTION_SNUM;
4701 /* Has it been modified ? If so delete and reload. */
4702 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4703 &last_mod) < 0) {
4704 /* Remove it from the array. */
4705 free_service_byindex(iService);
4706 /* and now reload it. */
4707 iService = load_usershare_service(pszServiceName);
4711 if (iService < 0) {
4712 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
4713 return GLOBAL_SECTION_SNUM;
4716 return (iService);
4719 /*******************************************************************
4720 A useful volume label function.
4721 ********************************************************************/
4723 const char *volume_label(TALLOC_CTX *ctx, int snum)
4725 char *ret;
4726 const char *label = lp_volume(ctx, snum);
4727 if (!*label) {
4728 label = lp_servicename(ctx, snum);
4731 /* This returns a 33 byte guarenteed null terminated string. */
4732 ret = talloc_strndup(ctx, label, 32);
4733 if (!ret) {
4734 return "";
4736 return ret;
4739 /*******************************************************************
4740 Get the default server type we will announce as via nmbd.
4741 ********************************************************************/
4743 int lp_default_server_announce(void)
4745 int default_server_announce = 0;
4746 default_server_announce |= SV_TYPE_WORKSTATION;
4747 default_server_announce |= SV_TYPE_SERVER;
4748 default_server_announce |= SV_TYPE_SERVER_UNIX;
4750 /* note that the flag should be set only if we have a
4751 printer service but nmbd doesn't actually load the
4752 services so we can't tell --jerry */
4754 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
4756 default_server_announce |= SV_TYPE_SERVER_NT;
4757 default_server_announce |= SV_TYPE_NT;
4759 switch (lp_server_role()) {
4760 case ROLE_DOMAIN_MEMBER:
4761 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
4762 break;
4763 case ROLE_DOMAIN_PDC:
4764 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
4765 break;
4766 case ROLE_DOMAIN_BDC:
4767 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
4768 break;
4769 case ROLE_STANDALONE:
4770 default:
4771 break;
4773 if (lp_time_server())
4774 default_server_announce |= SV_TYPE_TIME_SOURCE;
4776 if (lp_host_msdfs())
4777 default_server_announce |= SV_TYPE_DFS_SERVER;
4779 return default_server_announce;
4782 /***********************************************************
4783 If we are PDC then prefer us as DMB
4784 ************************************************************/
4786 bool lp_domain_master(void)
4788 if (Globals._domain_master == Auto)
4789 return (lp_server_role() == ROLE_DOMAIN_PDC);
4791 return (bool)Globals._domain_master;
4794 /***********************************************************
4795 If we are PDC then prefer us as DMB
4796 ************************************************************/
4798 static bool lp_domain_master_true_or_auto(void)
4800 if (Globals._domain_master) /* auto or yes */
4801 return true;
4803 return false;
4806 /***********************************************************
4807 If we are DMB then prefer us as LMB
4808 ************************************************************/
4810 bool lp_preferred_master(void)
4812 if (Globals.iPreferredMaster == Auto)
4813 return (lp_local_master() && lp_domain_master());
4815 return (bool)Globals.iPreferredMaster;
4818 /*******************************************************************
4819 Remove a service.
4820 ********************************************************************/
4822 void lp_remove_service(int snum)
4824 ServicePtrs[snum]->valid = false;
4827 /*******************************************************************
4828 Copy a service.
4829 ********************************************************************/
4831 void lp_copy_service(int snum, const char *new_name)
4833 do_section(new_name, NULL);
4834 if (snum >= 0) {
4835 snum = lp_servicenumber(new_name);
4836 if (snum >= 0) {
4837 char *name = lp_servicename(talloc_tos(), snum);
4838 lp_do_parameter(snum, "copy", name);
4843 const char *lp_printername(TALLOC_CTX *ctx, int snum)
4845 const char *ret = lp__printername(ctx, snum);
4846 if (ret == NULL || *ret == '\0') {
4847 ret = lp_const_servicename(snum);
4850 return ret;
4854 /***********************************************************
4855 Allow daemons such as winbindd to fix their logfile name.
4856 ************************************************************/
4858 void lp_set_logfile(const char *name)
4860 string_set(Globals.ctx, &Globals.logfile, name);
4861 debug_set_logfile(name);
4864 /*******************************************************************
4865 Return the max print jobs per queue.
4866 ********************************************************************/
4868 int lp_maxprintjobs(int snum)
4870 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
4871 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
4872 maxjobs = PRINT_MAX_JOBID - 1;
4874 return maxjobs;
4877 const char *lp_printcapname(void)
4879 if ((Globals.szPrintcapname != NULL) &&
4880 (Globals.szPrintcapname[0] != '\0'))
4881 return Globals.szPrintcapname;
4883 if (sDefault.printing == PRINT_CUPS) {
4884 return "cups";
4887 if (sDefault.printing == PRINT_BSD)
4888 return "/etc/printcap";
4890 return PRINTCAP_NAME;
4893 static uint32 spoolss_state;
4895 bool lp_disable_spoolss( void )
4897 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
4898 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
4900 return spoolss_state == SVCCTL_STOPPED ? true : false;
4903 void lp_set_spoolss_state( uint32 state )
4905 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
4907 spoolss_state = state;
4910 uint32 lp_get_spoolss_state( void )
4912 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
4915 /*******************************************************************
4916 Ensure we don't use sendfile if server smb signing is active.
4917 ********************************************************************/
4919 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
4921 bool sign_active = false;
4923 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
4924 if (get_Protocol() < PROTOCOL_NT1) {
4925 return false;
4927 if (signing_state) {
4928 sign_active = smb_signing_is_active(signing_state);
4930 return (lp__use_sendfile(snum) &&
4931 (get_remote_arch() != RA_WIN95) &&
4932 !sign_active);
4935 /*******************************************************************
4936 Turn off sendfile if we find the underlying OS doesn't support it.
4937 ********************************************************************/
4939 void set_use_sendfile(int snum, bool val)
4941 if (LP_SNUM_OK(snum))
4942 ServicePtrs[snum]->_use_sendfile = val;
4943 else
4944 sDefault._use_sendfile = val;
4947 /*******************************************************************
4948 Turn off storing DOS attributes if this share doesn't support it.
4949 ********************************************************************/
4951 void set_store_dos_attributes(int snum, bool val)
4953 if (!LP_SNUM_OK(snum))
4954 return;
4955 ServicePtrs[(snum)]->store_dos_attributes = val;
4958 void lp_set_mangling_method(const char *new_method)
4960 string_set(Globals.ctx, &Globals.mangling_method, new_method);
4963 /*******************************************************************
4964 Global state for POSIX pathname processing.
4965 ********************************************************************/
4967 static bool posix_pathnames;
4969 bool lp_posix_pathnames(void)
4971 return posix_pathnames;
4974 /*******************************************************************
4975 Change everything needed to ensure POSIX pathname processing (currently
4976 not much).
4977 ********************************************************************/
4979 void lp_set_posix_pathnames(void)
4981 posix_pathnames = true;
4984 /*******************************************************************
4985 Global state for POSIX lock processing - CIFS unix extensions.
4986 ********************************************************************/
4988 bool posix_default_lock_was_set;
4989 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
4991 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
4993 if (posix_default_lock_was_set) {
4994 return posix_cifsx_locktype;
4995 } else {
4996 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5000 /*******************************************************************
5001 ********************************************************************/
5003 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5005 posix_default_lock_was_set = true;
5006 posix_cifsx_locktype = val;
5009 int lp_min_receive_file_size(void)
5011 if (Globals.iminreceivefile < 0) {
5012 return 0;
5014 return Globals.iminreceivefile;
5017 /*******************************************************************
5018 Safe wide links checks.
5019 This helper function always verify the validity of wide links,
5020 even after a configuration file reload.
5021 ********************************************************************/
5023 static bool lp_widelinks_internal(int snum)
5025 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5026 sDefault.bWidelinks);
5029 void widelinks_warning(int snum)
5031 if (lp_allow_insecure_wide_links()) {
5032 return;
5035 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5036 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5037 "These parameters are incompatible. "
5038 "Wide links will be disabled for this share.\n",
5039 lp_servicename(talloc_tos(), snum) ));
5043 bool lp_widelinks(int snum)
5045 /* wide links is always incompatible with unix extensions */
5046 if (lp_unix_extensions()) {
5048 * Unless we have "allow insecure widelinks"
5049 * turned on.
5051 if (!lp_allow_insecure_wide_links()) {
5052 return false;
5056 return lp_widelinks_internal(snum);
5059 int lp_server_role(void)
5061 return lp_find_server_role(lp__server_role(),
5062 lp__security(),
5063 lp__domain_logons(),
5064 lp_domain_master_true_or_auto());
5067 int lp_security(void)
5069 return lp_find_security(lp__server_role(),
5070 lp__security());
5073 struct loadparm_global * get_globals(void)
5075 return &Globals;