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/>.
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.
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
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
57 #include "system/filesys.h"
59 #include "lib/param/loadparm.h"
60 #include "lib/param/param.h"
62 #include "lib/smbconf/smbconf.h"
63 #include "lib/smbconf/smbconf_init.h"
66 #include "../librpc/gen_ndr/svcctl.h"
68 #include "../libcli/smb/smb_signing.h"
69 #include "dbwrap/dbwrap.h"
70 #include "dbwrap/dbwrap_rbt.h"
71 #include "../lib/util/bitmap.h"
73 #ifdef HAVE_SYS_SYSCTL_H
74 #include <sys/sysctl.h>
77 #ifdef HAVE_HTTPCONNECTENCRYPT
78 #include <cups/http.h>
81 #ifdef CLUSTER_SUPPORT
82 #include "ctdb_private.h"
87 extern userdom_struct current_user_info;
89 /* the special value for the include parameter
90 * to be interpreted not as a file name but to
91 * trigger loading of the global smb.conf options
93 #ifndef INCLUDE_REGISTRY_NAME
94 #define INCLUDE_REGISTRY_NAME "registry"
97 static bool in_client = false; /* Not in the client by default */
98 static struct smbconf_csn conf_last_csn;
100 static int config_backend = CONFIG_BACKEND_FILE;
102 /* some helpful bits */
103 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
104 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
106 #define USERSHARE_VALID 1
107 #define USERSHARE_PENDING_DELETE 2
109 static bool defaults_saved = false;
111 #define LOADPARM_EXTRA_GLOBALS \
112 struct parmlist_entry *param_opt; \
113 char *realm_original; \
115 int iminreceivefile; \
116 char *szPrintcapname; \
118 int iPreferredMaster; \
119 char *szLdapMachineSuffix; \
120 char *szLdapUserSuffix; \
121 char *szLdapIdmapSuffix; \
122 char *szLdapGroupSuffix; \
125 char *szUsershareTemplateShare; \
128 char *szIdmapBackend; \
129 int winbindMaxDomainConnections; \
130 int ismb2_max_credits; \
132 char *tls_certfile; \
136 int bPreferredMaster;
138 #include "param/param_global.h"
140 static struct loadparm_global Globals;
142 /* This is a default service used to prime a services structure */
143 static struct loadparm_service sDefault =
148 .usershare_last_mod = {0, 0},
152 .invalid_users = NULL,
160 .rootpostexec = NULL,
161 .cups_options = NULL,
162 .printcommand = NULL,
165 .lppausecommand = NULL,
166 .lpresumecommand = NULL,
167 .queuepausecommand = NULL,
168 .queueresumecommand = NULL,
169 .szPrintername = NULL,
170 .printjob_username = NULL,
178 .veto_oplocks = NULL,
188 .aio_write_behind = NULL,
189 .dfree_command = NULL,
191 .iMaxPrintJobs = 1000,
192 .max_reported_jobs = 0,
193 .write_cache_size = 0,
195 .force_create_mode = 0,
198 .max_connections = 0,
199 .defaultcase = CASE_LOWER,
200 .printing = DEFAULT_PRINTING,
201 .oplock_contention_limit = 2,
204 .dfree_cache_time = 0,
205 .preexec_close = false,
206 .rootpreexec_close = false,
207 .casesensitive = Auto,
208 .preservecase = true,
209 .shortpreservecase = true,
210 .hide_dot_files = true,
211 .hide_special_files = false,
212 .hideunreadable = false,
213 .hideunwriteable_files = false,
215 .access_based_share_enum = false,
219 .administrative_share = false,
222 .print_notify_backchannel = false,
226 .store_dos_attributes = false,
227 .dmapi_support = false,
229 .strict_locking = Auto,
230 .posix_locking = true,
232 .kernel_oplocks = false,
233 .level2_oplocks = true,
235 .manglednames = true,
239 .strict_allocate = false,
240 .strict_sync = false,
243 .delete_readonly = false,
244 .fake_oplocks = false,
245 .recursive_veto_delete = false,
246 .dos_filemode = false,
247 .dos_filetimes = true,
248 .dos_filetime_resolution = false,
249 .fake_dir_create_times = false,
250 .blocking_locks = true,
251 .inherit_perms = false,
252 .inherit_acls = false,
253 .inherit_owner = false,
255 .use_client_driver = false,
256 .default_devmode = true,
257 .force_printername = false,
258 .nt_acl_support = true,
259 .force_unknown_acl_user = false,
260 ._use_sendfile = false,
261 .profile_acls = false,
262 .map_acl_inherit = false,
265 .acl_check_permissions = true,
266 .acl_map_full_control = true,
267 .acl_group_control = false,
268 .acl_allow_execute_always = false,
269 .change_notify = true,
270 .kernel_change_notify = true,
271 .allocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
274 .map_readonly = MAP_READONLY_YES,
275 #ifdef BROKEN_DIRECTORY_HANDLING
276 .directory_name_cache_size = 0,
278 .directory_name_cache_size = 100,
280 .smb_encrypt = SMB_SIGNING_DEFAULT,
281 .kernel_share_modes = true,
282 .durable_handles = true,
287 /* local variables */
288 static struct loadparm_service **ServicePtrs = NULL;
289 static int iNumServices = 0;
290 static int iServiceIndex = 0;
291 static struct db_context *ServiceHash;
292 static bool bInGlobalSection = true;
293 static bool bGlobalOnly = false;
295 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
297 /* prototypes for the special type handlers */
298 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
299 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
300 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
301 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
302 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
303 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
304 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
305 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
306 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
307 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
308 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
309 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
311 /* these are parameter handlers which are not needed in the
315 #define handle_logfile NULL
317 static void set_allowed_client_auth(void);
319 static void add_to_file_list(const char *fname, const char *subfname);
320 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
321 static void free_param_opts(struct parmlist_entry **popts);
323 #include "lib/param/param_table.c"
325 /* this is used to prevent lots of mallocs of size 1 */
326 static const char null_string[] = "";
329 Set a string value, allocing the space for the string
332 static bool string_init(char **dest,const char *src)
342 *dest = discard_const_p(char, null_string);
344 (*dest) = SMB_STRDUP(src);
345 if ((*dest) == NULL) {
346 DEBUG(0,("Out of memory in string_init\n"));
357 static void string_free(char **s)
361 if (*s == null_string)
367 Set a string value, deallocating any existing space, and allocing the space
371 static bool string_set(char **dest,const char *src)
374 return(string_init(dest,src));
377 /***************************************************************************
378 Initialise the sDefault parameter structure for the printer values.
379 ***************************************************************************/
381 static void init_printer_values(struct loadparm_service *pService)
383 /* choose defaults depending on the type of printing */
384 switch (pService->printing) {
389 string_set(&pService->lpqcommand, "lpq -P'%p'");
390 string_set(&pService->lprmcommand, "lprm -P'%p' %j");
391 string_set(&pService->printcommand, "lpr -r -P'%p' %s");
396 string_set(&pService->lpqcommand, "lpq -P'%p'");
397 string_set(&pService->lprmcommand, "lprm -P'%p' %j");
398 string_set(&pService->printcommand, "lpr -r -P'%p' %s");
399 string_set(&pService->queuepausecommand, "lpc stop '%p'");
400 string_set(&pService->queueresumecommand, "lpc start '%p'");
401 string_set(&pService->lppausecommand, "lpc hold '%p' %j");
402 string_set(&pService->lpresumecommand, "lpc release '%p' %j");
407 /* set the lpq command to contain the destination printer
408 name only. This is used by cups_queue_get() */
409 string_set(&pService->lpqcommand, "%p");
410 string_set(&pService->lprmcommand, "");
411 string_set(&pService->printcommand, "");
412 string_set(&pService->lppausecommand, "");
413 string_set(&pService->lpresumecommand, "");
414 string_set(&pService->queuepausecommand, "");
415 string_set(&pService->queueresumecommand, "");
420 string_set(&pService->lpqcommand, "lpstat -o%p");
421 string_set(&pService->lprmcommand, "cancel %p-%j");
422 string_set(&pService->printcommand, "lp -c -d%p %s; rm %s");
423 string_set(&pService->queuepausecommand, "disable %p");
424 string_set(&pService->queueresumecommand, "enable %p");
426 string_set(&pService->lppausecommand, "lp -i %p-%j -H hold");
427 string_set(&pService->lpresumecommand, "lp -i %p-%j -H resume");
432 string_set(&pService->lpqcommand, "lpq -P%p");
433 string_set(&pService->lprmcommand, "lprm -P%p %j");
434 string_set(&pService->printcommand, "lp -r -P%p %s");
437 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
442 TALLOC_CTX *tmp_ctx = talloc_stackframe();
445 tdbfile = talloc_asprintf(
446 tmp_ctx, "tdbfile=%s",
447 lp_parm_const_string(-1, "vlp", "tdbfile",
449 if (tdbfile == NULL) {
450 tdbfile="tdbfile=/tmp/vlp.tdb";
453 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
455 string_set(&pService->printcommand,
456 tmp ? tmp : "vlp print %p %s");
458 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
460 string_set(&pService->lpqcommand,
461 tmp ? tmp : "vlp lpq %p");
463 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
465 string_set(&pService->lprmcommand,
466 tmp ? tmp : "vlp lprm %p %j");
468 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
470 string_set(&pService->lppausecommand,
471 tmp ? tmp : "vlp lppause %p %j");
473 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
475 string_set(&pService->lpresumecommand,
476 tmp ? tmp : "vlp lpresume %p %j");
478 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
480 string_set(&pService->queuepausecommand,
481 tmp ? tmp : "vlp queuepause %p");
483 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
485 string_set(&pService->queueresumecommand,
486 tmp ? tmp : "vlp queueresume %p");
487 TALLOC_FREE(tmp_ctx);
491 #endif /* DEVELOPER */
496 * Function to return the default value for the maximum number of open
497 * file descriptors permitted. This function tries to consult the
498 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
499 * the smaller of those.
501 static int max_open_files(void)
503 int sysctl_max = MAX_OPEN_FILES;
504 int rlimit_max = MAX_OPEN_FILES;
506 #ifdef HAVE_SYSCTLBYNAME
508 size_t size = sizeof(sysctl_max);
509 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
514 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
520 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
521 rlimit_max = rl.rlim_cur;
523 #if defined(RLIM_INFINITY)
524 if(rl.rlim_cur == RLIM_INFINITY)
525 rlimit_max = MAX_OPEN_FILES;
530 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
531 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
532 "minimum Windows limit (%d)\n",
534 MIN_OPEN_FILES_WINDOWS));
535 sysctl_max = MIN_OPEN_FILES_WINDOWS;
538 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
539 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
540 "minimum Windows limit (%d)\n",
542 MIN_OPEN_FILES_WINDOWS));
543 rlimit_max = MIN_OPEN_FILES_WINDOWS;
546 return MIN(sysctl_max, rlimit_max);
550 * Common part of freeing allocated data for one parameter.
552 static void free_one_parameter_common(void *parm_ptr,
553 struct parm_struct parm)
555 if ((parm.type == P_STRING) ||
556 (parm.type == P_USTRING))
558 string_free((char**)parm_ptr);
559 } else if (parm.type == P_LIST) {
560 TALLOC_FREE(*((char***)parm_ptr));
565 * Free the allocated data for one parameter for a share
566 * given as a service struct.
568 static void free_one_parameter(struct loadparm_service *service,
569 struct parm_struct parm)
573 if (parm.p_class != P_LOCAL) {
577 parm_ptr = lp_parm_ptr(service, &parm);
579 free_one_parameter_common(parm_ptr, parm);
583 * Free the allocated parameter data of a share given
584 * as a service struct.
586 static void free_parameters(struct loadparm_service *service)
590 for (i=0; parm_table[i].label; i++) {
591 free_one_parameter(service, parm_table[i]);
596 * Free the allocated data for one parameter for a given share
597 * specified by an snum.
599 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
604 parm_ptr = lp_parm_ptr(NULL, &parm);
605 } else if (parm.p_class != P_LOCAL) {
608 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
611 free_one_parameter_common(parm_ptr, parm);
615 * Free the allocated parameter data for a share specified
618 static void free_parameters_by_snum(int snum)
622 for (i=0; parm_table[i].label; i++) {
623 free_one_parameter_by_snum(snum, parm_table[i]);
628 * Free the allocated global parameters.
630 static void free_global_parameters(void)
632 free_param_opts(&Globals.param_opt);
633 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
634 TALLOC_FREE(Globals.ctx);
637 struct lp_stored_option {
638 struct lp_stored_option *prev, *next;
643 static struct lp_stored_option *stored_options;
646 save options set by lp_set_cmdline() into a list. This list is
647 re-applied when we do a globals reset, so that cmdline set options
648 are sticky across reloads of smb.conf
650 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
652 struct lp_stored_option *entry, *entry_next;
653 for (entry = stored_options; entry != NULL; entry = entry_next) {
654 entry_next = entry->next;
655 if (strcmp(pszParmName, entry->label) == 0) {
656 DLIST_REMOVE(stored_options, entry);
662 entry = talloc(NULL, struct lp_stored_option);
667 entry->label = talloc_strdup(entry, pszParmName);
673 entry->value = talloc_strdup(entry, pszParmValue);
679 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
684 static bool apply_lp_set_cmdline(void)
686 struct lp_stored_option *entry = NULL;
687 for (entry = stored_options; entry != NULL; entry = entry->next) {
688 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
689 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
690 entry->label, entry->value));
697 /***************************************************************************
698 Initialise the global parameter structure.
699 ***************************************************************************/
701 static void init_globals(bool reinit_globals)
703 static bool done_init = false;
707 /* If requested to initialize only once and we've already done it... */
708 if (!reinit_globals && done_init) {
709 /* ... then we have nothing more to do */
714 /* The logfile can be set before this is invoked. Free it if so. */
715 if (Globals.logfile != NULL) {
716 string_free(&Globals.logfile);
717 Globals.logfile = NULL;
721 free_global_parameters();
724 /* This memset and the free_global_parameters() above will
725 * wipe out smb.conf options set with lp_set_cmdline(). The
726 * apply_lp_set_cmdline() call puts these values back in the
727 * table once the defaults are set */
728 ZERO_STRUCT(Globals);
730 Globals.ctx = talloc_new(NULL);
732 for (i = 0; parm_table[i].label; i++) {
733 if ((parm_table[i].type == P_STRING ||
734 parm_table[i].type == P_USTRING))
736 string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
741 string_set(&sDefault.fstype, FSTYPE_STRING);
742 string_set(&sDefault.printjob_username, "%U");
744 init_printer_values(&sDefault);
746 sDefault.ntvfs_handler = (const char **)str_list_make_v3(NULL, "unixuid default", NULL);
748 DEBUG(3, ("Initialising global parameters\n"));
750 /* Must manually force to upper case here, as this does not go via the handler */
751 string_set(&Globals.netbios_name, myhostname_upper());
753 string_set(&Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
754 string_set(&Globals.private_dir, get_dyn_PRIVATE_DIR());
756 /* use the new 'hash2' method by default, with a prefix of 1 */
757 string_set(&Globals.mangling_method, "hash2");
758 Globals.mangle_prefix = 1;
760 string_set(&Globals.guestaccount, GUEST_ACCOUNT);
762 /* using UTF8 by default allows us to support all chars */
763 string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
765 /* Use codepage 850 as a default for the dos character set */
766 string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
769 * Allow the default PASSWD_CHAT to be overridden in local.h.
771 string_set(&Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
773 string_set(&Globals.workgroup, DEFAULT_WORKGROUP);
775 string_set(&Globals.passwd_program, "");
776 string_set(&Globals.lockdir, get_dyn_LOCKDIR());
777 string_set(&Globals.szStateDir, get_dyn_STATEDIR());
778 string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
779 string_set(&Globals.piddir, get_dyn_PIDDIR());
780 string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
782 * By default support explicit binding to broadcast
785 Globals.nmbd_bind_explicit_broadcast = true;
787 if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
788 smb_panic("init_globals: ENOMEM");
790 string_set(&Globals.serverstring, s);
793 string_set(&Globals.panic_action, "/bin/sleep 999999999");
796 string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
798 string_set(&Globals.logon_drive, "");
799 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
800 string_set(&Globals.logon_home, "\\\\%N\\%U");
801 string_set(&Globals.logon_path, "\\\\%N\\%U\\profile");
803 Globals.name_resolve_order = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
804 string_set(&Globals.passwordserver, "*");
806 Globals.algorithmic_rid_base = BASE_RID;
808 Globals.load_printers = true;
809 Globals.printcap_cache_time = 750; /* 12.5 minutes */
811 Globals.config_backend = config_backend;
812 Globals.server_role = ROLE_AUTO;
814 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
815 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
816 Globals.max_xmit = 0x4104;
817 Globals.maxmux = 50; /* This is *needed* for profile support. */
818 Globals.lpqcachetime = 30; /* changed to handle large print servers better -- jerry */
819 Globals._disable_spoolss = false;
820 Globals.max_smbd_processes = 0;/* no limit specified */
821 Globals.usernamelevel = 0;
822 Globals.deadtime = 0;
823 Globals.getwd_cache = true;
824 Globals.large_readwrite = true;
825 Globals.max_log_size = 5000;
826 Globals.max_open_files = max_open_files();
827 Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
828 Globals.srv_maxprotocol = PROTOCOL_SMB3_00;
829 Globals.srv_minprotocol = PROTOCOL_LANMAN1;
830 Globals.cli_maxprotocol = PROTOCOL_NT1;
831 Globals.cli_minprotocol = PROTOCOL_CORE;
832 Globals.security = SEC_USER;
833 Globals.encrypted_passwords = true;
834 Globals.client_schannel = Auto;
835 Globals.winbind_sealed_pipes = true;
836 Globals.require_strong_key = true;
837 Globals.server_schannel = Auto;
838 Globals.bReadRaw = true;
839 Globals.bWriteRaw = true;
840 Globals.null_passwords = false;
841 Globals.obey_pam_restrictions = false;
843 Globals.syslog_only = false;
844 Globals.timestamp_logs = true;
845 string_set(&Globals.loglevel, "0");
846 Globals.debug_prefix_timestamp = false;
847 Globals.debug_hires_timestamp = true;
848 Globals.debug_pid = false;
849 Globals.debug_uid = false;
850 Globals.debug_class = false;
851 Globals.enable_core_files = true;
852 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
853 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
854 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
855 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
856 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
857 Globals.lm_interval = 60;
858 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
859 Globals.nis_home_map = false;
860 #ifdef WITH_NISPLUS_HOME
861 string_set(&Globals.nis_home_map_name, "auto_home.org_dir");
863 string_set(&Globals.nis_home_map_name, "auto.home");
866 Globals.time_server = false;
867 Globals.bind_interfaces_only = false;
868 Globals.unix_password_sync = false;
869 Globals.pam_password_change = false;
870 Globals.passwd_chat_debug = false;
871 Globals.passwd_chat_timeout = 2; /* 2 second default. */
872 Globals.nt_pipe_support = true; /* Do NT pipes by default. */
873 Globals.nt_status_support = true; /* Use NT status by default. */
874 Globals.stat_cache = true; /* use stat cache by default */
875 Globals.max_stat_cache_size = 256; /* 256k by default */
876 Globals.restrict_anonymous = 0;
877 Globals.client_lanman_auth = false; /* Do NOT use the LanMan hash if it is available */
878 Globals.client_plaintext_auth = false; /* Do NOT use a plaintext password even if is requested by the server */
879 Globals.lanman_auth = false; /* Do NOT use the LanMan hash, even if it is supplied */
880 Globals.ntlm_auth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
881 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 */
882 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
884 Globals.map_to_guest = 0; /* By Default, "Never" */
885 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
886 Globals.enhanced_browsing = true;
887 Globals.lock_spin_time = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
888 #ifdef MMAP_BLACKLIST
889 Globals.use_mmap = false;
891 Globals.use_mmap = true;
893 Globals.unicode = true;
894 Globals.unix_extensions = true;
895 Globals.reset_on_zero_vc = false;
896 Globals.log_writeable_files_on_exit = false;
897 Globals.create_krb5_conf = true;
898 Globals.winbindMaxDomainConnections = 1;
900 /* hostname lookups can be very expensive and are broken on
901 a large number of sites (tridge) */
902 Globals.hostname_lookups = false;
904 string_set(&Globals.passdb_backend, "tdbsam");
905 string_set(&Globals.ldap_suffix, "");
906 string_set(&Globals.szLdapMachineSuffix, "");
907 string_set(&Globals.szLdapUserSuffix, "");
908 string_set(&Globals.szLdapGroupSuffix, "");
909 string_set(&Globals.szLdapIdmapSuffix, "");
911 string_set(&Globals.ldap_admin_dn, "");
912 Globals.ldap_ssl = LDAP_SSL_START_TLS;
913 Globals.ldap_ssl_ads = false;
914 Globals.ldap_deref = -1;
915 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
916 Globals.ldap_delete_dn = false;
917 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
918 Globals.ldap_follow_referral = Auto;
919 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
920 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
921 Globals.ldap_page_size = LDAP_PAGE_SIZE;
923 Globals.ldap_debug_level = 0;
924 Globals.ldap_debug_threshold = 10;
926 /* This is what we tell the afs client. in reality we set the token
927 * to never expire, though, when this runs out the afs client will
928 * forget the token. Set to 0 to get NEVERDATE.*/
929 Globals.afs_token_lifetime = 604800;
930 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
932 /* these parameters are set to defaults that are more appropriate
933 for the increasing samba install base:
935 as a member of the workgroup, that will possibly become a
936 _local_ master browser (lm = true). this is opposed to a forced
937 local master browser startup (pm = true).
939 doesn't provide WINS server service by default (wsupp = false),
940 and doesn't provide domain master browser services by default, either.
944 Globals.ms_add_printer_wizard = true;
945 Globals.os_level = 20;
946 Globals.local_master = true;
947 Globals._domain_master = Auto; /* depending on _domain_logons */
948 Globals._domain_logons = false;
949 Globals.browse_list = true;
950 Globals.we_are_a_wins_server = false;
951 Globals.wins_proxy = false;
953 TALLOC_FREE(Globals.init_logon_delayed_hosts);
954 Globals.init_logon_delay = 100; /* 100 ms default delay */
956 Globals.wins_dns_proxy = true;
958 Globals.allow_trusted_domains = true;
959 string_set(&Globals.szIdmapBackend, "tdb");
961 string_set(&Globals.template_shell, "/bin/false");
962 string_set(&Globals.template_homedir, "/home/%D/%U");
963 string_set(&Globals.winbind_separator, "\\");
964 string_set(&Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
966 string_set(&Globals.cups_server, "");
967 string_set(&Globals.iprint_server, "");
969 #ifdef CLUSTER_SUPPORT
970 string_set(&Globals.ctdbd_socket, CTDB_PATH);
972 string_set(&Globals.ctdbd_socket, "");
975 Globals.cluster_addresses = NULL;
976 Globals.clustering = false;
977 Globals.ctdb_timeout = 0;
978 Globals.ctdb_locktime_warn_threshold = 0;
980 Globals.winbind_cache_time = 300; /* 5 minutes */
981 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
982 Globals.winbind_max_clients = 200;
983 Globals.winbind_enum_users = false;
984 Globals.winbind_enum_groups = false;
985 Globals.winbind_use_default_domain = false;
986 Globals.winbind_trusted_domains_only = false;
987 Globals.winbind_nested_groups = true;
988 Globals.winbind_expand_groups = 1;
989 Globals.winbind_nss_info = (const char **)str_list_make_v3(NULL, "template", NULL);
990 Globals.winbind_refresh_tickets = false;
991 Globals.winbind_offline_logon = false;
993 Globals.idmap_cache_time = 86400 * 7; /* a week by default */
994 Globals.idmap_negative_cache_time = 120; /* 2 minutes by default */
996 Globals.passdb_expand_explicit = false;
998 Globals.name_cache_timeout = 660; /* In seconds */
1000 Globals.use_spnego = true;
1001 Globals.client_use_spnego = true;
1003 Globals.client_signing = SMB_SIGNING_DEFAULT;
1004 Globals.server_signing = SMB_SIGNING_DEFAULT;
1006 Globals.defer_sharing_violations = true;
1007 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
1009 Globals.enable_privileges = true;
1010 Globals.host_msdfs = true;
1011 Globals.enable_asu_support = false;
1013 /* User defined shares. */
1014 if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
1015 smb_panic("init_globals: ENOMEM");
1017 string_set(&Globals.usershare_path, s);
1019 string_set(&Globals.szUsershareTemplateShare, "");
1020 Globals.usershare_max_shares = 0;
1021 /* By default disallow sharing of directories not owned by the sharer. */
1022 Globals.usershare_owner_only = true;
1023 /* By default disallow guest access to usershares. */
1024 Globals.usershare_allow_guests = false;
1026 Globals.keepalive = DEFAULT_KEEPALIVE;
1028 /* By default no shares out of the registry */
1029 Globals.registry_shares = false;
1031 Globals.iminreceivefile = 0;
1033 Globals.map_untrusted_to_domain = false;
1034 Globals.multicast_dns_register = true;
1036 Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
1037 Globals.smb2_max_write = DEFAULT_SMB2_MAX_WRITE;
1038 Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
1039 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1041 string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1043 Globals.server_services = (const char **)str_list_make_v3(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate dns", NULL);
1045 Globals.dcerpc_endpoint_servers = (const char **)str_list_make_v3(NULL, "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver", NULL);
1047 Globals.tls_enabled = true;
1049 string_set(&Globals.tls_keyfile, "tls/key.pem");
1050 string_set(&Globals.tls_certfile, "tls/cert.pem");
1051 string_set(&Globals.tls_cafile, "tls/ca.pem");
1053 string_set(&Globals.share_backend, "classic");
1055 Globals.iPreferredMaster = Auto;
1057 Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
1059 string_set(&Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
1061 string_set(&Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
1063 if (asprintf(&s, "%s/samba_kcc", get_dyn_SCRIPTSBINDIR()) < 0) {
1064 smb_panic("init_globals: ENOMEM");
1066 Globals.samba_kcc_command = (const char **)str_list_make_v3(NULL, s, NULL);
1069 if (asprintf(&s, "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR()) < 0) {
1070 smb_panic("init_globals: ENOMEM");
1072 Globals.dns_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1075 if (asprintf(&s, "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR()) < 0) {
1076 smb_panic("init_globals: ENOMEM");
1078 Globals.spn_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1081 Globals.nsupdate_command = (const char **)str_list_make_v3(NULL, "/usr/bin/nsupdate -g", NULL);
1083 Globals.rndc_command = (const char **)str_list_make_v3(NULL, "/usr/sbin/rndc", NULL);
1085 Globals.cldap_port = 389;
1087 Globals.dgram_port = 138;
1089 Globals.nbt_port = 137;
1091 Globals.krb5_port = 88;
1093 Globals.kpasswd_port = 464;
1095 Globals.web_port = 901;
1097 /* Now put back the settings that were set with lp_set_cmdline() */
1098 apply_lp_set_cmdline();
1101 /*******************************************************************
1102 Convenience routine to grab string parameters into talloced memory
1103 and run standard_sub_basic on them. The buffers can be written to by
1104 callers without affecting the source string.
1105 ********************************************************************/
1107 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1111 /* The follow debug is useful for tracking down memory problems
1112 especially if you have an inner loop that is calling a lp_*()
1113 function that returns a string. Perhaps this debug should be
1114 present all the time? */
1117 DEBUG(10, ("lp_string(%s)\n", s));
1123 ret = talloc_sub_basic(ctx,
1124 get_current_username(),
1125 current_user_info.domain,
1127 if (trim_char(ret, '\"', '\"')) {
1128 if (strchr(ret,'\"') != NULL) {
1130 ret = talloc_sub_basic(ctx,
1131 get_current_username(),
1132 current_user_info.domain,
1140 In this section all the functions that are used to access the
1141 parameters from the rest of the program are defined
1144 #define FN_GLOBAL_STRING(fn_name,ptr) \
1145 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1146 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1147 const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1148 #define FN_GLOBAL_LIST(fn_name,ptr) \
1149 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1150 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1151 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1152 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1153 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1154 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1155 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1157 #define FN_LOCAL_STRING(fn_name,val) \
1158 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));}
1159 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1160 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1161 #define FN_LOCAL_LIST(fn_name,val) \
1162 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1163 #define FN_LOCAL_BOOL(fn_name,val) \
1164 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1165 #define FN_LOCAL_INTEGER(fn_name,val) \
1166 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1168 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1169 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1170 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1171 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1172 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
1173 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1176 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1177 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1179 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1180 * build process or in smb.conf, we use that value. Otherwise they
1181 * default to the value of lp_lockdir(). */
1182 const char *lp_statedir(void) {
1183 if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1184 (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1185 return(*(char **)(&Globals.szStateDir) ?
1186 *(char **)(&Globals.szStateDir) : "");
1188 return(*(char **)(&Globals.lockdir) ?
1189 *(char **)(&Globals.lockdir) : "");
1191 const char *lp_cachedir(void) {
1192 if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1193 (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1194 return(*(char **)(&Globals.szCacheDir) ?
1195 *(char **)(&Globals.szCacheDir) : "");
1197 return(*(char **)(&Globals.lockdir) ?
1198 *(char **)(&Globals.lockdir) : "");
1200 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1201 winbindMaxDomainConnections)
1203 int lp_winbind_max_domain_connections(void)
1205 if (lp_winbind_offline_logon() &&
1206 lp_winbind_max_domain_connections_int() > 1) {
1207 DEBUG(1, ("offline logons active, restricting max domain "
1208 "connections to 1\n"));
1211 return MAX(1, lp_winbind_max_domain_connections_int());
1214 int lp_smb2_max_credits(void)
1216 if (Globals.ismb2_max_credits == 0) {
1217 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1219 return Globals.ismb2_max_credits;
1221 int lp_cups_encrypt(void)
1224 #ifdef HAVE_HTTPCONNECTENCRYPT
1225 switch (Globals.CupsEncrypt) {
1227 result = HTTP_ENCRYPT_REQUIRED;
1230 result = HTTP_ENCRYPT_ALWAYS;
1233 result = HTTP_ENCRYPT_NEVER;
1240 /* These functions remain in source3/param for now */
1242 FN_GLOBAL_STRING(configfile, szConfigFile)
1244 #include "lib/param/param_functions.c"
1246 FN_LOCAL_STRING(servicename, szService)
1247 FN_LOCAL_CONST_STRING(const_servicename, szService)
1249 /* local prototypes */
1251 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1252 static const char *get_boolean(bool bool_value);
1253 static int getservicebyname(const char *pszServiceName,
1254 struct loadparm_service *pserviceDest);
1255 static void copy_service(struct loadparm_service *pserviceDest,
1256 struct loadparm_service *pserviceSource,
1257 struct bitmap *pcopymapDest);
1258 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1260 static bool do_section(const char *pszSectionName, void *userdata);
1261 static void init_copymap(struct loadparm_service *pservice);
1262 static bool hash_a_service(const char *name, int number);
1263 static void free_service_byindex(int iService);
1264 static void show_parameter(int parmIndex);
1265 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1268 * This is a helper function for parametrical options support. It returns a
1269 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1270 * parametrical functions are quite simple
1272 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1275 bool global_section = false;
1277 struct parmlist_entry *data;
1279 if (service == NULL) {
1280 data = Globals.param_opt;
1281 global_section = true;
1283 data = service->param_opt;
1286 if (asprintf(¶m_key, "%s:%s", type, option) == -1) {
1287 DEBUG(0,("asprintf failed!\n"));
1292 if (strwicmp(data->key, param_key) == 0) {
1293 string_free(¶m_key);
1299 if (!global_section) {
1300 /* Try to fetch the same option but from globals */
1301 /* but only if we are not already working with Globals */
1302 data = Globals.param_opt;
1304 if (strwicmp(data->key, param_key) == 0) {
1305 string_free(¶m_key);
1312 string_free(¶m_key);
1318 * This is a helper function for parametrical options support. It returns a
1319 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1320 * parametrical functions are quite simple
1322 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1325 if (snum >= iNumServices) return NULL;
1328 return get_parametrics_by_service(NULL, type, option);
1330 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1335 #define MISSING_PARAMETER(name) \
1336 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1338 /*******************************************************************
1339 convenience routine to return int parameters.
1340 ********************************************************************/
1341 static int lp_int(const char *s)
1345 MISSING_PARAMETER(lp_int);
1349 return (int)strtol(s, NULL, 0);
1352 /*******************************************************************
1353 convenience routine to return unsigned long parameters.
1354 ********************************************************************/
1355 static unsigned long lp_ulong(const char *s)
1359 MISSING_PARAMETER(lp_ulong);
1363 return strtoul(s, NULL, 0);
1366 /*******************************************************************
1367 convenience routine to return boolean parameters.
1368 ********************************************************************/
1369 static bool lp_bool(const char *s)
1374 MISSING_PARAMETER(lp_bool);
1378 if (!set_boolean(s, &ret)) {
1379 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1386 /*******************************************************************
1387 convenience routine to return enum parameters.
1388 ********************************************************************/
1389 static int lp_enum(const char *s,const struct enum_list *_enum)
1393 if (!s || !*s || !_enum) {
1394 MISSING_PARAMETER(lp_enum);
1398 for (i=0; _enum[i].name; i++) {
1399 if (strequal(_enum[i].name,s))
1400 return _enum[i].value;
1403 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1407 #undef MISSING_PARAMETER
1409 /* Return parametric option from a given service. Type is a part of option before ':' */
1410 /* Parametric option has following syntax: 'Type: option = value' */
1411 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1413 struct parmlist_entry *data = get_parametrics(snum, type, option);
1415 if (data == NULL||data->value==NULL) {
1417 return lp_string(ctx, def);
1423 return lp_string(ctx, data->value);
1426 /* Return parametric option from a given service. Type is a part of option before ':' */
1427 /* Parametric option has following syntax: 'Type: option = value' */
1428 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1430 struct parmlist_entry *data = get_parametrics(snum, type, option);
1432 if (data == NULL||data->value==NULL)
1438 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1440 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1442 if (data == NULL||data->value==NULL)
1449 /* Return parametric option from a given service. Type is a part of option before ':' */
1450 /* Parametric option has following syntax: 'Type: option = value' */
1452 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1454 struct parmlist_entry *data = get_parametrics(snum, type, option);
1456 if (data == NULL||data->value==NULL)
1457 return (const char **)def;
1459 if (data->list==NULL) {
1460 data->list = str_list_make_v3(NULL, data->value, NULL);
1463 return (const char **)data->list;
1466 /* Return parametric option from a given service. Type is a part of option before ':' */
1467 /* Parametric option has following syntax: 'Type: option = value' */
1469 int lp_parm_int(int snum, const char *type, const char *option, int def)
1471 struct parmlist_entry *data = get_parametrics(snum, type, option);
1473 if (data && data->value && *data->value)
1474 return lp_int(data->value);
1479 /* Return parametric option from a given service. Type is a part of option before ':' */
1480 /* Parametric option has following syntax: 'Type: option = value' */
1482 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1484 struct parmlist_entry *data = get_parametrics(snum, type, option);
1486 if (data && data->value && *data->value)
1487 return lp_ulong(data->value);
1492 /* Return parametric option from a given service. Type is a part of option before ':' */
1493 /* Parametric option has following syntax: 'Type: option = value' */
1495 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1497 struct parmlist_entry *data = get_parametrics(snum, type, option);
1499 if (data && data->value && *data->value)
1500 return lp_bool(data->value);
1505 /* Return parametric option from a given service. Type is a part of option before ':' */
1506 /* Parametric option has following syntax: 'Type: option = value' */
1508 int lp_parm_enum(int snum, const char *type, const char *option,
1509 const struct enum_list *_enum, int def)
1511 struct parmlist_entry *data = get_parametrics(snum, type, option);
1513 if (data && data->value && *data->value && _enum)
1514 return lp_enum(data->value, _enum);
1520 /***************************************************************************
1521 Initialise a service to the defaults.
1522 ***************************************************************************/
1524 static void init_service(struct loadparm_service *pservice)
1526 memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1527 copy_service(pservice, &sDefault, NULL);
1532 * free a param_opts structure.
1533 * param_opts handling should be moved to talloc;
1534 * then this whole functions reduces to a TALLOC_FREE().
1537 static void free_param_opts(struct parmlist_entry **popts)
1539 struct parmlist_entry *opt, *next_opt;
1541 if (*popts != NULL) {
1542 DEBUG(5, ("Freeing parametrics:\n"));
1545 while (opt != NULL) {
1546 string_free(&opt->key);
1547 string_free(&opt->value);
1548 TALLOC_FREE(opt->list);
1549 next_opt = opt->next;
1556 /***************************************************************************
1557 Free the dynamically allocated parts of a service struct.
1558 ***************************************************************************/
1560 static void free_service(struct loadparm_service *pservice)
1565 if (pservice->szService)
1566 DEBUG(5, ("free_service: Freeing service %s\n",
1567 pservice->szService));
1569 free_parameters(pservice);
1571 string_free(&pservice->szService);
1572 TALLOC_FREE(pservice->copymap);
1574 free_param_opts(&pservice->param_opt);
1576 ZERO_STRUCTP(pservice);
1580 /***************************************************************************
1581 remove a service indexed in the ServicePtrs array from the ServiceHash
1582 and free the dynamically allocated parts
1583 ***************************************************************************/
1585 static void free_service_byindex(int idx)
1587 if ( !LP_SNUM_OK(idx) )
1590 ServicePtrs[idx]->valid = false;
1592 /* we have to cleanup the hash record */
1594 if (ServicePtrs[idx]->szService) {
1595 char *canon_name = canonicalize_servicename(
1597 ServicePtrs[idx]->szService );
1599 dbwrap_delete_bystring(ServiceHash, canon_name );
1600 TALLOC_FREE(canon_name);
1603 free_service(ServicePtrs[idx]);
1604 talloc_free_children(ServicePtrs[idx]);
1607 /***************************************************************************
1608 Add a new service to the services array initialising it with the given
1610 ***************************************************************************/
1612 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1615 struct loadparm_service tservice;
1616 int num_to_alloc = iNumServices + 1;
1617 struct loadparm_service **tsp = NULL;
1619 tservice = *pservice;
1621 /* it might already exist */
1623 i = getservicebyname(name, NULL);
1629 /* if not, then create one */
1631 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1633 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1637 ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1638 if (!ServicePtrs[iNumServices]) {
1639 DEBUG(0,("add_a_service: out of memory!\n"));
1644 ServicePtrs[i]->valid = true;
1646 init_service(ServicePtrs[i]);
1647 copy_service(ServicePtrs[i], &tservice, NULL);
1649 string_set(&ServicePtrs[i]->szService, name);
1651 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1652 i, ServicePtrs[i]->szService));
1654 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1661 /***************************************************************************
1662 Convert a string to uppercase and remove whitespaces.
1663 ***************************************************************************/
1665 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1670 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1674 result = talloc_strdup(ctx, src);
1675 SMB_ASSERT(result != NULL);
1677 if (!strlower_m(result)) {
1678 TALLOC_FREE(result);
1684 /***************************************************************************
1685 Add a name/index pair for the services array to the hash table.
1686 ***************************************************************************/
1688 static bool hash_a_service(const char *name, int idx)
1692 if ( !ServiceHash ) {
1693 DEBUG(10,("hash_a_service: creating servicehash\n"));
1694 ServiceHash = db_open_rbt(NULL);
1695 if ( !ServiceHash ) {
1696 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1701 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1704 canon_name = canonicalize_servicename(talloc_tos(), name );
1706 dbwrap_store_bystring(ServiceHash, canon_name,
1707 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1710 TALLOC_FREE(canon_name);
1715 /***************************************************************************
1716 Add a new home service, with the specified home directory, defaults coming
1718 ***************************************************************************/
1720 bool lp_add_home(const char *pszHomename, int iDefaultService,
1721 const char *user, const char *pszHomedir)
1725 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1726 pszHomedir[0] == '\0') {
1730 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1735 if (!(*(ServicePtrs[iDefaultService]->pathname))
1736 || strequal(ServicePtrs[iDefaultService]->pathname,
1737 lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1738 string_set(&ServicePtrs[i]->pathname, pszHomedir);
1741 if (!(*(ServicePtrs[i]->comment))) {
1742 char *comment = NULL;
1743 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1746 string_set(&ServicePtrs[i]->comment, comment);
1750 /* set the browseable flag from the global default */
1752 ServicePtrs[i]->browseable = sDefault.browseable;
1753 ServicePtrs[i]->access_based_share_enum = sDefault.access_based_share_enum;
1755 ServicePtrs[i]->autoloaded = true;
1757 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1758 user, ServicePtrs[i]->pathname ));
1763 /***************************************************************************
1764 Add a new service, based on an old one.
1765 ***************************************************************************/
1767 int lp_add_service(const char *pszService, int iDefaultService)
1769 if (iDefaultService < 0) {
1770 return add_a_service(&sDefault, pszService);
1773 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1776 /***************************************************************************
1777 Add the IPC service.
1778 ***************************************************************************/
1780 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1782 char *comment = NULL;
1783 int i = add_a_service(&sDefault, ipc_name);
1788 if (asprintf(&comment, "IPC Service (%s)",
1789 Globals.serverstring) < 0) {
1793 string_set(&ServicePtrs[i]->pathname, tmpdir());
1794 string_set(&ServicePtrs[i]->username, "");
1795 string_set(&ServicePtrs[i]->comment, comment);
1796 string_set(&ServicePtrs[i]->fstype, "IPC");
1797 ServicePtrs[i]->max_connections = 0;
1798 ServicePtrs[i]->bAvailable = true;
1799 ServicePtrs[i]->readonly = true;
1800 ServicePtrs[i]->guest_only = false;
1801 ServicePtrs[i]->administrative_share = true;
1802 ServicePtrs[i]->guest_ok = guest_ok;
1803 ServicePtrs[i]->print_ok = false;
1804 ServicePtrs[i]->browseable = sDefault.browseable;
1806 DEBUG(3, ("adding IPC service\n"));
1812 /***************************************************************************
1813 Add a new printer service, with defaults coming from service iFrom.
1814 ***************************************************************************/
1816 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1818 const char *comment = "From Printcap";
1819 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1824 /* note that we do NOT default the availability flag to true - */
1825 /* we take it from the default service passed. This allows all */
1826 /* dynamic printers to be disabled by disabling the [printers] */
1827 /* entry (if/when the 'available' keyword is implemented!). */
1829 /* the printer name is set to the service name. */
1830 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1831 string_set(&ServicePtrs[i]->comment, comment);
1833 /* set the browseable flag from the gloabl default */
1834 ServicePtrs[i]->browseable = sDefault.browseable;
1836 /* Printers cannot be read_only. */
1837 ServicePtrs[i]->readonly = false;
1838 /* No oplocks on printer services. */
1839 ServicePtrs[i]->oplocks = false;
1840 /* Printer services must be printable. */
1841 ServicePtrs[i]->print_ok = true;
1843 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1849 /***************************************************************************
1850 Check whether the given parameter name is valid.
1851 Parametric options (names containing a colon) are considered valid.
1852 ***************************************************************************/
1854 bool lp_parameter_is_valid(const char *pszParmName)
1856 return ((lpcfg_map_parameter(pszParmName) != -1) ||
1857 (strchr(pszParmName, ':') != NULL));
1860 /***************************************************************************
1861 Check whether the given name is the name of a global parameter.
1862 Returns true for strings belonging to parameters of class
1863 P_GLOBAL, false for all other strings, also for parametric options
1864 and strings not belonging to any option.
1865 ***************************************************************************/
1867 bool lp_parameter_is_global(const char *pszParmName)
1869 int num = lpcfg_map_parameter(pszParmName);
1872 return (parm_table[num].p_class == P_GLOBAL);
1878 /**************************************************************************
1879 Check whether the given name is the canonical name of a parameter.
1880 Returns false if it is not a valid parameter Name.
1881 For parametric options, true is returned.
1882 **************************************************************************/
1884 bool lp_parameter_is_canonical(const char *parm_name)
1886 if (!lp_parameter_is_valid(parm_name)) {
1890 return (lpcfg_map_parameter(parm_name) ==
1891 map_parameter_canonical(parm_name, NULL));
1894 /**************************************************************************
1895 Determine the canonical name for a parameter.
1896 Indicate when it is an inverse (boolean) synonym instead of a
1898 **************************************************************************/
1900 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1905 if (!lp_parameter_is_valid(parm_name)) {
1910 num = map_parameter_canonical(parm_name, inverse);
1912 /* parametric option */
1913 *canon_parm = parm_name;
1915 *canon_parm = parm_table[num].label;
1922 /**************************************************************************
1923 Determine the canonical name for a parameter.
1924 Turn the value given into the inverse boolean expression when
1925 the synonym is an invers boolean synonym.
1927 Return true if parm_name is a valid parameter name and
1928 in case it is an invers boolean synonym, if the val string could
1929 successfully be converted to the reverse bool.
1930 Return false in all other cases.
1931 **************************************************************************/
1933 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1935 const char **canon_parm,
1936 const char **canon_val)
1941 if (!lp_parameter_is_valid(parm_name)) {
1947 num = map_parameter_canonical(parm_name, &inverse);
1949 /* parametric option */
1950 *canon_parm = parm_name;
1953 *canon_parm = parm_table[num].label;
1955 if (!lp_invert_boolean(val, canon_val)) {
1967 /***************************************************************************
1968 Map a parameter's string representation to the index of the canonical
1969 form of the parameter (it might be a synonym).
1970 Returns -1 if the parameter string is not recognised.
1971 ***************************************************************************/
1973 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1975 int parm_num, canon_num;
1976 bool loc_inverse = false;
1978 parm_num = lpcfg_map_parameter(pszParmName);
1979 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1980 /* invalid, parametric or no canidate for synonyms ... */
1984 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1985 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1986 parm_num = canon_num;
1992 if (inverse != NULL) {
1993 *inverse = loc_inverse;
1998 /***************************************************************************
1999 return true if parameter number parm1 is a synonym of parameter
2000 number parm2 (parm2 being the principal name).
2001 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
2003 ***************************************************************************/
2005 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
2007 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
2008 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
2009 (parm_table[parm1].flags & FLAG_HIDE) &&
2010 !(parm_table[parm2].flags & FLAG_HIDE))
2012 if (inverse != NULL) {
2013 if ((parm_table[parm1].type == P_BOOLREV) &&
2014 (parm_table[parm2].type == P_BOOL))
2026 /***************************************************************************
2027 Show one parameter's name, type, [values,] and flags.
2028 (helper functions for show_parameter_list)
2029 ***************************************************************************/
2031 static void show_parameter(int parmIndex)
2033 int enumIndex, flagIndex;
2038 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2039 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2041 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2042 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2044 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2045 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2046 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2048 printf("%s=%s", parm_table[parmIndex].label,
2049 type[parm_table[parmIndex].type]);
2050 if (parm_table[parmIndex].type == P_ENUM) {
2053 parm_table[parmIndex].enum_list[enumIndex].name;
2057 enumIndex ? "|" : "",
2058 parm_table[parmIndex].enum_list[enumIndex].name);
2063 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2064 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2067 flag_names[flagIndex]);
2072 /* output synonyms */
2074 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2075 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2076 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2077 parm_table[parmIndex2].label);
2078 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2080 printf(" (synonyms: ");
2085 printf("%s%s", parm_table[parmIndex2].label,
2086 inverse ? "[i]" : "");
2096 /***************************************************************************
2097 Show all parameter's name, type, [values,] and flags.
2098 ***************************************************************************/
2100 void show_parameter_list(void)
2102 int classIndex, parmIndex;
2103 const char *section_names[] = { "local", "global", NULL};
2105 for (classIndex=0; section_names[classIndex]; classIndex++) {
2106 printf("[%s]\n", section_names[classIndex]);
2107 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2108 if (parm_table[parmIndex].p_class == classIndex) {
2109 show_parameter(parmIndex);
2115 /***************************************************************************
2116 Check if a given string correctly represents a boolean value.
2117 ***************************************************************************/
2119 bool lp_string_is_valid_boolean(const char *parm_value)
2121 return set_boolean(parm_value, NULL);
2124 /***************************************************************************
2125 Get the standard string representation of a boolean value ("yes" or "no")
2126 ***************************************************************************/
2128 static const char *get_boolean(bool bool_value)
2130 static const char *yes_str = "yes";
2131 static const char *no_str = "no";
2133 return (bool_value ? yes_str : no_str);
2136 /***************************************************************************
2137 Provide the string of the negated boolean value associated to the boolean
2138 given as a string. Returns false if the passed string does not correctly
2139 represent a boolean.
2140 ***************************************************************************/
2142 bool lp_invert_boolean(const char *str, const char **inverse_str)
2146 if (!set_boolean(str, &val)) {
2150 *inverse_str = get_boolean(!val);
2154 /***************************************************************************
2155 Provide the canonical string representation of a boolean value given
2156 as a string. Return true on success, false if the string given does
2157 not correctly represent a boolean.
2158 ***************************************************************************/
2160 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2164 if (!set_boolean(str, &val)) {
2168 *canon_str = get_boolean(val);
2172 /***************************************************************************
2173 Find a service by name. Otherwise works like get_service.
2174 ***************************************************************************/
2176 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2183 if (ServiceHash == NULL) {
2187 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2189 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2192 if (NT_STATUS_IS_OK(status) &&
2193 (data.dptr != NULL) &&
2194 (data.dsize == sizeof(iService)))
2196 iService = *(int *)data.dptr;
2199 TALLOC_FREE(canon_name);
2201 if ((iService != -1) && (LP_SNUM_OK(iService))
2202 && (pserviceDest != NULL)) {
2203 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2209 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2210 struct loadparm_service *lp_service(const char *pszServiceName)
2212 int iService = getservicebyname(pszServiceName, NULL);
2213 if (iService == -1 || !LP_SNUM_OK(iService)) {
2216 return ServicePtrs[iService];
2219 struct loadparm_service *lp_servicebynum(int snum)
2221 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2224 return ServicePtrs[snum];
2227 struct loadparm_service *lp_default_loadparm_service()
2233 /***************************************************************************
2234 Copy a service structure to another.
2235 If pcopymapDest is NULL then copy all fields
2236 ***************************************************************************/
2239 * Add a parametric option to a parmlist_entry,
2240 * replacing old value, if already present.
2242 static void set_param_opt(struct parmlist_entry **opt_list,
2243 const char *opt_name,
2244 const char *opt_value,
2247 struct parmlist_entry *new_opt, *opt;
2253 /* Traverse destination */
2255 /* If we already have same option, override it */
2256 if (strwicmp(opt->key, opt_name) == 0) {
2257 if ((opt->priority & FLAG_CMDLINE) &&
2258 !(priority & FLAG_CMDLINE)) {
2259 /* it's been marked as not to be
2263 string_free(&opt->value);
2264 TALLOC_FREE(opt->list);
2265 opt->value = SMB_STRDUP(opt_value);
2266 opt->priority = priority;
2273 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2274 new_opt->key = SMB_STRDUP(opt_name);
2275 new_opt->value = SMB_STRDUP(opt_value);
2276 new_opt->list = NULL;
2277 new_opt->priority = priority;
2278 DLIST_ADD(*opt_list, new_opt);
2282 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2283 struct bitmap *pcopymapDest)
2286 bool bcopyall = (pcopymapDest == NULL);
2287 struct parmlist_entry *data;
2289 for (i = 0; parm_table[i].label; i++)
2290 if (parm_table[i].p_class == P_LOCAL &&
2291 (bcopyall || bitmap_query(pcopymapDest,i))) {
2292 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2293 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2295 switch (parm_table[i].type) {
2298 *(bool *)dest_ptr = *(bool *)src_ptr;
2305 *(int *)dest_ptr = *(int *)src_ptr;
2309 *(char *)dest_ptr = *(char *)src_ptr;
2313 string_set((char **)dest_ptr,
2319 char *upper_string = strupper_talloc(talloc_tos(),
2321 string_set((char **)dest_ptr,
2323 TALLOC_FREE(upper_string);
2327 TALLOC_FREE(*((char ***)dest_ptr));
2328 *((char ***)dest_ptr) = str_list_copy(NULL,
2329 *(const char ***)src_ptr);
2337 init_copymap(pserviceDest);
2338 if (pserviceSource->copymap)
2339 bitmap_copy(pserviceDest->copymap,
2340 pserviceSource->copymap);
2343 data = pserviceSource->param_opt;
2345 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2350 /***************************************************************************
2351 Check a service for consistency. Return false if the service is in any way
2352 incomplete or faulty, else true.
2353 ***************************************************************************/
2355 bool service_ok(int iService)
2360 if (ServicePtrs[iService]->szService[0] == '\0') {
2361 DEBUG(0, ("The following message indicates an internal error:\n"));
2362 DEBUG(0, ("No service name in service entry.\n"));
2366 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2367 /* I can't see why you'd want a non-printable printer service... */
2368 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2369 if (!ServicePtrs[iService]->print_ok) {
2370 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2371 ServicePtrs[iService]->szService));
2372 ServicePtrs[iService]->print_ok = true;
2374 /* [printers] service must also be non-browsable. */
2375 if (ServicePtrs[iService]->browseable)
2376 ServicePtrs[iService]->browseable = false;
2379 if (ServicePtrs[iService]->pathname[0] == '\0' &&
2380 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2381 ServicePtrs[iService]->msdfs_proxy[0] == '\0'
2383 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2384 ServicePtrs[iService]->szService));
2385 ServicePtrs[iService]->bAvailable = false;
2388 /* If a service is flagged unavailable, log the fact at level 1. */
2389 if (!ServicePtrs[iService]->bAvailable)
2390 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2391 ServicePtrs[iService]->szService));
2396 static struct smbconf_ctx *lp_smbconf_ctx(void)
2399 static struct smbconf_ctx *conf_ctx = NULL;
2401 if (conf_ctx == NULL) {
2402 err = smbconf_init(NULL, &conf_ctx, "registry:");
2403 if (!SBC_ERROR_IS_OK(err)) {
2404 DEBUG(1, ("error initializing registry configuration: "
2405 "%s\n", sbcErrorString(err)));
2413 static bool process_smbconf_service(struct smbconf_service *service)
2418 if (service == NULL) {
2422 ret = do_section(service->name, NULL);
2426 for (count = 0; count < service->num_params; count++) {
2427 ret = do_parameter(service->param_names[count],
2428 service->param_values[count],
2434 if (iServiceIndex >= 0) {
2435 return service_ok(iServiceIndex);
2441 * load a service from registry and activate it
2443 bool process_registry_service(const char *service_name)
2446 struct smbconf_service *service = NULL;
2447 TALLOC_CTX *mem_ctx = talloc_stackframe();
2448 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2451 if (conf_ctx == NULL) {
2455 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2457 if (!smbconf_share_exists(conf_ctx, service_name)) {
2459 * Registry does not contain data for this service (yet),
2460 * but make sure lp_load doesn't return false.
2466 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2467 if (!SBC_ERROR_IS_OK(err)) {
2471 ret = process_smbconf_service(service);
2477 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2480 TALLOC_FREE(mem_ctx);
2485 * process_registry_globals
2487 static bool process_registry_globals(void)
2491 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2493 ret = do_parameter("registry shares", "yes", NULL);
2498 return process_registry_service(GLOBAL_NAME);
2501 bool process_registry_shares(void)
2505 struct smbconf_service **service = NULL;
2506 uint32_t num_shares = 0;
2507 TALLOC_CTX *mem_ctx = talloc_stackframe();
2508 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2511 if (conf_ctx == NULL) {
2515 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2516 if (!SBC_ERROR_IS_OK(err)) {
2522 for (count = 0; count < num_shares; count++) {
2523 if (strequal(service[count]->name, GLOBAL_NAME)) {
2526 ret = process_smbconf_service(service[count]);
2533 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2536 TALLOC_FREE(mem_ctx);
2541 * reload those shares from registry that are already
2542 * activated in the services array.
2544 static bool reload_registry_shares(void)
2549 for (i = 0; i < iNumServices; i++) {
2554 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2558 ret = process_registry_service(ServicePtrs[i]->szService);
2569 #define MAX_INCLUDE_DEPTH 100
2571 static uint8_t include_depth;
2573 static struct file_lists {
2574 struct file_lists *next;
2578 } *file_lists = NULL;
2580 /*******************************************************************
2581 Keep a linked list of all config files so we know when one has changed
2582 it's date and needs to be reloaded.
2583 ********************************************************************/
2585 static void add_to_file_list(const char *fname, const char *subfname)
2587 struct file_lists *f = file_lists;
2590 if (f->name && !strcmp(f->name, fname))
2596 f = SMB_MALLOC_P(struct file_lists);
2599 f->next = file_lists;
2600 f->name = SMB_STRDUP(fname);
2605 f->subfname = SMB_STRDUP(subfname);
2612 f->modtime = file_modtime(subfname);
2614 time_t t = file_modtime(subfname);
2622 * Free the file lists
2624 static void free_file_list(void)
2626 struct file_lists *f;
2627 struct file_lists *next;
2632 SAFE_FREE( f->name );
2633 SAFE_FREE( f->subfname );
2642 * Utility function for outsiders to check if we're running on registry.
2644 bool lp_config_backend_is_registry(void)
2646 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2650 * Utility function to check if the config backend is FILE.
2652 bool lp_config_backend_is_file(void)
2654 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2657 /*******************************************************************
2658 Check if a config file has changed date.
2659 ********************************************************************/
2661 bool lp_file_list_changed(void)
2663 struct file_lists *f = file_lists;
2665 DEBUG(6, ("lp_file_list_changed()\n"));
2670 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2671 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2673 if (conf_ctx == NULL) {
2676 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2679 DEBUGADD(6, ("registry config changed\n"));
2684 n2 = talloc_sub_basic(talloc_tos(),
2685 get_current_username(),
2686 current_user_info.domain,
2691 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2692 f->name, n2, ctime(&f->modtime)));
2694 mod_time = file_modtime(n2);
2697 ((f->modtime != mod_time) ||
2698 (f->subfname == NULL) ||
2699 (strcmp(n2, f->subfname) != 0)))
2702 ("file %s modified: %s\n", n2,
2704 f->modtime = mod_time;
2705 SAFE_FREE(f->subfname);
2706 f->subfname = SMB_STRDUP(n2);
2719 * Initialize iconv conversion descriptors.
2721 * This is called the first time it is needed, and also called again
2722 * every time the configuration is reloaded, because the charset or
2723 * codepage might have changed.
2725 static void init_iconv(void)
2727 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2729 true, global_iconv_handle);
2732 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2734 if (strcmp(*ptr, pszParmValue) != 0) {
2735 string_set(ptr, pszParmValue);
2741 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2743 bool is_utf8 = false;
2744 size_t len = strlen(pszParmValue);
2746 if (len == 4 || len == 5) {
2747 /* Don't use StrCaseCmp here as we don't want to
2748 initialize iconv. */
2749 if ((toupper_m(pszParmValue[0]) == 'U') &&
2750 (toupper_m(pszParmValue[1]) == 'T') &&
2751 (toupper_m(pszParmValue[2]) == 'F')) {
2753 if (pszParmValue[3] == '8') {
2757 if (pszParmValue[3] == '-' &&
2758 pszParmValue[4] == '8') {
2765 if (strcmp(*ptr, pszParmValue) != 0) {
2767 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2768 "be UTF8, using (default value) %s instead.\n",
2769 DEFAULT_DOS_CHARSET));
2770 pszParmValue = DEFAULT_DOS_CHARSET;
2772 string_set(ptr, pszParmValue);
2778 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2781 TALLOC_CTX *frame = talloc_stackframe();
2782 char *realm = strupper_talloc(frame, pszParmValue);
2783 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2785 ret &= string_set(&Globals.realm_original, pszParmValue);
2786 ret &= string_set(&Globals.realm, realm);
2787 ret &= string_set(&Globals.dnsdomain, dnsdomain);
2793 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2795 TALLOC_FREE(Globals.netbios_aliases);
2796 Globals.netbios_aliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2797 return set_netbios_aliases(Globals.netbios_aliases);
2800 /***************************************************************************
2801 Handle the include operation.
2802 ***************************************************************************/
2803 static bool bAllowIncludeRegistry = true;
2805 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2809 if (include_depth >= MAX_INCLUDE_DEPTH) {
2810 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2815 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2816 if (!bAllowIncludeRegistry) {
2819 if (bInGlobalSection) {
2822 ret = process_registry_globals();
2826 DEBUG(1, ("\"include = registry\" only effective "
2827 "in %s section\n", GLOBAL_NAME));
2832 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2833 current_user_info.domain,
2836 add_to_file_list(pszParmValue, fname);
2838 string_set(ptr, fname);
2840 if (file_exist(fname)) {
2843 ret = pm_process(fname, do_section, do_parameter, NULL);
2849 DEBUG(2, ("Can't find include file %s\n", fname));
2854 /***************************************************************************
2855 Handle the interpretation of the copy parameter.
2856 ***************************************************************************/
2858 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2862 struct loadparm_service serviceTemp;
2864 string_set(ptr, pszParmValue);
2866 init_service(&serviceTemp);
2870 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2872 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2873 if (iTemp == iServiceIndex) {
2874 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2876 copy_service(ServicePtrs[iServiceIndex],
2878 ServicePtrs[iServiceIndex]->copymap);
2882 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2886 free_service(&serviceTemp);
2890 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2892 Globals.ldap_debug_level = lp_int(pszParmValue);
2893 init_ldap_debugging();
2898 * idmap related parameters
2901 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2903 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2908 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2910 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2915 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2917 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2922 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2924 char *config_option = NULL;
2925 const char *range = NULL;
2928 SMB_ASSERT(low != NULL);
2929 SMB_ASSERT(high != NULL);
2931 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2935 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2937 if (config_option == NULL) {
2938 DEBUG(0, ("out of memory\n"));
2942 range = lp_parm_const_string(-1, config_option, "range", NULL);
2943 if (range == NULL) {
2944 DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2948 if (sscanf(range, "%u - %u", low, high) != 2) {
2949 DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2950 range, domain_name));
2957 talloc_free(config_option);
2962 bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2964 return lp_idmap_range("*", low, high);
2967 const char *lp_idmap_backend(const char *domain_name)
2969 char *config_option = NULL;
2970 const char *backend = NULL;
2972 if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2976 config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2978 if (config_option == NULL) {
2979 DEBUG(0, ("out of memory\n"));
2983 backend = lp_parm_const_string(-1, config_option, "backend", NULL);
2984 if (backend == NULL) {
2985 DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
2990 talloc_free(config_option);
2994 const char *lp_idmap_default_backend(void)
2996 return lp_idmap_backend("*");
2999 /***************************************************************************
3000 Handle the DEBUG level list.
3001 ***************************************************************************/
3003 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
3005 string_set(ptr, pszParmValueIn);
3006 return debug_parse_levels(pszParmValueIn);
3009 /***************************************************************************
3010 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3011 ***************************************************************************/
3013 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
3015 const char *suffix_string;
3017 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
3018 Globals.ldap_suffix );
3019 if ( !suffix_string ) {
3020 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3024 return suffix_string;
3027 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
3029 if (Globals.szLdapMachineSuffix[0])
3030 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
3032 return lp_string(ctx, Globals.ldap_suffix);
3035 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
3037 if (Globals.szLdapUserSuffix[0])
3038 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3040 return lp_string(ctx, Globals.ldap_suffix);
3043 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3045 if (Globals.szLdapGroupSuffix[0])
3046 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3048 return lp_string(ctx, Globals.ldap_suffix);
3051 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3053 if (Globals.szLdapIdmapSuffix[0])
3054 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3056 return lp_string(ctx, Globals.ldap_suffix);
3059 /****************************************************************************
3060 set the value for a P_ENUM
3061 ***************************************************************************/
3063 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3068 for (i = 0; parm->enum_list[i].name; i++) {
3069 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3070 *ptr = parm->enum_list[i].value;
3074 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3075 pszParmValue, parm->label));
3078 /***************************************************************************
3079 ***************************************************************************/
3081 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3083 static int parm_num = -1;
3084 struct loadparm_service *s;
3086 if ( parm_num == -1 )
3087 parm_num = lpcfg_map_parameter( "printing" );
3089 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3094 s = ServicePtrs[snum];
3096 init_printer_values( s );
3102 /***************************************************************************
3103 Initialise a copymap.
3104 ***************************************************************************/
3106 static void init_copymap(struct loadparm_service *pservice)
3110 TALLOC_FREE(pservice->copymap);
3112 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3113 if (!pservice->copymap)
3115 ("Couldn't allocate copymap!! (size %d)\n",
3116 (int)NUMPARAMETERS));
3118 for (i = 0; i < NUMPARAMETERS; i++)
3119 bitmap_set(pservice->copymap, i);
3123 return the parameter pointer for a parameter
3125 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3127 if (service == NULL) {
3128 if (parm->p_class == P_LOCAL)
3129 return (void *)(((char *)&sDefault)+parm->offset);
3130 else if (parm->p_class == P_GLOBAL)
3131 return (void *)(((char *)&Globals)+parm->offset);
3134 return (void *)(((char *)service) + parm->offset);
3138 /***************************************************************************
3139 Return the local pointer to a parameter given the service number and parameter
3140 ***************************************************************************/
3142 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3144 return lp_parm_ptr(ServicePtrs[snum], parm);
3147 /***************************************************************************
3148 Process a parameter for a particular service number. If snum < 0
3149 then assume we are in the globals.
3150 ***************************************************************************/
3152 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3155 void *parm_ptr = NULL; /* where we are going to store the result */
3156 struct parmlist_entry **opt_list;
3158 parmnum = lpcfg_map_parameter(pszParmName);
3161 if (strchr(pszParmName, ':') == NULL) {
3162 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3168 * We've got a parametric option
3171 opt_list = (snum < 0)
3172 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3173 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3178 /* if it's already been set by the command line, then we don't
3180 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3184 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3185 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3189 /* we might point at a service, the default service or a global */
3191 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3193 if (parm_table[parmnum].p_class == P_GLOBAL) {
3195 ("Global parameter %s found in service section!\n",
3199 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3203 if (!ServicePtrs[snum]->copymap)
3204 init_copymap(ServicePtrs[snum]);
3206 /* this handles the aliases - set the copymap for other entries with
3207 the same data pointer */
3208 for (i = 0; parm_table[i].label; i++) {
3209 if ((parm_table[i].offset == parm_table[parmnum].offset)
3210 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3211 bitmap_clear(ServicePtrs[snum]->copymap, i);
3216 /* if it is a special case then go ahead */
3217 if (parm_table[parmnum].special) {
3218 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3222 /* now switch on the type of variable it is */
3223 switch (parm_table[parmnum].type)
3226 *(bool *)parm_ptr = lp_bool(pszParmValue);
3230 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3234 *(int *)parm_ptr = lp_int(pszParmValue);
3238 *(char *)parm_ptr = *pszParmValue;
3242 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3244 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3251 if (conv_str_size_error(pszParmValue, &val)) {
3252 if (val <= INT_MAX) {
3253 *(int *)parm_ptr = (int)val;
3258 DEBUG(0,("lp_do_parameter(%s): value is not "
3259 "a valid size specifier!\n", pszParmValue));
3265 TALLOC_FREE(*((char ***)parm_ptr));
3266 *(char ***)parm_ptr = str_list_make_v3(
3267 NULL, pszParmValue, NULL);
3271 string_set((char **)parm_ptr, pszParmValue);
3276 char *upper_string = strupper_talloc(talloc_tos(),
3278 string_set((char **)parm_ptr, upper_string);
3279 TALLOC_FREE(upper_string);
3283 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3292 /***************************************************************************
3293 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3294 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3295 ***************************************************************************/
3297 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3300 parmnum = lpcfg_map_parameter(pszParmName);
3302 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3303 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3306 parm_table[parmnum].flags |= FLAG_CMDLINE;
3308 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3309 * be grouped in the table, so we don't have to search the
3312 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3313 && parm_table[i].p_class == parm_table[parmnum].p_class;
3315 parm_table[i].flags |= FLAG_CMDLINE;
3317 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3318 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3319 parm_table[i].flags |= FLAG_CMDLINE;
3323 store_lp_set_cmdline(pszParmName, pszParmValue);
3328 /* it might be parametric */
3329 if (strchr(pszParmName, ':') != NULL) {
3330 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3332 store_lp_set_cmdline(pszParmName, pszParmValue);
3337 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3341 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3343 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3346 /***************************************************************************
3347 Process a parameter.
3348 ***************************************************************************/
3350 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3353 if (!bInGlobalSection && bGlobalOnly)
3356 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3358 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3359 pszParmName, pszParmValue));
3363 set a option from the commandline in 'a=b' format. Use to support --option
3365 bool lp_set_option(const char *option)
3370 s = talloc_strdup(NULL, option);
3383 /* skip white spaces after the = sign */
3386 } while (*p == ' ');
3388 ret = lp_set_cmdline(s, p);
3393 /***************************************************************************
3394 Check if two parameters are equal.
3395 ***************************************************************************/
3397 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3402 return (*((bool *)ptr1) == *((bool *)ptr2));
3408 return (*((int *)ptr1) == *((int *)ptr2));
3411 return (*((char *)ptr1) == *((char *)ptr2));
3415 return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3420 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3425 return (p1 == p2 || strequal(p1, p2));
3433 /***************************************************************************
3434 Initialize any local variables in the sDefault table, after parsing a
3436 ***************************************************************************/
3438 static void init_locals(void)
3441 * We run this check once the [globals] is parsed, to force
3442 * the VFS objects and other per-share settings we need for
3443 * the standard way a AD DC is operated. We may change these
3444 * as our code evolves, which is why we force these settings.
3446 * We can't do this at the end of lp_load_ex(), as by that
3447 * point the services have been loaded and they will already
3448 * have "" as their vfs objects.
3450 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
3451 const char **vfs_objects = lp_vfs_objects(-1);
3452 if (!vfs_objects || !vfs_objects[0]) {
3453 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
3454 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
3455 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
3456 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
3458 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
3462 lp_do_parameter(-1, "map hidden", "no");
3463 lp_do_parameter(-1, "map system", "no");
3464 lp_do_parameter(-1, "map readonly", "no");
3465 lp_do_parameter(-1, "map archive", "no");
3466 lp_do_parameter(-1, "store dos attributes", "yes");
3470 /***************************************************************************
3471 Process a new section (service). At this stage all sections are services.
3472 Later we'll have special sections that permit server parameters to be set.
3473 Returns true on success, false on failure.
3474 ***************************************************************************/
3476 static bool do_section(const char *pszSectionName, void *userdata)
3479 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3480 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3483 /* if we were in a global section then do the local inits */
3484 if (bInGlobalSection && !isglobal)
3487 /* if we've just struck a global section, note the fact. */
3488 bInGlobalSection = isglobal;
3490 /* check for multiple global sections */
3491 if (bInGlobalSection) {
3492 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3496 if (!bInGlobalSection && bGlobalOnly)
3499 /* if we have a current service, tidy it up before moving on */
3502 if (iServiceIndex >= 0)
3503 bRetval = service_ok(iServiceIndex);
3505 /* if all is still well, move to the next record in the services array */
3507 /* We put this here to avoid an odd message order if messages are */
3508 /* issued by the post-processing of a previous section. */
3509 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3511 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3512 if (iServiceIndex < 0) {
3513 DEBUG(0, ("Failed to add a new service\n"));
3516 /* Clean all parametric options for service */
3517 /* They will be added during parsing again */
3518 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3525 /***************************************************************************
3526 Determine if a partcular base parameter is currentl set to the default value.
3527 ***************************************************************************/
3529 static bool is_default(int i)
3531 if (!defaults_saved)
3533 switch (parm_table[i].type) {
3536 return str_list_equal((const char **)parm_table[i].def.lvalue,
3537 *(const char ***)lp_parm_ptr(NULL,
3541 return strequal(parm_table[i].def.svalue,
3542 *(char **)lp_parm_ptr(NULL,
3546 return parm_table[i].def.bvalue ==
3547 *(bool *)lp_parm_ptr(NULL,
3550 return parm_table[i].def.cvalue ==
3551 *(char *)lp_parm_ptr(NULL,
3557 return parm_table[i].def.ivalue ==
3558 *(int *)lp_parm_ptr(NULL,
3566 /***************************************************************************
3567 Display the contents of the global structure.
3568 ***************************************************************************/
3570 static void dump_globals(FILE *f)
3573 struct parmlist_entry *data;
3575 fprintf(f, "[global]\n");
3577 for (i = 0; parm_table[i].label; i++)
3578 if (parm_table[i].p_class == P_GLOBAL &&
3579 !(parm_table[i].flags & FLAG_META) &&
3580 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3581 if (defaults_saved && is_default(i))
3583 fprintf(f, "\t%s = ", parm_table[i].label);
3584 lpcfg_print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3589 if (Globals.param_opt != NULL) {
3590 data = Globals.param_opt;
3592 fprintf(f, "\t%s = %s\n", data->key, data->value);
3599 /***************************************************************************
3600 Return true if a local parameter is currently set to the global default.
3601 ***************************************************************************/
3603 bool lp_is_default(int snum, struct parm_struct *parm)
3605 return equal_parameter(parm->type,
3606 lp_parm_ptr(ServicePtrs[snum], parm),
3607 lp_parm_ptr(NULL, parm));
3610 /***************************************************************************
3611 Display the contents of a single services record.
3612 ***************************************************************************/
3614 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3617 struct parmlist_entry *data;
3619 if (pService != &sDefault)
3620 fprintf(f, "[%s]\n", pService->szService);
3622 for (i = 0; parm_table[i].label; i++) {
3624 if (parm_table[i].p_class == P_LOCAL &&
3625 !(parm_table[i].flags & FLAG_META) &&
3626 (*parm_table[i].label != '-') &&
3627 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3629 if (pService == &sDefault) {
3630 if (defaults_saved && is_default(i))
3633 if (equal_parameter(parm_table[i].type,
3634 lp_parm_ptr(pService, &parm_table[i]),
3635 lp_parm_ptr(NULL, &parm_table[i])))
3639 fprintf(f, "\t%s = ", parm_table[i].label);
3640 lpcfg_print_parameter(&parm_table[i],
3641 lp_parm_ptr(pService, &parm_table[i]),
3647 if (pService->param_opt != NULL) {
3648 data = pService->param_opt;
3650 fprintf(f, "\t%s = %s\n", data->key, data->value);
3656 /***************************************************************************
3657 Display the contents of a parameter of a single services record.
3658 ***************************************************************************/
3660 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3662 bool result = false;
3663 fstring local_parm_name;
3665 const char *parm_opt_value;
3667 struct loadparm_context *lp_ctx;
3669 /* check for parametrical option */
3670 fstrcpy( local_parm_name, parm_name);
3671 parm_opt = strchr( local_parm_name, ':');
3676 if (strlen(parm_opt)) {
3677 parm_opt_value = lp_parm_const_string( snum,
3678 local_parm_name, parm_opt, NULL);
3679 if (parm_opt_value) {
3680 printf( "%s\n", parm_opt_value);
3687 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
3688 if (lp_ctx == NULL) {
3693 result = lpcfg_dump_a_parameter(lp_ctx, NULL, parm_name, f);
3695 result = lpcfg_dump_a_parameter(lp_ctx, ServicePtrs[snum], parm_name, f);
3697 TALLOC_FREE(lp_ctx);
3701 /***************************************************************************
3702 Return info about the requested parameter (given as a string).
3703 Return NULL when the string is not a valid parameter name.
3704 ***************************************************************************/
3706 struct parm_struct *lp_get_parameter(const char *param_name)
3708 int num = lpcfg_map_parameter(param_name);
3714 return &parm_table[num];
3717 /***************************************************************************
3718 Return info about the next parameter in a service.
3719 snum==GLOBAL_SECTION_SNUM gives the globals.
3720 Return NULL when out of parameters.
3721 ***************************************************************************/
3723 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3726 /* do the globals */
3727 for (; parm_table[*i].label; (*i)++) {
3728 if (parm_table[*i].p_class == P_SEPARATOR)
3729 return &parm_table[(*i)++];
3731 if ((*parm_table[*i].label == '-'))
3735 && (parm_table[*i].offset ==
3736 parm_table[(*i) - 1].offset)
3737 && (parm_table[*i].p_class ==
3738 parm_table[(*i) - 1].p_class))
3741 if (is_default(*i) && !allparameters)
3744 return &parm_table[(*i)++];
3747 struct loadparm_service *pService = ServicePtrs[snum];
3749 for (; parm_table[*i].label; (*i)++) {
3750 if (parm_table[*i].p_class == P_SEPARATOR)
3751 return &parm_table[(*i)++];
3753 if (parm_table[*i].p_class == P_LOCAL &&
3754 (*parm_table[*i].label != '-') &&
3756 (parm_table[*i].offset !=
3757 parm_table[(*i) - 1].offset)))
3759 if (allparameters ||
3760 !equal_parameter(parm_table[*i].type,
3761 lp_parm_ptr(pService,
3766 return &parm_table[(*i)++];
3777 /***************************************************************************
3778 Display the contents of a single copy structure.
3779 ***************************************************************************/
3780 static void dump_copy_map(bool *pcopymap)
3786 printf("\n\tNon-Copied parameters:\n");
3788 for (i = 0; parm_table[i].label; i++)
3789 if (parm_table[i].p_class == P_LOCAL &&
3790 parm_table[i].ptr && !pcopymap[i] &&
3791 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3793 printf("\t\t%s\n", parm_table[i].label);
3798 /***************************************************************************
3799 Return TRUE if the passed service number is within range.
3800 ***************************************************************************/
3802 bool lp_snum_ok(int iService)
3804 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3807 /***************************************************************************
3808 Auto-load some home services.
3809 ***************************************************************************/
3811 static void lp_add_auto_services(char *str)
3821 s = SMB_STRDUP(str);
3825 homes = lp_servicenumber(HOMES_NAME);
3827 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3828 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3831 if (lp_servicenumber(p) >= 0)
3834 home = get_user_home_dir(talloc_tos(), p);
3836 if (home && home[0] && homes >= 0)
3837 lp_add_home(p, homes, p, home);
3844 /***************************************************************************
3845 Auto-load one printer.
3846 ***************************************************************************/
3848 void lp_add_one_printer(const char *name, const char *comment,
3849 const char *location, void *pdata)
3851 int printers = lp_servicenumber(PRINTERS_NAME);
3854 if (lp_servicenumber(name) < 0) {
3855 lp_add_printer(name, printers);
3856 if ((i = lp_servicenumber(name)) >= 0) {
3857 string_set(&ServicePtrs[i]->comment, comment);
3858 ServicePtrs[i]->autoloaded = true;
3863 /***************************************************************************
3864 Have we loaded a services file yet?
3865 ***************************************************************************/
3867 bool lp_loaded(void)
3872 /***************************************************************************
3873 Unload unused services.
3874 ***************************************************************************/
3876 void lp_killunused(struct smbd_server_connection *sconn,
3877 bool (*snumused) (struct smbd_server_connection *, int))
3880 for (i = 0; i < iNumServices; i++) {
3884 /* don't kill autoloaded or usershare services */
3885 if ( ServicePtrs[i]->autoloaded ||
3886 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3890 if (!snumused || !snumused(sconn, i)) {
3891 free_service_byindex(i);
3897 * Kill all except autoloaded and usershare services - convenience wrapper
3899 void lp_kill_all_services(void)
3901 lp_killunused(NULL, NULL);
3904 /***************************************************************************
3906 ***************************************************************************/
3908 void lp_killservice(int iServiceIn)
3910 if (VALID(iServiceIn)) {
3911 free_service_byindex(iServiceIn);
3915 /***************************************************************************
3916 Save the curent values of all global and sDefault parameters into the
3917 defaults union. This allows testparm to show only the
3918 changed (ie. non-default) parameters.
3919 ***************************************************************************/
3921 static void lp_save_defaults(void)
3924 for (i = 0; parm_table[i].label; i++) {
3925 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3926 && parm_table[i].p_class == parm_table[i - 1].p_class)
3928 switch (parm_table[i].type) {
3931 parm_table[i].def.lvalue = str_list_copy(
3932 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3936 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3940 parm_table[i].def.bvalue =
3941 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3944 parm_table[i].def.cvalue =
3945 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3951 parm_table[i].def.ivalue =
3952 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3958 defaults_saved = true;
3961 /***********************************************************
3962 If we should send plaintext/LANMAN passwords in the clinet
3963 ************************************************************/
3965 static void set_allowed_client_auth(void)
3967 if (Globals.client_ntlmv2_auth) {
3968 Globals.client_lanman_auth = false;
3970 if (!Globals.client_lanman_auth) {
3971 Globals.client_plaintext_auth = false;
3975 /***************************************************************************
3977 The following code allows smbd to read a user defined share file.
3978 Yes, this is my intent. Yes, I'm comfortable with that...
3980 THE FOLLOWING IS SECURITY CRITICAL CODE.
3982 It washes your clothes, it cleans your house, it guards you while you sleep...
3983 Do not f%^k with it....
3984 ***************************************************************************/
3986 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3988 /***************************************************************************
3989 Check allowed stat state of a usershare file.
3990 Ensure we print out who is dicking with us so the admin can
3991 get their sorry ass fired.
3992 ***************************************************************************/
3994 static bool check_usershare_stat(const char *fname,
3995 const SMB_STRUCT_STAT *psbuf)
3997 if (!S_ISREG(psbuf->st_ex_mode)) {
3998 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3999 "not a regular file\n",
4000 fname, (unsigned int)psbuf->st_ex_uid ));
4004 /* Ensure this doesn't have the other write bit set. */
4005 if (psbuf->st_ex_mode & S_IWOTH) {
4006 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4007 "public write. Refusing to allow as a usershare file.\n",
4008 fname, (unsigned int)psbuf->st_ex_uid ));
4012 /* Should be 10k or less. */
4013 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4014 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4015 "too large (%u) to be a user share file.\n",
4016 fname, (unsigned int)psbuf->st_ex_uid,
4017 (unsigned int)psbuf->st_ex_size ));
4024 /***************************************************************************
4025 Parse the contents of a usershare file.
4026 ***************************************************************************/
4028 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4029 SMB_STRUCT_STAT *psbuf,
4030 const char *servicename,
4034 char **pp_sharepath,
4036 char **pp_cp_servicename,
4037 struct security_descriptor **ppsd,
4040 const char **prefixallowlist = lp_usershare_prefix_allow_list();
4041 const char **prefixdenylist = lp_usershare_prefix_deny_list();
4044 SMB_STRUCT_STAT sbuf;
4045 char *sharepath = NULL;
4046 char *comment = NULL;
4048 *pp_sharepath = NULL;
4051 *pallow_guest = false;
4054 return USERSHARE_MALFORMED_FILE;
4057 if (strcmp(lines[0], "#VERSION 1") == 0) {
4059 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4062 return USERSHARE_MALFORMED_FILE;
4065 return USERSHARE_BAD_VERSION;
4068 if (strncmp(lines[1], "path=", 5) != 0) {
4069 return USERSHARE_MALFORMED_PATH;
4072 sharepath = talloc_strdup(ctx, &lines[1][5]);
4074 return USERSHARE_POSIX_ERR;
4076 trim_string(sharepath, " ", " ");
4078 if (strncmp(lines[2], "comment=", 8) != 0) {
4079 return USERSHARE_MALFORMED_COMMENT_DEF;
4082 comment = talloc_strdup(ctx, &lines[2][8]);
4084 return USERSHARE_POSIX_ERR;
4086 trim_string(comment, " ", " ");
4087 trim_char(comment, '"', '"');
4089 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4090 return USERSHARE_MALFORMED_ACL_DEF;
4093 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4094 return USERSHARE_ACL_ERR;
4098 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4099 return USERSHARE_MALFORMED_ACL_DEF;
4101 if (lines[4][9] == 'y') {
4102 *pallow_guest = true;
4105 /* Backwards compatible extension to file version #2. */
4107 if (strncmp(lines[5], "sharename=", 10) != 0) {
4108 return USERSHARE_MALFORMED_SHARENAME_DEF;
4110 if (!strequal(&lines[5][10], servicename)) {
4111 return USERSHARE_BAD_SHARENAME;
4113 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4114 if (!*pp_cp_servicename) {
4115 return USERSHARE_POSIX_ERR;
4120 if (*pp_cp_servicename == NULL) {
4121 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4122 if (!*pp_cp_servicename) {
4123 return USERSHARE_POSIX_ERR;
4127 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->pathname) == 0)) {
4128 /* Path didn't change, no checks needed. */
4129 *pp_sharepath = sharepath;
4130 *pp_comment = comment;
4131 return USERSHARE_OK;
4134 /* The path *must* be absolute. */
4135 if (sharepath[0] != '/') {
4136 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4137 servicename, sharepath));
4138 return USERSHARE_PATH_NOT_ABSOLUTE;
4141 /* If there is a usershare prefix deny list ensure one of these paths
4142 doesn't match the start of the user given path. */
4143 if (prefixdenylist) {
4145 for ( i=0; prefixdenylist[i]; i++ ) {
4146 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4147 servicename, i, prefixdenylist[i], sharepath ));
4148 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4149 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4150 "usershare prefix deny list entries.\n",
4151 servicename, sharepath));
4152 return USERSHARE_PATH_IS_DENIED;
4157 /* If there is a usershare prefix allow list ensure one of these paths
4158 does match the start of the user given path. */
4160 if (prefixallowlist) {
4162 for ( i=0; prefixallowlist[i]; i++ ) {
4163 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4164 servicename, i, prefixallowlist[i], sharepath ));
4165 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4169 if (prefixallowlist[i] == NULL) {
4170 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4171 "usershare prefix allow list entries.\n",
4172 servicename, sharepath));
4173 return USERSHARE_PATH_NOT_ALLOWED;
4177 /* Ensure this is pointing to a directory. */
4178 dp = opendir(sharepath);
4181 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4182 servicename, sharepath));
4183 return USERSHARE_PATH_NOT_DIRECTORY;
4186 /* Ensure the owner of the usershare file has permission to share
4189 if (sys_stat(sharepath, &sbuf, false) == -1) {
4190 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4191 servicename, sharepath, strerror(errno) ));
4193 return USERSHARE_POSIX_ERR;
4198 if (!S_ISDIR(sbuf.st_ex_mode)) {
4199 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4200 servicename, sharepath ));
4201 return USERSHARE_PATH_NOT_DIRECTORY;
4204 /* Check if sharing is restricted to owner-only. */
4205 /* psbuf is the stat of the usershare definition file,
4206 sbuf is the stat of the target directory to be shared. */
4208 if (lp_usershare_owner_only()) {
4209 /* root can share anything. */
4210 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4211 return USERSHARE_PATH_NOT_ALLOWED;
4215 *pp_sharepath = sharepath;
4216 *pp_comment = comment;
4217 return USERSHARE_OK;
4220 /***************************************************************************
4221 Deal with a usershare file.
4224 -1 - Bad name, invalid contents.
4225 - service name already existed and not a usershare, problem
4226 with permissions to share directory etc.
4227 ***************************************************************************/
4229 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4231 SMB_STRUCT_STAT sbuf;
4232 SMB_STRUCT_STAT lsbuf;
4234 char *sharepath = NULL;
4235 char *comment = NULL;
4236 char *cp_service_name = NULL;
4237 char **lines = NULL;
4241 TALLOC_CTX *ctx = talloc_stackframe();
4242 struct security_descriptor *psd = NULL;
4243 bool guest_ok = false;
4244 char *canon_name = NULL;
4245 bool added_service = false;
4248 /* Ensure share name doesn't contain invalid characters. */
4249 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4250 DEBUG(0,("process_usershare_file: share name %s contains "
4251 "invalid characters (any of %s)\n",
4252 file_name, INVALID_SHARENAME_CHARS ));
4256 canon_name = canonicalize_servicename(ctx, file_name);
4261 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4266 /* Minimize the race condition by doing an lstat before we
4267 open and fstat. Ensure this isn't a symlink link. */
4269 if (sys_lstat(fname, &lsbuf, false) != 0) {
4270 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4271 fname, strerror(errno) ));
4275 /* This must be a regular file, not a symlink, directory or
4276 other strange filetype. */
4277 if (!check_usershare_stat(fname, &lsbuf)) {
4285 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4290 if (NT_STATUS_IS_OK(status) &&
4291 (data.dptr != NULL) &&
4292 (data.dsize == sizeof(iService))) {
4293 memcpy(&iService, data.dptr, sizeof(iService));
4297 if (iService != -1 &&
4298 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4299 &lsbuf.st_ex_mtime) == 0) {
4300 /* Nothing changed - Mark valid and return. */
4301 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4303 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4308 /* Try and open the file read only - no symlinks allowed. */
4310 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4312 fd = open(fname, O_RDONLY, 0);
4316 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4317 fname, strerror(errno) ));
4321 /* Now fstat to be *SURE* it's a regular file. */
4322 if (sys_fstat(fd, &sbuf, false) != 0) {
4324 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4325 fname, strerror(errno) ));
4329 /* Is it the same dev/inode as was lstated ? */
4330 if (!check_same_stat(&lsbuf, &sbuf)) {
4332 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4333 "Symlink spoofing going on ?\n", fname ));
4337 /* This must be a regular file, not a symlink, directory or
4338 other strange filetype. */
4339 if (!check_usershare_stat(fname, &sbuf)) {
4344 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4347 if (lines == NULL) {
4348 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4349 fname, (unsigned int)sbuf.st_ex_uid ));
4353 if (parse_usershare_file(ctx, &sbuf, file_name,
4354 iService, lines, numlines, &sharepath,
4355 &comment, &cp_service_name,
4356 &psd, &guest_ok) != USERSHARE_OK) {
4360 /* Everything ok - add the service possibly using a template. */
4362 const struct loadparm_service *sp = &sDefault;
4363 if (snum_template != -1) {
4364 sp = ServicePtrs[snum_template];
4367 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4368 DEBUG(0, ("process_usershare_file: Failed to add "
4369 "new service %s\n", cp_service_name));
4373 added_service = true;
4375 /* Read only is controlled by usershare ACL below. */
4376 ServicePtrs[iService]->readonly = false;
4379 /* Write the ACL of the new/modified share. */
4380 if (!set_share_security(canon_name, psd)) {
4381 DEBUG(0, ("process_usershare_file: Failed to set share "
4382 "security for user share %s\n",
4387 /* If from a template it may be marked invalid. */
4388 ServicePtrs[iService]->valid = true;
4390 /* Set the service as a valid usershare. */
4391 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4393 /* Set guest access. */
4394 if (lp_usershare_allow_guests()) {
4395 ServicePtrs[iService]->guest_ok = guest_ok;
4398 /* And note when it was loaded. */
4399 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4400 string_set(&ServicePtrs[iService]->pathname, sharepath);
4401 string_set(&ServicePtrs[iService]->comment, comment);
4407 if (ret == -1 && iService != -1 && added_service) {
4408 lp_remove_service(iService);
4416 /***************************************************************************
4417 Checks if a usershare entry has been modified since last load.
4418 ***************************************************************************/
4420 static bool usershare_exists(int iService, struct timespec *last_mod)
4422 SMB_STRUCT_STAT lsbuf;
4423 const char *usersharepath = Globals.usershare_path;
4426 if (asprintf(&fname, "%s/%s",
4428 ServicePtrs[iService]->szService) < 0) {
4432 if (sys_lstat(fname, &lsbuf, false) != 0) {
4437 if (!S_ISREG(lsbuf.st_ex_mode)) {
4443 *last_mod = lsbuf.st_ex_mtime;
4447 /***************************************************************************
4448 Load a usershare service by name. Returns a valid servicenumber or -1.
4449 ***************************************************************************/
4451 int load_usershare_service(const char *servicename)
4453 SMB_STRUCT_STAT sbuf;
4454 const char *usersharepath = Globals.usershare_path;
4455 int max_user_shares = Globals.usershare_max_shares;
4456 int snum_template = -1;
4458 if (*usersharepath == 0 || max_user_shares == 0) {
4462 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4463 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4464 usersharepath, strerror(errno) ));
4468 if (!S_ISDIR(sbuf.st_ex_mode)) {
4469 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4475 * This directory must be owned by root, and have the 't' bit set.
4476 * It also must not be writable by "other".
4480 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4482 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4484 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4485 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4490 /* Ensure the template share exists if it's set. */
4491 if (Globals.szUsershareTemplateShare[0]) {
4492 /* We can't use lp_servicenumber here as we are recommending that
4493 template shares have -valid=false set. */
4494 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4495 if (ServicePtrs[snum_template]->szService &&
4496 strequal(ServicePtrs[snum_template]->szService,
4497 Globals.szUsershareTemplateShare)) {
4502 if (snum_template == -1) {
4503 DEBUG(0,("load_usershare_service: usershare template share %s "
4504 "does not exist.\n",
4505 Globals.szUsershareTemplateShare ));
4510 return process_usershare_file(usersharepath, servicename, snum_template);
4513 /***************************************************************************
4514 Load all user defined shares from the user share directory.
4515 We only do this if we're enumerating the share list.
4516 This is the function that can delete usershares that have
4518 ***************************************************************************/
4520 int load_usershare_shares(struct smbd_server_connection *sconn,
4521 bool (*snumused) (struct smbd_server_connection *, int))
4524 SMB_STRUCT_STAT sbuf;
4526 int num_usershares = 0;
4527 int max_user_shares = Globals.usershare_max_shares;
4528 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4529 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4530 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4532 int snum_template = -1;
4533 const char *usersharepath = Globals.usershare_path;
4534 int ret = lp_numservices();
4535 TALLOC_CTX *tmp_ctx;
4537 if (max_user_shares == 0 || *usersharepath == '\0') {
4538 return lp_numservices();
4541 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4542 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4543 usersharepath, strerror(errno) ));
4548 * This directory must be owned by root, and have the 't' bit set.
4549 * It also must not be writable by "other".
4553 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4555 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4557 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4558 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4563 /* Ensure the template share exists if it's set. */
4564 if (Globals.szUsershareTemplateShare[0]) {
4565 /* We can't use lp_servicenumber here as we are recommending that
4566 template shares have -valid=false set. */
4567 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4568 if (ServicePtrs[snum_template]->szService &&
4569 strequal(ServicePtrs[snum_template]->szService,
4570 Globals.szUsershareTemplateShare)) {
4575 if (snum_template == -1) {
4576 DEBUG(0,("load_usershare_shares: usershare template share %s "
4577 "does not exist.\n",
4578 Globals.szUsershareTemplateShare ));
4583 /* Mark all existing usershares as pending delete. */
4584 for (iService = iNumServices - 1; iService >= 0; iService--) {
4585 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4586 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4590 dp = opendir(usersharepath);
4592 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4593 usersharepath, strerror(errno) ));
4597 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4599 num_dir_entries++ ) {
4601 const char *n = de->d_name;
4603 /* Ignore . and .. */
4605 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4611 /* Temporary file used when creating a share. */
4612 num_tmp_dir_entries++;
4615 /* Allow 20% tmp entries. */
4616 if (num_tmp_dir_entries > allowed_tmp_entries) {
4617 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4618 "in directory %s\n",
4619 num_tmp_dir_entries, usersharepath));
4623 r = process_usershare_file(usersharepath, n, snum_template);
4625 /* Update the services count. */
4627 if (num_usershares >= max_user_shares) {
4628 DEBUG(0,("load_usershare_shares: max user shares reached "
4629 "on file %s in directory %s\n",
4630 n, usersharepath ));
4633 } else if (r == -1) {
4634 num_bad_dir_entries++;
4637 /* Allow 20% bad entries. */
4638 if (num_bad_dir_entries > allowed_bad_entries) {
4639 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4640 "in directory %s\n",
4641 num_bad_dir_entries, usersharepath));
4645 /* Allow 20% bad entries. */
4646 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4647 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4648 "in directory %s\n",
4649 num_dir_entries, usersharepath));
4656 /* Sweep through and delete any non-refreshed usershares that are
4657 not currently in use. */
4658 tmp_ctx = talloc_stackframe();
4659 for (iService = iNumServices - 1; iService >= 0; iService--) {
4660 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4663 if (snumused && snumused(sconn, iService)) {
4667 servname = lp_servicename(tmp_ctx, iService);
4669 /* Remove from the share ACL db. */
4670 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4672 delete_share_security(servname);
4673 free_service_byindex(iService);
4676 talloc_free(tmp_ctx);
4678 return lp_numservices();
4681 /********************************************************
4682 Destroy global resources allocated in this file
4683 ********************************************************/
4685 void gfree_loadparm(void)
4691 /* Free resources allocated to services */
4693 for ( i = 0; i < iNumServices; i++ ) {
4695 free_service_byindex(i);
4699 SAFE_FREE( ServicePtrs );
4702 /* Now release all resources allocated to global
4703 parameters and the default service */
4705 free_global_parameters();
4709 /***************************************************************************
4710 Allow client apps to specify that they are a client
4711 ***************************************************************************/
4712 static void lp_set_in_client(bool b)
4718 /***************************************************************************
4719 Determine if we're running in a client app
4720 ***************************************************************************/
4721 static bool lp_is_in_client(void)
4726 /***************************************************************************
4727 Load the services array from the services file. Return true on success,
4729 ***************************************************************************/
4731 static bool lp_load_ex(const char *pszFname,
4735 bool initialize_globals,
4736 bool allow_include_registry,
4737 bool load_all_shares)
4744 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4746 bInGlobalSection = true;
4747 bGlobalOnly = global_only;
4748 bAllowIncludeRegistry = allow_include_registry;
4750 init_globals(initialize_globals);
4754 if (save_defaults) {
4759 if (!initialize_globals) {
4760 free_param_opts(&Globals.param_opt);
4761 apply_lp_set_cmdline();
4764 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4766 /* We get sections first, so have to start 'behind' to make up */
4769 if (lp_config_backend_is_file()) {
4770 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4771 current_user_info.domain,
4774 smb_panic("lp_load_ex: out of memory");
4777 add_to_file_list(pszFname, n2);
4779 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4782 /* finish up the last section */
4783 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4785 if (iServiceIndex >= 0) {
4786 bRetval = service_ok(iServiceIndex);
4790 if (lp_config_backend_is_registry()) {
4791 /* config backend changed to registry in config file */
4793 * We need to use this extra global variable here to
4794 * survive restart: init_globals uses this as a default
4795 * for config_backend. Otherwise, init_globals would
4796 * send us into an endless loop here.
4798 config_backend = CONFIG_BACKEND_REGISTRY;
4800 DEBUG(1, ("lp_load_ex: changing to config backend "
4803 lp_kill_all_services();
4804 return lp_load_ex(pszFname, global_only, save_defaults,
4805 add_ipc, initialize_globals,
4806 allow_include_registry,
4809 } else if (lp_config_backend_is_registry()) {
4810 bRetval = process_registry_globals();
4812 DEBUG(0, ("Illegal config backend given: %d\n",
4813 lp_config_backend()));
4817 if (bRetval && lp_registry_shares()) {
4818 if (load_all_shares) {
4819 bRetval = process_registry_shares();
4821 bRetval = reload_registry_shares();
4826 char *serv = lp_auto_services(talloc_tos());
4827 lp_add_auto_services(serv);
4832 /* When 'restrict anonymous = 2' guest connections to ipc$
4834 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4835 if ( lp_enable_asu_support() ) {
4836 lp_add_ipc("ADMIN$", false);
4840 set_allowed_client_auth();
4842 if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4843 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4844 lp_passwordserver()));
4849 /* Now we check we_are_a_wins_server and set szWINSserver to 127.0.0.1 */
4850 /* if we_are_a_wins_server is true and we are in the client */
4851 if (lp_is_in_client() && Globals.we_are_a_wins_server) {
4852 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4857 fault_configure(smb_panic_s3);
4860 * We run this check once the whole smb.conf is parsed, to
4861 * force some settings for the standard way a AD DC is
4862 * operated. We may changed these as our code evolves, which
4863 * is why we force these settings.
4865 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4866 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4868 lp_do_parameter(-1, "rpc_server:default", "external");
4869 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4870 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4871 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4872 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4873 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4874 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4875 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4876 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4879 bAllowIncludeRegistry = true;
4884 bool lp_load(const char *pszFname,
4888 bool initialize_globals)
4890 return lp_load_ex(pszFname,
4895 true, /* allow_include_registry */
4896 false); /* load_all_shares*/
4899 bool lp_load_initial_only(const char *pszFname)
4901 return lp_load_ex(pszFname,
4902 true, /* global only */
4903 false, /* save_defaults */
4904 false, /* add_ipc */
4905 true, /* initialize_globals */
4906 false, /* allow_include_registry */
4907 false); /* load_all_shares*/
4911 * most common lp_load wrapper, loading only the globals
4913 bool lp_load_global(const char *file_name)
4915 return lp_load_ex(file_name,
4916 true, /* global_only */
4917 false, /* save_defaults */
4918 false, /* add_ipc */
4919 true, /* initialize_globals */
4920 true, /* allow_include_registry */
4921 false); /* load_all_shares*/
4925 * lp_load wrapper, especially for clients
4927 bool lp_load_client(const char *file_name)
4929 lp_set_in_client(true);
4931 return lp_load_global(file_name);
4935 * lp_load wrapper, loading only globals, but intended
4936 * for subsequent calls, not reinitializing the globals
4939 bool lp_load_global_no_reinit(const char *file_name)
4941 return lp_load_ex(file_name,
4942 true, /* global_only */
4943 false, /* save_defaults */
4944 false, /* add_ipc */
4945 false, /* initialize_globals */
4946 true, /* allow_include_registry */
4947 false); /* load_all_shares*/
4951 * lp_load wrapper, especially for clients, no reinitialization
4953 bool lp_load_client_no_reinit(const char *file_name)
4955 lp_set_in_client(true);
4957 return lp_load_global_no_reinit(file_name);
4960 bool lp_load_with_registry_shares(const char *pszFname,
4964 bool initialize_globals)
4966 return lp_load_ex(pszFname,
4971 true, /* allow_include_registry */
4972 true); /* load_all_shares*/
4975 /***************************************************************************
4976 Return the max number of services.
4977 ***************************************************************************/
4979 int lp_numservices(void)
4981 return (iNumServices);
4984 /***************************************************************************
4985 Display the contents of the services array in human-readable form.
4986 ***************************************************************************/
4988 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4993 defaults_saved = false;
4997 dump_a_service(&sDefault, f);
4999 for (iService = 0; iService < maxtoprint; iService++) {
5001 lp_dump_one(f, show_defaults, iService);
5005 /***************************************************************************
5006 Display the contents of one service in human-readable form.
5007 ***************************************************************************/
5009 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5012 if (ServicePtrs[snum]->szService[0] == '\0')
5014 dump_a_service(ServicePtrs[snum], f);
5018 /***************************************************************************
5019 Return the number of the service with the given name, or -1 if it doesn't
5020 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5021 getservicebyname()! This works ONLY if all services have been loaded, and
5022 does not copy the found service.
5023 ***************************************************************************/
5025 int lp_servicenumber(const char *pszServiceName)
5028 fstring serviceName;
5030 if (!pszServiceName) {
5031 return GLOBAL_SECTION_SNUM;
5034 for (iService = iNumServices - 1; iService >= 0; iService--) {
5035 if (VALID(iService) && ServicePtrs[iService]->szService) {
5037 * The substitution here is used to support %U is
5040 fstrcpy(serviceName, ServicePtrs[iService]->szService);
5041 standard_sub_basic(get_current_username(),
5042 current_user_info.domain,
5043 serviceName,sizeof(serviceName));
5044 if (strequal(serviceName, pszServiceName)) {
5050 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5051 struct timespec last_mod;
5053 if (!usershare_exists(iService, &last_mod)) {
5054 /* Remove the share security tdb entry for it. */
5055 delete_share_security(lp_servicename(talloc_tos(), iService));
5056 /* Remove it from the array. */
5057 free_service_byindex(iService);
5058 /* Doesn't exist anymore. */
5059 return GLOBAL_SECTION_SNUM;
5062 /* Has it been modified ? If so delete and reload. */
5063 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5065 /* Remove it from the array. */
5066 free_service_byindex(iService);
5067 /* and now reload it. */
5068 iService = load_usershare_service(pszServiceName);
5073 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5074 return GLOBAL_SECTION_SNUM;
5080 /*******************************************************************
5081 A useful volume label function.
5082 ********************************************************************/
5084 const char *volume_label(TALLOC_CTX *ctx, int snum)
5087 const char *label = lp_volume(ctx, snum);
5089 label = lp_servicename(ctx, snum);
5092 /* This returns a 33 byte guarenteed null terminated string. */
5093 ret = talloc_strndup(ctx, label, 32);
5100 /*******************************************************************
5101 Get the default server type we will announce as via nmbd.
5102 ********************************************************************/
5104 int lp_default_server_announce(void)
5106 int default_server_announce = 0;
5107 default_server_announce |= SV_TYPE_WORKSTATION;
5108 default_server_announce |= SV_TYPE_SERVER;
5109 default_server_announce |= SV_TYPE_SERVER_UNIX;
5111 /* note that the flag should be set only if we have a
5112 printer service but nmbd doesn't actually load the
5113 services so we can't tell --jerry */
5115 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5117 default_server_announce |= SV_TYPE_SERVER_NT;
5118 default_server_announce |= SV_TYPE_NT;
5120 switch (lp_server_role()) {
5121 case ROLE_DOMAIN_MEMBER:
5122 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5124 case ROLE_DOMAIN_PDC:
5125 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5127 case ROLE_DOMAIN_BDC:
5128 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5130 case ROLE_STANDALONE:
5134 if (lp_time_server())
5135 default_server_announce |= SV_TYPE_TIME_SOURCE;
5137 if (lp_host_msdfs())
5138 default_server_announce |= SV_TYPE_DFS_SERVER;
5140 return default_server_announce;
5143 /***********************************************************
5144 If we are PDC then prefer us as DMB
5145 ************************************************************/
5147 bool lp_domain_master(void)
5149 if (Globals._domain_master == Auto)
5150 return (lp_server_role() == ROLE_DOMAIN_PDC);
5152 return (bool)Globals._domain_master;
5155 /***********************************************************
5156 If we are PDC then prefer us as DMB
5157 ************************************************************/
5159 static bool lp_domain_master_true_or_auto(void)
5161 if (Globals._domain_master) /* auto or yes */
5167 /***********************************************************
5168 If we are DMB then prefer us as LMB
5169 ************************************************************/
5171 bool lp_preferred_master(void)
5173 if (Globals.iPreferredMaster == Auto)
5174 return (lp_local_master() && lp_domain_master());
5176 return (bool)Globals.iPreferredMaster;
5179 /*******************************************************************
5181 ********************************************************************/
5183 void lp_remove_service(int snum)
5185 ServicePtrs[snum]->valid = false;
5188 /*******************************************************************
5190 ********************************************************************/
5192 void lp_copy_service(int snum, const char *new_name)
5194 do_section(new_name, NULL);
5196 snum = lp_servicenumber(new_name);
5198 char *name = lp_servicename(talloc_tos(), snum);
5199 lp_do_parameter(snum, "copy", name);
5204 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5206 const char *ret = lp__printername(ctx, snum);
5207 if (ret == NULL || *ret == '\0') {
5208 ret = lp_const_servicename(snum);
5215 /***********************************************************
5216 Allow daemons such as winbindd to fix their logfile name.
5217 ************************************************************/
5219 void lp_set_logfile(const char *name)
5221 string_set(&Globals.logfile, name);
5222 debug_set_logfile(name);
5225 /*******************************************************************
5226 Return the max print jobs per queue.
5227 ********************************************************************/
5229 int lp_maxprintjobs(int snum)
5231 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5232 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5233 maxjobs = PRINT_MAX_JOBID - 1;
5238 const char *lp_printcapname(void)
5240 if ((Globals.szPrintcapname != NULL) &&
5241 (Globals.szPrintcapname[0] != '\0'))
5242 return Globals.szPrintcapname;
5244 if (sDefault.printing == PRINT_CUPS) {
5248 if (sDefault.printing == PRINT_BSD)
5249 return "/etc/printcap";
5251 return PRINTCAP_NAME;
5254 static uint32 spoolss_state;
5256 bool lp_disable_spoolss( void )
5258 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5259 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5261 return spoolss_state == SVCCTL_STOPPED ? true : false;
5264 void lp_set_spoolss_state( uint32 state )
5266 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5268 spoolss_state = state;
5271 uint32 lp_get_spoolss_state( void )
5273 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5276 /*******************************************************************
5277 Ensure we don't use sendfile if server smb signing is active.
5278 ********************************************************************/
5280 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5282 bool sign_active = false;
5284 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5285 if (get_Protocol() < PROTOCOL_NT1) {
5288 if (signing_state) {
5289 sign_active = smb_signing_is_active(signing_state);
5291 return (lp__use_sendfile(snum) &&
5292 (get_remote_arch() != RA_WIN95) &&
5296 /*******************************************************************
5297 Turn off sendfile if we find the underlying OS doesn't support it.
5298 ********************************************************************/
5300 void set_use_sendfile(int snum, bool val)
5302 if (LP_SNUM_OK(snum))
5303 ServicePtrs[snum]->_use_sendfile = val;
5305 sDefault._use_sendfile = val;
5308 /*******************************************************************
5309 Turn off storing DOS attributes if this share doesn't support it.
5310 ********************************************************************/
5312 void set_store_dos_attributes(int snum, bool val)
5314 if (!LP_SNUM_OK(snum))
5316 ServicePtrs[(snum)]->store_dos_attributes = val;
5319 void lp_set_mangling_method(const char *new_method)
5321 string_set(&Globals.mangling_method, new_method);
5324 /*******************************************************************
5325 Global state for POSIX pathname processing.
5326 ********************************************************************/
5328 static bool posix_pathnames;
5330 bool lp_posix_pathnames(void)
5332 return posix_pathnames;
5335 /*******************************************************************
5336 Change everything needed to ensure POSIX pathname processing (currently
5338 ********************************************************************/
5340 void lp_set_posix_pathnames(void)
5342 posix_pathnames = true;
5345 /*******************************************************************
5346 Global state for POSIX lock processing - CIFS unix extensions.
5347 ********************************************************************/
5349 bool posix_default_lock_was_set;
5350 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5352 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5354 if (posix_default_lock_was_set) {
5355 return posix_cifsx_locktype;
5357 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5361 /*******************************************************************
5362 ********************************************************************/
5364 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5366 posix_default_lock_was_set = true;
5367 posix_cifsx_locktype = val;
5370 int lp_min_receive_file_size(void)
5372 if (Globals.iminreceivefile < 0) {
5375 return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5378 /*******************************************************************
5379 Safe wide links checks.
5380 This helper function always verify the validity of wide links,
5381 even after a configuration file reload.
5382 ********************************************************************/
5384 static bool lp_widelinks_internal(int snum)
5386 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5387 sDefault.bWidelinks);
5390 void widelinks_warning(int snum)
5392 if (lp_allow_insecure_widelinks()) {
5396 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5397 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5398 "These parameters are incompatible. "
5399 "Wide links will be disabled for this share.\n",
5400 lp_servicename(talloc_tos(), snum) ));
5404 bool lp_widelinks(int snum)
5406 /* wide links is always incompatible with unix extensions */
5407 if (lp_unix_extensions()) {
5409 * Unless we have "allow insecure widelinks"
5412 if (!lp_allow_insecure_widelinks()) {
5417 return lp_widelinks_internal(snum);
5420 bool lp_writeraw(void)
5422 if (lp_async_smb_echo_handler()) {
5425 return lp__writeraw();
5428 bool lp_readraw(void)
5430 if (lp_async_smb_echo_handler()) {
5433 return lp__readraw();
5436 int lp_server_role(void)
5438 return lp_find_server_role(lp__server_role(),
5440 lp__domain_logons(),
5441 lp_domain_master_true_or_auto());
5444 int lp_security(void)
5446 return lp_find_security(lp__server_role(),