s3: libsmb: Correctly do lifecycle management on cli->smb1.tcon and cli->smb2.tcon.
[Samba.git] / source3 / param / loadparm.c
blob297a7e9175a154ba3213d193aee9068c202b49e3
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"
72 #include "librpc/gen_ndr/nbt.h"
73 #include "source4/lib/tls/tls.h"
75 #ifdef HAVE_SYS_SYSCTL_H
76 #include <sys/sysctl.h>
77 #endif
79 bool bLoaded = false;
81 extern userdom_struct current_user_info;
83 /* the special value for the include parameter
84 * to be interpreted not as a file name but to
85 * trigger loading of the global smb.conf options
86 * from registry. */
87 #ifndef INCLUDE_REGISTRY_NAME
88 #define INCLUDE_REGISTRY_NAME "registry"
89 #endif
91 static bool in_client = false; /* Not in the client by default */
92 static struct smbconf_csn conf_last_csn;
94 static int config_backend = CONFIG_BACKEND_FILE;
96 /* some helpful bits */
97 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && \
98 (ServicePtrs != NULL) && \
99 (ServicePtrs[(i)] != NULL) && ServicePtrs[(i)]->valid)
100 #define VALID(i) ((ServicePtrs != NULL) && (ServicePtrs[i]!= NULL) && \
101 ServicePtrs[i]->valid)
103 #define USERSHARE_VALID 1
104 #define USERSHARE_PENDING_DELETE 2
106 static bool defaults_saved = false;
108 #include "lib/param/param_global.h"
110 static struct loadparm_global Globals;
112 /* This is a default service used to prime a services structure */
113 static struct loadparm_service sDefault =
115 .valid = true,
116 .autoloaded = false,
117 .usershare = 0,
118 .usershare_last_mod = {0, 0},
119 .szService = NULL,
120 .path = NULL,
121 .invalid_users = NULL,
122 .valid_users = NULL,
123 .admin_users = NULL,
124 .copy = NULL,
125 .include = NULL,
126 .preexec = NULL,
127 .postexec = NULL,
128 .root_preexec = NULL,
129 .root_postexec = NULL,
130 .cups_options = NULL,
131 .print_command = NULL,
132 .lpq_command = NULL,
133 .lprm_command = NULL,
134 .lppause_command = NULL,
135 .lpresume_command = NULL,
136 .queuepause_command = NULL,
137 .queueresume_command = NULL,
138 ._printername = NULL,
139 .printjob_username = NULL,
140 .dont_descend = NULL,
141 .hosts_allow = NULL,
142 .hosts_deny = NULL,
143 .magic_script = NULL,
144 .magic_output = NULL,
145 .veto_files = NULL,
146 .hide_files = NULL,
147 .veto_oplock_files = NULL,
148 .comment = NULL,
149 .force_user = NULL,
150 .force_group = NULL,
151 .read_list = NULL,
152 .write_list = NULL,
153 .volume = NULL,
154 .fstype = NULL,
155 .vfs_objects = NULL,
156 .msdfs_proxy = NULL,
157 .aio_write_behind = NULL,
158 .dfree_command = NULL,
159 .min_print_space = 0,
160 .max_print_jobs = 1000,
161 .max_reported_print_jobs = 0,
162 .write_cache_size = 0,
163 .create_mask = 0744,
164 .force_create_mode = 0,
165 .directory_mask = 0755,
166 .force_directory_mode = 0,
167 .max_connections = 0,
168 .default_case = CASE_LOWER,
169 .printing = DEFAULT_PRINTING,
170 .oplock_contention_limit = 2,
171 .csc_policy = 0,
172 .block_size = 1024,
173 .dfree_cache_time = 0,
174 .preexec_close = false,
175 .root_preexec_close = false,
176 .case_sensitive = Auto,
177 .preserve_case = true,
178 .short_preserve_case = true,
179 .hide_dot_files = true,
180 .hide_special_files = false,
181 .hide_unreadable = false,
182 .hide_unwriteable_files = false,
183 .browseable = true,
184 .access_based_share_enum = false,
185 .available = true,
186 .read_only = true,
187 .spotlight = false,
188 .guest_only = false,
189 .administrative_share = false,
190 .guest_ok = false,
191 .printable = false,
192 .print_notify_backchannel = false,
193 .map_system = false,
194 .map_hidden = false,
195 .map_archive = true,
196 .store_dos_attributes = false,
197 .dmapi_support = false,
198 .locking = true,
199 .strict_locking = Auto,
200 .posix_locking = true,
201 .oplocks = true,
202 .kernel_oplocks = false,
203 .level2_oplocks = true,
204 .mangled_names = MANGLED_NAMES_YES,
205 .wide_links = false,
206 .follow_symlinks = true,
207 .sync_always = false,
208 .strict_allocate = false,
209 .strict_rename = false,
210 .strict_sync = true,
211 .mangling_char = '~',
212 .copymap = NULL,
213 .delete_readonly = false,
214 .fake_oplocks = false,
215 .delete_veto_files = false,
216 .dos_filemode = false,
217 .dos_filetimes = true,
218 .dos_filetime_resolution = false,
219 .fake_directory_create_times = false,
220 .blocking_locks = true,
221 .inherit_permissions = false,
222 .inherit_acls = false,
223 .inherit_owner = false,
224 .msdfs_root = false,
225 .msdfs_shuffle_referrals = false,
226 .use_client_driver = false,
227 .default_devmode = true,
228 .force_printername = false,
229 .nt_acl_support = true,
230 .force_unknown_acl_user = false,
231 ._use_sendfile = false,
232 .profile_acls = false,
233 .map_acl_inherit = false,
234 .afs_share = false,
235 .ea_support = false,
236 .acl_check_permissions = true,
237 .acl_map_full_control = true,
238 .acl_group_control = false,
239 .acl_allow_execute_always = false,
240 .allocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
241 .aio_read_size = 0,
242 .aio_write_size = 0,
243 .map_readonly = MAP_READONLY_YES,
244 .directory_name_cache_size = 100,
245 .smb_encrypt = SMB_SIGNING_DEFAULT,
246 .kernel_share_modes = true,
247 .durable_handles = true,
248 .param_opt = NULL,
249 .dummy = ""
252 /* local variables */
253 static struct loadparm_service **ServicePtrs = NULL;
254 static int iNumServices = 0;
255 static int iServiceIndex = 0;
256 static struct db_context *ServiceHash;
257 static bool bInGlobalSection = true;
258 static bool bGlobalOnly = false;
259 static struct file_lists *file_lists = NULL;
260 static unsigned int *flags_list = NULL;
262 static void set_allowed_client_auth(void);
264 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue);
265 static void free_param_opts(struct parmlist_entry **popts);
268 * Function to return the default value for the maximum number of open
269 * file descriptors permitted. This function tries to consult the
270 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
271 * the smaller of those.
273 static int max_open_files(void)
275 int sysctl_max = MAX_OPEN_FILES;
276 int rlimit_max = MAX_OPEN_FILES;
278 #ifdef HAVE_SYSCTLBYNAME
280 size_t size = sizeof(sysctl_max);
281 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
284 #endif
286 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
288 struct rlimit rl;
290 ZERO_STRUCT(rl);
292 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
293 rlimit_max = rl.rlim_cur;
295 #if defined(RLIM_INFINITY)
296 if(rl.rlim_cur == RLIM_INFINITY)
297 rlimit_max = MAX_OPEN_FILES;
298 #endif
300 #endif
302 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
303 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
304 "minimum Windows limit (%d)\n",
305 sysctl_max,
306 MIN_OPEN_FILES_WINDOWS));
307 sysctl_max = MIN_OPEN_FILES_WINDOWS;
310 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
311 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
312 "minimum Windows limit (%d)\n",
313 rlimit_max,
314 MIN_OPEN_FILES_WINDOWS));
315 rlimit_max = MIN_OPEN_FILES_WINDOWS;
318 return MIN(sysctl_max, rlimit_max);
322 * Common part of freeing allocated data for one parameter.
324 static void free_one_parameter_common(void *parm_ptr,
325 struct parm_struct parm)
327 if ((parm.type == P_STRING) ||
328 (parm.type == P_USTRING))
330 lpcfg_string_free((char**)parm_ptr);
331 } else if (parm.type == P_LIST || parm.type == P_CMDLIST) {
332 TALLOC_FREE(*((char***)parm_ptr));
337 * Free the allocated data for one parameter for a share
338 * given as a service struct.
340 static void free_one_parameter(struct loadparm_service *service,
341 struct parm_struct parm)
343 void *parm_ptr;
345 if (parm.p_class != P_LOCAL) {
346 return;
349 parm_ptr = lp_parm_ptr(service, &parm);
351 free_one_parameter_common(parm_ptr, parm);
355 * Free the allocated parameter data of a share given
356 * as a service struct.
358 static void free_parameters(struct loadparm_service *service)
360 uint32_t i;
362 for (i=0; parm_table[i].label; i++) {
363 free_one_parameter(service, parm_table[i]);
368 * Free the allocated data for one parameter for a given share
369 * specified by an snum.
371 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
373 void *parm_ptr;
375 if (snum < 0) {
376 parm_ptr = lp_parm_ptr(NULL, &parm);
377 } else if (parm.p_class != P_LOCAL) {
378 return;
379 } else {
380 parm_ptr = lp_parm_ptr(ServicePtrs[snum], &parm);
383 free_one_parameter_common(parm_ptr, parm);
387 * Free the allocated parameter data for a share specified
388 * by an snum.
390 static void free_parameters_by_snum(int snum)
392 uint32_t i;
394 for (i=0; parm_table[i].label; i++) {
395 free_one_parameter_by_snum(snum, parm_table[i]);
400 * Free the allocated global parameters.
402 static void free_global_parameters(void)
404 uint32_t i;
405 struct parm_struct *parm;
407 free_param_opts(&Globals.param_opt);
408 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
410 /* Reset references in the defaults because the context is going to be freed */
411 for (i=0; parm_table[i].label; i++) {
412 parm = &parm_table[i];
413 if ((parm->type == P_STRING) ||
414 (parm->type == P_USTRING)) {
415 if ((parm->def.svalue != NULL) &&
416 (*(parm->def.svalue) != '\0')) {
417 if (talloc_parent(parm->def.svalue) == Globals.ctx) {
418 parm->def.svalue = NULL;
423 TALLOC_FREE(Globals.ctx);
426 struct lp_stored_option {
427 struct lp_stored_option *prev, *next;
428 const char *label;
429 const char *value;
432 static struct lp_stored_option *stored_options;
435 save options set by lp_set_cmdline() into a list. This list is
436 re-applied when we do a globals reset, so that cmdline set options
437 are sticky across reloads of smb.conf
439 bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
441 struct lp_stored_option *entry, *entry_next;
442 for (entry = stored_options; entry != NULL; entry = entry_next) {
443 entry_next = entry->next;
444 if (strcmp(pszParmName, entry->label) == 0) {
445 DLIST_REMOVE(stored_options, entry);
446 talloc_free(entry);
447 break;
451 entry = talloc(NULL, struct lp_stored_option);
452 if (!entry) {
453 return false;
456 entry->label = talloc_strdup(entry, pszParmName);
457 if (!entry->label) {
458 talloc_free(entry);
459 return false;
462 entry->value = talloc_strdup(entry, pszParmValue);
463 if (!entry->value) {
464 talloc_free(entry);
465 return false;
468 DLIST_ADD_END(stored_options, entry);
470 return true;
473 static bool apply_lp_set_cmdline(void)
475 struct lp_stored_option *entry = NULL;
476 for (entry = stored_options; entry != NULL; entry = entry->next) {
477 if (!lp_set_cmdline_helper(entry->label, entry->value)) {
478 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
479 entry->label, entry->value));
480 return false;
483 return true;
486 /***************************************************************************
487 Initialise the global parameter structure.
488 ***************************************************************************/
490 static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
492 static bool done_init = false;
493 char *s = NULL;
494 int i;
496 /* If requested to initialize only once and we've already done it... */
497 if (!reinit_globals && done_init) {
498 /* ... then we have nothing more to do */
499 return;
502 if (!done_init) {
503 /* The logfile can be set before this is invoked. Free it if so. */
504 lpcfg_string_free(&Globals.logfile);
505 done_init = true;
506 } else {
507 free_global_parameters();
510 /* This memset and the free_global_parameters() above will
511 * wipe out smb.conf options set with lp_set_cmdline(). The
512 * apply_lp_set_cmdline() call puts these values back in the
513 * table once the defaults are set */
514 ZERO_STRUCT(Globals);
516 Globals.ctx = talloc_pooled_object(NULL, char, 272, 2048);
518 /* Initialize the flags list if necessary */
519 if (flags_list == NULL) {
520 get_flags();
523 for (i = 0; parm_table[i].label; i++) {
524 if ((parm_table[i].type == P_STRING ||
525 parm_table[i].type == P_USTRING))
527 lpcfg_string_set(
528 Globals.ctx,
529 (char **)lp_parm_ptr(NULL, &parm_table[i]),
530 "");
535 lpcfg_string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
536 lpcfg_string_set(Globals.ctx, &sDefault.printjob_username, "%U");
538 init_printer_values(lp_ctx, Globals.ctx, &sDefault);
540 sDefault.ntvfs_handler = str_list_make_v3_const(NULL, "unixuid default", NULL);
542 DEBUG(3, ("Initialising global parameters\n"));
544 /* Must manually force to upper case here, as this does not go via the handler */
545 lpcfg_string_set(Globals.ctx, &Globals.netbios_name,
546 myhostname_upper());
548 lpcfg_string_set(Globals.ctx, &Globals.smb_passwd_file,
549 get_dyn_SMB_PASSWD_FILE());
550 lpcfg_string_set(Globals.ctx, &Globals.private_dir,
551 get_dyn_PRIVATE_DIR());
553 /* use the new 'hash2' method by default, with a prefix of 1 */
554 lpcfg_string_set(Globals.ctx, &Globals.mangling_method, "hash2");
555 Globals.mangle_prefix = 1;
557 lpcfg_string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
559 /* using UTF8 by default allows us to support all chars */
560 lpcfg_string_set(Globals.ctx, &Globals.unix_charset,
561 DEFAULT_UNIX_CHARSET);
563 /* Use codepage 850 as a default for the dos character set */
564 lpcfg_string_set(Globals.ctx, &Globals.dos_charset,
565 DEFAULT_DOS_CHARSET);
568 * Allow the default PASSWD_CHAT to be overridden in local.h.
570 lpcfg_string_set(Globals.ctx, &Globals.passwd_chat,
571 DEFAULT_PASSWD_CHAT);
573 lpcfg_string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
575 lpcfg_string_set(Globals.ctx, &Globals.passwd_program, "");
576 lpcfg_string_set(Globals.ctx, &Globals.lock_directory,
577 get_dyn_LOCKDIR());
578 lpcfg_string_set(Globals.ctx, &Globals.state_directory,
579 get_dyn_STATEDIR());
580 lpcfg_string_set(Globals.ctx, &Globals.cache_directory,
581 get_dyn_CACHEDIR());
582 lpcfg_string_set(Globals.ctx, &Globals.pid_directory,
583 get_dyn_PIDDIR());
584 lpcfg_string_set(Globals.ctx, &Globals.nbt_client_socket_address,
585 "0.0.0.0");
587 * By default support explicit binding to broadcast
588 * addresses.
590 Globals.nmbd_bind_explicit_broadcast = true;
592 s = talloc_asprintf(talloc_tos(), "Samba %s", samba_version_string());
593 if (s == NULL) {
594 smb_panic("init_globals: ENOMEM");
596 lpcfg_string_set(Globals.ctx, &Globals.server_string, s);
597 TALLOC_FREE(s);
598 #ifdef DEVELOPER
599 lpcfg_string_set(Globals.ctx, &Globals.panic_action,
600 "/bin/sleep 999999999");
601 #endif
603 lpcfg_string_set(Globals.ctx, &Globals.socket_options,
604 DEFAULT_SOCKET_OPTIONS);
606 lpcfg_string_set(Globals.ctx, &Globals.logon_drive, "");
607 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
608 lpcfg_string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
609 lpcfg_string_set(Globals.ctx, &Globals.logon_path,
610 "\\\\%N\\%U\\profile");
612 Globals.name_resolve_order =
613 str_list_make_v3_const(Globals.ctx,
614 DEFAULT_NAME_RESOLVE_ORDER,
615 NULL);
616 lpcfg_string_set(Globals.ctx, &Globals.password_server, "*");
618 Globals.algorithmic_rid_base = BASE_RID;
620 Globals.load_printers = true;
621 Globals.printcap_cache_time = 750; /* 12.5 minutes */
623 Globals.config_backend = config_backend;
624 Globals._server_role = ROLE_AUTO;
626 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
627 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
628 Globals.max_xmit = 0x4104;
629 Globals.max_mux = 50; /* This is *needed* for profile support. */
630 Globals.lpq_cache_time = 30; /* changed to handle large print servers better -- jerry */
631 Globals._disable_spoolss = false;
632 Globals.max_smbd_processes = 0;/* no limit specified */
633 Globals.username_level = 0;
634 Globals.deadtime = 0;
635 Globals.getwd_cache = true;
636 Globals.large_readwrite = true;
637 Globals.max_log_size = 5000;
638 Globals.max_open_files = max_open_files();
639 Globals.server_max_protocol = PROTOCOL_SMB3_11;
640 Globals.server_min_protocol = PROTOCOL_LANMAN1;
641 Globals._client_max_protocol = PROTOCOL_DEFAULT;
642 Globals.client_min_protocol = PROTOCOL_CORE;
643 Globals._client_ipc_max_protocol = PROTOCOL_DEFAULT;
644 Globals._client_ipc_min_protocol = PROTOCOL_DEFAULT;
645 Globals._security = SEC_AUTO;
646 Globals.encrypt_passwords = true;
647 Globals.client_schannel = Auto;
648 Globals.winbind_sealed_pipes = true;
649 Globals.require_strong_key = true;
650 Globals.server_schannel = Auto;
651 Globals.read_raw = true;
652 Globals.write_raw = true;
653 Globals.null_passwords = false;
654 Globals.old_password_allowed_period = 60;
655 Globals.obey_pam_restrictions = false;
656 Globals.syslog = 1;
657 Globals.syslog_only = false;
658 Globals.timestamp_logs = true;
659 lpcfg_string_set(Globals.ctx, &Globals.log_level, "0");
660 Globals.debug_prefix_timestamp = false;
661 Globals.debug_hires_timestamp = true;
662 Globals.debug_pid = false;
663 Globals.debug_uid = false;
664 Globals.debug_class = false;
665 Globals.enable_core_files = true;
666 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
667 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
668 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
669 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
670 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
671 Globals.lm_interval = 60;
672 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
673 Globals.nis_homedir = false;
674 #ifdef WITH_NISPLUS_HOME
675 lpcfg_string_set(Globals.ctx, &Globals.homedir_map,
676 "auto_home.org_dir");
677 #else
678 lpcfg_string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
679 #endif
680 #endif
681 Globals.time_server = false;
682 Globals.bind_interfaces_only = false;
683 Globals.unix_password_sync = false;
684 Globals.pam_password_change = false;
685 Globals.passwd_chat_debug = false;
686 Globals.passwd_chat_timeout = 2; /* 2 second default. */
687 Globals.nt_pipe_support = true; /* Do NT pipes by default. */
688 Globals.nt_status_support = true; /* Use NT status by default. */
689 Globals.smbd_profiling_level = 0;
690 Globals.stat_cache = true; /* use stat cache by default */
691 Globals.max_stat_cache_size = 256; /* 256k by default */
692 Globals.restrict_anonymous = 0;
693 Globals.client_lanman_auth = false; /* Do NOT use the LanMan hash if it is available */
694 Globals.client_plaintext_auth = false; /* Do NOT use a plaintext password even if is requested by the server */
695 Globals.lanman_auth = false; /* Do NOT use the LanMan hash, even if it is supplied */
696 Globals.ntlm_auth = false; /* Do NOT use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
697 Globals.raw_ntlmv2_auth = false; /* Reject NTLMv2 without NTLMSSP */
698 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 */
699 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
701 Globals.allow_dcerpc_auth_level_connect = false; /* we don't allow this by default */
703 Globals.map_to_guest = 0; /* By Default, "Never" */
704 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
705 Globals.enhanced_browsing = true;
706 Globals.lock_spin_time = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
707 #ifdef MMAP_BLACKLIST
708 Globals.use_mmap = false;
709 #else
710 Globals.use_mmap = true;
711 #endif
712 Globals.unicode = true;
713 Globals.unix_extensions = true;
714 Globals.reset_on_zero_vc = false;
715 Globals.log_writeable_files_on_exit = false;
716 Globals.create_krb5_conf = true;
717 Globals.include_system_krb5_conf = true;
718 Globals._winbind_max_domain_connections = 1;
720 /* hostname lookups can be very expensive and are broken on
721 a large number of sites (tridge) */
722 Globals.hostname_lookups = false;
724 Globals.change_notify = true,
725 Globals.kernel_change_notify = true,
727 lpcfg_string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
728 lpcfg_string_set(Globals.ctx, &Globals.ldap_suffix, "");
729 lpcfg_string_set(Globals.ctx, &Globals._ldap_machine_suffix, "");
730 lpcfg_string_set(Globals.ctx, &Globals._ldap_user_suffix, "");
731 lpcfg_string_set(Globals.ctx, &Globals._ldap_group_suffix, "");
732 lpcfg_string_set(Globals.ctx, &Globals._ldap_idmap_suffix, "");
734 lpcfg_string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
735 Globals.ldap_ssl = LDAP_SSL_START_TLS;
736 Globals.ldap_ssl_ads = false;
737 Globals.ldap_deref = -1;
738 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
739 Globals.ldap_delete_dn = false;
740 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
741 Globals.ldap_follow_referral = Auto;
742 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
743 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
744 Globals.ldap_page_size = LDAP_PAGE_SIZE;
746 Globals.ldap_debug_level = 0;
747 Globals.ldap_debug_threshold = 10;
749 Globals.client_ldap_sasl_wrapping = ADS_AUTH_SASL_SIGN;
751 Globals.ldap_server_require_strong_auth =
752 LDAP_SERVER_REQUIRE_STRONG_AUTH_YES;
754 /* This is what we tell the afs client. in reality we set the token
755 * to never expire, though, when this runs out the afs client will
756 * forget the token. Set to 0 to get NEVERDATE.*/
757 Globals.afs_token_lifetime = 604800;
758 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
760 /* these parameters are set to defaults that are more appropriate
761 for the increasing samba install base:
763 as a member of the workgroup, that will possibly become a
764 _local_ master browser (lm = true). this is opposed to a forced
765 local master browser startup (pm = true).
767 doesn't provide WINS server service by default (wsupp = false),
768 and doesn't provide domain master browser services by default, either.
772 Globals.show_add_printer_wizard = true;
773 Globals.os_level = 20;
774 Globals.local_master = true;
775 Globals._domain_master = Auto; /* depending on _domain_logons */
776 Globals._domain_logons = false;
777 Globals.browse_list = true;
778 Globals.we_are_a_wins_server = false;
779 Globals.wins_proxy = false;
781 TALLOC_FREE(Globals.init_logon_delayed_hosts);
782 Globals.init_logon_delay = 100; /* 100 ms default delay */
784 Globals.wins_dns_proxy = true;
786 Globals.allow_trusted_domains = true;
787 lpcfg_string_set(Globals.ctx, &Globals.idmap_backend, "tdb");
789 lpcfg_string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
790 lpcfg_string_set(Globals.ctx, &Globals.template_homedir,
791 "/home/%D/%U");
792 lpcfg_string_set(Globals.ctx, &Globals.winbind_separator, "\\");
793 lpcfg_string_set(Globals.ctx, &Globals.winbindd_socket_directory,
794 dyn_WINBINDD_SOCKET_DIR);
796 lpcfg_string_set(Globals.ctx, &Globals.cups_server, "");
797 lpcfg_string_set(Globals.ctx, &Globals.iprint_server, "");
799 lpcfg_string_set(Globals.ctx, &Globals._ctdbd_socket, "");
801 Globals.cluster_addresses = NULL;
802 Globals.clustering = false;
803 Globals.ctdb_timeout = 0;
804 Globals.ctdb_locktime_warn_threshold = 0;
806 Globals.winbind_cache_time = 300; /* 5 minutes */
807 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
808 Globals.winbind_request_timeout = 60; /* 60 seconds */
809 Globals.winbind_max_clients = 200;
810 Globals.winbind_enum_users = false;
811 Globals.winbind_enum_groups = false;
812 Globals.winbind_use_default_domain = false;
813 Globals.winbind_trusted_domains_only = false;
814 Globals.winbind_nested_groups = true;
815 Globals.winbind_expand_groups = 0;
816 Globals.winbind_nss_info = str_list_make_v3_const(NULL, "template", NULL);
817 Globals.winbind_refresh_tickets = false;
818 Globals.winbind_offline_logon = false;
820 Globals.idmap_cache_time = 86400 * 7; /* a week by default */
821 Globals.idmap_negative_cache_time = 120; /* 2 minutes by default */
823 Globals.passdb_expand_explicit = false;
825 Globals.name_cache_timeout = 660; /* In seconds */
827 Globals.use_spnego = true;
828 Globals.client_use_spnego = true;
830 Globals.client_signing = SMB_SIGNING_DEFAULT;
831 Globals._client_ipc_signing = SMB_SIGNING_DEFAULT;
832 Globals.server_signing = SMB_SIGNING_DEFAULT;
834 Globals.defer_sharing_violations = true;
835 Globals.smb_ports = str_list_make_v3_const(NULL, SMB_PORTS, NULL);
837 Globals.enable_privileges = true;
838 Globals.host_msdfs = true;
839 Globals.enable_asu_support = false;
841 /* User defined shares. */
842 s = talloc_asprintf(talloc_tos(), "%s/usershares", get_dyn_STATEDIR());
843 if (s == NULL) {
844 smb_panic("init_globals: ENOMEM");
846 lpcfg_string_set(Globals.ctx, &Globals.usershare_path, s);
847 TALLOC_FREE(s);
848 lpcfg_string_set(Globals.ctx, &Globals.usershare_template_share, "");
849 Globals.usershare_max_shares = 0;
850 /* By default disallow sharing of directories not owned by the sharer. */
851 Globals.usershare_owner_only = true;
852 /* By default disallow guest access to usershares. */
853 Globals.usershare_allow_guests = false;
855 Globals.keepalive = DEFAULT_KEEPALIVE;
857 /* By default no shares out of the registry */
858 Globals.registry_shares = false;
860 Globals.min_receivefile_size = 0;
862 Globals.map_untrusted_to_domain = Auto;
863 Globals.multicast_dns_register = true;
865 Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
866 Globals.smb2_max_write = DEFAULT_SMB2_MAX_WRITE;
867 Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
868 Globals.smb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
869 Globals.smb2_leases = true;
871 lpcfg_string_set(Globals.ctx, &Globals.ncalrpc_dir,
872 get_dyn_NCALRPCDIR());
874 Globals.server_services = str_list_make_v3_const(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns", NULL);
876 Globals.dcerpc_endpoint_servers = str_list_make_v3_const(NULL, "epmapper wkssvc rpcecho samr netlogon lsarpc drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver", NULL);
878 Globals.tls_enabled = true;
879 Globals.tls_verify_peer = TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE;
881 lpcfg_string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
882 lpcfg_string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
883 lpcfg_string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
884 lpcfg_string_set(Globals.ctx, &Globals.tls_priority,
885 "NORMAL:-VERS-SSL3.0");
887 lpcfg_string_set(Globals.ctx, &Globals.share_backend, "classic");
889 Globals._preferred_master = Auto;
891 Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
893 lpcfg_string_set(Globals.ctx, &Globals.ntp_signd_socket_directory,
894 get_dyn_NTP_SIGND_SOCKET_DIR());
896 s = talloc_asprintf(talloc_tos(), "%s/samba_kcc", get_dyn_SCRIPTSBINDIR());
897 if (s == NULL) {
898 smb_panic("init_globals: ENOMEM");
900 Globals.samba_kcc_command = str_list_make_v3_const(NULL, s, NULL);
901 TALLOC_FREE(s);
903 #ifdef MIT_KDC_PATH
904 Globals.mit_kdc_command = str_list_make_v3_const(NULL, MIT_KDC_PATH, NULL);
905 #endif
907 s = talloc_asprintf(talloc_tos(), "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR());
908 if (s == NULL) {
909 smb_panic("init_globals: ENOMEM");
911 Globals.dns_update_command = str_list_make_v3_const(NULL, s, NULL);
912 TALLOC_FREE(s);
914 s = talloc_asprintf(talloc_tos(), "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR());
915 if (s == NULL) {
916 smb_panic("init_globals: ENOMEM");
918 Globals.spn_update_command = str_list_make_v3_const(NULL, s, NULL);
919 TALLOC_FREE(s);
921 Globals.nsupdate_command = str_list_make_v3_const(NULL, "/usr/bin/nsupdate -g", NULL);
923 Globals.rndc_command = str_list_make_v3_const(NULL, "/usr/sbin/rndc", NULL);
925 Globals.cldap_port = 389;
927 Globals.dgram_port = NBT_DGRAM_SERVICE_PORT;
929 Globals.nbt_port = NBT_NAME_SERVICE_PORT;
931 Globals.krb5_port = 88;
933 Globals.kpasswd_port = 464;
935 Globals.web_port = 901;
937 Globals.aio_max_threads = 100;
939 lpcfg_string_set(Globals.ctx,
940 &Globals.rpc_server_dynamic_port_range,
941 "49152-65535");
942 Globals.rpc_low_port = SERVER_TCP_LOW_PORT;
943 Globals.rpc_high_port = SERVER_TCP_HIGH_PORT;
945 /* Now put back the settings that were set with lp_set_cmdline() */
946 apply_lp_set_cmdline();
949 /* Convenience routine to setup an lp_context with additional s3 variables */
950 static struct loadparm_context *setup_lp_context(TALLOC_CTX *mem_ctx)
952 struct loadparm_context *lp_ctx;
954 lp_ctx = loadparm_init_s3(mem_ctx,
955 loadparm_s3_helpers());
956 if (lp_ctx == NULL) {
957 DEBUG(0, ("loadparm_init_s3 failed\n"));
958 return NULL;
961 lp_ctx->sDefault = &sDefault;
962 lp_ctx->services = NULL; /* We do not want to access this directly */
963 lp_ctx->bInGlobalSection = bInGlobalSection;
964 lp_ctx->flags = flags_list;
966 return lp_ctx;
969 /*******************************************************************
970 Convenience routine to grab string parameters into talloced memory
971 and run standard_sub_basic on them. The buffers can be written to by
972 callers without affecting the source string.
973 ********************************************************************/
975 char *lp_string(TALLOC_CTX *ctx, const char *s)
977 char *ret;
979 /* The follow debug is useful for tracking down memory problems
980 especially if you have an inner loop that is calling a lp_*()
981 function that returns a string. Perhaps this debug should be
982 present all the time? */
984 #if 0
985 DEBUG(10, ("lp_string(%s)\n", s));
986 #endif
987 if (!s) {
988 return NULL;
991 ret = talloc_sub_basic(ctx,
992 get_current_username(),
993 current_user_info.domain,
995 if (trim_char(ret, '\"', '\"')) {
996 if (strchr(ret,'\"') != NULL) {
997 TALLOC_FREE(ret);
998 ret = talloc_sub_basic(ctx,
999 get_current_username(),
1000 current_user_info.domain,
1004 return ret;
1008 In this section all the functions that are used to access the
1009 parameters from the rest of the program are defined
1012 #define FN_GLOBAL_STRING(fn_name,ptr) \
1013 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1014 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1015 const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1016 #define FN_GLOBAL_LIST(fn_name,ptr) \
1017 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1018 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1019 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1020 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1021 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1022 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1023 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1025 #define FN_LOCAL_STRING(fn_name,val) \
1026 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));}
1027 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1028 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1029 #define FN_LOCAL_LIST(fn_name,val) \
1030 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1031 #define FN_LOCAL_BOOL(fn_name,val) \
1032 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1033 #define FN_LOCAL_INTEGER(fn_name,val) \
1034 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1036 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1037 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1038 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1039 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1040 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
1041 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1043 int lp_winbind_max_domain_connections(void)
1045 if (lp_winbind_offline_logon() &&
1046 lp__winbind_max_domain_connections() > 1) {
1047 DEBUG(1, ("offline logons active, restricting max domain "
1048 "connections to 1\n"));
1049 return 1;
1051 return MAX(1, lp__winbind_max_domain_connections());
1054 /* These functions remain in source3/param for now */
1056 #include "lib/param/param_functions.c"
1058 FN_LOCAL_STRING(servicename, szService)
1059 FN_LOCAL_CONST_STRING(const_servicename, szService)
1061 /* These functions cannot be auto-generated */
1062 FN_LOCAL_BOOL(autoloaded, autoloaded)
1063 FN_GLOBAL_CONST_STRING(dnsdomain, dnsdomain)
1065 /* local prototypes */
1067 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1068 static const char *get_boolean(bool bool_value);
1069 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1070 void *userdata);
1071 static bool hash_a_service(const char *name, int number);
1072 static void free_service_byindex(int iService);
1073 static void show_parameter(int parmIndex);
1074 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1075 static bool lp_parameter_value_is_valid(const char *parm_name, const char *val);
1078 * This is a helper function for parametrical options support. It returns a
1079 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1080 * parametrical functions are quite simple
1082 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1083 const char *option)
1085 if (snum >= iNumServices) return NULL;
1087 if (snum < 0) {
1088 return get_parametric_helper(NULL, type, option, Globals.param_opt);
1089 } else {
1090 return get_parametric_helper(ServicePtrs[snum],
1091 type, option, Globals.param_opt);
1095 static void discard_whitespace(char *str)
1097 size_t len = strlen(str);
1098 size_t i = 0;
1100 while (i < len) {
1101 if (isspace(str[i])) {
1102 memmove(&str[i], &str[i+1], len-i);
1103 len -= 1;
1104 continue;
1106 i += 1;
1111 * @brief Go through all global parametric parameters
1113 * @param regex_str A regular expression to scan param for
1114 * @param max_matches Max number of submatches the regexp expects
1115 * @param cb Function to call on match. Should return true
1116 * when it wants wi_scan_global_parametrics to stop
1117 * scanning
1118 * @param private_data Anonymous pointer passed to cb
1120 * @return 0: success, regcomp/regexec return value on error.
1121 * See "man regexec" for possible errors
1124 int lp_wi_scan_global_parametrics(
1125 const char *regex_str, size_t max_matches,
1126 bool (*cb)(const char *string, regmatch_t matches[],
1127 void *private_data),
1128 void *private_data)
1130 struct parmlist_entry *data;
1131 regex_t regex;
1132 int ret;
1134 ret = regcomp(&regex, regex_str, REG_ICASE);
1135 if (ret != 0) {
1136 return ret;
1139 for (data = Globals.param_opt; data != NULL; data = data->next) {
1140 size_t keylen = strlen(data->key);
1141 char key[keylen+1];
1142 regmatch_t matches[max_matches];
1143 bool stop;
1145 memcpy(key, data->key, sizeof(key));
1146 discard_whitespace(key);
1148 ret = regexec(&regex, key, max_matches, matches, 0);
1149 if (ret == REG_NOMATCH) {
1150 continue;
1152 if (ret != 0) {
1153 goto fail;
1156 stop = cb(key, matches, private_data);
1157 if (stop) {
1158 break;
1162 ret = 0;
1163 fail:
1164 regfree(&regex);
1165 return ret;
1169 #define MISSING_PARAMETER(name) \
1170 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1172 /*******************************************************************
1173 convenience routine to return enum parameters.
1174 ********************************************************************/
1175 static int lp_enum(const char *s,const struct enum_list *_enum)
1177 int i;
1179 if (!s || !*s || !_enum) {
1180 MISSING_PARAMETER(lp_enum);
1181 return (-1);
1184 for (i=0; _enum[i].name; i++) {
1185 if (strequal(_enum[i].name,s))
1186 return _enum[i].value;
1189 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1190 return (-1);
1193 #undef MISSING_PARAMETER
1195 /* Return parametric option from a given service. Type is a part of option before ':' */
1196 /* Parametric option has following syntax: 'Type: option = value' */
1197 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1199 struct parmlist_entry *data = get_parametrics(snum, type, option);
1201 if (data == NULL||data->value==NULL) {
1202 if (def) {
1203 return lp_string(ctx, def);
1204 } else {
1205 return NULL;
1209 return lp_string(ctx, data->value);
1212 /* Return parametric option from a given service. Type is a part of option before ':' */
1213 /* Parametric option has following syntax: 'Type: option = value' */
1214 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1216 struct parmlist_entry *data = get_parametrics(snum, type, option);
1218 if (data == NULL||data->value==NULL)
1219 return def;
1221 return data->value;
1225 /* Return parametric option from a given service. Type is a part of option before ':' */
1226 /* Parametric option has following syntax: 'Type: option = value' */
1228 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1230 struct parmlist_entry *data = get_parametrics(snum, type, option);
1232 if (data == NULL||data->value==NULL)
1233 return (const char **)def;
1235 if (data->list==NULL) {
1236 data->list = str_list_make_v3(NULL, data->value, NULL);
1239 return discard_const_p(const char *, data->list);
1242 /* Return parametric option from a given service. Type is a part of option before ':' */
1243 /* Parametric option has following syntax: 'Type: option = value' */
1245 int lp_parm_int(int snum, const char *type, const char *option, int def)
1247 struct parmlist_entry *data = get_parametrics(snum, type, option);
1249 if (data && data->value && *data->value)
1250 return lp_int(data->value);
1252 return def;
1255 /* Return parametric option from a given service. Type is a part of option before ':' */
1256 /* Parametric option has following syntax: 'Type: option = value' */
1258 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1260 struct parmlist_entry *data = get_parametrics(snum, type, option);
1262 if (data && data->value && *data->value)
1263 return lp_ulong(data->value);
1265 return def;
1268 /* Return parametric option from a given service. Type is a part of option before ':' */
1269 /* Parametric option has following syntax: 'Type: option = value' */
1271 unsigned long long lp_parm_ulonglong(int snum, const char *type,
1272 const char *option, unsigned long long def)
1274 struct parmlist_entry *data = get_parametrics(snum, type, option);
1276 if (data && data->value && *data->value) {
1277 return lp_ulonglong(data->value);
1280 return def;
1283 /* Return parametric option from a given service. Type is a part of option
1284 * before ':' */
1285 /* Parametric option has following syntax: 'Type: option = value' */
1287 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1289 struct parmlist_entry *data = get_parametrics(snum, type, option);
1291 if (data && data->value && *data->value)
1292 return lp_bool(data->value);
1294 return def;
1297 /* Return parametric option from a given service. Type is a part of option before ':' */
1298 /* Parametric option has following syntax: 'Type: option = value' */
1300 int lp_parm_enum(int snum, const char *type, const char *option,
1301 const struct enum_list *_enum, int def)
1303 struct parmlist_entry *data = get_parametrics(snum, type, option);
1305 if (data && data->value && *data->value && _enum)
1306 return lp_enum(data->value, _enum);
1308 return def;
1312 * free a param_opts structure.
1313 * param_opts handling should be moved to talloc;
1314 * then this whole functions reduces to a TALLOC_FREE().
1317 static void free_param_opts(struct parmlist_entry **popts)
1319 struct parmlist_entry *opt, *next_opt;
1321 if (*popts != NULL) {
1322 DEBUG(5, ("Freeing parametrics:\n"));
1324 opt = *popts;
1325 while (opt != NULL) {
1326 lpcfg_string_free(&opt->key);
1327 lpcfg_string_free(&opt->value);
1328 TALLOC_FREE(opt->list);
1329 next_opt = opt->next;
1330 TALLOC_FREE(opt);
1331 opt = next_opt;
1333 *popts = NULL;
1336 /***************************************************************************
1337 Free the dynamically allocated parts of a service struct.
1338 ***************************************************************************/
1340 static void free_service(struct loadparm_service *pservice)
1342 if (!pservice)
1343 return;
1345 if (pservice->szService)
1346 DEBUG(5, ("free_service: Freeing service %s\n",
1347 pservice->szService));
1349 free_parameters(pservice);
1351 lpcfg_string_free(&pservice->szService);
1352 TALLOC_FREE(pservice->copymap);
1354 free_param_opts(&pservice->param_opt);
1356 ZERO_STRUCTP(pservice);
1360 /***************************************************************************
1361 remove a service indexed in the ServicePtrs array from the ServiceHash
1362 and free the dynamically allocated parts
1363 ***************************************************************************/
1365 static void free_service_byindex(int idx)
1367 if ( !LP_SNUM_OK(idx) )
1368 return;
1370 ServicePtrs[idx]->valid = false;
1372 /* we have to cleanup the hash record */
1374 if (ServicePtrs[idx]->szService) {
1375 char *canon_name = canonicalize_servicename(
1376 talloc_tos(),
1377 ServicePtrs[idx]->szService );
1379 dbwrap_delete_bystring(ServiceHash, canon_name );
1380 TALLOC_FREE(canon_name);
1383 free_service(ServicePtrs[idx]);
1384 TALLOC_FREE(ServicePtrs[idx]);
1387 /***************************************************************************
1388 Add a new service to the services array initialising it with the given
1389 service.
1390 ***************************************************************************/
1392 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1394 int i;
1395 struct loadparm_service **tsp = NULL;
1397 /* it might already exist */
1398 if (name) {
1399 i = getservicebyname(name, NULL);
1400 if (i >= 0) {
1401 return (i);
1405 /* Re use empty slots if any before allocating new one.*/
1406 for (i=0; i < iNumServices; i++) {
1407 if (ServicePtrs[i] == NULL) {
1408 break;
1411 if (i == iNumServices) {
1412 /* if not, then create one */
1413 tsp = talloc_realloc(NULL, ServicePtrs,
1414 struct loadparm_service *,
1415 iNumServices + 1);
1416 if (tsp == NULL) {
1417 DEBUG(0, ("add_a_service: failed to enlarge "
1418 "ServicePtrs!\n"));
1419 return (-1);
1421 ServicePtrs = tsp;
1422 iNumServices++;
1424 ServicePtrs[i] = talloc_zero(ServicePtrs, struct loadparm_service);
1425 if (!ServicePtrs[i]) {
1426 DEBUG(0,("add_a_service: out of memory!\n"));
1427 return (-1);
1430 ServicePtrs[i]->valid = true;
1432 copy_service(ServicePtrs[i], pservice, NULL);
1433 if (name)
1434 lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->szService,
1435 name);
1437 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1438 i, ServicePtrs[i]->szService));
1440 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1441 return (-1);
1444 return (i);
1447 /***************************************************************************
1448 Convert a string to uppercase and remove whitespaces.
1449 ***************************************************************************/
1451 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1453 char *result;
1455 if ( !src ) {
1456 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1457 return NULL;
1460 result = talloc_strdup(ctx, src);
1461 SMB_ASSERT(result != NULL);
1463 if (!strlower_m(result)) {
1464 TALLOC_FREE(result);
1465 return NULL;
1467 return result;
1470 /***************************************************************************
1471 Add a name/index pair for the services array to the hash table.
1472 ***************************************************************************/
1474 static bool hash_a_service(const char *name, int idx)
1476 char *canon_name;
1478 if ( !ServiceHash ) {
1479 DEBUG(10,("hash_a_service: creating servicehash\n"));
1480 ServiceHash = db_open_rbt(NULL);
1481 if ( !ServiceHash ) {
1482 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1483 return false;
1487 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1488 idx, name));
1490 canon_name = canonicalize_servicename(talloc_tos(), name );
1492 dbwrap_store_bystring(ServiceHash, canon_name,
1493 make_tdb_data((uint8_t *)&idx, sizeof(idx)),
1494 TDB_REPLACE);
1496 TALLOC_FREE(canon_name);
1498 return true;
1501 /***************************************************************************
1502 Add a new home service, with the specified home directory, defaults coming
1503 from service ifrom.
1504 ***************************************************************************/
1506 bool lp_add_home(const char *pszHomename, int iDefaultService,
1507 const char *user, const char *pszHomedir)
1509 int i;
1511 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1512 pszHomedir[0] == '\0') {
1513 return false;
1516 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1518 if (i < 0)
1519 return false;
1521 if (!(*(ServicePtrs[iDefaultService]->path))
1522 || strequal(ServicePtrs[iDefaultService]->path,
1523 lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1524 lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path,
1525 pszHomedir);
1528 if (!(*(ServicePtrs[i]->comment))) {
1529 char *comment = talloc_asprintf(talloc_tos(), "Home directory of %s", user);
1530 if (comment == NULL) {
1531 return false;
1533 lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment,
1534 comment);
1535 TALLOC_FREE(comment);
1538 /* set the browseable flag from the global default */
1540 ServicePtrs[i]->browseable = sDefault.browseable;
1541 ServicePtrs[i]->access_based_share_enum = sDefault.access_based_share_enum;
1543 ServicePtrs[i]->autoloaded = true;
1545 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1546 user, ServicePtrs[i]->path ));
1548 return true;
1551 /***************************************************************************
1552 Add a new service, based on an old one.
1553 ***************************************************************************/
1555 int lp_add_service(const char *pszService, int iDefaultService)
1557 if (iDefaultService < 0) {
1558 return add_a_service(&sDefault, pszService);
1561 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1564 /***************************************************************************
1565 Add the IPC service.
1566 ***************************************************************************/
1568 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1570 char *comment = NULL;
1571 int i = add_a_service(&sDefault, ipc_name);
1573 if (i < 0)
1574 return false;
1576 comment = talloc_asprintf(talloc_tos(), "IPC Service (%s)",
1577 Globals.server_string);
1578 if (comment == NULL) {
1579 return false;
1582 lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
1583 lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1584 lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
1585 ServicePtrs[i]->max_connections = 0;
1586 ServicePtrs[i]->available = true;
1587 ServicePtrs[i]->read_only = true;
1588 ServicePtrs[i]->guest_only = false;
1589 ServicePtrs[i]->administrative_share = true;
1590 ServicePtrs[i]->guest_ok = guest_ok;
1591 ServicePtrs[i]->printable = false;
1592 ServicePtrs[i]->browseable = sDefault.browseable;
1593 ServicePtrs[i]->autoloaded = true;
1595 DEBUG(3, ("adding IPC service\n"));
1597 TALLOC_FREE(comment);
1598 return true;
1601 /***************************************************************************
1602 Add a new printer service, with defaults coming from service iFrom.
1603 ***************************************************************************/
1605 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1607 const char *comment = "From Printcap";
1608 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1610 if (i < 0)
1611 return false;
1613 /* note that we do NOT default the availability flag to true - */
1614 /* we take it from the default service passed. This allows all */
1615 /* dynamic printers to be disabled by disabling the [printers] */
1616 /* entry (if/when the 'available' keyword is implemented!). */
1618 /* the printer name is set to the service name. */
1619 lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->_printername,
1620 pszPrintername);
1621 lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
1623 /* set the browseable flag from the gloabl default */
1624 ServicePtrs[i]->browseable = sDefault.browseable;
1626 /* Printers cannot be read_only. */
1627 ServicePtrs[i]->read_only = false;
1628 /* No oplocks on printer services. */
1629 ServicePtrs[i]->oplocks = false;
1630 /* Printer services must be printable. */
1631 ServicePtrs[i]->printable = true;
1633 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1635 return true;
1639 /***************************************************************************
1640 Check whether the given parameter name is valid.
1641 Parametric options (names containing a colon) are considered valid.
1642 ***************************************************************************/
1644 bool lp_parameter_is_valid(const char *pszParmName)
1646 return ((lpcfg_map_parameter(pszParmName) != -1) ||
1647 (strchr(pszParmName, ':') != NULL));
1650 /***************************************************************************
1651 Check whether the given name is the name of a global parameter.
1652 Returns true for strings belonging to parameters of class
1653 P_GLOBAL, false for all other strings, also for parametric options
1654 and strings not belonging to any option.
1655 ***************************************************************************/
1657 bool lp_parameter_is_global(const char *pszParmName)
1659 int num = lpcfg_map_parameter(pszParmName);
1661 if (num >= 0) {
1662 return (parm_table[num].p_class == P_GLOBAL);
1665 return false;
1668 /**************************************************************************
1669 Determine the canonical name for a parameter.
1670 Indicate when it is an inverse (boolean) synonym instead of a
1671 "usual" synonym.
1672 **************************************************************************/
1674 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1675 bool *inverse)
1677 int num;
1679 if (!lp_parameter_is_valid(parm_name)) {
1680 *canon_parm = NULL;
1681 return false;
1684 num = map_parameter_canonical(parm_name, inverse);
1685 if (num < 0) {
1686 /* parametric option */
1687 *canon_parm = parm_name;
1688 } else {
1689 *canon_parm = parm_table[num].label;
1692 return true;
1696 /**************************************************************************
1697 Determine the canonical name for a parameter.
1698 Turn the value given into the inverse boolean expression when
1699 the synonym is an invers boolean synonym.
1701 Return true if
1702 - parm_name is a valid parameter name and
1703 - val is a valid value for this parameter and
1704 - in case the parameter is an inverse boolean synonym, if the val
1705 string could successfully be converted to the reverse bool.
1706 Return false in all other cases.
1707 **************************************************************************/
1709 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1710 const char *val,
1711 const char **canon_parm,
1712 const char **canon_val)
1714 int num;
1715 bool inverse;
1716 bool ret;
1718 if (!lp_parameter_is_valid(parm_name)) {
1719 *canon_parm = NULL;
1720 *canon_val = NULL;
1721 return false;
1724 num = map_parameter_canonical(parm_name, &inverse);
1725 if (num < 0) {
1726 /* parametric option */
1727 *canon_parm = parm_name;
1728 *canon_val = val;
1729 return true;
1732 *canon_parm = parm_table[num].label;
1733 if (inverse) {
1734 if (!lp_invert_boolean(val, canon_val)) {
1735 *canon_val = NULL;
1736 return false;
1738 } else {
1739 *canon_val = val;
1742 ret = lp_parameter_value_is_valid(*canon_parm, *canon_val);
1744 return ret;
1747 /***************************************************************************
1748 Map a parameter's string representation to the index of the canonical
1749 form of the parameter (it might be a synonym).
1750 Returns -1 if the parameter string is not recognised.
1751 ***************************************************************************/
1753 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1755 int parm_num, canon_num;
1756 bool loc_inverse = false;
1758 parm_num = lpcfg_map_parameter(pszParmName);
1759 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_SYNONYM)) {
1760 /* invalid, parametric or no canidate for synonyms ... */
1761 goto done;
1764 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1765 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1766 parm_num = canon_num;
1767 goto done;
1771 done:
1772 if (inverse != NULL) {
1773 *inverse = loc_inverse;
1775 return parm_num;
1778 /***************************************************************************
1779 return true if parameter number parm1 is a synonym of parameter
1780 number parm2 (parm2 being the principal name).
1781 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1782 false otherwise.
1783 ***************************************************************************/
1785 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
1787 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
1788 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
1789 (parm_table[parm1].flags & FLAG_SYNONYM) &&
1790 !(parm_table[parm2].flags & FLAG_SYNONYM))
1792 if (inverse != NULL) {
1793 if ((parm_table[parm1].type == P_BOOLREV) &&
1794 (parm_table[parm2].type == P_BOOL))
1796 *inverse = true;
1797 } else {
1798 *inverse = false;
1801 return true;
1803 return false;
1806 /***************************************************************************
1807 Show one parameter's name, type, [values,] and flags.
1808 (helper functions for show_parameter_list)
1809 ***************************************************************************/
1811 static void show_parameter(int parmIndex)
1813 int enumIndex, flagIndex;
1814 int parmIndex2;
1815 bool hadFlag;
1816 bool hadSyn;
1817 bool inverse;
1818 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
1819 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
1820 "P_ENUM", "P_BYTES", "P_CMDLIST" };
1821 unsigned flags[] = { FLAG_DEPRECATED, FLAG_SYNONYM };
1822 const char *flag_names[] = { "FLAG_DEPRECATED", "FLAG_SYNONYM", NULL};
1824 printf("%s=%s", parm_table[parmIndex].label,
1825 type[parm_table[parmIndex].type]);
1826 if (parm_table[parmIndex].type == P_ENUM) {
1827 printf(",");
1828 for (enumIndex=0;
1829 parm_table[parmIndex].enum_list[enumIndex].name;
1830 enumIndex++)
1832 printf("%s%s",
1833 enumIndex ? "|" : "",
1834 parm_table[parmIndex].enum_list[enumIndex].name);
1837 printf(",");
1838 hadFlag = false;
1839 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
1840 if (parm_table[parmIndex].flags & flags[flagIndex]) {
1841 printf("%s%s",
1842 hadFlag ? "|" : "",
1843 flag_names[flagIndex]);
1844 hadFlag = true;
1848 /* output synonyms */
1849 hadSyn = false;
1850 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
1851 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
1852 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
1853 parm_table[parmIndex2].label);
1854 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
1855 if (!hadSyn) {
1856 printf(" (synonyms: ");
1857 hadSyn = true;
1858 } else {
1859 printf(", ");
1861 printf("%s%s", parm_table[parmIndex2].label,
1862 inverse ? "[i]" : "");
1865 if (hadSyn) {
1866 printf(")");
1869 printf("\n");
1873 * Check the value for a P_ENUM
1875 static bool check_enum_parameter(struct parm_struct *parm, const char *value)
1877 int i;
1879 for (i = 0; parm->enum_list[i].name; i++) {
1880 if (strwicmp(value, parm->enum_list[i].name) == 0) {
1881 return true;
1884 return false;
1887 /**************************************************************************
1888 Check whether the given value is valid for the given parameter name.
1889 **************************************************************************/
1891 static bool lp_parameter_value_is_valid(const char *parm_name, const char *val)
1893 bool ret = false, tmp_bool;
1894 int num = lpcfg_map_parameter(parm_name), tmp_int;
1895 uint64_t tmp_int64 = 0;
1896 struct parm_struct *parm;
1898 /* parametric options (parameter names containing a colon) cannot
1899 be checked and are therefore considered valid. */
1900 if (strchr(parm_name, ':') != NULL) {
1901 return true;
1904 if (num >= 0) {
1905 parm = &parm_table[num];
1906 switch (parm->type) {
1907 case P_BOOL:
1908 case P_BOOLREV:
1909 ret = set_boolean(val, &tmp_bool);
1910 break;
1912 case P_INTEGER:
1913 ret = (sscanf(val, "%d", &tmp_int) == 1);
1914 break;
1916 case P_OCTAL:
1917 ret = (sscanf(val, "%o", &tmp_int) == 1);
1918 break;
1920 case P_ENUM:
1921 ret = check_enum_parameter(parm, val);
1922 break;
1924 case P_BYTES:
1925 if (conv_str_size_error(val, &tmp_int64) &&
1926 tmp_int64 <= INT_MAX) {
1927 ret = true;
1929 break;
1931 case P_CHAR:
1932 case P_LIST:
1933 case P_STRING:
1934 case P_USTRING:
1935 case P_CMDLIST:
1936 ret = true;
1937 break;
1940 return ret;
1943 /***************************************************************************
1944 Show all parameter's name, type, [values,] and flags.
1945 ***************************************************************************/
1947 void show_parameter_list(void)
1949 int classIndex, parmIndex;
1950 const char *section_names[] = { "local", "global", NULL};
1952 for (classIndex=0; section_names[classIndex]; classIndex++) {
1953 printf("[%s]\n", section_names[classIndex]);
1954 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
1955 if (parm_table[parmIndex].p_class == classIndex) {
1956 show_parameter(parmIndex);
1962 /***************************************************************************
1963 Get the standard string representation of a boolean value ("yes" or "no")
1964 ***************************************************************************/
1966 static const char *get_boolean(bool bool_value)
1968 static const char *yes_str = "yes";
1969 static const char *no_str = "no";
1971 return (bool_value ? yes_str : no_str);
1974 /***************************************************************************
1975 Provide the string of the negated boolean value associated to the boolean
1976 given as a string. Returns false if the passed string does not correctly
1977 represent a boolean.
1978 ***************************************************************************/
1980 bool lp_invert_boolean(const char *str, const char **inverse_str)
1982 bool val;
1984 if (!set_boolean(str, &val)) {
1985 return false;
1988 *inverse_str = get_boolean(!val);
1989 return true;
1992 /***************************************************************************
1993 Provide the canonical string representation of a boolean value given
1994 as a string. Return true on success, false if the string given does
1995 not correctly represent a boolean.
1996 ***************************************************************************/
1998 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2000 bool val;
2002 if (!set_boolean(str, &val)) {
2003 return false;
2006 *canon_str = get_boolean(val);
2007 return true;
2010 /***************************************************************************
2011 Find a service by name. Otherwise works like get_service.
2012 ***************************************************************************/
2014 int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2016 int iService = -1;
2017 char *canon_name;
2018 TDB_DATA data;
2019 NTSTATUS status;
2021 if (ServiceHash == NULL) {
2022 return -1;
2025 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2027 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2028 &data);
2030 if (NT_STATUS_IS_OK(status) &&
2031 (data.dptr != NULL) &&
2032 (data.dsize == sizeof(iService)))
2034 memcpy(&iService, data.dptr, sizeof(iService));
2037 TALLOC_FREE(canon_name);
2039 if ((iService != -1) && (LP_SNUM_OK(iService))
2040 && (pserviceDest != NULL)) {
2041 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2044 return (iService);
2047 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2048 struct loadparm_service *lp_service(const char *pszServiceName)
2050 int iService = getservicebyname(pszServiceName, NULL);
2051 if (iService == -1 || !LP_SNUM_OK(iService)) {
2052 return NULL;
2054 return ServicePtrs[iService];
2057 struct loadparm_service *lp_servicebynum(int snum)
2059 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2060 return NULL;
2062 return ServicePtrs[snum];
2065 struct loadparm_service *lp_default_loadparm_service()
2067 return &sDefault;
2070 static struct smbconf_ctx *lp_smbconf_ctx(void)
2072 sbcErr err;
2073 static struct smbconf_ctx *conf_ctx = NULL;
2075 if (conf_ctx == NULL) {
2076 err = smbconf_init(NULL, &conf_ctx, "registry:");
2077 if (!SBC_ERROR_IS_OK(err)) {
2078 DEBUG(1, ("error initializing registry configuration: "
2079 "%s\n", sbcErrorString(err)));
2080 conf_ctx = NULL;
2084 return conf_ctx;
2087 static bool process_smbconf_service(struct smbconf_service *service)
2089 uint32_t count;
2090 bool ret;
2092 if (service == NULL) {
2093 return false;
2096 ret = lp_do_section(service->name, NULL);
2097 if (ret != true) {
2098 return false;
2100 for (count = 0; count < service->num_params; count++) {
2102 if (!bInGlobalSection && bGlobalOnly) {
2103 ret = true;
2104 } else {
2105 const char *pszParmName = service->param_names[count];
2106 const char *pszParmValue = service->param_values[count];
2108 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2110 ret = lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2111 pszParmName, pszParmValue);
2114 if (ret != true) {
2115 return false;
2118 if (iServiceIndex >= 0) {
2119 return lpcfg_service_ok(ServicePtrs[iServiceIndex]);
2121 return true;
2125 * load a service from registry and activate it
2127 bool process_registry_service(const char *service_name)
2129 sbcErr err;
2130 struct smbconf_service *service = NULL;
2131 TALLOC_CTX *mem_ctx = talloc_stackframe();
2132 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2133 bool ret = false;
2135 if (conf_ctx == NULL) {
2136 goto done;
2139 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2141 if (!smbconf_share_exists(conf_ctx, service_name)) {
2143 * Registry does not contain data for this service (yet),
2144 * but make sure lp_load doesn't return false.
2146 ret = true;
2147 goto done;
2150 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2151 if (!SBC_ERROR_IS_OK(err)) {
2152 goto done;
2155 ret = process_smbconf_service(service);
2156 if (!ret) {
2157 goto done;
2160 /* store the csn */
2161 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2163 done:
2164 TALLOC_FREE(mem_ctx);
2165 return ret;
2169 * process_registry_globals
2171 static bool process_registry_globals(void)
2173 bool ret;
2175 add_to_file_list(NULL, &file_lists, INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2177 if (!bInGlobalSection && bGlobalOnly) {
2178 ret = true;
2179 } else {
2180 const char *pszParmName = "registry shares";
2181 const char *pszParmValue = "yes";
2183 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2185 ret = lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
2186 pszParmName, pszParmValue);
2189 if (!ret) {
2190 return ret;
2193 return process_registry_service(GLOBAL_NAME);
2196 bool process_registry_shares(void)
2198 sbcErr err;
2199 uint32_t count;
2200 struct smbconf_service **service = NULL;
2201 uint32_t num_shares = 0;
2202 TALLOC_CTX *mem_ctx = talloc_stackframe();
2203 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2204 bool ret = false;
2206 if (conf_ctx == NULL) {
2207 goto done;
2210 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2211 if (!SBC_ERROR_IS_OK(err)) {
2212 goto done;
2215 ret = true;
2217 for (count = 0; count < num_shares; count++) {
2218 if (strequal(service[count]->name, GLOBAL_NAME)) {
2219 continue;
2221 ret = process_smbconf_service(service[count]);
2222 if (!ret) {
2223 goto done;
2227 /* store the csn */
2228 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2230 done:
2231 TALLOC_FREE(mem_ctx);
2232 return ret;
2236 * reload those shares from registry that are already
2237 * activated in the services array.
2239 static bool reload_registry_shares(void)
2241 int i;
2242 bool ret = true;
2244 for (i = 0; i < iNumServices; i++) {
2245 if (!VALID(i)) {
2246 continue;
2249 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2250 continue;
2253 ret = process_registry_service(ServicePtrs[i]->szService);
2254 if (!ret) {
2255 goto done;
2259 done:
2260 return ret;
2264 #define MAX_INCLUDE_DEPTH 100
2266 static uint8_t include_depth;
2269 * Free the file lists
2271 static void free_file_list(void)
2273 struct file_lists *f;
2274 struct file_lists *next;
2276 f = file_lists;
2277 while( f ) {
2278 next = f->next;
2279 TALLOC_FREE( f );
2280 f = next;
2282 file_lists = NULL;
2287 * Utility function for outsiders to check if we're running on registry.
2289 bool lp_config_backend_is_registry(void)
2291 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2295 * Utility function to check if the config backend is FILE.
2297 bool lp_config_backend_is_file(void)
2299 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2302 /*******************************************************************
2303 Check if a config file has changed date.
2304 ********************************************************************/
2306 bool lp_file_list_changed(void)
2308 struct file_lists *f = file_lists;
2310 DEBUG(6, ("lp_file_list_changed()\n"));
2312 while (f) {
2313 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2314 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2316 if (conf_ctx == NULL) {
2317 return false;
2319 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2320 NULL))
2322 DEBUGADD(6, ("registry config changed\n"));
2323 return true;
2325 } else {
2326 time_t mod_time;
2327 char *n2 = NULL;
2329 n2 = talloc_sub_basic(talloc_tos(),
2330 get_current_username(),
2331 current_user_info.domain,
2332 f->name);
2333 if (!n2) {
2334 return false;
2336 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2337 f->name, n2, ctime(&f->modtime)));
2339 mod_time = file_modtime(n2);
2341 if (mod_time &&
2342 ((f->modtime != mod_time) ||
2343 (f->subfname == NULL) ||
2344 (strcmp(n2, f->subfname) != 0)))
2346 DEBUGADD(6,
2347 ("file %s modified: %s\n", n2,
2348 ctime(&mod_time)));
2349 f->modtime = mod_time;
2350 TALLOC_FREE(f->subfname);
2351 f->subfname = talloc_strdup(f, n2);
2352 if (f->subfname == NULL) {
2353 smb_panic("talloc_strdup failed");
2355 TALLOC_FREE(n2);
2356 return true;
2358 TALLOC_FREE(n2);
2360 f = f->next;
2362 return false;
2367 * Initialize iconv conversion descriptors.
2369 * This is called the first time it is needed, and also called again
2370 * every time the configuration is reloaded, because the charset or
2371 * codepage might have changed.
2373 static void init_iconv(void)
2375 struct smb_iconv_handle *ret = NULL;
2377 ret = reinit_iconv_handle(NULL,
2378 lp_dos_charset(),
2379 lp_unix_charset());
2380 if (ret == NULL) {
2381 smb_panic("reinit_iconv_handle failed");
2385 /***************************************************************************
2386 Handle the include operation.
2387 ***************************************************************************/
2388 static bool bAllowIncludeRegistry = true;
2390 bool lp_include(struct loadparm_context *lp_ctx, struct loadparm_service *service,
2391 const char *pszParmValue, char **ptr)
2393 char *fname;
2395 if (include_depth >= MAX_INCLUDE_DEPTH) {
2396 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2397 include_depth));
2398 return false;
2401 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2402 if (!bAllowIncludeRegistry) {
2403 return true;
2405 if (lp_ctx->bInGlobalSection) {
2406 bool ret;
2407 include_depth++;
2408 ret = process_registry_globals();
2409 include_depth--;
2410 return ret;
2411 } else {
2412 DEBUG(1, ("\"include = registry\" only effective "
2413 "in %s section\n", GLOBAL_NAME));
2414 return false;
2418 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2419 current_user_info.domain,
2420 pszParmValue);
2422 add_to_file_list(NULL, &file_lists, pszParmValue, fname);
2424 if (service == NULL) {
2425 lpcfg_string_set(Globals.ctx, ptr, fname);
2426 } else {
2427 lpcfg_string_set(service, ptr, fname);
2430 if (file_exist(fname)) {
2431 bool ret;
2432 include_depth++;
2433 ret = pm_process(fname, lp_do_section, do_parameter, lp_ctx);
2434 include_depth--;
2435 TALLOC_FREE(fname);
2436 return ret;
2439 DEBUG(2, ("Can't find include file %s\n", fname));
2440 TALLOC_FREE(fname);
2441 return true;
2444 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2446 char *config_option = NULL;
2447 const char *range = NULL;
2448 bool ret = false;
2450 SMB_ASSERT(low != NULL);
2451 SMB_ASSERT(high != NULL);
2453 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2454 domain_name = "*";
2457 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2458 domain_name);
2459 if (config_option == NULL) {
2460 DEBUG(0, ("out of memory\n"));
2461 return false;
2464 range = lp_parm_const_string(-1, config_option, "range", NULL);
2465 if (range == NULL) {
2466 DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2467 goto done;
2470 if (sscanf(range, "%u - %u", low, high) != 2) {
2471 DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2472 range, domain_name));
2473 goto done;
2476 ret = true;
2478 done:
2479 talloc_free(config_option);
2480 return ret;
2484 bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2486 return lp_idmap_range("*", low, high);
2489 const char *lp_idmap_backend(const char *domain_name)
2491 char *config_option = NULL;
2492 const char *backend = NULL;
2494 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2495 domain_name = "*";
2498 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2499 domain_name);
2500 if (config_option == NULL) {
2501 DEBUG(0, ("out of memory\n"));
2502 return false;
2505 backend = lp_parm_const_string(-1, config_option, "backend", NULL);
2506 if (backend == NULL) {
2507 DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
2508 goto done;
2511 done:
2512 talloc_free(config_option);
2513 return backend;
2516 const char *lp_idmap_default_backend(void)
2518 return lp_idmap_backend("*");
2521 /***************************************************************************
2522 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2523 ***************************************************************************/
2525 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2527 const char *suffix_string;
2529 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2530 Globals.ldap_suffix );
2531 if ( !suffix_string ) {
2532 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2533 return "";
2536 return suffix_string;
2539 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2541 if (Globals._ldap_machine_suffix[0])
2542 return append_ldap_suffix(ctx, Globals._ldap_machine_suffix);
2544 return lp_string(ctx, Globals.ldap_suffix);
2547 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
2549 if (Globals._ldap_user_suffix[0])
2550 return append_ldap_suffix(ctx, Globals._ldap_user_suffix);
2552 return lp_string(ctx, Globals.ldap_suffix);
2555 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
2557 if (Globals._ldap_group_suffix[0])
2558 return append_ldap_suffix(ctx, Globals._ldap_group_suffix);
2560 return lp_string(ctx, Globals.ldap_suffix);
2563 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
2565 if (Globals._ldap_idmap_suffix[0])
2566 return append_ldap_suffix(ctx, Globals._ldap_idmap_suffix);
2568 return lp_string(ctx, Globals.ldap_suffix);
2572 return the parameter pointer for a parameter
2574 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
2576 if (service == NULL) {
2577 if (parm->p_class == P_LOCAL)
2578 return (void *)(((char *)&sDefault)+parm->offset);
2579 else if (parm->p_class == P_GLOBAL)
2580 return (void *)(((char *)&Globals)+parm->offset);
2581 else return NULL;
2582 } else {
2583 return (void *)(((char *)service) + parm->offset);
2587 /***************************************************************************
2588 Process a parameter for a particular service number. If snum < 0
2589 then assume we are in the globals.
2590 ***************************************************************************/
2592 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
2594 TALLOC_CTX *frame = talloc_stackframe();
2595 struct loadparm_context *lp_ctx;
2596 bool ok;
2598 lp_ctx = setup_lp_context(frame);
2599 if (lp_ctx == NULL) {
2600 TALLOC_FREE(frame);
2601 return false;
2604 if (snum < 0) {
2605 ok = lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue);
2606 } else {
2607 ok = lpcfg_do_service_parameter(lp_ctx, ServicePtrs[snum],
2608 pszParmName, pszParmValue);
2611 TALLOC_FREE(frame);
2613 return ok;
2616 /***************************************************************************
2617 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
2618 FLAG_CMDLINE won't be overridden by loads from smb.conf.
2619 ***************************************************************************/
2621 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue)
2623 int parmnum, i;
2624 parmnum = lpcfg_map_parameter(pszParmName);
2625 if (parmnum >= 0) {
2626 flags_list[parmnum] &= ~FLAG_CMDLINE;
2627 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
2628 return false;
2630 flags_list[parmnum] |= FLAG_CMDLINE;
2632 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
2633 * be grouped in the table, so we don't have to search the
2634 * whole table */
2635 for (i=parmnum-1;
2636 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
2637 && parm_table[i].p_class == parm_table[parmnum].p_class;
2638 i--) {
2639 flags_list[i] |= FLAG_CMDLINE;
2641 for (i=parmnum+1;i<num_parameters() && parm_table[i].offset == parm_table[parmnum].offset
2642 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
2643 flags_list[i] |= FLAG_CMDLINE;
2646 return true;
2649 /* it might be parametric */
2650 if (strchr(pszParmName, ':') != NULL) {
2651 set_param_opt(NULL, &Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
2652 return true;
2655 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
2656 return false;
2659 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
2661 bool ret;
2662 TALLOC_CTX *frame = talloc_stackframe();
2663 struct loadparm_context *lp_ctx;
2665 lp_ctx = setup_lp_context(frame);
2666 if (lp_ctx == NULL) {
2667 TALLOC_FREE(frame);
2668 return false;
2671 ret = lpcfg_set_cmdline(lp_ctx, pszParmName, pszParmValue);
2673 TALLOC_FREE(frame);
2674 return ret;
2677 /***************************************************************************
2678 Process a parameter.
2679 ***************************************************************************/
2681 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
2682 void *userdata)
2684 if (!bInGlobalSection && bGlobalOnly)
2685 return true;
2687 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
2689 if (bInGlobalSection) {
2690 return lpcfg_do_global_parameter(userdata, pszParmName, pszParmValue);
2691 } else {
2692 return lpcfg_do_service_parameter(userdata, ServicePtrs[iServiceIndex],
2693 pszParmName, pszParmValue);
2697 /***************************************************************************
2698 Initialize any local variables in the sDefault table, after parsing a
2699 [globals] section.
2700 ***************************************************************************/
2702 static void init_locals(void)
2705 * We run this check once the [globals] is parsed, to force
2706 * the VFS objects and other per-share settings we need for
2707 * the standard way a AD DC is operated. We may change these
2708 * as our code evolves, which is why we force these settings.
2710 * We can't do this at the end of lp_load_ex(), as by that
2711 * point the services have been loaded and they will already
2712 * have "" as their vfs objects.
2714 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
2715 const char **vfs_objects = lp_vfs_objects(-1);
2716 if (!vfs_objects || !vfs_objects[0]) {
2717 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
2718 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
2719 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
2720 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
2721 } else {
2722 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
2726 lp_do_parameter(-1, "map hidden", "no");
2727 lp_do_parameter(-1, "map system", "no");
2728 lp_do_parameter(-1, "map readonly", "no");
2729 lp_do_parameter(-1, "map archive", "no");
2730 lp_do_parameter(-1, "store dos attributes", "yes");
2734 /***************************************************************************
2735 Process a new section (service). At this stage all sections are services.
2736 Later we'll have special sections that permit server parameters to be set.
2737 Returns true on success, false on failure.
2738 ***************************************************************************/
2740 bool lp_do_section(const char *pszSectionName, void *userdata)
2742 struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
2743 bool bRetval;
2744 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2745 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2746 bRetval = false;
2748 /* if we were in a global section then do the local inits */
2749 if (bInGlobalSection && !isglobal)
2750 init_locals();
2752 /* if we've just struck a global section, note the fact. */
2753 bInGlobalSection = isglobal;
2754 if (lp_ctx != NULL) {
2755 lp_ctx->bInGlobalSection = isglobal;
2758 /* check for multiple global sections */
2759 if (bInGlobalSection) {
2760 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2761 return true;
2764 if (!bInGlobalSection && bGlobalOnly)
2765 return true;
2767 /* if we have a current service, tidy it up before moving on */
2768 bRetval = true;
2770 if (iServiceIndex >= 0)
2771 bRetval = lpcfg_service_ok(ServicePtrs[iServiceIndex]);
2773 /* if all is still well, move to the next record in the services array */
2774 if (bRetval) {
2775 /* We put this here to avoid an odd message order if messages are */
2776 /* issued by the post-processing of a previous section. */
2777 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2779 iServiceIndex = add_a_service(&sDefault, pszSectionName);
2780 if (iServiceIndex < 0) {
2781 DEBUG(0, ("Failed to add a new service\n"));
2782 return false;
2784 /* Clean all parametric options for service */
2785 /* They will be added during parsing again */
2786 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
2789 return bRetval;
2792 /***************************************************************************
2793 Display the contents of a parameter of a single services record.
2794 ***************************************************************************/
2796 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
2798 bool result = false;
2799 struct loadparm_context *lp_ctx;
2801 lp_ctx = setup_lp_context(talloc_tos());
2802 if (lp_ctx == NULL) {
2803 return false;
2806 if (isGlobal) {
2807 result = lpcfg_dump_a_parameter(lp_ctx, NULL, parm_name, f);
2808 } else {
2809 result = lpcfg_dump_a_parameter(lp_ctx, ServicePtrs[snum], parm_name, f);
2811 TALLOC_FREE(lp_ctx);
2812 return result;
2815 #if 0
2816 /***************************************************************************
2817 Display the contents of a single copy structure.
2818 ***************************************************************************/
2819 static void dump_copy_map(bool *pcopymap)
2821 int i;
2822 if (!pcopymap)
2823 return;
2825 printf("\n\tNon-Copied parameters:\n");
2827 for (i = 0; parm_table[i].label; i++)
2828 if (parm_table[i].p_class == P_LOCAL &&
2829 parm_table[i].ptr && !pcopymap[i] &&
2830 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
2832 printf("\t\t%s\n", parm_table[i].label);
2835 #endif
2837 /***************************************************************************
2838 Return TRUE if the passed service number is within range.
2839 ***************************************************************************/
2841 bool lp_snum_ok(int iService)
2843 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->available);
2846 /***************************************************************************
2847 Auto-load some home services.
2848 ***************************************************************************/
2850 static void lp_add_auto_services(char *str)
2852 char *s;
2853 char *p;
2854 int homes;
2855 char *saveptr;
2857 if (!str)
2858 return;
2860 s = talloc_strdup(talloc_tos(), str);
2861 if (!s) {
2862 smb_panic("talloc_strdup failed");
2863 return;
2866 homes = lp_servicenumber(HOMES_NAME);
2868 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
2869 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
2870 char *home;
2872 if (lp_servicenumber(p) >= 0)
2873 continue;
2875 home = get_user_home_dir(talloc_tos(), p);
2877 if (home && home[0] && homes >= 0)
2878 lp_add_home(p, homes, p, home);
2880 TALLOC_FREE(home);
2882 TALLOC_FREE(s);
2885 /***************************************************************************
2886 Auto-load one printer.
2887 ***************************************************************************/
2889 void lp_add_one_printer(const char *name, const char *comment,
2890 const char *location, void *pdata)
2892 int printers = lp_servicenumber(PRINTERS_NAME);
2893 int i;
2895 if (lp_servicenumber(name) < 0) {
2896 lp_add_printer(name, printers);
2897 if ((i = lp_servicenumber(name)) >= 0) {
2898 lpcfg_string_set(ServicePtrs[i],
2899 &ServicePtrs[i]->comment, comment);
2900 ServicePtrs[i]->autoloaded = true;
2905 /***************************************************************************
2906 Have we loaded a services file yet?
2907 ***************************************************************************/
2909 bool lp_loaded(void)
2911 return (bLoaded);
2914 /***************************************************************************
2915 Unload unused services.
2916 ***************************************************************************/
2918 void lp_killunused(struct smbd_server_connection *sconn,
2919 bool (*snumused) (struct smbd_server_connection *, int))
2921 int i;
2922 for (i = 0; i < iNumServices; i++) {
2923 if (!VALID(i))
2924 continue;
2926 /* don't kill autoloaded or usershare services */
2927 if ( ServicePtrs[i]->autoloaded ||
2928 ServicePtrs[i]->usershare == USERSHARE_VALID) {
2929 continue;
2932 if (!snumused || !snumused(sconn, i)) {
2933 free_service_byindex(i);
2939 * Kill all except autoloaded and usershare services - convenience wrapper
2941 void lp_kill_all_services(void)
2943 lp_killunused(NULL, NULL);
2946 /***************************************************************************
2947 Unload a service.
2948 ***************************************************************************/
2950 void lp_killservice(int iServiceIn)
2952 if (VALID(iServiceIn)) {
2953 free_service_byindex(iServiceIn);
2957 /***************************************************************************
2958 Save the curent values of all global and sDefault parameters into the
2959 defaults union. This allows testparm to show only the
2960 changed (ie. non-default) parameters.
2961 ***************************************************************************/
2963 static void lp_save_defaults(void)
2965 int i;
2966 struct parmlist_entry * parm;
2967 for (i = 0; parm_table[i].label; i++) {
2968 if (!(flags_list[i] & FLAG_CMDLINE)) {
2969 flags_list[i] |= FLAG_DEFAULT;
2972 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
2973 && parm_table[i].p_class == parm_table[i - 1].p_class)
2974 continue;
2975 switch (parm_table[i].type) {
2976 case P_LIST:
2977 case P_CMDLIST:
2978 parm_table[i].def.lvalue = str_list_copy(
2979 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
2980 break;
2981 case P_STRING:
2982 case P_USTRING:
2983 lpcfg_string_set(
2984 Globals.ctx,
2985 &parm_table[i].def.svalue,
2986 *(char **)lp_parm_ptr(
2987 NULL, &parm_table[i]));
2988 if (parm_table[i].def.svalue == NULL) {
2989 smb_panic("lpcfg_string_set() failed");
2991 break;
2992 case P_BOOL:
2993 case P_BOOLREV:
2994 parm_table[i].def.bvalue =
2995 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
2996 break;
2997 case P_CHAR:
2998 parm_table[i].def.cvalue =
2999 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3000 break;
3001 case P_INTEGER:
3002 case P_OCTAL:
3003 case P_ENUM:
3004 case P_BYTES:
3005 parm_table[i].def.ivalue =
3006 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3007 break;
3011 for (parm=Globals.param_opt; parm; parm=parm->next) {
3012 if (!(parm->priority & FLAG_CMDLINE)) {
3013 parm->priority |= FLAG_DEFAULT;
3017 for (parm=sDefault.param_opt; parm; parm=parm->next) {
3018 if (!(parm->priority & FLAG_CMDLINE)) {
3019 parm->priority |= FLAG_DEFAULT;
3023 defaults_saved = true;
3026 /***********************************************************
3027 If we should send plaintext/LANMAN passwords in the clinet
3028 ************************************************************/
3030 static void set_allowed_client_auth(void)
3032 if (Globals.client_ntlmv2_auth) {
3033 Globals.client_lanman_auth = false;
3035 if (!Globals.client_lanman_auth) {
3036 Globals.client_plaintext_auth = false;
3040 /***************************************************************************
3041 JRA.
3042 The following code allows smbd to read a user defined share file.
3043 Yes, this is my intent. Yes, I'm comfortable with that...
3045 THE FOLLOWING IS SECURITY CRITICAL CODE.
3047 It washes your clothes, it cleans your house, it guards you while you sleep...
3048 Do not f%^k with it....
3049 ***************************************************************************/
3051 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3053 /***************************************************************************
3054 Check allowed stat state of a usershare file.
3055 Ensure we print out who is dicking with us so the admin can
3056 get their sorry ass fired.
3057 ***************************************************************************/
3059 static bool check_usershare_stat(const char *fname,
3060 const SMB_STRUCT_STAT *psbuf)
3062 if (!S_ISREG(psbuf->st_ex_mode)) {
3063 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3064 "not a regular file\n",
3065 fname, (unsigned int)psbuf->st_ex_uid ));
3066 return false;
3069 /* Ensure this doesn't have the other write bit set. */
3070 if (psbuf->st_ex_mode & S_IWOTH) {
3071 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
3072 "public write. Refusing to allow as a usershare file.\n",
3073 fname, (unsigned int)psbuf->st_ex_uid ));
3074 return false;
3077 /* Should be 10k or less. */
3078 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
3079 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3080 "too large (%u) to be a user share file.\n",
3081 fname, (unsigned int)psbuf->st_ex_uid,
3082 (unsigned int)psbuf->st_ex_size ));
3083 return false;
3086 return true;
3089 /***************************************************************************
3090 Parse the contents of a usershare file.
3091 ***************************************************************************/
3093 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
3094 SMB_STRUCT_STAT *psbuf,
3095 const char *servicename,
3096 int snum,
3097 char **lines,
3098 int numlines,
3099 char **pp_sharepath,
3100 char **pp_comment,
3101 char **pp_cp_servicename,
3102 struct security_descriptor **ppsd,
3103 bool *pallow_guest)
3105 const char **prefixallowlist = lp_usershare_prefix_allow_list();
3106 const char **prefixdenylist = lp_usershare_prefix_deny_list();
3107 int us_vers;
3108 DIR *dp;
3109 SMB_STRUCT_STAT sbuf;
3110 char *sharepath = NULL;
3111 char *comment = NULL;
3113 *pp_sharepath = NULL;
3114 *pp_comment = NULL;
3116 *pallow_guest = false;
3118 if (numlines < 4) {
3119 return USERSHARE_MALFORMED_FILE;
3122 if (strcmp(lines[0], "#VERSION 1") == 0) {
3123 us_vers = 1;
3124 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
3125 us_vers = 2;
3126 if (numlines < 5) {
3127 return USERSHARE_MALFORMED_FILE;
3129 } else {
3130 return USERSHARE_BAD_VERSION;
3133 if (strncmp(lines[1], "path=", 5) != 0) {
3134 return USERSHARE_MALFORMED_PATH;
3137 sharepath = talloc_strdup(ctx, &lines[1][5]);
3138 if (!sharepath) {
3139 return USERSHARE_POSIX_ERR;
3141 trim_string(sharepath, " ", " ");
3143 if (strncmp(lines[2], "comment=", 8) != 0) {
3144 return USERSHARE_MALFORMED_COMMENT_DEF;
3147 comment = talloc_strdup(ctx, &lines[2][8]);
3148 if (!comment) {
3149 return USERSHARE_POSIX_ERR;
3151 trim_string(comment, " ", " ");
3152 trim_char(comment, '"', '"');
3154 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
3155 return USERSHARE_MALFORMED_ACL_DEF;
3158 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
3159 return USERSHARE_ACL_ERR;
3162 if (us_vers == 2) {
3163 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
3164 return USERSHARE_MALFORMED_ACL_DEF;
3166 if (lines[4][9] == 'y') {
3167 *pallow_guest = true;
3170 /* Backwards compatible extension to file version #2. */
3171 if (numlines > 5) {
3172 if (strncmp(lines[5], "sharename=", 10) != 0) {
3173 return USERSHARE_MALFORMED_SHARENAME_DEF;
3175 if (!strequal(&lines[5][10], servicename)) {
3176 return USERSHARE_BAD_SHARENAME;
3178 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
3179 if (!*pp_cp_servicename) {
3180 return USERSHARE_POSIX_ERR;
3185 if (*pp_cp_servicename == NULL) {
3186 *pp_cp_servicename = talloc_strdup(ctx, servicename);
3187 if (!*pp_cp_servicename) {
3188 return USERSHARE_POSIX_ERR;
3192 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->path) == 0)) {
3193 /* Path didn't change, no checks needed. */
3194 *pp_sharepath = sharepath;
3195 *pp_comment = comment;
3196 return USERSHARE_OK;
3199 /* The path *must* be absolute. */
3200 if (sharepath[0] != '/') {
3201 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
3202 servicename, sharepath));
3203 return USERSHARE_PATH_NOT_ABSOLUTE;
3206 /* If there is a usershare prefix deny list ensure one of these paths
3207 doesn't match the start of the user given path. */
3208 if (prefixdenylist) {
3209 int i;
3210 for ( i=0; prefixdenylist[i]; i++ ) {
3211 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
3212 servicename, i, prefixdenylist[i], sharepath ));
3213 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
3214 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
3215 "usershare prefix deny list entries.\n",
3216 servicename, sharepath));
3217 return USERSHARE_PATH_IS_DENIED;
3222 /* If there is a usershare prefix allow list ensure one of these paths
3223 does match the start of the user given path. */
3225 if (prefixallowlist) {
3226 int i;
3227 for ( i=0; prefixallowlist[i]; i++ ) {
3228 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
3229 servicename, i, prefixallowlist[i], sharepath ));
3230 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
3231 break;
3234 if (prefixallowlist[i] == NULL) {
3235 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
3236 "usershare prefix allow list entries.\n",
3237 servicename, sharepath));
3238 return USERSHARE_PATH_NOT_ALLOWED;
3242 /* Ensure this is pointing to a directory. */
3243 dp = opendir(sharepath);
3245 if (!dp) {
3246 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3247 servicename, sharepath));
3248 return USERSHARE_PATH_NOT_DIRECTORY;
3251 /* Ensure the owner of the usershare file has permission to share
3252 this directory. */
3254 if (sys_stat(sharepath, &sbuf, false) == -1) {
3255 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
3256 servicename, sharepath, strerror(errno) ));
3257 closedir(dp);
3258 return USERSHARE_POSIX_ERR;
3261 closedir(dp);
3263 if (!S_ISDIR(sbuf.st_ex_mode)) {
3264 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
3265 servicename, sharepath ));
3266 return USERSHARE_PATH_NOT_DIRECTORY;
3269 /* Check if sharing is restricted to owner-only. */
3270 /* psbuf is the stat of the usershare definition file,
3271 sbuf is the stat of the target directory to be shared. */
3273 if (lp_usershare_owner_only()) {
3274 /* root can share anything. */
3275 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
3276 return USERSHARE_PATH_NOT_ALLOWED;
3280 *pp_sharepath = sharepath;
3281 *pp_comment = comment;
3282 return USERSHARE_OK;
3285 /***************************************************************************
3286 Deal with a usershare file.
3287 Returns:
3288 >= 0 - snum
3289 -1 - Bad name, invalid contents.
3290 - service name already existed and not a usershare, problem
3291 with permissions to share directory etc.
3292 ***************************************************************************/
3294 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
3296 SMB_STRUCT_STAT sbuf;
3297 SMB_STRUCT_STAT lsbuf;
3298 char *fname = NULL;
3299 char *sharepath = NULL;
3300 char *comment = NULL;
3301 char *cp_service_name = NULL;
3302 char **lines = NULL;
3303 int numlines = 0;
3304 int fd = -1;
3305 int iService = -1;
3306 TALLOC_CTX *ctx = talloc_stackframe();
3307 struct security_descriptor *psd = NULL;
3308 bool guest_ok = false;
3309 char *canon_name = NULL;
3310 bool added_service = false;
3311 int ret = -1;
3313 /* Ensure share name doesn't contain invalid characters. */
3314 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
3315 DEBUG(0,("process_usershare_file: share name %s contains "
3316 "invalid characters (any of %s)\n",
3317 file_name, INVALID_SHARENAME_CHARS ));
3318 goto out;
3321 canon_name = canonicalize_servicename(ctx, file_name);
3322 if (!canon_name) {
3323 goto out;
3326 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
3327 if (!fname) {
3328 goto out;
3331 /* Minimize the race condition by doing an lstat before we
3332 open and fstat. Ensure this isn't a symlink link. */
3334 if (sys_lstat(fname, &lsbuf, false) != 0) {
3335 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
3336 fname, strerror(errno) ));
3337 goto out;
3340 /* This must be a regular file, not a symlink, directory or
3341 other strange filetype. */
3342 if (!check_usershare_stat(fname, &lsbuf)) {
3343 goto out;
3347 TDB_DATA data;
3348 NTSTATUS status;
3350 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
3351 canon_name, &data);
3353 iService = -1;
3355 if (NT_STATUS_IS_OK(status) &&
3356 (data.dptr != NULL) &&
3357 (data.dsize == sizeof(iService))) {
3358 memcpy(&iService, data.dptr, sizeof(iService));
3362 if (iService != -1 &&
3363 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
3364 &lsbuf.st_ex_mtime) == 0) {
3365 /* Nothing changed - Mark valid and return. */
3366 DEBUG(10,("process_usershare_file: service %s not changed.\n",
3367 canon_name ));
3368 ServicePtrs[iService]->usershare = USERSHARE_VALID;
3369 ret = iService;
3370 goto out;
3373 /* Try and open the file read only - no symlinks allowed. */
3374 #ifdef O_NOFOLLOW
3375 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
3376 #else
3377 fd = open(fname, O_RDONLY, 0);
3378 #endif
3380 if (fd == -1) {
3381 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
3382 fname, strerror(errno) ));
3383 goto out;
3386 /* Now fstat to be *SURE* it's a regular file. */
3387 if (sys_fstat(fd, &sbuf, false) != 0) {
3388 close(fd);
3389 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
3390 fname, strerror(errno) ));
3391 goto out;
3394 /* Is it the same dev/inode as was lstated ? */
3395 if (!check_same_stat(&lsbuf, &sbuf)) {
3396 close(fd);
3397 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
3398 "Symlink spoofing going on ?\n", fname ));
3399 goto out;
3402 /* This must be a regular file, not a symlink, directory or
3403 other strange filetype. */
3404 if (!check_usershare_stat(fname, &sbuf)) {
3405 close(fd);
3406 goto out;
3409 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
3411 close(fd);
3412 if (lines == NULL) {
3413 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
3414 fname, (unsigned int)sbuf.st_ex_uid ));
3415 goto out;
3418 if (parse_usershare_file(ctx, &sbuf, file_name,
3419 iService, lines, numlines, &sharepath,
3420 &comment, &cp_service_name,
3421 &psd, &guest_ok) != USERSHARE_OK) {
3422 goto out;
3425 /* Everything ok - add the service possibly using a template. */
3426 if (iService < 0) {
3427 const struct loadparm_service *sp = &sDefault;
3428 if (snum_template != -1) {
3429 sp = ServicePtrs[snum_template];
3432 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
3433 DEBUG(0, ("process_usershare_file: Failed to add "
3434 "new service %s\n", cp_service_name));
3435 goto out;
3438 added_service = true;
3440 /* Read only is controlled by usershare ACL below. */
3441 ServicePtrs[iService]->read_only = false;
3444 /* Write the ACL of the new/modified share. */
3445 if (!set_share_security(canon_name, psd)) {
3446 DEBUG(0, ("process_usershare_file: Failed to set share "
3447 "security for user share %s\n",
3448 canon_name ));
3449 goto out;
3452 /* If from a template it may be marked invalid. */
3453 ServicePtrs[iService]->valid = true;
3455 /* Set the service as a valid usershare. */
3456 ServicePtrs[iService]->usershare = USERSHARE_VALID;
3458 /* Set guest access. */
3459 if (lp_usershare_allow_guests()) {
3460 ServicePtrs[iService]->guest_ok = guest_ok;
3463 /* And note when it was loaded. */
3464 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
3465 lpcfg_string_set(ServicePtrs[iService], &ServicePtrs[iService]->path,
3466 sharepath);
3467 lpcfg_string_set(ServicePtrs[iService],
3468 &ServicePtrs[iService]->comment, comment);
3470 ret = iService;
3472 out:
3474 if (ret == -1 && iService != -1 && added_service) {
3475 lp_remove_service(iService);
3478 TALLOC_FREE(lines);
3479 TALLOC_FREE(ctx);
3480 return ret;
3483 /***************************************************************************
3484 Checks if a usershare entry has been modified since last load.
3485 ***************************************************************************/
3487 static bool usershare_exists(int iService, struct timespec *last_mod)
3489 SMB_STRUCT_STAT lsbuf;
3490 const char *usersharepath = Globals.usershare_path;
3491 char *fname;
3493 fname = talloc_asprintf(talloc_tos(),
3494 "%s/%s",
3495 usersharepath,
3496 ServicePtrs[iService]->szService);
3497 if (fname == NULL) {
3498 return false;
3501 if (sys_lstat(fname, &lsbuf, false) != 0) {
3502 TALLOC_FREE(fname);
3503 return false;
3506 if (!S_ISREG(lsbuf.st_ex_mode)) {
3507 TALLOC_FREE(fname);
3508 return false;
3511 TALLOC_FREE(fname);
3512 *last_mod = lsbuf.st_ex_mtime;
3513 return true;
3516 /***************************************************************************
3517 Load a usershare service by name. Returns a valid servicenumber or -1.
3518 ***************************************************************************/
3520 int load_usershare_service(const char *servicename)
3522 SMB_STRUCT_STAT sbuf;
3523 const char *usersharepath = Globals.usershare_path;
3524 int max_user_shares = Globals.usershare_max_shares;
3525 int snum_template = -1;
3527 if (*usersharepath == 0 || max_user_shares == 0) {
3528 return -1;
3531 if (sys_stat(usersharepath, &sbuf, false) != 0) {
3532 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
3533 usersharepath, strerror(errno) ));
3534 return -1;
3537 if (!S_ISDIR(sbuf.st_ex_mode)) {
3538 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
3539 usersharepath ));
3540 return -1;
3544 * This directory must be owned by root, and have the 't' bit set.
3545 * It also must not be writable by "other".
3548 #ifdef S_ISVTX
3549 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
3550 #else
3551 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
3552 #endif
3553 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
3554 "or does not have the sticky bit 't' set or is writable by anyone.\n",
3555 usersharepath ));
3556 return -1;
3559 /* Ensure the template share exists if it's set. */
3560 if (Globals.usershare_template_share[0]) {
3561 /* We can't use lp_servicenumber here as we are recommending that
3562 template shares have -valid=false set. */
3563 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
3564 if (ServicePtrs[snum_template]->szService &&
3565 strequal(ServicePtrs[snum_template]->szService,
3566 Globals.usershare_template_share)) {
3567 break;
3571 if (snum_template == -1) {
3572 DEBUG(0,("load_usershare_service: usershare template share %s "
3573 "does not exist.\n",
3574 Globals.usershare_template_share ));
3575 return -1;
3579 return process_usershare_file(usersharepath, servicename, snum_template);
3582 /***************************************************************************
3583 Load all user defined shares from the user share directory.
3584 We only do this if we're enumerating the share list.
3585 This is the function that can delete usershares that have
3586 been removed.
3587 ***************************************************************************/
3589 int load_usershare_shares(struct smbd_server_connection *sconn,
3590 bool (*snumused) (struct smbd_server_connection *, int))
3592 DIR *dp;
3593 SMB_STRUCT_STAT sbuf;
3594 struct dirent *de;
3595 int num_usershares = 0;
3596 int max_user_shares = Globals.usershare_max_shares;
3597 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
3598 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
3599 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
3600 int iService;
3601 int snum_template = -1;
3602 const char *usersharepath = Globals.usershare_path;
3603 int ret = lp_numservices();
3604 TALLOC_CTX *tmp_ctx;
3606 if (max_user_shares == 0 || *usersharepath == '\0') {
3607 return lp_numservices();
3610 if (sys_stat(usersharepath, &sbuf, false) != 0) {
3611 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
3612 usersharepath, strerror(errno) ));
3613 return ret;
3617 * This directory must be owned by root, and have the 't' bit set.
3618 * It also must not be writable by "other".
3621 #ifdef S_ISVTX
3622 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
3623 #else
3624 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
3625 #endif
3626 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
3627 "or does not have the sticky bit 't' set or is writable by anyone.\n",
3628 usersharepath ));
3629 return ret;
3632 /* Ensure the template share exists if it's set. */
3633 if (Globals.usershare_template_share[0]) {
3634 /* We can't use lp_servicenumber here as we are recommending that
3635 template shares have -valid=false set. */
3636 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
3637 if (ServicePtrs[snum_template]->szService &&
3638 strequal(ServicePtrs[snum_template]->szService,
3639 Globals.usershare_template_share)) {
3640 break;
3644 if (snum_template == -1) {
3645 DEBUG(0,("load_usershare_shares: usershare template share %s "
3646 "does not exist.\n",
3647 Globals.usershare_template_share ));
3648 return ret;
3652 /* Mark all existing usershares as pending delete. */
3653 for (iService = iNumServices - 1; iService >= 0; iService--) {
3654 if (VALID(iService) && ServicePtrs[iService]->usershare) {
3655 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
3659 dp = opendir(usersharepath);
3660 if (!dp) {
3661 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
3662 usersharepath, strerror(errno) ));
3663 return ret;
3666 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
3667 (de = readdir(dp));
3668 num_dir_entries++ ) {
3669 int r;
3670 const char *n = de->d_name;
3672 /* Ignore . and .. */
3673 if (*n == '.') {
3674 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
3675 continue;
3679 if (n[0] == ':') {
3680 /* Temporary file used when creating a share. */
3681 num_tmp_dir_entries++;
3684 /* Allow 20% tmp entries. */
3685 if (num_tmp_dir_entries > allowed_tmp_entries) {
3686 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
3687 "in directory %s\n",
3688 num_tmp_dir_entries, usersharepath));
3689 break;
3692 r = process_usershare_file(usersharepath, n, snum_template);
3693 if (r == 0) {
3694 /* Update the services count. */
3695 num_usershares++;
3696 if (num_usershares >= max_user_shares) {
3697 DEBUG(0,("load_usershare_shares: max user shares reached "
3698 "on file %s in directory %s\n",
3699 n, usersharepath ));
3700 break;
3702 } else if (r == -1) {
3703 num_bad_dir_entries++;
3706 /* Allow 20% bad entries. */
3707 if (num_bad_dir_entries > allowed_bad_entries) {
3708 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
3709 "in directory %s\n",
3710 num_bad_dir_entries, usersharepath));
3711 break;
3714 /* Allow 20% bad entries. */
3715 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
3716 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
3717 "in directory %s\n",
3718 num_dir_entries, usersharepath));
3719 break;
3723 closedir(dp);
3725 /* Sweep through and delete any non-refreshed usershares that are
3726 not currently in use. */
3727 tmp_ctx = talloc_stackframe();
3728 for (iService = iNumServices - 1; iService >= 0; iService--) {
3729 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
3730 char *servname;
3732 if (snumused && snumused(sconn, iService)) {
3733 continue;
3736 servname = lp_servicename(tmp_ctx, iService);
3738 /* Remove from the share ACL db. */
3739 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
3740 servname ));
3741 delete_share_security(servname);
3742 free_service_byindex(iService);
3745 talloc_free(tmp_ctx);
3747 return lp_numservices();
3750 /********************************************************
3751 Destroy global resources allocated in this file
3752 ********************************************************/
3754 void gfree_loadparm(void)
3756 int i;
3758 free_file_list();
3760 /* Free resources allocated to services */
3762 for ( i = 0; i < iNumServices; i++ ) {
3763 if ( VALID(i) ) {
3764 free_service_byindex(i);
3768 TALLOC_FREE( ServicePtrs );
3769 iNumServices = 0;
3771 /* Now release all resources allocated to global
3772 parameters and the default service */
3774 free_global_parameters();
3778 /***************************************************************************
3779 Allow client apps to specify that they are a client
3780 ***************************************************************************/
3781 static void lp_set_in_client(bool b)
3783 in_client = b;
3787 /***************************************************************************
3788 Determine if we're running in a client app
3789 ***************************************************************************/
3790 static bool lp_is_in_client(void)
3792 return in_client;
3795 static void lp_enforce_ad_dc_settings(void)
3797 lp_do_parameter(GLOBAL_SECTION_SNUM, "passdb backend", "samba_dsdb");
3798 lp_do_parameter(GLOBAL_SECTION_SNUM,
3799 "winbindd:use external pipes", "true");
3800 lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:default", "external");
3801 lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:svcctl", "embedded");
3802 lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:srvsvc", "embedded");
3803 lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:eventlog", "embedded");
3804 lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:ntsvcs", "embedded");
3805 lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:winreg", "embedded");
3806 lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:spoolss", "embedded");
3807 lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_daemon:spoolssd", "embedded");
3808 lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:tcpip", "no");
3811 /***************************************************************************
3812 Load the services array from the services file. Return true on success,
3813 false on failure.
3814 ***************************************************************************/
3816 static bool lp_load_ex(const char *pszFname,
3817 bool global_only,
3818 bool save_defaults,
3819 bool add_ipc,
3820 bool reinit_globals,
3821 bool allow_include_registry,
3822 bool load_all_shares)
3824 char *n2 = NULL;
3825 bool bRetval;
3826 TALLOC_CTX *frame = talloc_stackframe();
3827 struct loadparm_context *lp_ctx;
3829 bRetval = false;
3831 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
3833 bInGlobalSection = true;
3834 bGlobalOnly = global_only;
3835 bAllowIncludeRegistry = allow_include_registry;
3837 lp_ctx = setup_lp_context(talloc_tos());
3839 init_globals(lp_ctx, reinit_globals);
3841 free_file_list();
3843 if (save_defaults) {
3844 init_locals();
3845 lp_save_defaults();
3848 if (!reinit_globals) {
3849 free_param_opts(&Globals.param_opt);
3850 apply_lp_set_cmdline();
3853 lp_do_parameter(-1, "idmap config * : backend", Globals.idmap_backend);
3855 /* We get sections first, so have to start 'behind' to make up */
3856 iServiceIndex = -1;
3858 if (lp_config_backend_is_file()) {
3859 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
3860 current_user_info.domain,
3861 pszFname);
3862 if (!n2) {
3863 smb_panic("lp_load_ex: out of memory");
3866 add_to_file_list(NULL, &file_lists, pszFname, n2);
3868 bRetval = pm_process(n2, lp_do_section, do_parameter, lp_ctx);
3869 TALLOC_FREE(n2);
3871 /* finish up the last section */
3872 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
3873 if (bRetval) {
3874 if (iServiceIndex >= 0) {
3875 bRetval = lpcfg_service_ok(ServicePtrs[iServiceIndex]);
3879 if (lp_config_backend_is_registry()) {
3880 bool ok;
3881 /* config backend changed to registry in config file */
3883 * We need to use this extra global variable here to
3884 * survive restart: init_globals uses this as a default
3885 * for config_backend. Otherwise, init_globals would
3886 * send us into an endless loop here.
3889 config_backend = CONFIG_BACKEND_REGISTRY;
3890 /* start over */
3891 DEBUG(1, ("lp_load_ex: changing to config backend "
3892 "registry\n"));
3893 init_globals(lp_ctx, true);
3895 TALLOC_FREE(lp_ctx);
3897 lp_kill_all_services();
3898 ok = lp_load_ex(pszFname, global_only, save_defaults,
3899 add_ipc, reinit_globals,
3900 allow_include_registry,
3901 load_all_shares);
3902 TALLOC_FREE(frame);
3903 return ok;
3905 } else if (lp_config_backend_is_registry()) {
3906 bRetval = process_registry_globals();
3907 } else {
3908 DEBUG(0, ("Illegal config backend given: %d\n",
3909 lp_config_backend()));
3910 bRetval = false;
3913 if (bRetval && lp_registry_shares()) {
3914 if (load_all_shares) {
3915 bRetval = process_registry_shares();
3916 } else {
3917 bRetval = reload_registry_shares();
3922 char *serv = lp_auto_services(talloc_tos());
3923 lp_add_auto_services(serv);
3924 TALLOC_FREE(serv);
3927 if (add_ipc) {
3928 /* When 'restrict anonymous = 2' guest connections to ipc$
3929 are denied */
3930 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
3931 if ( lp_enable_asu_support() ) {
3932 lp_add_ipc("ADMIN$", false);
3936 set_allowed_client_auth();
3938 if (lp_security() == SEC_ADS && strchr(lp_password_server(), ':')) {
3939 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
3940 lp_password_server()));
3943 bLoaded = true;
3945 /* Now we check we_are_a_wins_server and set szWINSserver to 127.0.0.1 */
3946 /* if we_are_a_wins_server is true and we are in the client */
3947 if (lp_is_in_client() && Globals.we_are_a_wins_server) {
3948 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
3951 init_iconv();
3953 fault_configure(smb_panic_s3);
3956 * We run this check once the whole smb.conf is parsed, to
3957 * force some settings for the standard way a AD DC is
3958 * operated. We may change these as our code evolves, which
3959 * is why we force these settings.
3961 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
3962 lp_enforce_ad_dc_settings();
3965 bAllowIncludeRegistry = true;
3967 TALLOC_FREE(frame);
3968 return (bRetval);
3971 static bool lp_load(const char *pszFname,
3972 bool global_only,
3973 bool save_defaults,
3974 bool add_ipc,
3975 bool reinit_globals)
3977 return lp_load_ex(pszFname,
3978 global_only,
3979 save_defaults,
3980 add_ipc,
3981 reinit_globals,
3982 true, /* allow_include_registry */
3983 false); /* load_all_shares*/
3986 bool lp_load_initial_only(const char *pszFname)
3988 return lp_load_ex(pszFname,
3989 true, /* global only */
3990 true, /* save_defaults */
3991 false, /* add_ipc */
3992 true, /* reinit_globals */
3993 false, /* allow_include_registry */
3994 false); /* load_all_shares*/
3998 * most common lp_load wrapper, loading only the globals
4000 * If this is used in a daemon or client utility it should be called
4001 * after processing popt.
4003 bool lp_load_global(const char *file_name)
4005 return lp_load(file_name,
4006 true, /* global_only */
4007 false, /* save_defaults */
4008 false, /* add_ipc */
4009 true); /* reinit_globals */
4013 * The typical lp_load wrapper with shares, loads global and
4014 * shares, including IPC, but does not force immediate
4015 * loading of all shares from registry.
4017 bool lp_load_with_shares(const char *file_name)
4019 return lp_load(file_name,
4020 false, /* global_only */
4021 false, /* save_defaults */
4022 true, /* add_ipc */
4023 true); /* reinit_globals */
4027 * lp_load wrapper, especially for clients
4029 bool lp_load_client(const char *file_name)
4031 lp_set_in_client(true);
4033 return lp_load_global(file_name);
4037 * lp_load wrapper, loading only globals, but intended
4038 * for subsequent calls, not reinitializing the globals
4039 * to default values
4041 bool lp_load_global_no_reinit(const char *file_name)
4043 return lp_load(file_name,
4044 true, /* global_only */
4045 false, /* save_defaults */
4046 false, /* add_ipc */
4047 false); /* reinit_globals */
4051 * lp_load wrapper, loading globals and shares,
4052 * intended for subsequent calls, i.e. not reinitializing
4053 * the globals to default values.
4055 bool lp_load_no_reinit(const char *file_name)
4057 return lp_load(file_name,
4058 false, /* global_only */
4059 false, /* save_defaults */
4060 false, /* add_ipc */
4061 false); /* reinit_globals */
4066 * lp_load wrapper, especially for clients, no reinitialization
4068 bool lp_load_client_no_reinit(const char *file_name)
4070 lp_set_in_client(true);
4072 return lp_load_global_no_reinit(file_name);
4075 bool lp_load_with_registry_shares(const char *pszFname)
4077 return lp_load_ex(pszFname,
4078 false, /* global_only */
4079 true, /* save_defaults */
4080 false, /* add_ipc */
4081 false, /* reinit_globals */
4082 true, /* allow_include_registry */
4083 true); /* load_all_shares*/
4086 /***************************************************************************
4087 Return the max number of services.
4088 ***************************************************************************/
4090 int lp_numservices(void)
4092 return (iNumServices);
4095 /***************************************************************************
4096 Display the contents of the services array in human-readable form.
4097 ***************************************************************************/
4099 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4101 int iService;
4102 struct loadparm_context *lp_ctx;
4104 if (show_defaults)
4105 defaults_saved = false;
4107 lp_ctx = setup_lp_context(talloc_tos());
4108 if (lp_ctx == NULL) {
4109 return;
4112 lpcfg_dump_globals(lp_ctx, f, !defaults_saved);
4114 lpcfg_dump_a_service(&sDefault, &sDefault, f, flags_list, show_defaults);
4116 for (iService = 0; iService < maxtoprint; iService++) {
4117 fprintf(f,"\n");
4118 lp_dump_one(f, show_defaults, iService);
4122 /***************************************************************************
4123 Display the contents of one service in human-readable form.
4124 ***************************************************************************/
4126 void lp_dump_one(FILE * f, bool show_defaults, int snum)
4128 if (VALID(snum)) {
4129 if (ServicePtrs[snum]->szService[0] == '\0')
4130 return;
4131 lpcfg_dump_a_service(ServicePtrs[snum], &sDefault, f,
4132 flags_list, show_defaults);
4136 /***************************************************************************
4137 Return the number of the service with the given name, or -1 if it doesn't
4138 exist. Note that this is a DIFFERENT ANIMAL from the internal function
4139 getservicebyname()! This works ONLY if all services have been loaded, and
4140 does not copy the found service.
4141 ***************************************************************************/
4143 int lp_servicenumber(const char *pszServiceName)
4145 int iService;
4146 fstring serviceName;
4148 if (!pszServiceName) {
4149 return GLOBAL_SECTION_SNUM;
4152 for (iService = iNumServices - 1; iService >= 0; iService--) {
4153 if (VALID(iService) && ServicePtrs[iService]->szService) {
4155 * The substitution here is used to support %U in
4156 * service names
4158 fstrcpy(serviceName, ServicePtrs[iService]->szService);
4159 standard_sub_basic(get_current_username(),
4160 current_user_info.domain,
4161 serviceName,sizeof(serviceName));
4162 if (strequal(serviceName, pszServiceName)) {
4163 break;
4168 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
4169 struct timespec last_mod;
4171 if (!usershare_exists(iService, &last_mod)) {
4172 /* Remove the share security tdb entry for it. */
4173 delete_share_security(lp_servicename(talloc_tos(), iService));
4174 /* Remove it from the array. */
4175 free_service_byindex(iService);
4176 /* Doesn't exist anymore. */
4177 return GLOBAL_SECTION_SNUM;
4180 /* Has it been modified ? If so delete and reload. */
4181 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4182 &last_mod) < 0) {
4183 /* Remove it from the array. */
4184 free_service_byindex(iService);
4185 /* and now reload it. */
4186 iService = load_usershare_service(pszServiceName);
4190 if (iService < 0) {
4191 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
4192 return GLOBAL_SECTION_SNUM;
4195 return (iService);
4198 /*******************************************************************
4199 A useful volume label function.
4200 ********************************************************************/
4202 const char *volume_label(TALLOC_CTX *ctx, int snum)
4204 char *ret;
4205 const char *label = lp_volume(ctx, snum);
4206 if (!*label) {
4207 label = lp_servicename(ctx, snum);
4210 /* This returns a 33 byte guarenteed null terminated string. */
4211 ret = talloc_strndup(ctx, label, 32);
4212 if (!ret) {
4213 return "";
4215 return ret;
4218 /*******************************************************************
4219 Get the default server type we will announce as via nmbd.
4220 ********************************************************************/
4222 int lp_default_server_announce(void)
4224 int default_server_announce = 0;
4225 default_server_announce |= SV_TYPE_WORKSTATION;
4226 default_server_announce |= SV_TYPE_SERVER;
4227 default_server_announce |= SV_TYPE_SERVER_UNIX;
4229 /* note that the flag should be set only if we have a
4230 printer service but nmbd doesn't actually load the
4231 services so we can't tell --jerry */
4233 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
4235 default_server_announce |= SV_TYPE_SERVER_NT;
4236 default_server_announce |= SV_TYPE_NT;
4238 switch (lp_server_role()) {
4239 case ROLE_DOMAIN_MEMBER:
4240 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
4241 break;
4242 case ROLE_DOMAIN_PDC:
4243 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
4244 break;
4245 case ROLE_DOMAIN_BDC:
4246 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
4247 break;
4248 case ROLE_STANDALONE:
4249 default:
4250 break;
4252 if (lp_time_server())
4253 default_server_announce |= SV_TYPE_TIME_SOURCE;
4255 if (lp_host_msdfs())
4256 default_server_announce |= SV_TYPE_DFS_SERVER;
4258 return default_server_announce;
4261 /***********************************************************
4262 If we are PDC then prefer us as DMB
4263 ************************************************************/
4265 bool lp_domain_master(void)
4267 if (Globals._domain_master == Auto)
4268 return (lp_server_role() == ROLE_DOMAIN_PDC);
4270 return (bool)Globals._domain_master;
4273 /***********************************************************
4274 If we are PDC then prefer us as DMB
4275 ************************************************************/
4277 static bool lp_domain_master_true_or_auto(void)
4279 if (Globals._domain_master) /* auto or yes */
4280 return true;
4282 return false;
4285 /***********************************************************
4286 If we are DMB then prefer us as LMB
4287 ************************************************************/
4289 bool lp_preferred_master(void)
4291 int preferred_master = lp__preferred_master();
4293 if (preferred_master == Auto)
4294 return (lp_local_master() && lp_domain_master());
4296 return (bool)preferred_master;
4299 /*******************************************************************
4300 Remove a service.
4301 ********************************************************************/
4303 void lp_remove_service(int snum)
4305 ServicePtrs[snum]->valid = false;
4308 const char *lp_printername(TALLOC_CTX *ctx, int snum)
4310 const char *ret = lp__printername(ctx, snum);
4311 if (ret == NULL || *ret == '\0') {
4312 ret = lp_const_servicename(snum);
4315 return ret;
4319 /***********************************************************
4320 Allow daemons such as winbindd to fix their logfile name.
4321 ************************************************************/
4323 void lp_set_logfile(const char *name)
4325 lpcfg_string_set(Globals.ctx, &Globals.logfile, name);
4326 debug_set_logfile(name);
4329 /*******************************************************************
4330 Return the max print jobs per queue.
4331 ********************************************************************/
4333 int lp_maxprintjobs(int snum)
4335 int maxjobs = lp_max_print_jobs(snum);
4337 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
4338 maxjobs = PRINT_MAX_JOBID - 1;
4340 return maxjobs;
4343 const char *lp_printcapname(void)
4345 const char *printcap_name = lp_printcap_name();
4347 if ((printcap_name != NULL) &&
4348 (printcap_name[0] != '\0'))
4349 return printcap_name;
4351 if (sDefault.printing == PRINT_CUPS) {
4352 return "cups";
4355 if (sDefault.printing == PRINT_BSD)
4356 return "/etc/printcap";
4358 return PRINTCAP_NAME;
4361 static uint32_t spoolss_state;
4363 bool lp_disable_spoolss( void )
4365 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
4366 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
4368 return spoolss_state == SVCCTL_STOPPED ? true : false;
4371 void lp_set_spoolss_state( uint32_t state )
4373 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
4375 spoolss_state = state;
4378 uint32_t lp_get_spoolss_state( void )
4380 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
4383 /*******************************************************************
4384 Ensure we don't use sendfile if server smb signing is active.
4385 ********************************************************************/
4387 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
4389 bool sign_active = false;
4391 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
4392 if (get_Protocol() < PROTOCOL_NT1) {
4393 return false;
4395 if (signing_state) {
4396 sign_active = smb_signing_is_active(signing_state);
4398 return (lp__use_sendfile(snum) &&
4399 (get_remote_arch() != RA_WIN95) &&
4400 !sign_active);
4403 /*******************************************************************
4404 Turn off sendfile if we find the underlying OS doesn't support it.
4405 ********************************************************************/
4407 void set_use_sendfile(int snum, bool val)
4409 if (LP_SNUM_OK(snum))
4410 ServicePtrs[snum]->_use_sendfile = val;
4411 else
4412 sDefault._use_sendfile = val;
4415 void lp_set_mangling_method(const char *new_method)
4417 lpcfg_string_set(Globals.ctx, &Globals.mangling_method, new_method);
4420 /*******************************************************************
4421 Global state for POSIX pathname processing.
4422 ********************************************************************/
4424 static bool posix_pathnames;
4426 bool lp_posix_pathnames(void)
4428 return posix_pathnames;
4431 /*******************************************************************
4432 Change everything needed to ensure POSIX pathname processing (currently
4433 not much).
4434 ********************************************************************/
4436 void lp_set_posix_pathnames(void)
4438 posix_pathnames = true;
4441 /*******************************************************************
4442 Global state for POSIX lock processing - CIFS unix extensions.
4443 ********************************************************************/
4445 bool posix_default_lock_was_set;
4446 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
4448 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
4450 if (posix_default_lock_was_set) {
4451 return posix_cifsx_locktype;
4452 } else {
4453 return (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
4454 POSIX_LOCK : WINDOWS_LOCK;
4458 /*******************************************************************
4459 ********************************************************************/
4461 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
4463 posix_default_lock_was_set = true;
4464 posix_cifsx_locktype = val;
4467 int lp_min_receive_file_size(void)
4469 int min_receivefile_size = lp_min_receivefile_size();
4471 if (min_receivefile_size < 0) {
4472 return 0;
4474 return min_receivefile_size;
4477 /*******************************************************************
4478 Safe wide links checks.
4479 This helper function always verify the validity of wide links,
4480 even after a configuration file reload.
4481 ********************************************************************/
4483 void widelinks_warning(int snum)
4485 if (lp_allow_insecure_wide_links()) {
4486 return;
4489 if (lp_unix_extensions() && lp_wide_links(snum)) {
4490 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
4491 "These parameters are incompatible. "
4492 "Wide links will be disabled for this share.\n",
4493 lp_servicename(talloc_tos(), snum) ));
4497 bool lp_widelinks(int snum)
4499 /* wide links is always incompatible with unix extensions */
4500 if (lp_unix_extensions()) {
4502 * Unless we have "allow insecure widelinks"
4503 * turned on.
4505 if (!lp_allow_insecure_wide_links()) {
4506 return false;
4510 return lp_wide_links(snum);
4513 int lp_server_role(void)
4515 return lp_find_server_role(lp__server_role(),
4516 lp__security(),
4517 lp__domain_logons(),
4518 lp_domain_master_true_or_auto());
4521 int lp_security(void)
4523 return lp_find_security(lp__server_role(),
4524 lp__security());
4527 int lp_client_max_protocol(void)
4529 int client_max_protocol = lp__client_max_protocol();
4530 if (client_max_protocol == PROTOCOL_DEFAULT) {
4531 return PROTOCOL_NT1;
4533 return client_max_protocol;
4536 int lp_client_ipc_min_protocol(void)
4538 int client_ipc_min_protocol = lp__client_ipc_min_protocol();
4539 if (client_ipc_min_protocol == PROTOCOL_DEFAULT) {
4540 client_ipc_min_protocol = lp_client_min_protocol();
4542 if (client_ipc_min_protocol < PROTOCOL_NT1) {
4543 return PROTOCOL_NT1;
4545 return client_ipc_min_protocol;
4548 int lp_client_ipc_max_protocol(void)
4550 int client_ipc_max_protocol = lp__client_ipc_max_protocol();
4551 if (client_ipc_max_protocol == PROTOCOL_DEFAULT) {
4552 return PROTOCOL_LATEST;
4554 if (client_ipc_max_protocol < PROTOCOL_NT1) {
4555 return PROTOCOL_NT1;
4557 return client_ipc_max_protocol;
4560 int lp_client_ipc_signing(void)
4562 int client_ipc_signing = lp__client_ipc_signing();
4563 if (client_ipc_signing == SMB_SIGNING_DEFAULT) {
4564 return SMB_SIGNING_REQUIRED;
4566 return client_ipc_signing;
4569 int lp_rpc_low_port(void)
4571 return Globals.rpc_low_port;
4574 int lp_rpc_high_port(void)
4576 return Globals.rpc_high_port;
4579 struct loadparm_global * get_globals(void)
4581 return &Globals;
4584 unsigned int * get_flags(void)
4586 if (flags_list == NULL) {
4587 flags_list = talloc_zero_array(NULL, unsigned int, num_parameters());
4590 return flags_list;