param: rename lp function and variable from "readlist" to "read_list"
[Samba/wip.git] / source3 / param / loadparm.c
blob9df05b68791a930aed3ddd895d7017cf5bcbbf46
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 #ifdef CLUSTER_SUPPORT
82 #include "ctdb_private.h"
83 #endif
85 bool bLoaded = false;
87 extern userdom_struct current_user_info;
89 /* the special value for the include parameter
90 * to be interpreted not as a file name but to
91 * trigger loading of the global smb.conf options
92 * from registry. */
93 #ifndef INCLUDE_REGISTRY_NAME
94 #define INCLUDE_REGISTRY_NAME "registry"
95 #endif
97 static bool in_client = false; /* Not in the client by default */
98 static struct smbconf_csn conf_last_csn;
100 static int config_backend = CONFIG_BACKEND_FILE;
102 /* some helpful bits */
103 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
104 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
106 #define USERSHARE_VALID 1
107 #define USERSHARE_PENDING_DELETE 2
109 static bool defaults_saved = false;
111 #define LOADPARM_EXTRA_GLOBALS \
112 struct parmlist_entry *param_opt; \
113 char *realm_original; \
114 char *loglevel; \
115 int iminreceivefile; \
116 char *szPrintcapname; \
117 int CupsEncrypt; \
118 int iPreferredMaster; \
119 char *szLdapMachineSuffix; \
120 char *szLdapUserSuffix; \
121 char *szLdapIdmapSuffix; \
122 char *szLdapGroupSuffix; \
123 char *szStateDir; \
124 char *szCacheDir; \
125 char *szUsershareTemplateShare; \
126 char *szIdmapUID; \
127 char *szIdmapGID; \
128 char *szIdmapBackend; \
129 int winbindMaxDomainConnections; \
130 int ismb2_max_credits; \
131 char *tls_keyfile; \
132 char *tls_certfile; \
133 char *tls_cafile; \
134 char *tls_crlfile; \
135 char *tls_dhpfile;
137 #include "param/param_global.h"
139 static struct loadparm_global Globals;
141 /* This is a default service used to prime a services structure */
142 static struct loadparm_service sDefault =
144 .valid = true,
145 .autoloaded = false,
146 .usershare = 0,
147 .usershare_last_mod = {0, 0},
148 .szService = NULL,
149 .path = NULL,
150 .username = NULL,
151 .invalid_users = NULL,
152 .valid_users = NULL,
153 .admin_users = NULL,
154 .szCopy = NULL,
155 .szInclude = NULL,
156 .preexec = NULL,
157 .postexec = NULL,
158 .root_preexec = NULL,
159 .root_postexec = NULL,
160 .cups_options = NULL,
161 .print_command = NULL,
162 .lpq_command = NULL,
163 .lprm_command = NULL,
164 .lppause_command = NULL,
165 .lpresume_command = NULL,
166 .queuepause_command = NULL,
167 .queueresume_command = NULL,
168 ._printername = NULL,
169 .printjob_username = NULL,
170 .dont_descend = NULL,
171 .hosts_allow = NULL,
172 .hosts_deny = NULL,
173 .magic_script = NULL,
174 .magic_output = NULL,
175 .veto_files = NULL,
176 .hide_files = NULL,
177 .veto_oplock_files = NULL,
178 .comment = NULL,
179 .force_user = NULL,
180 .force_group = NULL,
181 .read_list = NULL,
182 .writelist = NULL,
183 .volume = NULL,
184 .fstype = NULL,
185 .vfs_objects = NULL,
186 .msdfs_proxy = NULL,
187 .aio_write_behind = NULL,
188 .dfree_command = NULL,
189 .minprintspace = 0,
190 .iMaxPrintJobs = 1000,
191 .max_reported_print_jobs = 0,
192 .write_cache_size = 0,
193 .create_mask = 0744,
194 .force_create_mode = 0,
195 .directory_mask = 0755,
196 .force_directory_mode = 0,
197 .max_connections = 0,
198 .default_case = CASE_LOWER,
199 .printing = DEFAULT_PRINTING,
200 .oplock_contention_limit = 2,
201 .csc_policy = 0,
202 .block_size = 1024,
203 .dfree_cache_time = 0,
204 .preexec_close = false,
205 .root_preexec_close = false,
206 .case_sensitive = Auto,
207 .preserve_case = true,
208 .short_preserve_case = true,
209 .hide_dot_files = true,
210 .hide_special_files = false,
211 .hide_unreadable = false,
212 .hide_unwriteable_files = false,
213 .browseable = true,
214 .access_based_share_enum = false,
215 .bAvailable = true,
216 .read_only = true,
217 .guest_only = false,
218 .administrative_share = false,
219 .guest_ok = false,
220 .printable = false,
221 .print_notify_backchannel = false,
222 .map_system = false,
223 .map_hidden = false,
224 .map_archive = true,
225 .store_dos_attributes = false,
226 .dmapi_support = false,
227 .locking = true,
228 .strict_locking = Auto,
229 .posix_locking = true,
230 .oplocks = true,
231 .kernel_oplocks = false,
232 .level2_oplocks = true,
233 .only_user = false,
234 .mangled_names = true,
235 .bWidelinks = false,
236 .follow_symlinks = true,
237 .syncalways = false,
238 .strict_allocate = false,
239 .strict_sync = false,
240 .mangling_char = '~',
241 .copymap = NULL,
242 .delete_readonly = false,
243 .fake_oplocks = false,
244 .delete_veto_files = false,
245 .dos_filemode = false,
246 .dos_filetimes = true,
247 .dos_filetime_resolution = false,
248 .fake_directory_create_times = false,
249 .blocking_locks = true,
250 .inherit_permissions = false,
251 .inherit_acls = false,
252 .inherit_owner = false,
253 .msdfs_root = false,
254 .use_client_driver = false,
255 .default_devmode = true,
256 .force_printername = false,
257 .nt_acl_support = true,
258 .force_unknown_acl_user = false,
259 ._use_sendfile = false,
260 .profile_acls = false,
261 .map_acl_inherit = false,
262 .afs_share = false,
263 .ea_support = false,
264 .acl_check_permissions = true,
265 .acl_map_full_control = true,
266 .acl_group_control = false,
267 .acl_allow_execute_always = false,
268 .change_notify = true,
269 .kernel_change_notify = true,
270 .allocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
271 .aio_read_size = 0,
272 .aio_write_size = 0,
273 .map_readonly = MAP_READONLY_YES,
274 .directory_name_cache_size = 100,
275 .smb_encrypt = SMB_SIGNING_DEFAULT,
276 .kernel_share_modes = true,
277 .durable_handles = true,
278 .param_opt = NULL,
279 .dummy = ""
282 /* local variables */
283 static struct loadparm_service **ServicePtrs = NULL;
284 static int iNumServices = 0;
285 static int iServiceIndex = 0;
286 static struct db_context *ServiceHash;
287 static bool bInGlobalSection = true;
288 static bool bGlobalOnly = false;
290 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
292 /* prototypes for the special type handlers */
293 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
294 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
295 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
296 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
297 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
298 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
299 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
300 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
301 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
302 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
303 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
304 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
306 /* these are parameter handlers which are not needed in the
307 * source3 code
310 #define handle_logfile NULL
312 static void set_allowed_client_auth(void);
314 static void add_to_file_list(const char *fname, const char *subfname);
315 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
316 static void free_param_opts(struct parmlist_entry **popts);
318 #include "lib/param/param_table.c"
320 /* this is used to prevent lots of mallocs of size 1 */
321 static const char null_string[] = "";
324 Set a string value, allocing the space for the string
327 static bool string_init(char **dest,const char *src)
329 size_t l;
331 if (!src)
332 src = "";
334 l = strlen(src);
336 if (l == 0) {
337 *dest = discard_const_p(char, null_string);
338 } else {
339 (*dest) = SMB_STRDUP(src);
340 if ((*dest) == NULL) {
341 DEBUG(0,("Out of memory in string_init\n"));
342 return false;
345 return(true);
349 Free a string value.
352 static void string_free(char **s)
354 if (!s || !(*s))
355 return;
356 if (*s == null_string)
357 *s = NULL;
358 SAFE_FREE(*s);
362 Set a string value, deallocating any existing space, and allocing the space
363 for the string
366 static bool string_set(char **dest,const char *src)
368 string_free(dest);
369 return(string_init(dest,src));
372 /***************************************************************************
373 Initialise the sDefault parameter structure for the printer values.
374 ***************************************************************************/
376 static void init_printer_values(struct loadparm_service *pService)
378 /* choose defaults depending on the type of printing */
379 switch (pService->printing) {
380 case PRINT_BSD:
381 case PRINT_AIX:
382 case PRINT_LPRNT:
383 case PRINT_LPROS2:
384 string_set(&pService->lpq_command, "lpq -P'%p'");
385 string_set(&pService->lprm_command, "lprm -P'%p' %j");
386 string_set(&pService->print_command, "lpr -r -P'%p' %s");
387 break;
389 case PRINT_LPRNG:
390 case PRINT_PLP:
391 string_set(&pService->lpq_command, "lpq -P'%p'");
392 string_set(&pService->lprm_command, "lprm -P'%p' %j");
393 string_set(&pService->print_command, "lpr -r -P'%p' %s");
394 string_set(&pService->queuepause_command, "lpc stop '%p'");
395 string_set(&pService->queueresume_command, "lpc start '%p'");
396 string_set(&pService->lppause_command, "lpc hold '%p' %j");
397 string_set(&pService->lpresume_command, "lpc release '%p' %j");
398 break;
400 case PRINT_CUPS:
401 case PRINT_IPRINT:
402 /* set the lpq command to contain the destination printer
403 name only. This is used by cups_queue_get() */
404 string_set(&pService->lpq_command, "%p");
405 string_set(&pService->lprm_command, "");
406 string_set(&pService->print_command, "");
407 string_set(&pService->lppause_command, "");
408 string_set(&pService->lpresume_command, "");
409 string_set(&pService->queuepause_command, "");
410 string_set(&pService->queueresume_command, "");
411 break;
413 case PRINT_SYSV:
414 case PRINT_HPUX:
415 string_set(&pService->lpq_command, "lpstat -o%p");
416 string_set(&pService->lprm_command, "cancel %p-%j");
417 string_set(&pService->print_command, "lp -c -d%p %s; rm %s");
418 string_set(&pService->queuepause_command, "disable %p");
419 string_set(&pService->queueresume_command, "enable %p");
420 #ifndef HPUX
421 string_set(&pService->lppause_command, "lp -i %p-%j -H hold");
422 string_set(&pService->lpresume_command, "lp -i %p-%j -H resume");
423 #endif /* HPUX */
424 break;
426 case PRINT_QNX:
427 string_set(&pService->lpq_command, "lpq -P%p");
428 string_set(&pService->lprm_command, "lprm -P%p %j");
429 string_set(&pService->print_command, "lp -r -P%p %s");
430 break;
432 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
434 case PRINT_TEST:
435 case PRINT_VLP: {
436 const char *tdbfile;
437 TALLOC_CTX *tmp_ctx = talloc_stackframe();
438 char *tmp;
440 tdbfile = talloc_asprintf(
441 tmp_ctx, "tdbfile=%s",
442 lp_parm_const_string(-1, "vlp", "tdbfile",
443 "/tmp/vlp.tdb"));
444 if (tdbfile == NULL) {
445 tdbfile="tdbfile=/tmp/vlp.tdb";
448 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
449 tdbfile);
450 string_set(&pService->print_command,
451 tmp ? tmp : "vlp print %p %s");
453 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
454 tdbfile);
455 string_set(&pService->lpq_command,
456 tmp ? tmp : "vlp lpq %p");
458 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
459 tdbfile);
460 string_set(&pService->lprm_command,
461 tmp ? tmp : "vlp lprm %p %j");
463 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
464 tdbfile);
465 string_set(&pService->lppause_command,
466 tmp ? tmp : "vlp lppause %p %j");
468 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
469 tdbfile);
470 string_set(&pService->lpresume_command,
471 tmp ? tmp : "vlp lpresume %p %j");
473 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
474 tdbfile);
475 string_set(&pService->queuepause_command,
476 tmp ? tmp : "vlp queuepause %p");
478 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
479 tdbfile);
480 string_set(&pService->queueresume_command,
481 tmp ? tmp : "vlp queueresume %p");
482 TALLOC_FREE(tmp_ctx);
484 break;
486 #endif /* DEVELOPER */
491 * Function to return the default value for the maximum number of open
492 * file descriptors permitted. This function tries to consult the
493 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
494 * the smaller of those.
496 static int max_open_files(void)
498 int sysctl_max = MAX_OPEN_FILES;
499 int rlimit_max = MAX_OPEN_FILES;
501 #ifdef HAVE_SYSCTLBYNAME
503 size_t size = sizeof(sysctl_max);
504 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
507 #endif
509 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
511 struct rlimit rl;
513 ZERO_STRUCT(rl);
515 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
516 rlimit_max = rl.rlim_cur;
518 #if defined(RLIM_INFINITY)
519 if(rl.rlim_cur == RLIM_INFINITY)
520 rlimit_max = MAX_OPEN_FILES;
521 #endif
523 #endif
525 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
526 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
527 "minimum Windows limit (%d)\n",
528 sysctl_max,
529 MIN_OPEN_FILES_WINDOWS));
530 sysctl_max = MIN_OPEN_FILES_WINDOWS;
533 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
534 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
535 "minimum Windows limit (%d)\n",
536 rlimit_max,
537 MIN_OPEN_FILES_WINDOWS));
538 rlimit_max = MIN_OPEN_FILES_WINDOWS;
541 return MIN(sysctl_max, rlimit_max);
545 * Common part of freeing allocated data for one parameter.
547 static void free_one_parameter_common(void *parm_ptr,
548 struct parm_struct parm)
550 if ((parm.type == P_STRING) ||
551 (parm.type == P_USTRING))
553 string_free((char**)parm_ptr);
554 } else if (parm.type == P_LIST) {
555 TALLOC_FREE(*((char***)parm_ptr));
560 * Free the allocated data for one parameter for a share
561 * given as a service struct.
563 static void free_one_parameter(struct loadparm_service *service,
564 struct parm_struct parm)
566 void *parm_ptr;
568 if (parm.p_class != P_LOCAL) {
569 return;
572 parm_ptr = lp_parm_ptr(service, &parm);
574 free_one_parameter_common(parm_ptr, parm);
578 * Free the allocated parameter data of a share given
579 * as a service struct.
581 static void free_parameters(struct loadparm_service *service)
583 uint32_t i;
585 for (i=0; parm_table[i].label; i++) {
586 free_one_parameter(service, parm_table[i]);
591 * Free the allocated data for one parameter for a given share
592 * specified by an snum.
594 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
596 void *parm_ptr;
598 if (snum < 0) {
599 parm_ptr = lp_parm_ptr(NULL, &parm);
600 } else if (parm.p_class != P_LOCAL) {
601 return;
602 } else {
603 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
606 free_one_parameter_common(parm_ptr, parm);
610 * Free the allocated parameter data for a share specified
611 * by an snum.
613 static void free_parameters_by_snum(int snum)
615 uint32_t i;
617 for (i=0; parm_table[i].label; i++) {
618 free_one_parameter_by_snum(snum, parm_table[i]);
623 * Free the allocated global parameters.
625 static void free_global_parameters(void)
627 free_param_opts(&Globals.param_opt);
628 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
629 TALLOC_FREE(Globals.ctx);
632 struct lp_stored_option {
633 struct lp_stored_option *prev, *next;
634 const char *label;
635 const char *value;
638 static struct lp_stored_option *stored_options;
641 save options set by lp_set_cmdline() into a list. This list is
642 re-applied when we do a globals reset, so that cmdline set options
643 are sticky across reloads of smb.conf
645 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
647 struct lp_stored_option *entry, *entry_next;
648 for (entry = stored_options; entry != NULL; entry = entry_next) {
649 entry_next = entry->next;
650 if (strcmp(pszParmName, entry->label) == 0) {
651 DLIST_REMOVE(stored_options, entry);
652 talloc_free(entry);
653 break;
657 entry = talloc(NULL, struct lp_stored_option);
658 if (!entry) {
659 return false;
662 entry->label = talloc_strdup(entry, pszParmName);
663 if (!entry->label) {
664 talloc_free(entry);
665 return false;
668 entry->value = talloc_strdup(entry, pszParmValue);
669 if (!entry->value) {
670 talloc_free(entry);
671 return false;
674 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
676 return true;
679 static bool apply_lp_set_cmdline(void)
681 struct lp_stored_option *entry = NULL;
682 for (entry = stored_options; entry != NULL; entry = entry->next) {
683 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
684 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
685 entry->label, entry->value));
686 return false;
689 return true;
692 /***************************************************************************
693 Initialise the global parameter structure.
694 ***************************************************************************/
696 static void init_globals(bool reinit_globals)
698 static bool done_init = false;
699 char *s = NULL;
700 int i;
702 /* If requested to initialize only once and we've already done it... */
703 if (!reinit_globals && done_init) {
704 /* ... then we have nothing more to do */
705 return;
708 if (!done_init) {
709 /* The logfile can be set before this is invoked. Free it if so. */
710 if (Globals.logfile != NULL) {
711 string_free(&Globals.logfile);
712 Globals.logfile = NULL;
714 done_init = true;
715 } else {
716 free_global_parameters();
719 /* This memset and the free_global_parameters() above will
720 * wipe out smb.conf options set with lp_set_cmdline(). The
721 * apply_lp_set_cmdline() call puts these values back in the
722 * table once the defaults are set */
723 ZERO_STRUCT(Globals);
725 Globals.ctx = talloc_new(NULL);
727 for (i = 0; parm_table[i].label; i++) {
728 if ((parm_table[i].type == P_STRING ||
729 parm_table[i].type == P_USTRING))
731 string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
736 string_set(&sDefault.fstype, FSTYPE_STRING);
737 string_set(&sDefault.printjob_username, "%U");
739 init_printer_values(&sDefault);
741 sDefault.ntvfs_handler = (const char **)str_list_make_v3(NULL, "unixuid default", NULL);
743 DEBUG(3, ("Initialising global parameters\n"));
745 /* Must manually force to upper case here, as this does not go via the handler */
746 string_set(&Globals.netbios_name, myhostname_upper());
748 string_set(&Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
749 string_set(&Globals.private_dir, get_dyn_PRIVATE_DIR());
751 /* use the new 'hash2' method by default, with a prefix of 1 */
752 string_set(&Globals.mangling_method, "hash2");
753 Globals.mangle_prefix = 1;
755 string_set(&Globals.guest_account, GUEST_ACCOUNT);
757 /* using UTF8 by default allows us to support all chars */
758 string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
760 /* Use codepage 850 as a default for the dos character set */
761 string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
764 * Allow the default PASSWD_CHAT to be overridden in local.h.
766 string_set(&Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
768 string_set(&Globals.workgroup, DEFAULT_WORKGROUP);
770 string_set(&Globals.passwd_program, "");
771 string_set(&Globals.lock_directory, get_dyn_LOCKDIR());
772 string_set(&Globals.szStateDir, get_dyn_STATEDIR());
773 string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
774 string_set(&Globals.pid_directory, get_dyn_PIDDIR());
775 string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
777 * By default support explicit binding to broadcast
778 * addresses.
780 Globals.nmbd_bind_explicit_broadcast = true;
782 if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
783 smb_panic("init_globals: ENOMEM");
785 string_set(&Globals.server_string, s);
786 SAFE_FREE(s);
787 #ifdef DEVELOPER
788 string_set(&Globals.panic_action, "/bin/sleep 999999999");
789 #endif
791 string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
793 string_set(&Globals.logon_drive, "");
794 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
795 string_set(&Globals.logon_home, "\\\\%N\\%U");
796 string_set(&Globals.logon_path, "\\\\%N\\%U\\profile");
798 Globals.name_resolve_order = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
799 string_set(&Globals.password_server, "*");
801 Globals.algorithmic_rid_base = BASE_RID;
803 Globals.load_printers = true;
804 Globals.printcap_cache_time = 750; /* 12.5 minutes */
806 Globals.config_backend = config_backend;
807 Globals._server_role = ROLE_AUTO;
809 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
810 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
811 Globals.max_xmit = 0x4104;
812 Globals.max_mux = 50; /* This is *needed* for profile support. */
813 Globals.lpq_cache_time = 30; /* changed to handle large print servers better -- jerry */
814 Globals._disable_spoolss = false;
815 Globals.max_smbd_processes = 0;/* no limit specified */
816 Globals.usernamelevel = 0;
817 Globals.deadtime = 0;
818 Globals.getwd_cache = true;
819 Globals.large_readwrite = true;
820 Globals.max_log_size = 5000;
821 Globals.max_open_files = max_open_files();
822 Globals.server_max_protocol = PROTOCOL_SMB3_00;
823 Globals.server_min_protocol = PROTOCOL_LANMAN1;
824 Globals.client_max_protocol = PROTOCOL_NT1;
825 Globals.client_min_protocol = PROTOCOL_CORE;
826 Globals._security = SEC_AUTO;
827 Globals.encrypt_passwords = true;
828 Globals.client_schannel = Auto;
829 Globals.winbind_sealed_pipes = true;
830 Globals.require_strong_key = true;
831 Globals.server_schannel = Auto;
832 Globals.bReadRaw = true;
833 Globals.bWriteRaw = true;
834 Globals.null_passwords = false;
835 Globals.obey_pam_restrictions = false;
836 Globals.syslog = 1;
837 Globals.syslog_only = false;
838 Globals.timestamp_logs = true;
839 string_set(&Globals.loglevel, "0");
840 Globals.debug_prefix_timestamp = false;
841 Globals.debug_hires_timestamp = true;
842 Globals.debug_pid = false;
843 Globals.debug_uid = false;
844 Globals.debug_class = false;
845 Globals.enable_core_files = true;
846 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
847 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
848 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
849 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
850 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
851 Globals.lm_interval = 60;
852 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
853 Globals.nis_home_map = false;
854 #ifdef WITH_NISPLUS_HOME
855 string_set(&Globals.homedir_map, "auto_home.org_dir");
856 #else
857 string_set(&Globals.homedir_map, "auto.home");
858 #endif
859 #endif
860 Globals.time_server = false;
861 Globals.bind_interfaces_only = false;
862 Globals.unix_password_sync = false;
863 Globals.pam_password_change = false;
864 Globals.passwd_chat_debug = false;
865 Globals.passwd_chat_timeout = 2; /* 2 second default. */
866 Globals.nt_pipe_support = true; /* Do NT pipes by default. */
867 Globals.nt_status_support = true; /* Use NT status by default. */
868 Globals.stat_cache = true; /* use stat cache by default */
869 Globals.max_stat_cache_size = 256; /* 256k by default */
870 Globals.restrict_anonymous = 0;
871 Globals.client_lanman_auth = false; /* Do NOT use the LanMan hash if it is available */
872 Globals.client_plaintext_auth = false; /* Do NOT use a plaintext password even if is requested by the server */
873 Globals.lanman_auth = false; /* Do NOT use the LanMan hash, even if it is supplied */
874 Globals.ntlm_auth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
875 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 */
876 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
878 Globals.map_to_guest = 0; /* By Default, "Never" */
879 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
880 Globals.enhanced_browsing = true;
881 Globals.lock_spin_time = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
882 #ifdef MMAP_BLACKLIST
883 Globals.use_mmap = false;
884 #else
885 Globals.use_mmap = true;
886 #endif
887 Globals.unicode = true;
888 Globals.unix_extensions = true;
889 Globals.reset_on_zero_vc = false;
890 Globals.log_writeable_files_on_exit = false;
891 Globals.create_krb5_conf = true;
892 Globals.winbindMaxDomainConnections = 1;
894 /* hostname lookups can be very expensive and are broken on
895 a large number of sites (tridge) */
896 Globals.hostname_lookups = false;
898 string_set(&Globals.passdb_backend, "tdbsam");
899 string_set(&Globals.ldap_suffix, "");
900 string_set(&Globals.szLdapMachineSuffix, "");
901 string_set(&Globals.szLdapUserSuffix, "");
902 string_set(&Globals.szLdapGroupSuffix, "");
903 string_set(&Globals.szLdapIdmapSuffix, "");
905 string_set(&Globals.ldap_admin_dn, "");
906 Globals.ldap_ssl = LDAP_SSL_START_TLS;
907 Globals.ldap_ssl_ads = false;
908 Globals.ldap_deref = -1;
909 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
910 Globals.ldap_delete_dn = false;
911 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
912 Globals.ldap_follow_referral = Auto;
913 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
914 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
915 Globals.ldap_page_size = LDAP_PAGE_SIZE;
917 Globals.ldap_debug_level = 0;
918 Globals.ldap_debug_threshold = 10;
920 /* This is what we tell the afs client. in reality we set the token
921 * to never expire, though, when this runs out the afs client will
922 * forget the token. Set to 0 to get NEVERDATE.*/
923 Globals.afs_token_lifetime = 604800;
924 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
926 /* these parameters are set to defaults that are more appropriate
927 for the increasing samba install base:
929 as a member of the workgroup, that will possibly become a
930 _local_ master browser (lm = true). this is opposed to a forced
931 local master browser startup (pm = true).
933 doesn't provide WINS server service by default (wsupp = false),
934 and doesn't provide domain master browser services by default, either.
938 Globals.show_add_printer_wizard = true;
939 Globals.os_level = 20;
940 Globals.local_master = true;
941 Globals._domain_master = Auto; /* depending on _domain_logons */
942 Globals._domain_logons = false;
943 Globals.browse_list = true;
944 Globals.we_are_a_wins_server = false;
945 Globals.wins_proxy = false;
947 TALLOC_FREE(Globals.init_logon_delayed_hosts);
948 Globals.init_logon_delay = 100; /* 100 ms default delay */
950 Globals.wins_dns_proxy = true;
952 Globals.allow_trusted_domains = true;
953 string_set(&Globals.szIdmapBackend, "tdb");
955 string_set(&Globals.template_shell, "/bin/false");
956 string_set(&Globals.template_homedir, "/home/%D/%U");
957 string_set(&Globals.winbind_separator, "\\");
958 string_set(&Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
960 string_set(&Globals.cups_server, "");
961 string_set(&Globals.iprint_server, "");
963 #ifdef CLUSTER_SUPPORT
964 string_set(&Globals.ctdbd_socket, CTDB_PATH);
965 #else
966 string_set(&Globals.ctdbd_socket, "");
967 #endif
969 Globals.cluster_addresses = NULL;
970 Globals.clustering = false;
971 Globals.ctdb_timeout = 0;
972 Globals.ctdb_locktime_warn_threshold = 0;
974 Globals.winbind_cache_time = 300; /* 5 minutes */
975 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
976 Globals.winbind_max_clients = 200;
977 Globals.winbind_enum_users = false;
978 Globals.winbind_enum_groups = false;
979 Globals.winbind_use_default_domain = false;
980 Globals.winbind_trusted_domains_only = false;
981 Globals.winbind_nested_groups = true;
982 Globals.winbind_expand_groups = 1;
983 Globals.winbind_nss_info = (const char **)str_list_make_v3(NULL, "template", NULL);
984 Globals.winbind_refresh_tickets = false;
985 Globals.winbind_offline_logon = false;
987 Globals.idmap_cache_time = 86400 * 7; /* a week by default */
988 Globals.idmap_negative_cache_time = 120; /* 2 minutes by default */
990 Globals.passdb_expand_explicit = false;
992 Globals.name_cache_timeout = 660; /* In seconds */
994 Globals.use_spnego = true;
995 Globals.client_use_spnego = true;
997 Globals.client_signing = SMB_SIGNING_DEFAULT;
998 Globals.server_signing = SMB_SIGNING_DEFAULT;
1000 Globals.defer_sharing_violations = true;
1001 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
1003 Globals.enable_privileges = true;
1004 Globals.host_msdfs = true;
1005 Globals.enable_asu_support = false;
1007 /* User defined shares. */
1008 if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
1009 smb_panic("init_globals: ENOMEM");
1011 string_set(&Globals.usershare_path, s);
1012 SAFE_FREE(s);
1013 string_set(&Globals.szUsershareTemplateShare, "");
1014 Globals.usershare_max_shares = 0;
1015 /* By default disallow sharing of directories not owned by the sharer. */
1016 Globals.usershare_owner_only = true;
1017 /* By default disallow guest access to usershares. */
1018 Globals.usershare_allow_guests = false;
1020 Globals.keepalive = DEFAULT_KEEPALIVE;
1022 /* By default no shares out of the registry */
1023 Globals.registry_shares = false;
1025 Globals.iminreceivefile = 0;
1027 Globals.map_untrusted_to_domain = false;
1028 Globals.multicast_dns_register = true;
1030 Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
1031 Globals.smb2_max_write = DEFAULT_SMB2_MAX_WRITE;
1032 Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
1033 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1035 string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1037 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);
1039 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);
1041 Globals.tls_enabled = true;
1043 string_set(&Globals.tls_keyfile, "tls/key.pem");
1044 string_set(&Globals.tls_certfile, "tls/cert.pem");
1045 string_set(&Globals.tls_cafile, "tls/ca.pem");
1047 string_set(&Globals.share_backend, "classic");
1049 Globals.iPreferredMaster = Auto;
1051 Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
1053 string_set(&Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
1055 string_set(&Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
1057 if (asprintf(&s, "%s/samba_kcc", get_dyn_SCRIPTSBINDIR()) < 0) {
1058 smb_panic("init_globals: ENOMEM");
1060 Globals.samba_kcc_command = (const char **)str_list_make_v3(NULL, s, NULL);
1061 SAFE_FREE(s);
1063 if (asprintf(&s, "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR()) < 0) {
1064 smb_panic("init_globals: ENOMEM");
1066 Globals.dns_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1067 SAFE_FREE(s);
1069 if (asprintf(&s, "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR()) < 0) {
1070 smb_panic("init_globals: ENOMEM");
1072 Globals.spn_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1073 SAFE_FREE(s);
1075 Globals.nsupdate_command = (const char **)str_list_make_v3(NULL, "/usr/bin/nsupdate -g", NULL);
1077 Globals.rndc_command = (const char **)str_list_make_v3(NULL, "/usr/sbin/rndc", NULL);
1079 Globals.cldap_port = 389;
1081 Globals.dgram_port = 138;
1083 Globals.nbt_port = 137;
1085 Globals.krb5_port = 88;
1087 Globals.kpasswd_port = 464;
1089 Globals.web_port = 901;
1091 /* Now put back the settings that were set with lp_set_cmdline() */
1092 apply_lp_set_cmdline();
1095 /*******************************************************************
1096 Convenience routine to grab string parameters into talloced memory
1097 and run standard_sub_basic on them. The buffers can be written to by
1098 callers without affecting the source string.
1099 ********************************************************************/
1101 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1103 char *ret;
1105 /* The follow debug is useful for tracking down memory problems
1106 especially if you have an inner loop that is calling a lp_*()
1107 function that returns a string. Perhaps this debug should be
1108 present all the time? */
1110 #if 0
1111 DEBUG(10, ("lp_string(%s)\n", s));
1112 #endif
1113 if (!s) {
1114 return NULL;
1117 ret = talloc_sub_basic(ctx,
1118 get_current_username(),
1119 current_user_info.domain,
1121 if (trim_char(ret, '\"', '\"')) {
1122 if (strchr(ret,'\"') != NULL) {
1123 TALLOC_FREE(ret);
1124 ret = talloc_sub_basic(ctx,
1125 get_current_username(),
1126 current_user_info.domain,
1130 return ret;
1134 In this section all the functions that are used to access the
1135 parameters from the rest of the program are defined
1138 #define FN_GLOBAL_STRING(fn_name,ptr) \
1139 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1140 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1141 const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1142 #define FN_GLOBAL_LIST(fn_name,ptr) \
1143 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1144 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1145 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1146 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1147 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1148 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1149 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1151 #define FN_LOCAL_STRING(fn_name,val) \
1152 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));}
1153 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1154 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1155 #define FN_LOCAL_LIST(fn_name,val) \
1156 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1157 #define FN_LOCAL_BOOL(fn_name,val) \
1158 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1159 #define FN_LOCAL_INTEGER(fn_name,val) \
1160 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1162 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1163 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1164 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1165 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1166 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
1167 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1170 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1171 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1173 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1174 * build process or in smb.conf, we use that value. Otherwise they
1175 * default to the value of lp_lock_directory(). */
1176 const char *lp_statedir(void) {
1177 if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1178 (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1179 return(*(char **)(&Globals.szStateDir) ?
1180 *(char **)(&Globals.szStateDir) : "");
1181 else
1182 return(*(char **)(&Globals.lock_directory) ?
1183 *(char **)(&Globals.lock_directory) : "");
1185 const char *lp_cachedir(void) {
1186 if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1187 (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1188 return(*(char **)(&Globals.szCacheDir) ?
1189 *(char **)(&Globals.szCacheDir) : "");
1190 else
1191 return(*(char **)(&Globals.lock_directory) ?
1192 *(char **)(&Globals.lock_directory) : "");
1194 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1195 winbindMaxDomainConnections)
1197 int lp_winbind_max_domain_connections(void)
1199 if (lp_winbind_offline_logon() &&
1200 lp_winbind_max_domain_connections_int() > 1) {
1201 DEBUG(1, ("offline logons active, restricting max domain "
1202 "connections to 1\n"));
1203 return 1;
1205 return MAX(1, lp_winbind_max_domain_connections_int());
1208 int lp_smb2_max_credits(void)
1210 if (Globals.ismb2_max_credits == 0) {
1211 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1213 return Globals.ismb2_max_credits;
1215 int lp_cups_encrypt(void)
1217 int result = 0;
1218 #ifdef HAVE_HTTPCONNECTENCRYPT
1219 switch (Globals.CupsEncrypt) {
1220 case Auto:
1221 result = HTTP_ENCRYPT_REQUIRED;
1222 break;
1223 case true:
1224 result = HTTP_ENCRYPT_ALWAYS;
1225 break;
1226 case false:
1227 result = HTTP_ENCRYPT_NEVER;
1228 break;
1230 #endif
1231 return result;
1234 /* These functions remain in source3/param for now */
1236 FN_GLOBAL_STRING(configfile, szConfigFile)
1238 #include "lib/param/param_functions.c"
1240 FN_LOCAL_STRING(servicename, szService)
1241 FN_LOCAL_CONST_STRING(const_servicename, szService)
1243 /* local prototypes */
1245 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1246 static const char *get_boolean(bool bool_value);
1247 static int getservicebyname(const char *pszServiceName,
1248 struct loadparm_service *pserviceDest);
1249 static void copy_service(struct loadparm_service *pserviceDest,
1250 struct loadparm_service *pserviceSource,
1251 struct bitmap *pcopymapDest);
1252 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1253 void *userdata);
1254 static bool do_section(const char *pszSectionName, void *userdata);
1255 static void init_copymap(struct loadparm_service *pservice);
1256 static bool hash_a_service(const char *name, int number);
1257 static void free_service_byindex(int iService);
1258 static void show_parameter(int parmIndex);
1259 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1262 * This is a helper function for parametrical options support. It returns a
1263 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1264 * parametrical functions are quite simple
1266 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1267 const char *option)
1269 bool global_section = false;
1270 char* param_key;
1271 struct parmlist_entry *data;
1273 if (service == NULL) {
1274 data = Globals.param_opt;
1275 global_section = true;
1276 } else {
1277 data = service->param_opt;
1280 if (asprintf(&param_key, "%s:%s", type, option) == -1) {
1281 DEBUG(0,("asprintf failed!\n"));
1282 return NULL;
1285 while (data) {
1286 if (strwicmp(data->key, param_key) == 0) {
1287 string_free(&param_key);
1288 return data;
1290 data = data->next;
1293 if (!global_section) {
1294 /* Try to fetch the same option but from globals */
1295 /* but only if we are not already working with Globals */
1296 data = Globals.param_opt;
1297 while (data) {
1298 if (strwicmp(data->key, param_key) == 0) {
1299 string_free(&param_key);
1300 return data;
1302 data = data->next;
1306 string_free(&param_key);
1308 return NULL;
1312 * This is a helper function for parametrical options support. It returns a
1313 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1314 * parametrical functions are quite simple
1316 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1317 const char *option)
1319 if (snum >= iNumServices) return NULL;
1321 if (snum < 0) {
1322 return get_parametrics_by_service(NULL, type, option);
1323 } else {
1324 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1329 #define MISSING_PARAMETER(name) \
1330 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1332 /*******************************************************************
1333 convenience routine to return int parameters.
1334 ********************************************************************/
1335 static int lp_int(const char *s)
1338 if (!s || !*s) {
1339 MISSING_PARAMETER(lp_int);
1340 return (-1);
1343 return (int)strtol(s, NULL, 0);
1346 /*******************************************************************
1347 convenience routine to return unsigned long parameters.
1348 ********************************************************************/
1349 static unsigned long lp_ulong(const char *s)
1352 if (!s || !*s) {
1353 MISSING_PARAMETER(lp_ulong);
1354 return (0);
1357 return strtoul(s, NULL, 0);
1360 /*******************************************************************
1361 convenience routine to return boolean parameters.
1362 ********************************************************************/
1363 static bool lp_bool(const char *s)
1365 bool ret = false;
1367 if (!s || !*s) {
1368 MISSING_PARAMETER(lp_bool);
1369 return false;
1372 if (!set_boolean(s, &ret)) {
1373 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1374 return false;
1377 return ret;
1380 /*******************************************************************
1381 convenience routine to return enum parameters.
1382 ********************************************************************/
1383 static int lp_enum(const char *s,const struct enum_list *_enum)
1385 int i;
1387 if (!s || !*s || !_enum) {
1388 MISSING_PARAMETER(lp_enum);
1389 return (-1);
1392 for (i=0; _enum[i].name; i++) {
1393 if (strequal(_enum[i].name,s))
1394 return _enum[i].value;
1397 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1398 return (-1);
1401 #undef MISSING_PARAMETER
1403 /* Return parametric option from a given service. Type is a part of option before ':' */
1404 /* Parametric option has following syntax: 'Type: option = value' */
1405 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1407 struct parmlist_entry *data = get_parametrics(snum, type, option);
1409 if (data == NULL||data->value==NULL) {
1410 if (def) {
1411 return lp_string(ctx, def);
1412 } else {
1413 return NULL;
1417 return lp_string(ctx, data->value);
1420 /* Return parametric option from a given service. Type is a part of option before ':' */
1421 /* Parametric option has following syntax: 'Type: option = value' */
1422 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1424 struct parmlist_entry *data = get_parametrics(snum, type, option);
1426 if (data == NULL||data->value==NULL)
1427 return def;
1429 return data->value;
1432 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1434 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1436 if (data == NULL||data->value==NULL)
1437 return NULL;
1439 return data->value;
1443 /* Return parametric option from a given service. Type is a part of option before ':' */
1444 /* Parametric option has following syntax: 'Type: option = value' */
1446 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1448 struct parmlist_entry *data = get_parametrics(snum, type, option);
1450 if (data == NULL||data->value==NULL)
1451 return (const char **)def;
1453 if (data->list==NULL) {
1454 data->list = str_list_make_v3(NULL, data->value, NULL);
1457 return (const char **)data->list;
1460 /* Return parametric option from a given service. Type is a part of option before ':' */
1461 /* Parametric option has following syntax: 'Type: option = value' */
1463 int lp_parm_int(int snum, const char *type, const char *option, int def)
1465 struct parmlist_entry *data = get_parametrics(snum, type, option);
1467 if (data && data->value && *data->value)
1468 return lp_int(data->value);
1470 return def;
1473 /* Return parametric option from a given service. Type is a part of option before ':' */
1474 /* Parametric option has following syntax: 'Type: option = value' */
1476 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1478 struct parmlist_entry *data = get_parametrics(snum, type, option);
1480 if (data && data->value && *data->value)
1481 return lp_ulong(data->value);
1483 return def;
1486 /* Return parametric option from a given service. Type is a part of option before ':' */
1487 /* Parametric option has following syntax: 'Type: option = value' */
1489 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1491 struct parmlist_entry *data = get_parametrics(snum, type, option);
1493 if (data && data->value && *data->value)
1494 return lp_bool(data->value);
1496 return def;
1499 /* Return parametric option from a given service. Type is a part of option before ':' */
1500 /* Parametric option has following syntax: 'Type: option = value' */
1502 int lp_parm_enum(int snum, const char *type, const char *option,
1503 const struct enum_list *_enum, int def)
1505 struct parmlist_entry *data = get_parametrics(snum, type, option);
1507 if (data && data->value && *data->value && _enum)
1508 return lp_enum(data->value, _enum);
1510 return def;
1514 /***************************************************************************
1515 Initialise a service to the defaults.
1516 ***************************************************************************/
1518 static void init_service(struct loadparm_service *pservice)
1520 memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1521 copy_service(pservice, &sDefault, NULL);
1526 * free a param_opts structure.
1527 * param_opts handling should be moved to talloc;
1528 * then this whole functions reduces to a TALLOC_FREE().
1531 static void free_param_opts(struct parmlist_entry **popts)
1533 struct parmlist_entry *opt, *next_opt;
1535 if (*popts != NULL) {
1536 DEBUG(5, ("Freeing parametrics:\n"));
1538 opt = *popts;
1539 while (opt != NULL) {
1540 string_free(&opt->key);
1541 string_free(&opt->value);
1542 TALLOC_FREE(opt->list);
1543 next_opt = opt->next;
1544 SAFE_FREE(opt);
1545 opt = next_opt;
1547 *popts = NULL;
1550 /***************************************************************************
1551 Free the dynamically allocated parts of a service struct.
1552 ***************************************************************************/
1554 static void free_service(struct loadparm_service *pservice)
1556 if (!pservice)
1557 return;
1559 if (pservice->szService)
1560 DEBUG(5, ("free_service: Freeing service %s\n",
1561 pservice->szService));
1563 free_parameters(pservice);
1565 string_free(&pservice->szService);
1566 TALLOC_FREE(pservice->copymap);
1568 free_param_opts(&pservice->param_opt);
1570 ZERO_STRUCTP(pservice);
1574 /***************************************************************************
1575 remove a service indexed in the ServicePtrs array from the ServiceHash
1576 and free the dynamically allocated parts
1577 ***************************************************************************/
1579 static void free_service_byindex(int idx)
1581 if ( !LP_SNUM_OK(idx) )
1582 return;
1584 ServicePtrs[idx]->valid = false;
1586 /* we have to cleanup the hash record */
1588 if (ServicePtrs[idx]->szService) {
1589 char *canon_name = canonicalize_servicename(
1590 talloc_tos(),
1591 ServicePtrs[idx]->szService );
1593 dbwrap_delete_bystring(ServiceHash, canon_name );
1594 TALLOC_FREE(canon_name);
1597 free_service(ServicePtrs[idx]);
1598 talloc_free_children(ServicePtrs[idx]);
1601 /***************************************************************************
1602 Add a new service to the services array initialising it with the given
1603 service.
1604 ***************************************************************************/
1606 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1608 int i;
1609 struct loadparm_service tservice;
1610 int num_to_alloc = iNumServices + 1;
1611 struct loadparm_service **tsp = NULL;
1613 tservice = *pservice;
1615 /* it might already exist */
1616 if (name) {
1617 i = getservicebyname(name, NULL);
1618 if (i >= 0) {
1619 return (i);
1623 /* if not, then create one */
1624 i = iNumServices;
1625 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1626 if (tsp == NULL) {
1627 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1628 return (-1);
1630 ServicePtrs = tsp;
1631 ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1632 if (!ServicePtrs[iNumServices]) {
1633 DEBUG(0,("add_a_service: out of memory!\n"));
1634 return (-1);
1636 iNumServices++;
1638 ServicePtrs[i]->valid = true;
1640 init_service(ServicePtrs[i]);
1641 copy_service(ServicePtrs[i], &tservice, NULL);
1642 if (name)
1643 string_set(&ServicePtrs[i]->szService, name);
1645 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1646 i, ServicePtrs[i]->szService));
1648 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1649 return (-1);
1652 return (i);
1655 /***************************************************************************
1656 Convert a string to uppercase and remove whitespaces.
1657 ***************************************************************************/
1659 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1661 char *result;
1663 if ( !src ) {
1664 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1665 return NULL;
1668 result = talloc_strdup(ctx, src);
1669 SMB_ASSERT(result != NULL);
1671 if (!strlower_m(result)) {
1672 TALLOC_FREE(result);
1673 return NULL;
1675 return result;
1678 /***************************************************************************
1679 Add a name/index pair for the services array to the hash table.
1680 ***************************************************************************/
1682 static bool hash_a_service(const char *name, int idx)
1684 char *canon_name;
1686 if ( !ServiceHash ) {
1687 DEBUG(10,("hash_a_service: creating servicehash\n"));
1688 ServiceHash = db_open_rbt(NULL);
1689 if ( !ServiceHash ) {
1690 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1691 return false;
1695 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1696 idx, name));
1698 canon_name = canonicalize_servicename(talloc_tos(), name );
1700 dbwrap_store_bystring(ServiceHash, canon_name,
1701 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1702 TDB_REPLACE);
1704 TALLOC_FREE(canon_name);
1706 return true;
1709 /***************************************************************************
1710 Add a new home service, with the specified home directory, defaults coming
1711 from service ifrom.
1712 ***************************************************************************/
1714 bool lp_add_home(const char *pszHomename, int iDefaultService,
1715 const char *user, const char *pszHomedir)
1717 int i;
1719 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1720 pszHomedir[0] == '\0') {
1721 return false;
1724 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1726 if (i < 0)
1727 return false;
1729 if (!(*(ServicePtrs[iDefaultService]->path))
1730 || strequal(ServicePtrs[iDefaultService]->path,
1731 lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1732 string_set(&ServicePtrs[i]->path, pszHomedir);
1735 if (!(*(ServicePtrs[i]->comment))) {
1736 char *comment = NULL;
1737 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1738 return false;
1740 string_set(&ServicePtrs[i]->comment, comment);
1741 SAFE_FREE(comment);
1744 /* set the browseable flag from the global default */
1746 ServicePtrs[i]->browseable = sDefault.browseable;
1747 ServicePtrs[i]->access_based_share_enum = sDefault.access_based_share_enum;
1749 ServicePtrs[i]->autoloaded = true;
1751 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1752 user, ServicePtrs[i]->path ));
1754 return true;
1757 /***************************************************************************
1758 Add a new service, based on an old one.
1759 ***************************************************************************/
1761 int lp_add_service(const char *pszService, int iDefaultService)
1763 if (iDefaultService < 0) {
1764 return add_a_service(&sDefault, pszService);
1767 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1770 /***************************************************************************
1771 Add the IPC service.
1772 ***************************************************************************/
1774 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1776 char *comment = NULL;
1777 int i = add_a_service(&sDefault, ipc_name);
1779 if (i < 0)
1780 return false;
1782 if (asprintf(&comment, "IPC Service (%s)",
1783 Globals.server_string) < 0) {
1784 return false;
1787 string_set(&ServicePtrs[i]->path, tmpdir());
1788 string_set(&ServicePtrs[i]->username, "");
1789 string_set(&ServicePtrs[i]->comment, comment);
1790 string_set(&ServicePtrs[i]->fstype, "IPC");
1791 ServicePtrs[i]->max_connections = 0;
1792 ServicePtrs[i]->bAvailable = true;
1793 ServicePtrs[i]->read_only = true;
1794 ServicePtrs[i]->guest_only = false;
1795 ServicePtrs[i]->administrative_share = true;
1796 ServicePtrs[i]->guest_ok = guest_ok;
1797 ServicePtrs[i]->printable = false;
1798 ServicePtrs[i]->browseable = sDefault.browseable;
1800 DEBUG(3, ("adding IPC service\n"));
1802 SAFE_FREE(comment);
1803 return true;
1806 /***************************************************************************
1807 Add a new printer service, with defaults coming from service iFrom.
1808 ***************************************************************************/
1810 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1812 const char *comment = "From Printcap";
1813 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1815 if (i < 0)
1816 return false;
1818 /* note that we do NOT default the availability flag to true - */
1819 /* we take it from the default service passed. This allows all */
1820 /* dynamic printers to be disabled by disabling the [printers] */
1821 /* entry (if/when the 'available' keyword is implemented!). */
1823 /* the printer name is set to the service name. */
1824 string_set(&ServicePtrs[i]->_printername, pszPrintername);
1825 string_set(&ServicePtrs[i]->comment, comment);
1827 /* set the browseable flag from the gloabl default */
1828 ServicePtrs[i]->browseable = sDefault.browseable;
1830 /* Printers cannot be read_only. */
1831 ServicePtrs[i]->read_only = false;
1832 /* No oplocks on printer services. */
1833 ServicePtrs[i]->oplocks = false;
1834 /* Printer services must be printable. */
1835 ServicePtrs[i]->printable = true;
1837 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1839 return true;
1843 /***************************************************************************
1844 Check whether the given parameter name is valid.
1845 Parametric options (names containing a colon) are considered valid.
1846 ***************************************************************************/
1848 bool lp_parameter_is_valid(const char *pszParmName)
1850 return ((lpcfg_map_parameter(pszParmName) != -1) ||
1851 (strchr(pszParmName, ':') != NULL));
1854 /***************************************************************************
1855 Check whether the given name is the name of a global parameter.
1856 Returns true for strings belonging to parameters of class
1857 P_GLOBAL, false for all other strings, also for parametric options
1858 and strings not belonging to any option.
1859 ***************************************************************************/
1861 bool lp_parameter_is_global(const char *pszParmName)
1863 int num = lpcfg_map_parameter(pszParmName);
1865 if (num >= 0) {
1866 return (parm_table[num].p_class == P_GLOBAL);
1869 return false;
1872 /**************************************************************************
1873 Check whether the given name is the canonical name of a parameter.
1874 Returns false if it is not a valid parameter Name.
1875 For parametric options, true is returned.
1876 **************************************************************************/
1878 bool lp_parameter_is_canonical(const char *parm_name)
1880 if (!lp_parameter_is_valid(parm_name)) {
1881 return false;
1884 return (lpcfg_map_parameter(parm_name) ==
1885 map_parameter_canonical(parm_name, NULL));
1888 /**************************************************************************
1889 Determine the canonical name for a parameter.
1890 Indicate when it is an inverse (boolean) synonym instead of a
1891 "usual" synonym.
1892 **************************************************************************/
1894 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1895 bool *inverse)
1897 int num;
1899 if (!lp_parameter_is_valid(parm_name)) {
1900 *canon_parm = NULL;
1901 return false;
1904 num = map_parameter_canonical(parm_name, inverse);
1905 if (num < 0) {
1906 /* parametric option */
1907 *canon_parm = parm_name;
1908 } else {
1909 *canon_parm = parm_table[num].label;
1912 return true;
1916 /**************************************************************************
1917 Determine the canonical name for a parameter.
1918 Turn the value given into the inverse boolean expression when
1919 the synonym is an invers boolean synonym.
1921 Return true if parm_name is a valid parameter name and
1922 in case it is an invers boolean synonym, if the val string could
1923 successfully be converted to the reverse bool.
1924 Return false in all other cases.
1925 **************************************************************************/
1927 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1928 const char *val,
1929 const char **canon_parm,
1930 const char **canon_val)
1932 int num;
1933 bool inverse;
1935 if (!lp_parameter_is_valid(parm_name)) {
1936 *canon_parm = NULL;
1937 *canon_val = NULL;
1938 return false;
1941 num = map_parameter_canonical(parm_name, &inverse);
1942 if (num < 0) {
1943 /* parametric option */
1944 *canon_parm = parm_name;
1945 *canon_val = val;
1946 } else {
1947 *canon_parm = parm_table[num].label;
1948 if (inverse) {
1949 if (!lp_invert_boolean(val, canon_val)) {
1950 *canon_val = NULL;
1951 return false;
1953 } else {
1954 *canon_val = val;
1958 return true;
1961 /***************************************************************************
1962 Map a parameter's string representation to the index of the canonical
1963 form of the parameter (it might be a synonym).
1964 Returns -1 if the parameter string is not recognised.
1965 ***************************************************************************/
1967 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1969 int parm_num, canon_num;
1970 bool loc_inverse = false;
1972 parm_num = lpcfg_map_parameter(pszParmName);
1973 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1974 /* invalid, parametric or no canidate for synonyms ... */
1975 goto done;
1978 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1979 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1980 parm_num = canon_num;
1981 goto done;
1985 done:
1986 if (inverse != NULL) {
1987 *inverse = loc_inverse;
1989 return parm_num;
1992 /***************************************************************************
1993 return true if parameter number parm1 is a synonym of parameter
1994 number parm2 (parm2 being the principal name).
1995 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1996 false otherwise.
1997 ***************************************************************************/
1999 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
2001 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
2002 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
2003 (parm_table[parm1].flags & FLAG_HIDE) &&
2004 !(parm_table[parm2].flags & FLAG_HIDE))
2006 if (inverse != NULL) {
2007 if ((parm_table[parm1].type == P_BOOLREV) &&
2008 (parm_table[parm2].type == P_BOOL))
2010 *inverse = true;
2011 } else {
2012 *inverse = false;
2015 return true;
2017 return false;
2020 /***************************************************************************
2021 Show one parameter's name, type, [values,] and flags.
2022 (helper functions for show_parameter_list)
2023 ***************************************************************************/
2025 static void show_parameter(int parmIndex)
2027 int enumIndex, flagIndex;
2028 int parmIndex2;
2029 bool hadFlag;
2030 bool hadSyn;
2031 bool inverse;
2032 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2033 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2034 "P_ENUM", "P_SEP"};
2035 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2036 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2037 FLAG_HIDE};
2038 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2039 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2040 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2042 printf("%s=%s", parm_table[parmIndex].label,
2043 type[parm_table[parmIndex].type]);
2044 if (parm_table[parmIndex].type == P_ENUM) {
2045 printf(",");
2046 for (enumIndex=0;
2047 parm_table[parmIndex].enum_list[enumIndex].name;
2048 enumIndex++)
2050 printf("%s%s",
2051 enumIndex ? "|" : "",
2052 parm_table[parmIndex].enum_list[enumIndex].name);
2055 printf(",");
2056 hadFlag = false;
2057 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2058 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2059 printf("%s%s",
2060 hadFlag ? "|" : "",
2061 flag_names[flagIndex]);
2062 hadFlag = true;
2066 /* output synonyms */
2067 hadSyn = false;
2068 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2069 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2070 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2071 parm_table[parmIndex2].label);
2072 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2073 if (!hadSyn) {
2074 printf(" (synonyms: ");
2075 hadSyn = true;
2076 } else {
2077 printf(", ");
2079 printf("%s%s", parm_table[parmIndex2].label,
2080 inverse ? "[i]" : "");
2083 if (hadSyn) {
2084 printf(")");
2087 printf("\n");
2090 /***************************************************************************
2091 Show all parameter's name, type, [values,] and flags.
2092 ***************************************************************************/
2094 void show_parameter_list(void)
2096 int classIndex, parmIndex;
2097 const char *section_names[] = { "local", "global", NULL};
2099 for (classIndex=0; section_names[classIndex]; classIndex++) {
2100 printf("[%s]\n", section_names[classIndex]);
2101 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2102 if (parm_table[parmIndex].p_class == classIndex) {
2103 show_parameter(parmIndex);
2109 /***************************************************************************
2110 Check if a given string correctly represents a boolean value.
2111 ***************************************************************************/
2113 bool lp_string_is_valid_boolean(const char *parm_value)
2115 return set_boolean(parm_value, NULL);
2118 /***************************************************************************
2119 Get the standard string representation of a boolean value ("yes" or "no")
2120 ***************************************************************************/
2122 static const char *get_boolean(bool bool_value)
2124 static const char *yes_str = "yes";
2125 static const char *no_str = "no";
2127 return (bool_value ? yes_str : no_str);
2130 /***************************************************************************
2131 Provide the string of the negated boolean value associated to the boolean
2132 given as a string. Returns false if the passed string does not correctly
2133 represent a boolean.
2134 ***************************************************************************/
2136 bool lp_invert_boolean(const char *str, const char **inverse_str)
2138 bool val;
2140 if (!set_boolean(str, &val)) {
2141 return false;
2144 *inverse_str = get_boolean(!val);
2145 return true;
2148 /***************************************************************************
2149 Provide the canonical string representation of a boolean value given
2150 as a string. Return true on success, false if the string given does
2151 not correctly represent a boolean.
2152 ***************************************************************************/
2154 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2156 bool val;
2158 if (!set_boolean(str, &val)) {
2159 return false;
2162 *canon_str = get_boolean(val);
2163 return true;
2166 /***************************************************************************
2167 Find a service by name. Otherwise works like get_service.
2168 ***************************************************************************/
2170 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2172 int iService = -1;
2173 char *canon_name;
2174 TDB_DATA data;
2175 NTSTATUS status;
2177 if (ServiceHash == NULL) {
2178 return -1;
2181 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2183 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2184 &data);
2186 if (NT_STATUS_IS_OK(status) &&
2187 (data.dptr != NULL) &&
2188 (data.dsize == sizeof(iService)))
2190 iService = *(int *)data.dptr;
2193 TALLOC_FREE(canon_name);
2195 if ((iService != -1) && (LP_SNUM_OK(iService))
2196 && (pserviceDest != NULL)) {
2197 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2200 return (iService);
2203 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2204 struct loadparm_service *lp_service(const char *pszServiceName)
2206 int iService = getservicebyname(pszServiceName, NULL);
2207 if (iService == -1 || !LP_SNUM_OK(iService)) {
2208 return NULL;
2210 return ServicePtrs[iService];
2213 struct loadparm_service *lp_servicebynum(int snum)
2215 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2216 return NULL;
2218 return ServicePtrs[snum];
2221 struct loadparm_service *lp_default_loadparm_service()
2223 return &sDefault;
2227 /***************************************************************************
2228 Copy a service structure to another.
2229 If pcopymapDest is NULL then copy all fields
2230 ***************************************************************************/
2233 * Add a parametric option to a parmlist_entry,
2234 * replacing old value, if already present.
2236 static void set_param_opt(struct parmlist_entry **opt_list,
2237 const char *opt_name,
2238 const char *opt_value,
2239 unsigned priority)
2241 struct parmlist_entry *new_opt, *opt;
2242 bool not_added;
2244 opt = *opt_list;
2245 not_added = true;
2247 /* Traverse destination */
2248 while (opt) {
2249 /* If we already have same option, override it */
2250 if (strwicmp(opt->key, opt_name) == 0) {
2251 if ((opt->priority & FLAG_CMDLINE) &&
2252 !(priority & FLAG_CMDLINE)) {
2253 /* it's been marked as not to be
2254 overridden */
2255 return;
2257 string_free(&opt->value);
2258 TALLOC_FREE(opt->list);
2259 opt->value = SMB_STRDUP(opt_value);
2260 opt->priority = priority;
2261 not_added = false;
2262 break;
2264 opt = opt->next;
2266 if (not_added) {
2267 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2268 new_opt->key = SMB_STRDUP(opt_name);
2269 new_opt->value = SMB_STRDUP(opt_value);
2270 new_opt->list = NULL;
2271 new_opt->priority = priority;
2272 DLIST_ADD(*opt_list, new_opt);
2276 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2277 struct bitmap *pcopymapDest)
2279 int i;
2280 bool bcopyall = (pcopymapDest == NULL);
2281 struct parmlist_entry *data;
2283 for (i = 0; parm_table[i].label; i++)
2284 if (parm_table[i].p_class == P_LOCAL &&
2285 (bcopyall || bitmap_query(pcopymapDest,i))) {
2286 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2287 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2289 switch (parm_table[i].type) {
2290 case P_BOOL:
2291 case P_BOOLREV:
2292 *(bool *)dest_ptr = *(bool *)src_ptr;
2293 break;
2295 case P_INTEGER:
2296 case P_ENUM:
2297 case P_OCTAL:
2298 case P_BYTES:
2299 *(int *)dest_ptr = *(int *)src_ptr;
2300 break;
2302 case P_CHAR:
2303 *(char *)dest_ptr = *(char *)src_ptr;
2304 break;
2306 case P_STRING:
2307 string_set((char **)dest_ptr,
2308 *(char **)src_ptr);
2309 break;
2311 case P_USTRING:
2313 char *upper_string = strupper_talloc(talloc_tos(),
2314 *(char **)src_ptr);
2315 string_set((char **)dest_ptr,
2316 upper_string);
2317 TALLOC_FREE(upper_string);
2318 break;
2320 case P_LIST:
2321 TALLOC_FREE(*((char ***)dest_ptr));
2322 *((char ***)dest_ptr) = str_list_copy(NULL,
2323 *(const char ***)src_ptr);
2324 break;
2325 default:
2326 break;
2330 if (bcopyall) {
2331 init_copymap(pserviceDest);
2332 if (pserviceSource->copymap)
2333 bitmap_copy(pserviceDest->copymap,
2334 pserviceSource->copymap);
2337 data = pserviceSource->param_opt;
2338 while (data) {
2339 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2340 data = data->next;
2344 /***************************************************************************
2345 Check a service for consistency. Return false if the service is in any way
2346 incomplete or faulty, else true.
2347 ***************************************************************************/
2349 bool service_ok(int iService)
2351 bool bRetval;
2353 bRetval = true;
2354 if (ServicePtrs[iService]->szService[0] == '\0') {
2355 DEBUG(0, ("The following message indicates an internal error:\n"));
2356 DEBUG(0, ("No service name in service entry.\n"));
2357 bRetval = false;
2360 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2361 /* I can't see why you'd want a non-printable printer service... */
2362 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2363 if (!ServicePtrs[iService]->printable) {
2364 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2365 ServicePtrs[iService]->szService));
2366 ServicePtrs[iService]->printable = true;
2368 /* [printers] service must also be non-browsable. */
2369 if (ServicePtrs[iService]->browseable)
2370 ServicePtrs[iService]->browseable = false;
2373 if (ServicePtrs[iService]->path[0] == '\0' &&
2374 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2375 ServicePtrs[iService]->msdfs_proxy[0] == '\0'
2377 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2378 ServicePtrs[iService]->szService));
2379 ServicePtrs[iService]->bAvailable = false;
2382 /* If a service is flagged unavailable, log the fact at level 1. */
2383 if (!ServicePtrs[iService]->bAvailable)
2384 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2385 ServicePtrs[iService]->szService));
2387 return (bRetval);
2390 static struct smbconf_ctx *lp_smbconf_ctx(void)
2392 sbcErr err;
2393 static struct smbconf_ctx *conf_ctx = NULL;
2395 if (conf_ctx == NULL) {
2396 err = smbconf_init(NULL, &conf_ctx, "registry:");
2397 if (!SBC_ERROR_IS_OK(err)) {
2398 DEBUG(1, ("error initializing registry configuration: "
2399 "%s\n", sbcErrorString(err)));
2400 conf_ctx = NULL;
2404 return conf_ctx;
2407 static bool process_smbconf_service(struct smbconf_service *service)
2409 uint32_t count;
2410 bool ret;
2412 if (service == NULL) {
2413 return false;
2416 ret = do_section(service->name, NULL);
2417 if (ret != true) {
2418 return false;
2420 for (count = 0; count < service->num_params; count++) {
2421 ret = do_parameter(service->param_names[count],
2422 service->param_values[count],
2423 NULL);
2424 if (ret != true) {
2425 return false;
2428 if (iServiceIndex >= 0) {
2429 return service_ok(iServiceIndex);
2431 return true;
2435 * load a service from registry and activate it
2437 bool process_registry_service(const char *service_name)
2439 sbcErr err;
2440 struct smbconf_service *service = NULL;
2441 TALLOC_CTX *mem_ctx = talloc_stackframe();
2442 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2443 bool ret = false;
2445 if (conf_ctx == NULL) {
2446 goto done;
2449 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2451 if (!smbconf_share_exists(conf_ctx, service_name)) {
2453 * Registry does not contain data for this service (yet),
2454 * but make sure lp_load doesn't return false.
2456 ret = true;
2457 goto done;
2460 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2461 if (!SBC_ERROR_IS_OK(err)) {
2462 goto done;
2465 ret = process_smbconf_service(service);
2466 if (!ret) {
2467 goto done;
2470 /* store the csn */
2471 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2473 done:
2474 TALLOC_FREE(mem_ctx);
2475 return ret;
2479 * process_registry_globals
2481 static bool process_registry_globals(void)
2483 bool ret;
2485 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2487 ret = do_parameter("registry shares", "yes", NULL);
2488 if (!ret) {
2489 return ret;
2492 return process_registry_service(GLOBAL_NAME);
2495 bool process_registry_shares(void)
2497 sbcErr err;
2498 uint32_t count;
2499 struct smbconf_service **service = NULL;
2500 uint32_t num_shares = 0;
2501 TALLOC_CTX *mem_ctx = talloc_stackframe();
2502 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2503 bool ret = false;
2505 if (conf_ctx == NULL) {
2506 goto done;
2509 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2510 if (!SBC_ERROR_IS_OK(err)) {
2511 goto done;
2514 ret = true;
2516 for (count = 0; count < num_shares; count++) {
2517 if (strequal(service[count]->name, GLOBAL_NAME)) {
2518 continue;
2520 ret = process_smbconf_service(service[count]);
2521 if (!ret) {
2522 goto done;
2526 /* store the csn */
2527 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2529 done:
2530 TALLOC_FREE(mem_ctx);
2531 return ret;
2535 * reload those shares from registry that are already
2536 * activated in the services array.
2538 static bool reload_registry_shares(void)
2540 int i;
2541 bool ret = true;
2543 for (i = 0; i < iNumServices; i++) {
2544 if (!VALID(i)) {
2545 continue;
2548 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2549 continue;
2552 ret = process_registry_service(ServicePtrs[i]->szService);
2553 if (!ret) {
2554 goto done;
2558 done:
2559 return ret;
2563 #define MAX_INCLUDE_DEPTH 100
2565 static uint8_t include_depth;
2567 static struct file_lists {
2568 struct file_lists *next;
2569 char *name;
2570 char *subfname;
2571 time_t modtime;
2572 } *file_lists = NULL;
2574 /*******************************************************************
2575 Keep a linked list of all config files so we know when one has changed
2576 it's date and needs to be reloaded.
2577 ********************************************************************/
2579 static void add_to_file_list(const char *fname, const char *subfname)
2581 struct file_lists *f = file_lists;
2583 while (f) {
2584 if (f->name && !strcmp(f->name, fname))
2585 break;
2586 f = f->next;
2589 if (!f) {
2590 f = SMB_MALLOC_P(struct file_lists);
2591 if (!f)
2592 return;
2593 f->next = file_lists;
2594 f->name = SMB_STRDUP(fname);
2595 if (!f->name) {
2596 SAFE_FREE(f);
2597 return;
2599 f->subfname = SMB_STRDUP(subfname);
2600 if (!f->subfname) {
2601 SAFE_FREE(f->name);
2602 SAFE_FREE(f);
2603 return;
2605 file_lists = f;
2606 f->modtime = file_modtime(subfname);
2607 } else {
2608 time_t t = file_modtime(subfname);
2609 if (t)
2610 f->modtime = t;
2612 return;
2616 * Free the file lists
2618 static void free_file_list(void)
2620 struct file_lists *f;
2621 struct file_lists *next;
2623 f = file_lists;
2624 while( f ) {
2625 next = f->next;
2626 SAFE_FREE( f->name );
2627 SAFE_FREE( f->subfname );
2628 SAFE_FREE( f );
2629 f = next;
2631 file_lists = NULL;
2636 * Utility function for outsiders to check if we're running on registry.
2638 bool lp_config_backend_is_registry(void)
2640 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2644 * Utility function to check if the config backend is FILE.
2646 bool lp_config_backend_is_file(void)
2648 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2651 /*******************************************************************
2652 Check if a config file has changed date.
2653 ********************************************************************/
2655 bool lp_file_list_changed(void)
2657 struct file_lists *f = file_lists;
2659 DEBUG(6, ("lp_file_list_changed()\n"));
2661 while (f) {
2662 time_t mod_time;
2664 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2665 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2667 if (conf_ctx == NULL) {
2668 return false;
2670 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2671 NULL))
2673 DEBUGADD(6, ("registry config changed\n"));
2674 return true;
2676 } else {
2677 char *n2 = NULL;
2678 n2 = talloc_sub_basic(talloc_tos(),
2679 get_current_username(),
2680 current_user_info.domain,
2681 f->name);
2682 if (!n2) {
2683 return false;
2685 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2686 f->name, n2, ctime(&f->modtime)));
2688 mod_time = file_modtime(n2);
2690 if (mod_time &&
2691 ((f->modtime != mod_time) ||
2692 (f->subfname == NULL) ||
2693 (strcmp(n2, f->subfname) != 0)))
2695 DEBUGADD(6,
2696 ("file %s modified: %s\n", n2,
2697 ctime(&mod_time)));
2698 f->modtime = mod_time;
2699 SAFE_FREE(f->subfname);
2700 f->subfname = SMB_STRDUP(n2);
2701 TALLOC_FREE(n2);
2702 return true;
2704 TALLOC_FREE(n2);
2706 f = f->next;
2708 return false;
2713 * Initialize iconv conversion descriptors.
2715 * This is called the first time it is needed, and also called again
2716 * every time the configuration is reloaded, because the charset or
2717 * codepage might have changed.
2719 static void init_iconv(void)
2721 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2722 lp_unix_charset(),
2723 true, global_iconv_handle);
2726 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2728 if (strcmp(*ptr, pszParmValue) != 0) {
2729 string_set(ptr, pszParmValue);
2730 init_iconv();
2732 return true;
2735 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2737 bool is_utf8 = false;
2738 size_t len = strlen(pszParmValue);
2740 if (len == 4 || len == 5) {
2741 /* Don't use StrCaseCmp here as we don't want to
2742 initialize iconv. */
2743 if ((toupper_m(pszParmValue[0]) == 'U') &&
2744 (toupper_m(pszParmValue[1]) == 'T') &&
2745 (toupper_m(pszParmValue[2]) == 'F')) {
2746 if (len == 4) {
2747 if (pszParmValue[3] == '8') {
2748 is_utf8 = true;
2750 } else {
2751 if (pszParmValue[3] == '-' &&
2752 pszParmValue[4] == '8') {
2753 is_utf8 = true;
2759 if (strcmp(*ptr, pszParmValue) != 0) {
2760 if (is_utf8) {
2761 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2762 "be UTF8, using (default value) %s instead.\n",
2763 DEFAULT_DOS_CHARSET));
2764 pszParmValue = DEFAULT_DOS_CHARSET;
2766 string_set(ptr, pszParmValue);
2767 init_iconv();
2769 return true;
2772 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2774 bool ret = true;
2775 TALLOC_CTX *frame = talloc_stackframe();
2776 char *realm = strupper_talloc(frame, pszParmValue);
2777 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2779 ret &= string_set(&Globals.realm_original, pszParmValue);
2780 ret &= string_set(&Globals.realm, realm);
2781 ret &= string_set(&Globals.dnsdomain, dnsdomain);
2782 TALLOC_FREE(frame);
2784 return ret;
2787 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2789 TALLOC_FREE(Globals.netbios_aliases);
2790 Globals.netbios_aliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2791 return set_netbios_aliases(Globals.netbios_aliases);
2794 /***************************************************************************
2795 Handle the include operation.
2796 ***************************************************************************/
2797 static bool bAllowIncludeRegistry = true;
2799 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2801 char *fname;
2803 if (include_depth >= MAX_INCLUDE_DEPTH) {
2804 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2805 include_depth));
2806 return false;
2809 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2810 if (!bAllowIncludeRegistry) {
2811 return true;
2813 if (bInGlobalSection) {
2814 bool ret;
2815 include_depth++;
2816 ret = process_registry_globals();
2817 include_depth--;
2818 return ret;
2819 } else {
2820 DEBUG(1, ("\"include = registry\" only effective "
2821 "in %s section\n", GLOBAL_NAME));
2822 return false;
2826 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2827 current_user_info.domain,
2828 pszParmValue);
2830 add_to_file_list(pszParmValue, fname);
2832 string_set(ptr, fname);
2834 if (file_exist(fname)) {
2835 bool ret;
2836 include_depth++;
2837 ret = pm_process(fname, do_section, do_parameter, NULL);
2838 include_depth--;
2839 TALLOC_FREE(fname);
2840 return ret;
2843 DEBUG(2, ("Can't find include file %s\n", fname));
2844 TALLOC_FREE(fname);
2845 return true;
2848 /***************************************************************************
2849 Handle the interpretation of the copy parameter.
2850 ***************************************************************************/
2852 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2854 bool bRetval;
2855 int iTemp;
2856 struct loadparm_service serviceTemp;
2858 string_set(ptr, pszParmValue);
2860 init_service(&serviceTemp);
2862 bRetval = false;
2864 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2866 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2867 if (iTemp == iServiceIndex) {
2868 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2869 } else {
2870 copy_service(ServicePtrs[iServiceIndex],
2871 &serviceTemp,
2872 ServicePtrs[iServiceIndex]->copymap);
2873 bRetval = true;
2875 } else {
2876 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2877 bRetval = false;
2880 free_service(&serviceTemp);
2881 return (bRetval);
2884 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2886 Globals.ldap_debug_level = lp_int(pszParmValue);
2887 init_ldap_debugging();
2888 return true;
2892 * idmap related parameters
2895 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2897 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2899 return true;
2902 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2904 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2906 return true;
2909 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2911 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2913 return true;
2916 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2918 char *config_option = NULL;
2919 const char *range = NULL;
2920 bool ret = false;
2922 SMB_ASSERT(low != NULL);
2923 SMB_ASSERT(high != NULL);
2925 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2926 domain_name = "*";
2929 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2930 domain_name);
2931 if (config_option == NULL) {
2932 DEBUG(0, ("out of memory\n"));
2933 return false;
2936 range = lp_parm_const_string(-1, config_option, "range", NULL);
2937 if (range == NULL) {
2938 DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2939 goto done;
2942 if (sscanf(range, "%u - %u", low, high) != 2) {
2943 DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2944 range, domain_name));
2945 goto done;
2948 ret = true;
2950 done:
2951 talloc_free(config_option);
2952 return ret;
2956 bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2958 return lp_idmap_range("*", low, high);
2961 const char *lp_idmap_backend(const char *domain_name)
2963 char *config_option = NULL;
2964 const char *backend = NULL;
2966 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2967 domain_name = "*";
2970 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2971 domain_name);
2972 if (config_option == NULL) {
2973 DEBUG(0, ("out of memory\n"));
2974 return false;
2977 backend = lp_parm_const_string(-1, config_option, "backend", NULL);
2978 if (backend == NULL) {
2979 DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
2980 goto done;
2983 done:
2984 talloc_free(config_option);
2985 return backend;
2988 const char *lp_idmap_default_backend(void)
2990 return lp_idmap_backend("*");
2993 /***************************************************************************
2994 Handle the DEBUG level list.
2995 ***************************************************************************/
2997 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2999 string_set(ptr, pszParmValueIn);
3000 return debug_parse_levels(pszParmValueIn);
3003 /***************************************************************************
3004 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3005 ***************************************************************************/
3007 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
3009 const char *suffix_string;
3011 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
3012 Globals.ldap_suffix );
3013 if ( !suffix_string ) {
3014 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3015 return "";
3018 return suffix_string;
3021 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
3023 if (Globals.szLdapMachineSuffix[0])
3024 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
3026 return lp_string(ctx, Globals.ldap_suffix);
3029 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
3031 if (Globals.szLdapUserSuffix[0])
3032 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3034 return lp_string(ctx, Globals.ldap_suffix);
3037 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3039 if (Globals.szLdapGroupSuffix[0])
3040 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3042 return lp_string(ctx, Globals.ldap_suffix);
3045 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3047 if (Globals.szLdapIdmapSuffix[0])
3048 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3050 return lp_string(ctx, Globals.ldap_suffix);
3053 /****************************************************************************
3054 set the value for a P_ENUM
3055 ***************************************************************************/
3057 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3058 int *ptr )
3060 int i;
3062 for (i = 0; parm->enum_list[i].name; i++) {
3063 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3064 *ptr = parm->enum_list[i].value;
3065 return;
3068 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3069 pszParmValue, parm->label));
3072 /***************************************************************************
3073 ***************************************************************************/
3075 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3077 static int parm_num = -1;
3078 struct loadparm_service *s;
3080 if ( parm_num == -1 )
3081 parm_num = lpcfg_map_parameter( "printing" );
3083 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3085 if ( snum < 0 )
3086 s = &sDefault;
3087 else
3088 s = ServicePtrs[snum];
3090 init_printer_values( s );
3092 return true;
3096 /***************************************************************************
3097 Initialise a copymap.
3098 ***************************************************************************/
3100 static void init_copymap(struct loadparm_service *pservice)
3102 int i;
3104 TALLOC_FREE(pservice->copymap);
3106 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3107 if (!pservice->copymap)
3108 DEBUG(0,
3109 ("Couldn't allocate copymap!! (size %d)\n",
3110 (int)NUMPARAMETERS));
3111 else
3112 for (i = 0; i < NUMPARAMETERS; i++)
3113 bitmap_set(pservice->copymap, i);
3117 return the parameter pointer for a parameter
3119 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3121 if (service == NULL) {
3122 if (parm->p_class == P_LOCAL)
3123 return (void *)(((char *)&sDefault)+parm->offset);
3124 else if (parm->p_class == P_GLOBAL)
3125 return (void *)(((char *)&Globals)+parm->offset);
3126 else return NULL;
3127 } else {
3128 return (void *)(((char *)service) + parm->offset);
3132 /***************************************************************************
3133 Return the local pointer to a parameter given the service number and parameter
3134 ***************************************************************************/
3136 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3138 return lp_parm_ptr(ServicePtrs[snum], parm);
3141 /***************************************************************************
3142 Process a parameter for a particular service number. If snum < 0
3143 then assume we are in the globals.
3144 ***************************************************************************/
3146 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3148 int parmnum, i;
3149 void *parm_ptr = NULL; /* where we are going to store the result */
3150 struct parmlist_entry **opt_list;
3152 parmnum = lpcfg_map_parameter(pszParmName);
3154 if (parmnum < 0) {
3155 if (strchr(pszParmName, ':') == NULL) {
3156 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3157 pszParmName));
3158 return true;
3162 * We've got a parametric option
3165 opt_list = (snum < 0)
3166 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3167 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3169 return true;
3172 /* if it's already been set by the command line, then we don't
3173 override here */
3174 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3175 return true;
3178 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3179 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3180 pszParmName));
3183 /* we might point at a service, the default service or a global */
3184 if (snum < 0) {
3185 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3186 } else {
3187 if (parm_table[parmnum].p_class == P_GLOBAL) {
3188 DEBUG(0,
3189 ("Global parameter %s found in service section!\n",
3190 pszParmName));
3191 return true;
3193 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3196 if (snum >= 0) {
3197 if (!ServicePtrs[snum]->copymap)
3198 init_copymap(ServicePtrs[snum]);
3200 /* this handles the aliases - set the copymap for other entries with
3201 the same data pointer */
3202 for (i = 0; parm_table[i].label; i++) {
3203 if ((parm_table[i].offset == parm_table[parmnum].offset)
3204 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3205 bitmap_clear(ServicePtrs[snum]->copymap, i);
3210 /* if it is a special case then go ahead */
3211 if (parm_table[parmnum].special) {
3212 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3213 (char **)parm_ptr);
3216 /* now switch on the type of variable it is */
3217 switch (parm_table[parmnum].type)
3219 case P_BOOL:
3220 *(bool *)parm_ptr = lp_bool(pszParmValue);
3221 break;
3223 case P_BOOLREV:
3224 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3225 break;
3227 case P_INTEGER:
3228 *(int *)parm_ptr = lp_int(pszParmValue);
3229 break;
3231 case P_CHAR:
3232 *(char *)parm_ptr = *pszParmValue;
3233 break;
3235 case P_OCTAL:
3236 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3237 if ( i != 1 ) {
3238 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3240 break;
3242 case P_BYTES:
3244 uint64_t val;
3245 if (conv_str_size_error(pszParmValue, &val)) {
3246 if (val <= INT_MAX) {
3247 *(int *)parm_ptr = (int)val;
3248 break;
3252 DEBUG(0,("lp_do_parameter(%s): value is not "
3253 "a valid size specifier!\n", pszParmValue));
3254 return false;
3257 case P_LIST:
3258 case P_CMDLIST:
3259 TALLOC_FREE(*((char ***)parm_ptr));
3260 *(char ***)parm_ptr = str_list_make_v3(
3261 NULL, pszParmValue, NULL);
3262 break;
3264 case P_STRING:
3265 string_set((char **)parm_ptr, pszParmValue);
3266 break;
3268 case P_USTRING:
3270 char *upper_string = strupper_talloc(talloc_tos(),
3271 pszParmValue);
3272 string_set((char **)parm_ptr, upper_string);
3273 TALLOC_FREE(upper_string);
3274 break;
3276 case P_ENUM:
3277 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3278 break;
3279 case P_SEP:
3280 break;
3283 return true;
3286 /***************************************************************************
3287 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3288 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3289 ***************************************************************************/
3291 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3293 int parmnum, i;
3294 parmnum = lpcfg_map_parameter(pszParmName);
3295 if (parmnum >= 0) {
3296 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3297 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3298 return false;
3300 parm_table[parmnum].flags |= FLAG_CMDLINE;
3302 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3303 * be grouped in the table, so we don't have to search the
3304 * whole table */
3305 for (i=parmnum-1;
3306 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3307 && parm_table[i].p_class == parm_table[parmnum].p_class;
3308 i--) {
3309 parm_table[i].flags |= FLAG_CMDLINE;
3311 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3312 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3313 parm_table[i].flags |= FLAG_CMDLINE;
3316 if (store_values) {
3317 store_lp_set_cmdline(pszParmName, pszParmValue);
3319 return true;
3322 /* it might be parametric */
3323 if (strchr(pszParmName, ':') != NULL) {
3324 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3325 if (store_values) {
3326 store_lp_set_cmdline(pszParmName, pszParmValue);
3328 return true;
3331 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3332 return true;
3335 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3337 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3340 /***************************************************************************
3341 Process a parameter.
3342 ***************************************************************************/
3344 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3345 void *userdata)
3347 if (!bInGlobalSection && bGlobalOnly)
3348 return true;
3350 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3352 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3353 pszParmName, pszParmValue));
3357 set a option from the commandline in 'a=b' format. Use to support --option
3359 bool lp_set_option(const char *option)
3361 char *p, *s;
3362 bool ret;
3364 s = talloc_strdup(NULL, option);
3365 if (!s) {
3366 return false;
3369 p = strchr(s, '=');
3370 if (!p) {
3371 talloc_free(s);
3372 return false;
3375 *p = 0;
3377 /* skip white spaces after the = sign */
3378 do {
3379 p++;
3380 } while (*p == ' ');
3382 ret = lp_set_cmdline(s, p);
3383 talloc_free(s);
3384 return ret;
3387 /***************************************************************************
3388 Initialize any local variables in the sDefault table, after parsing a
3389 [globals] section.
3390 ***************************************************************************/
3392 static void init_locals(void)
3395 * We run this check once the [globals] is parsed, to force
3396 * the VFS objects and other per-share settings we need for
3397 * the standard way a AD DC is operated. We may change these
3398 * as our code evolves, which is why we force these settings.
3400 * We can't do this at the end of lp_load_ex(), as by that
3401 * point the services have been loaded and they will already
3402 * have "" as their vfs objects.
3404 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
3405 const char **vfs_objects = lp_vfs_objects(-1);
3406 if (!vfs_objects || !vfs_objects[0]) {
3407 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
3408 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
3409 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
3410 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
3411 } else {
3412 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
3416 lp_do_parameter(-1, "map hidden", "no");
3417 lp_do_parameter(-1, "map system", "no");
3418 lp_do_parameter(-1, "map readonly", "no");
3419 lp_do_parameter(-1, "map archive", "no");
3420 lp_do_parameter(-1, "store dos attributes", "yes");
3424 /***************************************************************************
3425 Process a new section (service). At this stage all sections are services.
3426 Later we'll have special sections that permit server parameters to be set.
3427 Returns true on success, false on failure.
3428 ***************************************************************************/
3430 static bool do_section(const char *pszSectionName, void *userdata)
3432 bool bRetval;
3433 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3434 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3435 bRetval = false;
3437 /* if we were in a global section then do the local inits */
3438 if (bInGlobalSection && !isglobal)
3439 init_locals();
3441 /* if we've just struck a global section, note the fact. */
3442 bInGlobalSection = isglobal;
3444 /* check for multiple global sections */
3445 if (bInGlobalSection) {
3446 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3447 return true;
3450 if (!bInGlobalSection && bGlobalOnly)
3451 return true;
3453 /* if we have a current service, tidy it up before moving on */
3454 bRetval = true;
3456 if (iServiceIndex >= 0)
3457 bRetval = service_ok(iServiceIndex);
3459 /* if all is still well, move to the next record in the services array */
3460 if (bRetval) {
3461 /* We put this here to avoid an odd message order if messages are */
3462 /* issued by the post-processing of a previous section. */
3463 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3465 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3466 if (iServiceIndex < 0) {
3467 DEBUG(0, ("Failed to add a new service\n"));
3468 return false;
3470 /* Clean all parametric options for service */
3471 /* They will be added during parsing again */
3472 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3475 return bRetval;
3479 /***************************************************************************
3480 Determine if a partcular base parameter is currentl set to the default value.
3481 ***************************************************************************/
3483 static bool is_default(int i)
3485 switch (parm_table[i].type) {
3486 case P_LIST:
3487 case P_CMDLIST:
3488 return str_list_equal((const char **)parm_table[i].def.lvalue,
3489 *(const char ***)lp_parm_ptr(NULL,
3490 &parm_table[i]));
3491 case P_STRING:
3492 case P_USTRING:
3493 return strequal(parm_table[i].def.svalue,
3494 *(char **)lp_parm_ptr(NULL,
3495 &parm_table[i]));
3496 case P_BOOL:
3497 case P_BOOLREV:
3498 return parm_table[i].def.bvalue ==
3499 *(bool *)lp_parm_ptr(NULL,
3500 &parm_table[i]);
3501 case P_CHAR:
3502 return parm_table[i].def.cvalue ==
3503 *(char *)lp_parm_ptr(NULL,
3504 &parm_table[i]);
3505 case P_INTEGER:
3506 case P_OCTAL:
3507 case P_ENUM:
3508 case P_BYTES:
3509 return parm_table[i].def.ivalue ==
3510 *(int *)lp_parm_ptr(NULL,
3511 &parm_table[i]);
3512 case P_SEP:
3513 break;
3515 return false;
3518 /***************************************************************************
3519 Display the contents of the global structure.
3520 ***************************************************************************/
3522 static void dump_globals(FILE *f)
3524 int i;
3525 struct parmlist_entry *data;
3527 fprintf(f, "[global]\n");
3529 for (i = 0; parm_table[i].label; i++)
3530 if (parm_table[i].p_class == P_GLOBAL &&
3531 !(parm_table[i].flags & FLAG_META) &&
3532 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3533 if (defaults_saved && is_default(i))
3534 continue;
3535 fprintf(f, "\t%s = ", parm_table[i].label);
3536 lpcfg_print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3537 &parm_table[i]),
3539 fprintf(f, "\n");
3541 if (Globals.param_opt != NULL) {
3542 data = Globals.param_opt;
3543 while(data) {
3544 fprintf(f, "\t%s = %s\n", data->key, data->value);
3545 data = data->next;
3551 /***************************************************************************
3552 Display the contents of a single services record.
3553 ***************************************************************************/
3555 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3557 int i;
3558 struct parmlist_entry *data;
3560 if (pService != &sDefault)
3561 fprintf(f, "[%s]\n", pService->szService);
3563 for (i = 0; parm_table[i].label; i++) {
3565 if (parm_table[i].p_class == P_LOCAL &&
3566 !(parm_table[i].flags & FLAG_META) &&
3567 (*parm_table[i].label != '-') &&
3568 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3570 if (pService == &sDefault) {
3571 if (defaults_saved && is_default(i))
3572 continue;
3573 } else {
3574 if (lpcfg_equal_parameter(parm_table[i].type,
3575 lp_parm_ptr(pService, &parm_table[i]),
3576 lp_parm_ptr(NULL, &parm_table[i])))
3577 continue;
3580 fprintf(f, "\t%s = ", parm_table[i].label);
3581 lpcfg_print_parameter(&parm_table[i],
3582 lp_parm_ptr(pService, &parm_table[i]),
3584 fprintf(f, "\n");
3588 if (pService->param_opt != NULL) {
3589 data = pService->param_opt;
3590 while(data) {
3591 fprintf(f, "\t%s = %s\n", data->key, data->value);
3592 data = data->next;
3597 /***************************************************************************
3598 Display the contents of a parameter of a single services record.
3599 ***************************************************************************/
3601 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3603 bool result = false;
3604 fstring local_parm_name;
3605 char *parm_opt;
3606 const char *parm_opt_value;
3608 struct loadparm_context *lp_ctx;
3610 /* check for parametrical option */
3611 fstrcpy( local_parm_name, parm_name);
3612 parm_opt = strchr( local_parm_name, ':');
3614 if (parm_opt) {
3615 *parm_opt = '\0';
3616 parm_opt++;
3617 if (strlen(parm_opt)) {
3618 parm_opt_value = lp_parm_const_string( snum,
3619 local_parm_name, parm_opt, NULL);
3620 if (parm_opt_value) {
3621 printf( "%s\n", parm_opt_value);
3622 result = true;
3625 return result;
3628 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
3629 if (lp_ctx == NULL) {
3630 return false;
3633 if (isGlobal) {
3634 result = lpcfg_dump_a_parameter(lp_ctx, NULL, parm_name, f);
3635 } else {
3636 result = lpcfg_dump_a_parameter(lp_ctx, ServicePtrs[snum], parm_name, f);
3638 TALLOC_FREE(lp_ctx);
3639 return result;
3642 /***************************************************************************
3643 Return info about the requested parameter (given as a string).
3644 Return NULL when the string is not a valid parameter name.
3645 ***************************************************************************/
3647 struct parm_struct *lp_get_parameter(const char *param_name)
3649 int num = lpcfg_map_parameter(param_name);
3651 if (num < 0) {
3652 return NULL;
3655 return &parm_table[num];
3658 #if 0
3659 /***************************************************************************
3660 Display the contents of a single copy structure.
3661 ***************************************************************************/
3662 static void dump_copy_map(bool *pcopymap)
3664 int i;
3665 if (!pcopymap)
3666 return;
3668 printf("\n\tNon-Copied parameters:\n");
3670 for (i = 0; parm_table[i].label; i++)
3671 if (parm_table[i].p_class == P_LOCAL &&
3672 parm_table[i].ptr && !pcopymap[i] &&
3673 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3675 printf("\t\t%s\n", parm_table[i].label);
3678 #endif
3680 /***************************************************************************
3681 Return TRUE if the passed service number is within range.
3682 ***************************************************************************/
3684 bool lp_snum_ok(int iService)
3686 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3689 /***************************************************************************
3690 Auto-load some home services.
3691 ***************************************************************************/
3693 static void lp_add_auto_services(char *str)
3695 char *s;
3696 char *p;
3697 int homes;
3698 char *saveptr;
3700 if (!str)
3701 return;
3703 s = SMB_STRDUP(str);
3704 if (!s)
3705 return;
3707 homes = lp_servicenumber(HOMES_NAME);
3709 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3710 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3711 char *home;
3713 if (lp_servicenumber(p) >= 0)
3714 continue;
3716 home = get_user_home_dir(talloc_tos(), p);
3718 if (home && home[0] && homes >= 0)
3719 lp_add_home(p, homes, p, home);
3721 TALLOC_FREE(home);
3723 SAFE_FREE(s);
3726 /***************************************************************************
3727 Auto-load one printer.
3728 ***************************************************************************/
3730 void lp_add_one_printer(const char *name, const char *comment,
3731 const char *location, void *pdata)
3733 int printers = lp_servicenumber(PRINTERS_NAME);
3734 int i;
3736 if (lp_servicenumber(name) < 0) {
3737 lp_add_printer(name, printers);
3738 if ((i = lp_servicenumber(name)) >= 0) {
3739 string_set(&ServicePtrs[i]->comment, comment);
3740 ServicePtrs[i]->autoloaded = true;
3745 /***************************************************************************
3746 Have we loaded a services file yet?
3747 ***************************************************************************/
3749 bool lp_loaded(void)
3751 return (bLoaded);
3754 /***************************************************************************
3755 Unload unused services.
3756 ***************************************************************************/
3758 void lp_killunused(struct smbd_server_connection *sconn,
3759 bool (*snumused) (struct smbd_server_connection *, int))
3761 int i;
3762 for (i = 0; i < iNumServices; i++) {
3763 if (!VALID(i))
3764 continue;
3766 /* don't kill autoloaded or usershare services */
3767 if ( ServicePtrs[i]->autoloaded ||
3768 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3769 continue;
3772 if (!snumused || !snumused(sconn, i)) {
3773 free_service_byindex(i);
3779 * Kill all except autoloaded and usershare services - convenience wrapper
3781 void lp_kill_all_services(void)
3783 lp_killunused(NULL, NULL);
3786 /***************************************************************************
3787 Unload a service.
3788 ***************************************************************************/
3790 void lp_killservice(int iServiceIn)
3792 if (VALID(iServiceIn)) {
3793 free_service_byindex(iServiceIn);
3797 /***************************************************************************
3798 Save the curent values of all global and sDefault parameters into the
3799 defaults union. This allows testparm to show only the
3800 changed (ie. non-default) parameters.
3801 ***************************************************************************/
3803 static void lp_save_defaults(void)
3805 int i;
3806 for (i = 0; parm_table[i].label; i++) {
3807 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3808 && parm_table[i].p_class == parm_table[i - 1].p_class)
3809 continue;
3810 switch (parm_table[i].type) {
3811 case P_LIST:
3812 case P_CMDLIST:
3813 parm_table[i].def.lvalue = str_list_copy(
3814 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3815 break;
3816 case P_STRING:
3817 case P_USTRING:
3818 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3819 break;
3820 case P_BOOL:
3821 case P_BOOLREV:
3822 parm_table[i].def.bvalue =
3823 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3824 break;
3825 case P_CHAR:
3826 parm_table[i].def.cvalue =
3827 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3828 break;
3829 case P_INTEGER:
3830 case P_OCTAL:
3831 case P_ENUM:
3832 case P_BYTES:
3833 parm_table[i].def.ivalue =
3834 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3835 break;
3836 case P_SEP:
3837 break;
3840 defaults_saved = true;
3843 /***********************************************************
3844 If we should send plaintext/LANMAN passwords in the clinet
3845 ************************************************************/
3847 static void set_allowed_client_auth(void)
3849 if (Globals.client_ntlmv2_auth) {
3850 Globals.client_lanman_auth = false;
3852 if (!Globals.client_lanman_auth) {
3853 Globals.client_plaintext_auth = false;
3857 /***************************************************************************
3858 JRA.
3859 The following code allows smbd to read a user defined share file.
3860 Yes, this is my intent. Yes, I'm comfortable with that...
3862 THE FOLLOWING IS SECURITY CRITICAL CODE.
3864 It washes your clothes, it cleans your house, it guards you while you sleep...
3865 Do not f%^k with it....
3866 ***************************************************************************/
3868 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3870 /***************************************************************************
3871 Check allowed stat state of a usershare file.
3872 Ensure we print out who is dicking with us so the admin can
3873 get their sorry ass fired.
3874 ***************************************************************************/
3876 static bool check_usershare_stat(const char *fname,
3877 const SMB_STRUCT_STAT *psbuf)
3879 if (!S_ISREG(psbuf->st_ex_mode)) {
3880 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3881 "not a regular file\n",
3882 fname, (unsigned int)psbuf->st_ex_uid ));
3883 return false;
3886 /* Ensure this doesn't have the other write bit set. */
3887 if (psbuf->st_ex_mode & S_IWOTH) {
3888 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
3889 "public write. Refusing to allow as a usershare file.\n",
3890 fname, (unsigned int)psbuf->st_ex_uid ));
3891 return false;
3894 /* Should be 10k or less. */
3895 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
3896 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3897 "too large (%u) to be a user share file.\n",
3898 fname, (unsigned int)psbuf->st_ex_uid,
3899 (unsigned int)psbuf->st_ex_size ));
3900 return false;
3903 return true;
3906 /***************************************************************************
3907 Parse the contents of a usershare file.
3908 ***************************************************************************/
3910 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
3911 SMB_STRUCT_STAT *psbuf,
3912 const char *servicename,
3913 int snum,
3914 char **lines,
3915 int numlines,
3916 char **pp_sharepath,
3917 char **pp_comment,
3918 char **pp_cp_servicename,
3919 struct security_descriptor **ppsd,
3920 bool *pallow_guest)
3922 const char **prefixallowlist = lp_usershare_prefix_allow_list();
3923 const char **prefixdenylist = lp_usershare_prefix_deny_list();
3924 int us_vers;
3925 DIR *dp;
3926 SMB_STRUCT_STAT sbuf;
3927 char *sharepath = NULL;
3928 char *comment = NULL;
3930 *pp_sharepath = NULL;
3931 *pp_comment = NULL;
3933 *pallow_guest = false;
3935 if (numlines < 4) {
3936 return USERSHARE_MALFORMED_FILE;
3939 if (strcmp(lines[0], "#VERSION 1") == 0) {
3940 us_vers = 1;
3941 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
3942 us_vers = 2;
3943 if (numlines < 5) {
3944 return USERSHARE_MALFORMED_FILE;
3946 } else {
3947 return USERSHARE_BAD_VERSION;
3950 if (strncmp(lines[1], "path=", 5) != 0) {
3951 return USERSHARE_MALFORMED_PATH;
3954 sharepath = talloc_strdup(ctx, &lines[1][5]);
3955 if (!sharepath) {
3956 return USERSHARE_POSIX_ERR;
3958 trim_string(sharepath, " ", " ");
3960 if (strncmp(lines[2], "comment=", 8) != 0) {
3961 return USERSHARE_MALFORMED_COMMENT_DEF;
3964 comment = talloc_strdup(ctx, &lines[2][8]);
3965 if (!comment) {
3966 return USERSHARE_POSIX_ERR;
3968 trim_string(comment, " ", " ");
3969 trim_char(comment, '"', '"');
3971 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
3972 return USERSHARE_MALFORMED_ACL_DEF;
3975 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
3976 return USERSHARE_ACL_ERR;
3979 if (us_vers == 2) {
3980 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
3981 return USERSHARE_MALFORMED_ACL_DEF;
3983 if (lines[4][9] == 'y') {
3984 *pallow_guest = true;
3987 /* Backwards compatible extension to file version #2. */
3988 if (numlines > 5) {
3989 if (strncmp(lines[5], "sharename=", 10) != 0) {
3990 return USERSHARE_MALFORMED_SHARENAME_DEF;
3992 if (!strequal(&lines[5][10], servicename)) {
3993 return USERSHARE_BAD_SHARENAME;
3995 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
3996 if (!*pp_cp_servicename) {
3997 return USERSHARE_POSIX_ERR;
4002 if (*pp_cp_servicename == NULL) {
4003 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4004 if (!*pp_cp_servicename) {
4005 return USERSHARE_POSIX_ERR;
4009 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->path) == 0)) {
4010 /* Path didn't change, no checks needed. */
4011 *pp_sharepath = sharepath;
4012 *pp_comment = comment;
4013 return USERSHARE_OK;
4016 /* The path *must* be absolute. */
4017 if (sharepath[0] != '/') {
4018 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4019 servicename, sharepath));
4020 return USERSHARE_PATH_NOT_ABSOLUTE;
4023 /* If there is a usershare prefix deny list ensure one of these paths
4024 doesn't match the start of the user given path. */
4025 if (prefixdenylist) {
4026 int i;
4027 for ( i=0; prefixdenylist[i]; i++ ) {
4028 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4029 servicename, i, prefixdenylist[i], sharepath ));
4030 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4031 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4032 "usershare prefix deny list entries.\n",
4033 servicename, sharepath));
4034 return USERSHARE_PATH_IS_DENIED;
4039 /* If there is a usershare prefix allow list ensure one of these paths
4040 does match the start of the user given path. */
4042 if (prefixallowlist) {
4043 int i;
4044 for ( i=0; prefixallowlist[i]; i++ ) {
4045 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4046 servicename, i, prefixallowlist[i], sharepath ));
4047 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4048 break;
4051 if (prefixallowlist[i] == NULL) {
4052 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4053 "usershare prefix allow list entries.\n",
4054 servicename, sharepath));
4055 return USERSHARE_PATH_NOT_ALLOWED;
4059 /* Ensure this is pointing to a directory. */
4060 dp = opendir(sharepath);
4062 if (!dp) {
4063 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4064 servicename, sharepath));
4065 return USERSHARE_PATH_NOT_DIRECTORY;
4068 /* Ensure the owner of the usershare file has permission to share
4069 this directory. */
4071 if (sys_stat(sharepath, &sbuf, false) == -1) {
4072 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4073 servicename, sharepath, strerror(errno) ));
4074 closedir(dp);
4075 return USERSHARE_POSIX_ERR;
4078 closedir(dp);
4080 if (!S_ISDIR(sbuf.st_ex_mode)) {
4081 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4082 servicename, sharepath ));
4083 return USERSHARE_PATH_NOT_DIRECTORY;
4086 /* Check if sharing is restricted to owner-only. */
4087 /* psbuf is the stat of the usershare definition file,
4088 sbuf is the stat of the target directory to be shared. */
4090 if (lp_usershare_owner_only()) {
4091 /* root can share anything. */
4092 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4093 return USERSHARE_PATH_NOT_ALLOWED;
4097 *pp_sharepath = sharepath;
4098 *pp_comment = comment;
4099 return USERSHARE_OK;
4102 /***************************************************************************
4103 Deal with a usershare file.
4104 Returns:
4105 >= 0 - snum
4106 -1 - Bad name, invalid contents.
4107 - service name already existed and not a usershare, problem
4108 with permissions to share directory etc.
4109 ***************************************************************************/
4111 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4113 SMB_STRUCT_STAT sbuf;
4114 SMB_STRUCT_STAT lsbuf;
4115 char *fname = NULL;
4116 char *sharepath = NULL;
4117 char *comment = NULL;
4118 char *cp_service_name = NULL;
4119 char **lines = NULL;
4120 int numlines = 0;
4121 int fd = -1;
4122 int iService = -1;
4123 TALLOC_CTX *ctx = talloc_stackframe();
4124 struct security_descriptor *psd = NULL;
4125 bool guest_ok = false;
4126 char *canon_name = NULL;
4127 bool added_service = false;
4128 int ret = -1;
4130 /* Ensure share name doesn't contain invalid characters. */
4131 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4132 DEBUG(0,("process_usershare_file: share name %s contains "
4133 "invalid characters (any of %s)\n",
4134 file_name, INVALID_SHARENAME_CHARS ));
4135 goto out;
4138 canon_name = canonicalize_servicename(ctx, file_name);
4139 if (!canon_name) {
4140 goto out;
4143 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4144 if (!fname) {
4145 goto out;
4148 /* Minimize the race condition by doing an lstat before we
4149 open and fstat. Ensure this isn't a symlink link. */
4151 if (sys_lstat(fname, &lsbuf, false) != 0) {
4152 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4153 fname, strerror(errno) ));
4154 goto out;
4157 /* This must be a regular file, not a symlink, directory or
4158 other strange filetype. */
4159 if (!check_usershare_stat(fname, &lsbuf)) {
4160 goto out;
4164 TDB_DATA data;
4165 NTSTATUS status;
4167 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4168 canon_name, &data);
4170 iService = -1;
4172 if (NT_STATUS_IS_OK(status) &&
4173 (data.dptr != NULL) &&
4174 (data.dsize == sizeof(iService))) {
4175 memcpy(&iService, data.dptr, sizeof(iService));
4179 if (iService != -1 &&
4180 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4181 &lsbuf.st_ex_mtime) == 0) {
4182 /* Nothing changed - Mark valid and return. */
4183 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4184 canon_name ));
4185 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4186 ret = iService;
4187 goto out;
4190 /* Try and open the file read only - no symlinks allowed. */
4191 #ifdef O_NOFOLLOW
4192 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4193 #else
4194 fd = open(fname, O_RDONLY, 0);
4195 #endif
4197 if (fd == -1) {
4198 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4199 fname, strerror(errno) ));
4200 goto out;
4203 /* Now fstat to be *SURE* it's a regular file. */
4204 if (sys_fstat(fd, &sbuf, false) != 0) {
4205 close(fd);
4206 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4207 fname, strerror(errno) ));
4208 goto out;
4211 /* Is it the same dev/inode as was lstated ? */
4212 if (!check_same_stat(&lsbuf, &sbuf)) {
4213 close(fd);
4214 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4215 "Symlink spoofing going on ?\n", fname ));
4216 goto out;
4219 /* This must be a regular file, not a symlink, directory or
4220 other strange filetype. */
4221 if (!check_usershare_stat(fname, &sbuf)) {
4222 close(fd);
4223 goto out;
4226 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4228 close(fd);
4229 if (lines == NULL) {
4230 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4231 fname, (unsigned int)sbuf.st_ex_uid ));
4232 goto out;
4235 if (parse_usershare_file(ctx, &sbuf, file_name,
4236 iService, lines, numlines, &sharepath,
4237 &comment, &cp_service_name,
4238 &psd, &guest_ok) != USERSHARE_OK) {
4239 goto out;
4242 /* Everything ok - add the service possibly using a template. */
4243 if (iService < 0) {
4244 const struct loadparm_service *sp = &sDefault;
4245 if (snum_template != -1) {
4246 sp = ServicePtrs[snum_template];
4249 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4250 DEBUG(0, ("process_usershare_file: Failed to add "
4251 "new service %s\n", cp_service_name));
4252 goto out;
4255 added_service = true;
4257 /* Read only is controlled by usershare ACL below. */
4258 ServicePtrs[iService]->read_only = false;
4261 /* Write the ACL of the new/modified share. */
4262 if (!set_share_security(canon_name, psd)) {
4263 DEBUG(0, ("process_usershare_file: Failed to set share "
4264 "security for user share %s\n",
4265 canon_name ));
4266 goto out;
4269 /* If from a template it may be marked invalid. */
4270 ServicePtrs[iService]->valid = true;
4272 /* Set the service as a valid usershare. */
4273 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4275 /* Set guest access. */
4276 if (lp_usershare_allow_guests()) {
4277 ServicePtrs[iService]->guest_ok = guest_ok;
4280 /* And note when it was loaded. */
4281 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4282 string_set(&ServicePtrs[iService]->path, sharepath);
4283 string_set(&ServicePtrs[iService]->comment, comment);
4285 ret = iService;
4287 out:
4289 if (ret == -1 && iService != -1 && added_service) {
4290 lp_remove_service(iService);
4293 TALLOC_FREE(lines);
4294 TALLOC_FREE(ctx);
4295 return ret;
4298 /***************************************************************************
4299 Checks if a usershare entry has been modified since last load.
4300 ***************************************************************************/
4302 static bool usershare_exists(int iService, struct timespec *last_mod)
4304 SMB_STRUCT_STAT lsbuf;
4305 const char *usersharepath = Globals.usershare_path;
4306 char *fname;
4308 if (asprintf(&fname, "%s/%s",
4309 usersharepath,
4310 ServicePtrs[iService]->szService) < 0) {
4311 return false;
4314 if (sys_lstat(fname, &lsbuf, false) != 0) {
4315 SAFE_FREE(fname);
4316 return false;
4319 if (!S_ISREG(lsbuf.st_ex_mode)) {
4320 SAFE_FREE(fname);
4321 return false;
4324 SAFE_FREE(fname);
4325 *last_mod = lsbuf.st_ex_mtime;
4326 return true;
4329 /***************************************************************************
4330 Load a usershare service by name. Returns a valid servicenumber or -1.
4331 ***************************************************************************/
4333 int load_usershare_service(const char *servicename)
4335 SMB_STRUCT_STAT sbuf;
4336 const char *usersharepath = Globals.usershare_path;
4337 int max_user_shares = Globals.usershare_max_shares;
4338 int snum_template = -1;
4340 if (*usersharepath == 0 || max_user_shares == 0) {
4341 return -1;
4344 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4345 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4346 usersharepath, strerror(errno) ));
4347 return -1;
4350 if (!S_ISDIR(sbuf.st_ex_mode)) {
4351 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4352 usersharepath ));
4353 return -1;
4357 * This directory must be owned by root, and have the 't' bit set.
4358 * It also must not be writable by "other".
4361 #ifdef S_ISVTX
4362 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4363 #else
4364 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4365 #endif
4366 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4367 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4368 usersharepath ));
4369 return -1;
4372 /* Ensure the template share exists if it's set. */
4373 if (Globals.szUsershareTemplateShare[0]) {
4374 /* We can't use lp_servicenumber here as we are recommending that
4375 template shares have -valid=false set. */
4376 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4377 if (ServicePtrs[snum_template]->szService &&
4378 strequal(ServicePtrs[snum_template]->szService,
4379 Globals.szUsershareTemplateShare)) {
4380 break;
4384 if (snum_template == -1) {
4385 DEBUG(0,("load_usershare_service: usershare template share %s "
4386 "does not exist.\n",
4387 Globals.szUsershareTemplateShare ));
4388 return -1;
4392 return process_usershare_file(usersharepath, servicename, snum_template);
4395 /***************************************************************************
4396 Load all user defined shares from the user share directory.
4397 We only do this if we're enumerating the share list.
4398 This is the function that can delete usershares that have
4399 been removed.
4400 ***************************************************************************/
4402 int load_usershare_shares(struct smbd_server_connection *sconn,
4403 bool (*snumused) (struct smbd_server_connection *, int))
4405 DIR *dp;
4406 SMB_STRUCT_STAT sbuf;
4407 struct dirent *de;
4408 int num_usershares = 0;
4409 int max_user_shares = Globals.usershare_max_shares;
4410 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4411 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4412 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4413 int iService;
4414 int snum_template = -1;
4415 const char *usersharepath = Globals.usershare_path;
4416 int ret = lp_numservices();
4417 TALLOC_CTX *tmp_ctx;
4419 if (max_user_shares == 0 || *usersharepath == '\0') {
4420 return lp_numservices();
4423 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4424 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4425 usersharepath, strerror(errno) ));
4426 return ret;
4430 * This directory must be owned by root, and have the 't' bit set.
4431 * It also must not be writable by "other".
4434 #ifdef S_ISVTX
4435 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4436 #else
4437 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4438 #endif
4439 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4440 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4441 usersharepath ));
4442 return ret;
4445 /* Ensure the template share exists if it's set. */
4446 if (Globals.szUsershareTemplateShare[0]) {
4447 /* We can't use lp_servicenumber here as we are recommending that
4448 template shares have -valid=false set. */
4449 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4450 if (ServicePtrs[snum_template]->szService &&
4451 strequal(ServicePtrs[snum_template]->szService,
4452 Globals.szUsershareTemplateShare)) {
4453 break;
4457 if (snum_template == -1) {
4458 DEBUG(0,("load_usershare_shares: usershare template share %s "
4459 "does not exist.\n",
4460 Globals.szUsershareTemplateShare ));
4461 return ret;
4465 /* Mark all existing usershares as pending delete. */
4466 for (iService = iNumServices - 1; iService >= 0; iService--) {
4467 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4468 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4472 dp = opendir(usersharepath);
4473 if (!dp) {
4474 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4475 usersharepath, strerror(errno) ));
4476 return ret;
4479 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4480 (de = readdir(dp));
4481 num_dir_entries++ ) {
4482 int r;
4483 const char *n = de->d_name;
4485 /* Ignore . and .. */
4486 if (*n == '.') {
4487 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4488 continue;
4492 if (n[0] == ':') {
4493 /* Temporary file used when creating a share. */
4494 num_tmp_dir_entries++;
4497 /* Allow 20% tmp entries. */
4498 if (num_tmp_dir_entries > allowed_tmp_entries) {
4499 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4500 "in directory %s\n",
4501 num_tmp_dir_entries, usersharepath));
4502 break;
4505 r = process_usershare_file(usersharepath, n, snum_template);
4506 if (r == 0) {
4507 /* Update the services count. */
4508 num_usershares++;
4509 if (num_usershares >= max_user_shares) {
4510 DEBUG(0,("load_usershare_shares: max user shares reached "
4511 "on file %s in directory %s\n",
4512 n, usersharepath ));
4513 break;
4515 } else if (r == -1) {
4516 num_bad_dir_entries++;
4519 /* Allow 20% bad entries. */
4520 if (num_bad_dir_entries > allowed_bad_entries) {
4521 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4522 "in directory %s\n",
4523 num_bad_dir_entries, usersharepath));
4524 break;
4527 /* Allow 20% bad entries. */
4528 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4529 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4530 "in directory %s\n",
4531 num_dir_entries, usersharepath));
4532 break;
4536 closedir(dp);
4538 /* Sweep through and delete any non-refreshed usershares that are
4539 not currently in use. */
4540 tmp_ctx = talloc_stackframe();
4541 for (iService = iNumServices - 1; iService >= 0; iService--) {
4542 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4543 char *servname;
4545 if (snumused && snumused(sconn, iService)) {
4546 continue;
4549 servname = lp_servicename(tmp_ctx, iService);
4551 /* Remove from the share ACL db. */
4552 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4553 servname ));
4554 delete_share_security(servname);
4555 free_service_byindex(iService);
4558 talloc_free(tmp_ctx);
4560 return lp_numservices();
4563 /********************************************************
4564 Destroy global resources allocated in this file
4565 ********************************************************/
4567 void gfree_loadparm(void)
4569 int i;
4571 free_file_list();
4573 /* Free resources allocated to services */
4575 for ( i = 0; i < iNumServices; i++ ) {
4576 if ( VALID(i) ) {
4577 free_service_byindex(i);
4581 SAFE_FREE( ServicePtrs );
4582 iNumServices = 0;
4584 /* Now release all resources allocated to global
4585 parameters and the default service */
4587 free_global_parameters();
4591 /***************************************************************************
4592 Allow client apps to specify that they are a client
4593 ***************************************************************************/
4594 static void lp_set_in_client(bool b)
4596 in_client = b;
4600 /***************************************************************************
4601 Determine if we're running in a client app
4602 ***************************************************************************/
4603 static bool lp_is_in_client(void)
4605 return in_client;
4608 /***************************************************************************
4609 Load the services array from the services file. Return true on success,
4610 false on failure.
4611 ***************************************************************************/
4613 static bool lp_load_ex(const char *pszFname,
4614 bool global_only,
4615 bool save_defaults,
4616 bool add_ipc,
4617 bool initialize_globals,
4618 bool allow_include_registry,
4619 bool load_all_shares)
4621 char *n2 = NULL;
4622 bool bRetval;
4624 bRetval = false;
4626 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4628 bInGlobalSection = true;
4629 bGlobalOnly = global_only;
4630 bAllowIncludeRegistry = allow_include_registry;
4632 init_globals(initialize_globals);
4634 free_file_list();
4636 if (save_defaults) {
4637 init_locals();
4638 lp_save_defaults();
4641 if (!initialize_globals) {
4642 free_param_opts(&Globals.param_opt);
4643 apply_lp_set_cmdline();
4646 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4648 /* We get sections first, so have to start 'behind' to make up */
4649 iServiceIndex = -1;
4651 if (lp_config_backend_is_file()) {
4652 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4653 current_user_info.domain,
4654 pszFname);
4655 if (!n2) {
4656 smb_panic("lp_load_ex: out of memory");
4659 add_to_file_list(pszFname, n2);
4661 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4662 TALLOC_FREE(n2);
4664 /* finish up the last section */
4665 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4666 if (bRetval) {
4667 if (iServiceIndex >= 0) {
4668 bRetval = service_ok(iServiceIndex);
4672 if (lp_config_backend_is_registry()) {
4673 /* config backend changed to registry in config file */
4675 * We need to use this extra global variable here to
4676 * survive restart: init_globals uses this as a default
4677 * for config_backend. Otherwise, init_globals would
4678 * send us into an endless loop here.
4680 config_backend = CONFIG_BACKEND_REGISTRY;
4681 /* start over */
4682 DEBUG(1, ("lp_load_ex: changing to config backend "
4683 "registry\n"));
4684 init_globals(true);
4685 lp_kill_all_services();
4686 return lp_load_ex(pszFname, global_only, save_defaults,
4687 add_ipc, initialize_globals,
4688 allow_include_registry,
4689 load_all_shares);
4691 } else if (lp_config_backend_is_registry()) {
4692 bRetval = process_registry_globals();
4693 } else {
4694 DEBUG(0, ("Illegal config backend given: %d\n",
4695 lp_config_backend()));
4696 bRetval = false;
4699 if (bRetval && lp_registry_shares()) {
4700 if (load_all_shares) {
4701 bRetval = process_registry_shares();
4702 } else {
4703 bRetval = reload_registry_shares();
4708 char *serv = lp_auto_services(talloc_tos());
4709 lp_add_auto_services(serv);
4710 TALLOC_FREE(serv);
4713 if (add_ipc) {
4714 /* When 'restrict anonymous = 2' guest connections to ipc$
4715 are denied */
4716 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4717 if ( lp_enable_asu_support() ) {
4718 lp_add_ipc("ADMIN$", false);
4722 set_allowed_client_auth();
4724 if (lp_security() == SEC_ADS && strchr(lp_password_server(), ':')) {
4725 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4726 lp_password_server()));
4729 bLoaded = true;
4731 /* Now we check we_are_a_wins_server and set szWINSserver to 127.0.0.1 */
4732 /* if we_are_a_wins_server is true and we are in the client */
4733 if (lp_is_in_client() && Globals.we_are_a_wins_server) {
4734 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4737 init_iconv();
4739 fault_configure(smb_panic_s3);
4742 * We run this check once the whole smb.conf is parsed, to
4743 * force some settings for the standard way a AD DC is
4744 * operated. We may changed these as our code evolves, which
4745 * is why we force these settings.
4747 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4748 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4750 lp_do_parameter(-1, "rpc_server:default", "external");
4751 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4752 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4753 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4754 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4755 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4756 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4757 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4758 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4761 bAllowIncludeRegistry = true;
4763 return (bRetval);
4766 bool lp_load(const char *pszFname,
4767 bool global_only,
4768 bool save_defaults,
4769 bool add_ipc,
4770 bool initialize_globals)
4772 return lp_load_ex(pszFname,
4773 global_only,
4774 save_defaults,
4775 add_ipc,
4776 initialize_globals,
4777 true, /* allow_include_registry */
4778 false); /* load_all_shares*/
4781 bool lp_load_initial_only(const char *pszFname)
4783 return lp_load_ex(pszFname,
4784 true, /* global only */
4785 false, /* save_defaults */
4786 false, /* add_ipc */
4787 true, /* initialize_globals */
4788 false, /* allow_include_registry */
4789 false); /* load_all_shares*/
4793 * most common lp_load wrapper, loading only the globals
4795 bool lp_load_global(const char *file_name)
4797 return lp_load_ex(file_name,
4798 true, /* global_only */
4799 false, /* save_defaults */
4800 false, /* add_ipc */
4801 true, /* initialize_globals */
4802 true, /* allow_include_registry */
4803 false); /* load_all_shares*/
4807 * lp_load wrapper, especially for clients
4809 bool lp_load_client(const char *file_name)
4811 lp_set_in_client(true);
4813 return lp_load_global(file_name);
4817 * lp_load wrapper, loading only globals, but intended
4818 * for subsequent calls, not reinitializing the globals
4819 * to default values
4821 bool lp_load_global_no_reinit(const char *file_name)
4823 return lp_load_ex(file_name,
4824 true, /* global_only */
4825 false, /* save_defaults */
4826 false, /* add_ipc */
4827 false, /* initialize_globals */
4828 true, /* allow_include_registry */
4829 false); /* load_all_shares*/
4833 * lp_load wrapper, especially for clients, no reinitialization
4835 bool lp_load_client_no_reinit(const char *file_name)
4837 lp_set_in_client(true);
4839 return lp_load_global_no_reinit(file_name);
4842 bool lp_load_with_registry_shares(const char *pszFname,
4843 bool global_only,
4844 bool save_defaults,
4845 bool add_ipc,
4846 bool initialize_globals)
4848 return lp_load_ex(pszFname,
4849 global_only,
4850 save_defaults,
4851 add_ipc,
4852 initialize_globals,
4853 true, /* allow_include_registry */
4854 true); /* load_all_shares*/
4857 /***************************************************************************
4858 Return the max number of services.
4859 ***************************************************************************/
4861 int lp_numservices(void)
4863 return (iNumServices);
4866 /***************************************************************************
4867 Display the contents of the services array in human-readable form.
4868 ***************************************************************************/
4870 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4872 int iService;
4874 if (show_defaults)
4875 defaults_saved = false;
4877 dump_globals(f);
4879 dump_a_service(&sDefault, f);
4881 for (iService = 0; iService < maxtoprint; iService++) {
4882 fprintf(f,"\n");
4883 lp_dump_one(f, show_defaults, iService);
4887 /***************************************************************************
4888 Display the contents of one service in human-readable form.
4889 ***************************************************************************/
4891 void lp_dump_one(FILE * f, bool show_defaults, int snum)
4893 if (VALID(snum)) {
4894 if (ServicePtrs[snum]->szService[0] == '\0')
4895 return;
4896 dump_a_service(ServicePtrs[snum], f);
4900 /***************************************************************************
4901 Return the number of the service with the given name, or -1 if it doesn't
4902 exist. Note that this is a DIFFERENT ANIMAL from the internal function
4903 getservicebyname()! This works ONLY if all services have been loaded, and
4904 does not copy the found service.
4905 ***************************************************************************/
4907 int lp_servicenumber(const char *pszServiceName)
4909 int iService;
4910 fstring serviceName;
4912 if (!pszServiceName) {
4913 return GLOBAL_SECTION_SNUM;
4916 for (iService = iNumServices - 1; iService >= 0; iService--) {
4917 if (VALID(iService) && ServicePtrs[iService]->szService) {
4919 * The substitution here is used to support %U is
4920 * service names
4922 fstrcpy(serviceName, ServicePtrs[iService]->szService);
4923 standard_sub_basic(get_current_username(),
4924 current_user_info.domain,
4925 serviceName,sizeof(serviceName));
4926 if (strequal(serviceName, pszServiceName)) {
4927 break;
4932 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
4933 struct timespec last_mod;
4935 if (!usershare_exists(iService, &last_mod)) {
4936 /* Remove the share security tdb entry for it. */
4937 delete_share_security(lp_servicename(talloc_tos(), iService));
4938 /* Remove it from the array. */
4939 free_service_byindex(iService);
4940 /* Doesn't exist anymore. */
4941 return GLOBAL_SECTION_SNUM;
4944 /* Has it been modified ? If so delete and reload. */
4945 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4946 &last_mod) < 0) {
4947 /* Remove it from the array. */
4948 free_service_byindex(iService);
4949 /* and now reload it. */
4950 iService = load_usershare_service(pszServiceName);
4954 if (iService < 0) {
4955 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
4956 return GLOBAL_SECTION_SNUM;
4959 return (iService);
4962 /*******************************************************************
4963 A useful volume label function.
4964 ********************************************************************/
4966 const char *volume_label(TALLOC_CTX *ctx, int snum)
4968 char *ret;
4969 const char *label = lp_volume(ctx, snum);
4970 if (!*label) {
4971 label = lp_servicename(ctx, snum);
4974 /* This returns a 33 byte guarenteed null terminated string. */
4975 ret = talloc_strndup(ctx, label, 32);
4976 if (!ret) {
4977 return "";
4979 return ret;
4982 /*******************************************************************
4983 Get the default server type we will announce as via nmbd.
4984 ********************************************************************/
4986 int lp_default_server_announce(void)
4988 int default_server_announce = 0;
4989 default_server_announce |= SV_TYPE_WORKSTATION;
4990 default_server_announce |= SV_TYPE_SERVER;
4991 default_server_announce |= SV_TYPE_SERVER_UNIX;
4993 /* note that the flag should be set only if we have a
4994 printer service but nmbd doesn't actually load the
4995 services so we can't tell --jerry */
4997 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
4999 default_server_announce |= SV_TYPE_SERVER_NT;
5000 default_server_announce |= SV_TYPE_NT;
5002 switch (lp_server_role()) {
5003 case ROLE_DOMAIN_MEMBER:
5004 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5005 break;
5006 case ROLE_DOMAIN_PDC:
5007 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5008 break;
5009 case ROLE_DOMAIN_BDC:
5010 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5011 break;
5012 case ROLE_STANDALONE:
5013 default:
5014 break;
5016 if (lp_time_server())
5017 default_server_announce |= SV_TYPE_TIME_SOURCE;
5019 if (lp_host_msdfs())
5020 default_server_announce |= SV_TYPE_DFS_SERVER;
5022 return default_server_announce;
5025 /***********************************************************
5026 If we are PDC then prefer us as DMB
5027 ************************************************************/
5029 bool lp_domain_master(void)
5031 if (Globals._domain_master == Auto)
5032 return (lp_server_role() == ROLE_DOMAIN_PDC);
5034 return (bool)Globals._domain_master;
5037 /***********************************************************
5038 If we are PDC then prefer us as DMB
5039 ************************************************************/
5041 static bool lp_domain_master_true_or_auto(void)
5043 if (Globals._domain_master) /* auto or yes */
5044 return true;
5046 return false;
5049 /***********************************************************
5050 If we are DMB then prefer us as LMB
5051 ************************************************************/
5053 bool lp_preferred_master(void)
5055 if (Globals.iPreferredMaster == Auto)
5056 return (lp_local_master() && lp_domain_master());
5058 return (bool)Globals.iPreferredMaster;
5061 /*******************************************************************
5062 Remove a service.
5063 ********************************************************************/
5065 void lp_remove_service(int snum)
5067 ServicePtrs[snum]->valid = false;
5070 /*******************************************************************
5071 Copy a service.
5072 ********************************************************************/
5074 void lp_copy_service(int snum, const char *new_name)
5076 do_section(new_name, NULL);
5077 if (snum >= 0) {
5078 snum = lp_servicenumber(new_name);
5079 if (snum >= 0) {
5080 char *name = lp_servicename(talloc_tos(), snum);
5081 lp_do_parameter(snum, "copy", name);
5086 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5088 const char *ret = lp__printername(ctx, snum);
5089 if (ret == NULL || *ret == '\0') {
5090 ret = lp_const_servicename(snum);
5093 return ret;
5097 /***********************************************************
5098 Allow daemons such as winbindd to fix their logfile name.
5099 ************************************************************/
5101 void lp_set_logfile(const char *name)
5103 string_set(&Globals.logfile, name);
5104 debug_set_logfile(name);
5107 /*******************************************************************
5108 Return the max print jobs per queue.
5109 ********************************************************************/
5111 int lp_maxprintjobs(int snum)
5113 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5114 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5115 maxjobs = PRINT_MAX_JOBID - 1;
5117 return maxjobs;
5120 const char *lp_printcapname(void)
5122 if ((Globals.szPrintcapname != NULL) &&
5123 (Globals.szPrintcapname[0] != '\0'))
5124 return Globals.szPrintcapname;
5126 if (sDefault.printing == PRINT_CUPS) {
5127 return "cups";
5130 if (sDefault.printing == PRINT_BSD)
5131 return "/etc/printcap";
5133 return PRINTCAP_NAME;
5136 static uint32 spoolss_state;
5138 bool lp_disable_spoolss( void )
5140 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5141 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5143 return spoolss_state == SVCCTL_STOPPED ? true : false;
5146 void lp_set_spoolss_state( uint32 state )
5148 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5150 spoolss_state = state;
5153 uint32 lp_get_spoolss_state( void )
5155 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5158 /*******************************************************************
5159 Ensure we don't use sendfile if server smb signing is active.
5160 ********************************************************************/
5162 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5164 bool sign_active = false;
5166 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5167 if (get_Protocol() < PROTOCOL_NT1) {
5168 return false;
5170 if (signing_state) {
5171 sign_active = smb_signing_is_active(signing_state);
5173 return (lp__use_sendfile(snum) &&
5174 (get_remote_arch() != RA_WIN95) &&
5175 !sign_active);
5178 /*******************************************************************
5179 Turn off sendfile if we find the underlying OS doesn't support it.
5180 ********************************************************************/
5182 void set_use_sendfile(int snum, bool val)
5184 if (LP_SNUM_OK(snum))
5185 ServicePtrs[snum]->_use_sendfile = val;
5186 else
5187 sDefault._use_sendfile = val;
5190 /*******************************************************************
5191 Turn off storing DOS attributes if this share doesn't support it.
5192 ********************************************************************/
5194 void set_store_dos_attributes(int snum, bool val)
5196 if (!LP_SNUM_OK(snum))
5197 return;
5198 ServicePtrs[(snum)]->store_dos_attributes = val;
5201 void lp_set_mangling_method(const char *new_method)
5203 string_set(&Globals.mangling_method, new_method);
5206 /*******************************************************************
5207 Global state for POSIX pathname processing.
5208 ********************************************************************/
5210 static bool posix_pathnames;
5212 bool lp_posix_pathnames(void)
5214 return posix_pathnames;
5217 /*******************************************************************
5218 Change everything needed to ensure POSIX pathname processing (currently
5219 not much).
5220 ********************************************************************/
5222 void lp_set_posix_pathnames(void)
5224 posix_pathnames = true;
5227 /*******************************************************************
5228 Global state for POSIX lock processing - CIFS unix extensions.
5229 ********************************************************************/
5231 bool posix_default_lock_was_set;
5232 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5234 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5236 if (posix_default_lock_was_set) {
5237 return posix_cifsx_locktype;
5238 } else {
5239 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5243 /*******************************************************************
5244 ********************************************************************/
5246 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5248 posix_default_lock_was_set = true;
5249 posix_cifsx_locktype = val;
5252 int lp_min_receive_file_size(void)
5254 if (Globals.iminreceivefile < 0) {
5255 return 0;
5257 return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5260 /*******************************************************************
5261 Safe wide links checks.
5262 This helper function always verify the validity of wide links,
5263 even after a configuration file reload.
5264 ********************************************************************/
5266 static bool lp_widelinks_internal(int snum)
5268 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5269 sDefault.bWidelinks);
5272 void widelinks_warning(int snum)
5274 if (lp_allow_insecure_wide_links()) {
5275 return;
5278 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5279 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5280 "These parameters are incompatible. "
5281 "Wide links will be disabled for this share.\n",
5282 lp_servicename(talloc_tos(), snum) ));
5286 bool lp_widelinks(int snum)
5288 /* wide links is always incompatible with unix extensions */
5289 if (lp_unix_extensions()) {
5291 * Unless we have "allow insecure widelinks"
5292 * turned on.
5294 if (!lp_allow_insecure_wide_links()) {
5295 return false;
5299 return lp_widelinks_internal(snum);
5302 bool lp_writeraw(void)
5304 if (lp_async_smb_echo_handler()) {
5305 return false;
5307 return lp__writeraw();
5310 bool lp_readraw(void)
5312 if (lp_async_smb_echo_handler()) {
5313 return false;
5315 return lp__readraw();
5318 int lp_server_role(void)
5320 return lp_find_server_role(lp__server_role(),
5321 lp__security(),
5322 lp__domain_logons(),
5323 lp_domain_master_true_or_auto());
5326 int lp_security(void)
5328 return lp_find_security(lp__server_role(),
5329 lp__security());