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"
61 #include "lib/smbconf/smbconf.h"
62 #include "lib/smbconf/smbconf_init.h"
65 #include "../librpc/gen_ndr/svcctl.h"
67 #include "../libcli/smb/smb_signing.h"
68 #include "dbwrap/dbwrap.h"
69 #include "dbwrap/dbwrap_rbt.h"
70 #include "../lib/util/bitmap.h"
71 #include "../source4/dns_server/dns_update.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; \
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 int winbindMaxDomainConnections; \
129 int ismb2_max_credits; \
131 char *tls_certfile; \
135 char *panic_action; \
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 .szInvalidUsers = NULL,
153 .szValidUsers = NULL,
154 .szAdminUsers = NULL,
159 .szRootPreExec = NULL,
160 .szRootPostExec = NULL,
161 .szCupsOptions = NULL,
162 .szPrintcommand = NULL,
163 .szLpqcommand = NULL,
164 .szLprmcommand = NULL,
165 .szLppausecommand = NULL,
166 .szLpresumecommand = NULL,
167 .szQueuepausecommand = NULL,
168 .szQueueresumecommand = NULL,
169 .szPrintername = NULL,
170 .szPrintjobUsername = NULL,
171 .szDontdescend = NULL,
172 .szHostsallow = NULL,
174 .szMagicScript = NULL,
175 .szMagicOutput = NULL,
178 .szVetoOplockFiles = NULL,
186 .szVfsObjects = NULL,
187 .szMSDfsProxy = NULL,
188 .szAioWriteBehind = NULL,
191 .iMaxPrintJobs = 1000,
192 .iMaxReportedPrintJobs = 0,
193 .iWriteCacheSize = 0,
194 .iCreate_mask = 0744,
195 .iCreate_force_mode = 0,
196 .iSecurity_mask = 0777,
197 .iSecurity_force_mode = 0,
199 .iDir_force_mode = 0,
200 .iDir_Security_mask = 0777,
201 .iDir_Security_force_mode = 0,
202 .iMaxConnections = 0,
203 .iDefaultCase = CASE_LOWER,
204 .iPrinting = DEFAULT_PRINTING,
205 .iOplockContentionLimit = 2,
208 .iDfreeCacheTime = 0,
209 .bPreexecClose = false,
210 .bRootpreexecClose = false,
211 .iCaseSensitive = Auto,
212 .bCasePreserve = true,
213 .bShortCasePreserve = true,
214 .bHideDotFiles = true,
215 .bHideSpecialFiles = false,
216 .bHideUnReadable = false,
217 .bHideUnWriteableFiles = false,
219 .bAccessBasedShareEnum = false,
223 .bGuest_only = false,
224 .bAdministrative_share = false,
227 .bPrintNotifyBackchannel = true,
228 .bMap_system = false,
229 .bMap_hidden = false,
230 .bMap_archive = true,
231 .bStoreDosAttributes = false,
232 .bDmapiSupport = false,
234 .iStrictLocking = Auto,
235 .bPosixLocking = true,
238 .bKernelOplocks = false,
239 .bLevel2OpLocks = true,
241 .bMangledNames = true,
244 .bSyncAlways = false,
245 .bStrictAllocate = false,
246 .bStrictSync = false,
249 .bDeleteReadonly = false,
250 .bFakeOplocks = false,
251 .bDeleteVetoFiles = false,
252 .bDosFilemode = false,
253 .bDosFiletimes = true,
254 .bDosFiletimeResolution = false,
255 .bFakeDirCreateTimes = false,
256 .bBlockingLocks = true,
257 .bInheritPerms = false,
258 .bInheritACLS = false,
259 .bInheritOwner = false,
261 .bUseClientDriver = false,
262 .bDefaultDevmode = true,
263 .bForcePrintername = false,
264 .bNTAclSupport = true,
265 .bForceUnknownAclUser = false,
266 .bUseSendfile = false,
267 .bProfileAcls = false,
268 .bMap_acl_inherit = false,
271 .bAclCheckPermissions = true,
272 .bAclMapFullControl = true,
273 .bAclGroupControl = false,
274 .bChangeNotify = true,
275 .bKernelChangeNotify = true,
276 .iallocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
279 .iMap_readonly = MAP_READONLY_YES,
280 #ifdef BROKEN_DIRECTORY_HANDLING
281 .iDirectoryNameCacheSize = 0,
283 .iDirectoryNameCacheSize = 100,
285 .ismb_encrypt = Auto,
290 /* local variables */
291 static struct loadparm_service **ServicePtrs = NULL;
292 static int iNumServices = 0;
293 static int iServiceIndex = 0;
294 static struct db_context *ServiceHash;
295 static int *invalid_services = NULL;
296 static int num_invalid_services = 0;
297 static bool bInGlobalSection = true;
298 static bool bGlobalOnly = false;
300 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
302 /* prototypes for the special type handlers */
303 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
304 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
305 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
306 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
307 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
308 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
309 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
310 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
311 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
312 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
313 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
314 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
316 /* these are parameter handlers which are not needed in the
320 #define handle_logfile NULL
322 static void set_allowed_client_auth(void);
324 static void add_to_file_list(const char *fname, const char *subfname);
325 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
326 static void free_param_opts(struct parmlist_entry **popts);
328 #include "lib/param/param_table.c"
330 /***************************************************************************
331 Initialise the sDefault parameter structure for the printer values.
332 ***************************************************************************/
334 static void init_printer_values(struct loadparm_service *pService)
336 /* choose defaults depending on the type of printing */
337 switch (pService->iPrinting) {
342 string_set(&pService->szLpqcommand, "lpq -P'%p'");
343 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
344 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
349 string_set(&pService->szLpqcommand, "lpq -P'%p'");
350 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
351 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
352 string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
353 string_set(&pService->szQueueresumecommand, "lpc start '%p'");
354 string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
355 string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
361 /* set the lpq command to contain the destination printer
362 name only. This is used by cups_queue_get() */
363 string_set(&pService->szLpqcommand, "%p");
364 string_set(&pService->szLprmcommand, "");
365 string_set(&pService->szPrintcommand, "");
366 string_set(&pService->szLppausecommand, "");
367 string_set(&pService->szLpresumecommand, "");
368 string_set(&pService->szQueuepausecommand, "");
369 string_set(&pService->szQueueresumecommand, "");
371 string_set(&pService->szLpqcommand, "lpq -P'%p'");
372 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
373 string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
374 string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
375 string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
376 string_set(&pService->szQueuepausecommand, "disable '%p'");
377 string_set(&pService->szQueueresumecommand, "enable '%p'");
378 #endif /* HAVE_CUPS */
383 string_set(&pService->szLpqcommand, "lpstat -o%p");
384 string_set(&pService->szLprmcommand, "cancel %p-%j");
385 string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
386 string_set(&pService->szQueuepausecommand, "disable %p");
387 string_set(&pService->szQueueresumecommand, "enable %p");
389 string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
390 string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
395 string_set(&pService->szLpqcommand, "lpq -P%p");
396 string_set(&pService->szLprmcommand, "lprm -P%p %j");
397 string_set(&pService->szPrintcommand, "lp -r -P%p %s");
400 #if defined(DEVELOPER) || defined(ENABLE_BUILD_FARM_HACKS)
405 TALLOC_CTX *tmp_ctx = talloc_stackframe();
408 tdbfile = talloc_asprintf(
409 tmp_ctx, "tdbfile=%s",
410 lp_parm_const_string(-1, "vlp", "tdbfile",
412 if (tdbfile == NULL) {
413 tdbfile="tdbfile=/tmp/vlp.tdb";
416 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
418 string_set(&pService->szPrintcommand,
419 tmp ? tmp : "vlp print %p %s");
421 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
423 string_set(&pService->szLpqcommand,
424 tmp ? tmp : "vlp lpq %p");
426 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
428 string_set(&pService->szLprmcommand,
429 tmp ? tmp : "vlp lprm %p %j");
431 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
433 string_set(&pService->szLppausecommand,
434 tmp ? tmp : "vlp lppause %p %j");
436 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
438 string_set(&pService->szLpresumecommand,
439 tmp ? tmp : "vlp lpresume %p %j");
441 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
443 string_set(&pService->szQueuepausecommand,
444 tmp ? tmp : "vlp queuepause %p");
446 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
448 string_set(&pService->szQueueresumecommand,
449 tmp ? tmp : "vlp queueresume %p");
450 TALLOC_FREE(tmp_ctx);
454 #endif /* DEVELOPER */
459 * Function to return the default value for the maximum number of open
460 * file descriptors permitted. This function tries to consult the
461 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
462 * the smaller of those.
464 static int max_open_files(void)
466 int sysctl_max = MAX_OPEN_FILES;
467 int rlimit_max = MAX_OPEN_FILES;
469 #ifdef HAVE_SYSCTLBYNAME
471 size_t size = sizeof(sysctl_max);
472 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
477 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
483 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
484 rlimit_max = rl.rlim_cur;
486 #if defined(RLIM_INFINITY)
487 if(rl.rlim_cur == RLIM_INFINITY)
488 rlimit_max = MAX_OPEN_FILES;
493 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
494 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
495 "minimum Windows limit (%d)\n",
497 MIN_OPEN_FILES_WINDOWS));
498 sysctl_max = MIN_OPEN_FILES_WINDOWS;
501 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
502 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
503 "minimum Windows limit (%d)\n",
505 MIN_OPEN_FILES_WINDOWS));
506 rlimit_max = MIN_OPEN_FILES_WINDOWS;
509 return MIN(sysctl_max, rlimit_max);
513 * Common part of freeing allocated data for one parameter.
515 static void free_one_parameter_common(void *parm_ptr,
516 struct parm_struct parm)
518 if ((parm.type == P_STRING) ||
519 (parm.type == P_USTRING))
521 string_free((char**)parm_ptr);
522 } else if (parm.type == P_LIST) {
523 TALLOC_FREE(*((char***)parm_ptr));
528 * Free the allocated data for one parameter for a share
529 * given as a service struct.
531 static void free_one_parameter(struct loadparm_service *service,
532 struct parm_struct parm)
536 if (parm.p_class != P_LOCAL) {
540 parm_ptr = lp_parm_ptr(service, &parm);
542 free_one_parameter_common(parm_ptr, parm);
546 * Free the allocated parameter data of a share given
547 * as a service struct.
549 static void free_parameters(struct loadparm_service *service)
553 for (i=0; parm_table[i].label; i++) {
554 free_one_parameter(service, parm_table[i]);
559 * Free the allocated data for one parameter for a given share
560 * specified by an snum.
562 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
567 parm_ptr = lp_parm_ptr(NULL, &parm);
568 } else if (parm.p_class != P_LOCAL) {
571 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
574 free_one_parameter_common(parm_ptr, parm);
578 * Free the allocated parameter data for a share specified
581 static void free_parameters_by_snum(int snum)
585 for (i=0; parm_table[i].label; i++) {
586 free_one_parameter_by_snum(snum, parm_table[i]);
591 * Free the allocated global parameters.
593 static void free_global_parameters(void)
595 free_param_opts(&Globals.param_opt);
596 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
599 static int map_parameter(const char *pszParmName);
601 struct lp_stored_option {
602 struct lp_stored_option *prev, *next;
607 static struct lp_stored_option *stored_options;
610 save options set by lp_set_cmdline() into a list. This list is
611 re-applied when we do a globals reset, so that cmdline set options
612 are sticky across reloads of smb.conf
614 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
616 struct lp_stored_option *entry, *entry_next;
617 for (entry = stored_options; entry != NULL; entry = entry_next) {
618 entry_next = entry->next;
619 if (strcmp(pszParmName, entry->label) == 0) {
620 DLIST_REMOVE(stored_options, entry);
626 entry = talloc(NULL, struct lp_stored_option);
631 entry->label = talloc_strdup(entry, pszParmName);
637 entry->value = talloc_strdup(entry, pszParmValue);
643 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
648 static bool apply_lp_set_cmdline(void)
650 struct lp_stored_option *entry = NULL;
651 for (entry = stored_options; entry != NULL; entry = entry->next) {
652 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
653 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
654 entry->label, entry->value));
661 /***************************************************************************
662 Initialise the global parameter structure.
663 ***************************************************************************/
665 static void init_globals(bool reinit_globals)
667 static bool done_init = false;
671 /* If requested to initialize only once and we've already done it... */
672 if (!reinit_globals && done_init) {
673 /* ... then we have nothing more to do */
678 /* The logfile can be set before this is invoked. Free it if so. */
679 if (Globals.logfile != NULL) {
680 string_free(&Globals.logfile);
681 Globals.logfile = NULL;
685 free_global_parameters();
688 /* This memset and the free_global_parameters() above will
689 * wipe out smb.conf options set with lp_set_cmdline(). The
690 * apply_lp_set_cmdline() call puts these values back in the
691 * table once the defaults are set */
692 ZERO_STRUCT(Globals);
694 for (i = 0; parm_table[i].label; i++) {
695 if ((parm_table[i].type == P_STRING ||
696 parm_table[i].type == P_USTRING))
698 string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
703 string_set(&sDefault.fstype, FSTYPE_STRING);
704 string_set(&sDefault.szPrintjobUsername, "%U");
706 init_printer_values(&sDefault);
709 DEBUG(3, ("Initialising global parameters\n"));
711 /* Must manually force to upper case here, as this does not go via the handler */
712 string_set(&Globals.szNetbiosName, myhostname_upper());
714 string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
715 string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
717 /* use the new 'hash2' method by default, with a prefix of 1 */
718 string_set(&Globals.szManglingMethod, "hash2");
719 Globals.mangle_prefix = 1;
721 string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
723 /* using UTF8 by default allows us to support all chars */
724 string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
726 /* Use codepage 850 as a default for the dos character set */
727 string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
730 * Allow the default PASSWD_CHAT to be overridden in local.h.
732 string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
734 string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
736 string_set(&Globals.szPasswdProgram, "");
737 string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
738 string_set(&Globals.szStateDir, get_dyn_STATEDIR());
739 string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
740 string_set(&Globals.szPidDir, get_dyn_PIDDIR());
741 string_set(&Globals.szSocketAddress, "0.0.0.0");
743 * By default support explicit binding to broadcast
746 Globals.bNmbdBindExplicitBroadcast = true;
748 if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
749 smb_panic("init_globals: ENOMEM");
751 string_set(&Globals.szServerString, s);
754 string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
757 string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
759 string_set(&Globals.szLogonDrive, "");
760 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
761 string_set(&Globals.szLogonHome, "\\\\%N\\%U");
762 string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
764 Globals.szNameResolveOrder = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
765 string_set(&Globals.szPasswordServer, "*");
767 Globals.AlgorithmicRidBase = BASE_RID;
769 Globals.bLoadPrinters = true;
770 Globals.PrintcapCacheTime = 750; /* 12.5 minutes */
772 Globals.ConfigBackend = config_backend;
773 Globals.server_role = ROLE_AUTO;
775 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
776 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
777 Globals.max_xmit = 0x4104;
778 Globals.max_mux = 50; /* This is *needed* for profile support. */
779 Globals.lpqcachetime = 30; /* changed to handle large print servers better -- jerry */
780 Globals.bDisableSpoolss = false;
781 Globals.iMaxSmbdProcesses = 0;/* no limit specified */
782 Globals.pwordlevel = 0;
783 Globals.unamelevel = 0;
784 Globals.deadtime = 0;
785 Globals.getwd_cache = true;
786 Globals.bLargeReadwrite = true;
787 Globals.max_log_size = 5000;
788 Globals.max_open_files = max_open_files();
789 Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
790 Globals.srv_maxprotocol = PROTOCOL_SMB2_10;
791 Globals.srv_minprotocol = PROTOCOL_LANMAN1;
792 Globals.security = SEC_USER;
793 Globals.paranoid_server_security = true;
794 Globals.bEncryptPasswords = true;
795 Globals.clientSchannel = Auto;
796 Globals.serverSchannel = Auto;
797 Globals.bReadRaw = true;
798 Globals.bWriteRaw = true;
799 Globals.bNullPasswords = false;
800 Globals.bObeyPamRestrictions = false;
802 Globals.bSyslogOnly = false;
803 Globals.bTimestampLogs = true;
804 string_set(&Globals.loglevel, "0");
805 Globals.bDebugPrefixTimestamp = false;
806 Globals.bDebugHiresTimestamp = true;
807 Globals.bDebugPid = false;
808 Globals.bDebugUid = false;
809 Globals.bDebugClass = false;
810 Globals.bEnableCoreFiles = true;
811 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
812 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
813 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
814 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
815 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
816 Globals.lm_interval = 60;
817 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
818 Globals.bNISHomeMap = false;
819 #ifdef WITH_NISPLUS_HOME
820 string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
822 string_set(&Globals.szNISHomeMapName, "auto.home");
825 Globals.bTimeServer = false;
826 Globals.bBindInterfacesOnly = false;
827 Globals.bUnixPasswdSync = false;
828 Globals.bPamPasswordChange = false;
829 Globals.bPasswdChatDebug = false;
830 Globals.iPasswdChatTimeout = 2; /* 2 second default. */
831 Globals.bNTPipeSupport = true; /* Do NT pipes by default. */
832 Globals.bNTStatusSupport = true; /* Use NT status by default. */
833 Globals.bStatCache = true; /* use stat cache by default */
834 Globals.iMaxStatCacheSize = 256; /* 256k by default */
835 Globals.restrict_anonymous = 0;
836 Globals.bClientLanManAuth = false; /* Do NOT use the LanMan hash if it is available */
837 Globals.bClientPlaintextAuth = false; /* Do NOT use a plaintext password even if is requested by the server */
838 Globals.bLanmanAuth = false; /* Do NOT use the LanMan hash, even if it is supplied */
839 Globals.bNTLMAuth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
840 Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
841 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
843 Globals.map_to_guest = 0; /* By Default, "Never" */
844 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
845 Globals.enhanced_browsing = true;
846 Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
847 #ifdef MMAP_BLACKLIST
848 Globals.bUseMmap = false;
850 Globals.bUseMmap = true;
852 Globals.bUnicode = true;
853 Globals.bUnixExtensions = true;
854 Globals.bResetOnZeroVC = false;
855 Globals.bLogWriteableFilesOnExit = false;
856 Globals.bCreateKrb5Conf = true;
857 Globals.winbindMaxDomainConnections = 1;
859 /* hostname lookups can be very expensive and are broken on
860 a large number of sites (tridge) */
861 Globals.bHostnameLookups = false;
863 string_set(&Globals.passdb_backend, "tdbsam");
864 string_set(&Globals.szLdapSuffix, "");
865 string_set(&Globals.szLdapMachineSuffix, "");
866 string_set(&Globals.szLdapUserSuffix, "");
867 string_set(&Globals.szLdapGroupSuffix, "");
868 string_set(&Globals.szLdapIdmapSuffix, "");
870 string_set(&Globals.szLdapAdminDn, "");
871 Globals.ldap_ssl = LDAP_SSL_START_TLS;
872 Globals.ldap_ssl_ads = false;
873 Globals.ldap_deref = -1;
874 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
875 Globals.ldap_delete_dn = false;
876 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
877 Globals.ldap_follow_referral = Auto;
878 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
879 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
880 Globals.ldap_page_size = LDAP_PAGE_SIZE;
882 Globals.ldap_debug_level = 0;
883 Globals.ldap_debug_threshold = 10;
885 /* This is what we tell the afs client. in reality we set the token
886 * to never expire, though, when this runs out the afs client will
887 * forget the token. Set to 0 to get NEVERDATE.*/
888 Globals.iAfsTokenLifetime = 604800;
889 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
891 /* these parameters are set to defaults that are more appropriate
892 for the increasing samba install base:
894 as a member of the workgroup, that will possibly become a
895 _local_ master browser (lm = true). this is opposed to a forced
896 local master browser startup (pm = true).
898 doesn't provide WINS server service by default (wsupp = false),
899 and doesn't provide domain master browser services by default, either.
903 Globals.bMsAddPrinterWizard = true;
904 Globals.os_level = 20;
905 Globals.bLocalMaster = true;
906 Globals.domain_master = Auto; /* depending on bDomainLogons */
907 Globals.bDomainLogons = false;
908 Globals.bBrowseList = true;
909 Globals.bWINSsupport = false;
910 Globals.bWINSproxy = false;
912 TALLOC_FREE(Globals.szInitLogonDelayedHosts);
913 Globals.InitLogonDelay = 100; /* 100 ms default delay */
915 Globals.bWINSdnsProxy = true;
917 Globals.bAllowTrustedDomains = true;
918 string_set(&Globals.szIdmapBackend, "tdb");
920 string_set(&Globals.szTemplateShell, "/bin/false");
921 string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
922 string_set(&Globals.szWinbindSeparator, "\\");
924 string_set(&Globals.szCupsServer, "");
925 string_set(&Globals.szIPrintServer, "");
927 #ifdef CLUSTER_SUPPORT
928 string_set(&Globals.ctdbdSocket, CTDB_PATH);
930 string_set(&Globals.ctdbdSocket, "");
933 Globals.szClusterAddresses = NULL;
934 Globals.clustering = false;
935 Globals.ctdb_timeout = 0;
936 Globals.ctdb_locktime_warn_threshold = 0;
938 Globals.winbind_cache_time = 300; /* 5 minutes */
939 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
940 Globals.winbind_max_clients = 200;
941 Globals.bWinbindEnumUsers = false;
942 Globals.bWinbindEnumGroups = false;
943 Globals.bWinbindUseDefaultDomain = false;
944 Globals.bWinbindTrustedDomainsOnly = false;
945 Globals.bWinbindNestedGroups = true;
946 Globals.winbind_expand_groups = 1;
947 Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
948 Globals.bWinbindRefreshTickets = false;
949 Globals.bWinbindOfflineLogon = false;
951 Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
952 Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
954 Globals.bPassdbExpandExplicit = false;
956 Globals.name_cache_timeout = 660; /* In seconds */
958 Globals.bUseSpnego = true;
959 Globals.bClientUseSpnego = true;
961 Globals.client_signing = SMB_SIGNING_DEFAULT;
962 Globals.server_signing = SMB_SIGNING_DEFAULT;
964 Globals.bDeferSharingViolations = true;
965 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
967 Globals.bEnablePrivileges = true;
968 Globals.bHostMSDfs = true;
969 Globals.bASUSupport = false;
971 /* User defined shares. */
972 if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
973 smb_panic("init_globals: ENOMEM");
975 string_set(&Globals.szUsersharePath, s);
977 string_set(&Globals.szUsershareTemplateShare, "");
978 Globals.iUsershareMaxShares = 0;
979 /* By default disallow sharing of directories not owned by the sharer. */
980 Globals.bUsershareOwnerOnly = true;
981 /* By default disallow guest access to usershares. */
982 Globals.bUsershareAllowGuests = false;
984 Globals.iKeepalive = DEFAULT_KEEPALIVE;
986 /* By default no shares out of the registry */
987 Globals.bRegistryShares = false;
989 Globals.iminreceivefile = 0;
991 Globals.bMapUntrustedToDomain = false;
992 Globals.bMulticastDnsRegister = true;
994 Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
995 Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
996 Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
997 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
999 string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1001 /* Now put back the settings that were set with lp_set_cmdline() */
1002 apply_lp_set_cmdline();
1005 /*******************************************************************
1006 Convenience routine to grab string parameters into talloced memory
1007 and run standard_sub_basic on them. The buffers can be written to by
1008 callers without affecting the source string.
1009 ********************************************************************/
1011 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1015 /* The follow debug is useful for tracking down memory problems
1016 especially if you have an inner loop that is calling a lp_*()
1017 function that returns a string. Perhaps this debug should be
1018 present all the time? */
1021 DEBUG(10, ("lp_string(%s)\n", s));
1027 ret = talloc_sub_basic(ctx,
1028 get_current_username(),
1029 current_user_info.domain,
1031 if (trim_char(ret, '\"', '\"')) {
1032 if (strchr(ret,'\"') != NULL) {
1034 ret = talloc_sub_basic(ctx,
1035 get_current_username(),
1036 current_user_info.domain,
1044 In this section all the functions that are used to access the
1045 parameters from the rest of the program are defined
1048 #define FN_GLOBAL_STRING(fn_name,ptr) \
1049 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1050 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1051 const char *lp_ ## fn_name(void) {return(*(const char **)(&Globals.ptr) ? *(const char **)(&Globals.ptr) : "");}
1052 #define FN_GLOBAL_LIST(fn_name,ptr) \
1053 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1054 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1055 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1056 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1057 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1058 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1059 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1061 #define FN_LOCAL_STRING(fn_name,val) \
1062 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));}
1063 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1064 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1065 #define FN_LOCAL_LIST(fn_name,val) \
1066 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1067 #define FN_LOCAL_BOOL(fn_name,val) \
1068 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1069 #define FN_LOCAL_INTEGER(fn_name,val) \
1070 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1072 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1073 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1074 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1075 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1076 #define FN_LOCAL_CHAR(fn_name,val) \
1077 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1080 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1081 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1083 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1084 * build process or in smb.conf, we use that value. Otherwise they
1085 * default to the value of lp_lockdir(). */
1086 const char *lp_statedir(void) {
1087 if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1088 (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1089 return(*(char **)(&Globals.szStateDir) ?
1090 *(char **)(&Globals.szStateDir) : "");
1092 return(*(char **)(&Globals.szLockDir) ?
1093 *(char **)(&Globals.szLockDir) : "");
1095 const char *lp_cachedir(void) {
1096 if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1097 (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1098 return(*(char **)(&Globals.szCacheDir) ?
1099 *(char **)(&Globals.szCacheDir) : "");
1101 return(*(char **)(&Globals.szLockDir) ?
1102 *(char **)(&Globals.szLockDir) : "");
1104 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1105 winbindMaxDomainConnections)
1107 int lp_winbind_max_domain_connections(void)
1109 if (lp_winbind_offline_logon() &&
1110 lp_winbind_max_domain_connections_int() > 1) {
1111 DEBUG(1, ("offline logons active, restricting max domain "
1112 "connections to 1\n"));
1115 return MAX(1, lp_winbind_max_domain_connections_int());
1118 int lp_smb2_max_credits(void)
1120 if (Globals.ismb2_max_credits == 0) {
1121 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1123 return Globals.ismb2_max_credits;
1125 int lp_cups_encrypt(void)
1128 #ifdef HAVE_HTTPCONNECTENCRYPT
1129 switch (Globals.CupsEncrypt) {
1131 result = HTTP_ENCRYPT_REQUIRED;
1134 result = HTTP_ENCRYPT_ALWAYS;
1137 result = HTTP_ENCRYPT_NEVER;
1144 /* These functions remain in source3/param for now */
1146 FN_GLOBAL_STRING(configfile, szConfigFile)
1148 #include "lib/param/param_functions.c"
1150 FN_LOCAL_STRING(servicename, szService)
1151 FN_LOCAL_CONST_STRING(const_servicename, szService)
1153 /* local prototypes */
1155 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1156 static const char *get_boolean(bool bool_value);
1157 static int getservicebyname(const char *pszServiceName,
1158 struct loadparm_service *pserviceDest);
1159 static void copy_service(struct loadparm_service *pserviceDest,
1160 struct loadparm_service *pserviceSource,
1161 struct bitmap *pcopymapDest);
1162 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1164 static bool do_section(const char *pszSectionName, void *userdata);
1165 static void init_copymap(struct loadparm_service *pservice);
1166 static bool hash_a_service(const char *name, int number);
1167 static void free_service_byindex(int iService);
1168 static void show_parameter(int parmIndex);
1169 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1172 * This is a helper function for parametrical options support. It returns a
1173 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1174 * parametrical functions are quite simple
1176 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1179 bool global_section = false;
1181 struct parmlist_entry *data;
1183 if (service == NULL) {
1184 data = Globals.param_opt;
1185 global_section = true;
1187 data = service->param_opt;
1190 if (asprintf(¶m_key, "%s:%s", type, option) == -1) {
1191 DEBUG(0,("asprintf failed!\n"));
1196 if (strwicmp(data->key, param_key) == 0) {
1197 string_free(¶m_key);
1203 if (!global_section) {
1204 /* Try to fetch the same option but from globals */
1205 /* but only if we are not already working with Globals */
1206 data = Globals.param_opt;
1208 if (strwicmp(data->key, param_key) == 0) {
1209 string_free(¶m_key);
1216 string_free(¶m_key);
1222 * This is a helper function for parametrical options support. It returns a
1223 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1224 * parametrical functions are quite simple
1226 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1229 if (snum >= iNumServices) return NULL;
1232 return get_parametrics_by_service(NULL, type, option);
1234 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1239 #define MISSING_PARAMETER(name) \
1240 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1242 /*******************************************************************
1243 convenience routine to return int parameters.
1244 ********************************************************************/
1245 static int lp_int(const char *s)
1249 MISSING_PARAMETER(lp_int);
1253 return (int)strtol(s, NULL, 0);
1256 /*******************************************************************
1257 convenience routine to return unsigned long parameters.
1258 ********************************************************************/
1259 static unsigned long lp_ulong(const char *s)
1263 MISSING_PARAMETER(lp_ulong);
1267 return strtoul(s, NULL, 0);
1270 /*******************************************************************
1271 convenience routine to return boolean parameters.
1272 ********************************************************************/
1273 static bool lp_bool(const char *s)
1278 MISSING_PARAMETER(lp_bool);
1282 if (!set_boolean(s, &ret)) {
1283 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1290 /*******************************************************************
1291 convenience routine to return enum parameters.
1292 ********************************************************************/
1293 static int lp_enum(const char *s,const struct enum_list *_enum)
1297 if (!s || !*s || !_enum) {
1298 MISSING_PARAMETER(lp_enum);
1302 for (i=0; _enum[i].name; i++) {
1303 if (strequal(_enum[i].name,s))
1304 return _enum[i].value;
1307 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1311 #undef MISSING_PARAMETER
1313 /* Return parametric option from a given service. Type is a part of option before ':' */
1314 /* Parametric option has following syntax: 'Type: option = value' */
1315 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1317 struct parmlist_entry *data = get_parametrics(snum, type, option);
1319 if (data == NULL||data->value==NULL) {
1321 return lp_string(ctx, def);
1327 return lp_string(ctx, data->value);
1330 /* Return parametric option from a given service. Type is a part of option before ':' */
1331 /* Parametric option has following syntax: 'Type: option = value' */
1332 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1334 struct parmlist_entry *data = get_parametrics(snum, type, option);
1336 if (data == NULL||data->value==NULL)
1342 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1344 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1346 if (data == NULL||data->value==NULL)
1353 /* Return parametric option from a given service. Type is a part of option before ':' */
1354 /* Parametric option has following syntax: 'Type: option = value' */
1356 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1358 struct parmlist_entry *data = get_parametrics(snum, type, option);
1360 if (data == NULL||data->value==NULL)
1361 return (const char **)def;
1363 if (data->list==NULL) {
1364 data->list = str_list_make_v3(NULL, data->value, NULL);
1367 return (const char **)data->list;
1370 /* Return parametric option from a given service. Type is a part of option before ':' */
1371 /* Parametric option has following syntax: 'Type: option = value' */
1373 int lp_parm_int(int snum, const char *type, const char *option, int def)
1375 struct parmlist_entry *data = get_parametrics(snum, type, option);
1377 if (data && data->value && *data->value)
1378 return lp_int(data->value);
1383 /* Return parametric option from a given service. Type is a part of option before ':' */
1384 /* Parametric option has following syntax: 'Type: option = value' */
1386 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1388 struct parmlist_entry *data = get_parametrics(snum, type, option);
1390 if (data && data->value && *data->value)
1391 return lp_ulong(data->value);
1396 /* Return parametric option from a given service. Type is a part of option before ':' */
1397 /* Parametric option has following syntax: 'Type: option = value' */
1399 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1401 struct parmlist_entry *data = get_parametrics(snum, type, option);
1403 if (data && data->value && *data->value)
1404 return lp_bool(data->value);
1409 /* Return parametric option from a given service. Type is a part of option before ':' */
1410 /* Parametric option has following syntax: 'Type: option = value' */
1412 int lp_parm_enum(int snum, const char *type, const char *option,
1413 const struct enum_list *_enum, int def)
1415 struct parmlist_entry *data = get_parametrics(snum, type, option);
1417 if (data && data->value && *data->value && _enum)
1418 return lp_enum(data->value, _enum);
1424 /***************************************************************************
1425 Initialise a service to the defaults.
1426 ***************************************************************************/
1428 static void init_service(struct loadparm_service *pservice)
1430 memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1431 copy_service(pservice, &sDefault, NULL);
1436 * free a param_opts structure.
1437 * param_opts handling should be moved to talloc;
1438 * then this whole functions reduces to a TALLOC_FREE().
1441 static void free_param_opts(struct parmlist_entry **popts)
1443 struct parmlist_entry *opt, *next_opt;
1445 if (popts == NULL) {
1449 if (*popts != NULL) {
1450 DEBUG(5, ("Freeing parametrics:\n"));
1453 while (opt != NULL) {
1454 string_free(&opt->key);
1455 string_free(&opt->value);
1456 TALLOC_FREE(opt->list);
1457 next_opt = opt->next;
1464 /***************************************************************************
1465 Free the dynamically allocated parts of a service struct.
1466 ***************************************************************************/
1468 static void free_service(struct loadparm_service *pservice)
1473 if (pservice->szService)
1474 DEBUG(5, ("free_service: Freeing service %s\n",
1475 pservice->szService));
1477 free_parameters(pservice);
1479 string_free(&pservice->szService);
1480 TALLOC_FREE(pservice->copymap);
1482 free_param_opts(&pservice->param_opt);
1484 ZERO_STRUCTP(pservice);
1488 /***************************************************************************
1489 remove a service indexed in the ServicePtrs array from the ServiceHash
1490 and free the dynamically allocated parts
1491 ***************************************************************************/
1493 static void free_service_byindex(int idx)
1495 if ( !LP_SNUM_OK(idx) )
1498 ServicePtrs[idx]->valid = false;
1499 invalid_services[num_invalid_services++] = idx;
1501 /* we have to cleanup the hash record */
1503 if (ServicePtrs[idx]->szService) {
1504 char *canon_name = canonicalize_servicename(
1506 ServicePtrs[idx]->szService );
1508 dbwrap_delete_bystring(ServiceHash, canon_name );
1509 TALLOC_FREE(canon_name);
1512 free_service(ServicePtrs[idx]);
1515 /***************************************************************************
1516 Add a new service to the services array initialising it with the given
1518 ***************************************************************************/
1520 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1523 struct loadparm_service tservice;
1524 int num_to_alloc = iNumServices + 1;
1526 tservice = *pservice;
1528 /* it might already exist */
1530 i = getservicebyname(name, NULL);
1536 /* find an invalid one */
1538 if (num_invalid_services > 0) {
1539 i = invalid_services[--num_invalid_services];
1542 /* if not, then create one */
1543 if (i == iNumServices) {
1544 struct loadparm_service **tsp;
1547 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1549 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1553 ServicePtrs[iNumServices] = SMB_MALLOC_P(struct loadparm_service);
1554 if (!ServicePtrs[iNumServices]) {
1555 DEBUG(0,("add_a_service: out of memory!\n"));
1560 /* enlarge invalid_services here for now... */
1561 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
1563 if (tinvalid == NULL) {
1564 DEBUG(0,("add_a_service: failed to enlarge "
1565 "invalid_services!\n"));
1568 invalid_services = tinvalid;
1570 free_service_byindex(i);
1573 ServicePtrs[i]->valid = true;
1575 init_service(ServicePtrs[i]);
1576 copy_service(ServicePtrs[i], &tservice, NULL);
1578 string_set(&ServicePtrs[i]->szService, name);
1580 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1581 i, ServicePtrs[i]->szService));
1583 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1590 /***************************************************************************
1591 Convert a string to uppercase and remove whitespaces.
1592 ***************************************************************************/
1594 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1599 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1603 result = talloc_strdup(ctx, src);
1604 SMB_ASSERT(result != NULL);
1610 /***************************************************************************
1611 Add a name/index pair for the services array to the hash table.
1612 ***************************************************************************/
1614 static bool hash_a_service(const char *name, int idx)
1618 if ( !ServiceHash ) {
1619 DEBUG(10,("hash_a_service: creating servicehash\n"));
1620 ServiceHash = db_open_rbt(NULL);
1621 if ( !ServiceHash ) {
1622 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1627 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1630 canon_name = canonicalize_servicename(talloc_tos(), name );
1632 dbwrap_store_bystring(ServiceHash, canon_name,
1633 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1636 TALLOC_FREE(canon_name);
1641 /***************************************************************************
1642 Add a new home service, with the specified home directory, defaults coming
1644 ***************************************************************************/
1646 bool lp_add_home(const char *pszHomename, int iDefaultService,
1647 const char *user, const char *pszHomedir)
1651 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1652 pszHomedir[0] == '\0') {
1656 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1661 if (!(*(ServicePtrs[iDefaultService]->szPath))
1662 || strequal(ServicePtrs[iDefaultService]->szPath,
1663 lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1664 string_set(&ServicePtrs[i]->szPath, pszHomedir);
1667 if (!(*(ServicePtrs[i]->comment))) {
1668 char *comment = NULL;
1669 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1672 string_set(&ServicePtrs[i]->comment, comment);
1676 /* set the browseable flag from the global default */
1678 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1679 ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
1681 ServicePtrs[i]->autoloaded = true;
1683 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1684 user, ServicePtrs[i]->szPath ));
1689 /***************************************************************************
1690 Add a new service, based on an old one.
1691 ***************************************************************************/
1693 int lp_add_service(const char *pszService, int iDefaultService)
1695 if (iDefaultService < 0) {
1696 return add_a_service(&sDefault, pszService);
1699 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1702 /***************************************************************************
1703 Add the IPC service.
1704 ***************************************************************************/
1706 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1708 char *comment = NULL;
1709 int i = add_a_service(&sDefault, ipc_name);
1714 if (asprintf(&comment, "IPC Service (%s)",
1715 Globals.szServerString) < 0) {
1719 string_set(&ServicePtrs[i]->szPath, tmpdir());
1720 string_set(&ServicePtrs[i]->szUsername, "");
1721 string_set(&ServicePtrs[i]->comment, comment);
1722 string_set(&ServicePtrs[i]->fstype, "IPC");
1723 ServicePtrs[i]->iMaxConnections = 0;
1724 ServicePtrs[i]->bAvailable = true;
1725 ServicePtrs[i]->bRead_only = true;
1726 ServicePtrs[i]->bGuest_only = false;
1727 ServicePtrs[i]->bAdministrative_share = true;
1728 ServicePtrs[i]->bGuest_ok = guest_ok;
1729 ServicePtrs[i]->bPrint_ok = false;
1730 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1732 DEBUG(3, ("adding IPC service\n"));
1738 /***************************************************************************
1739 Add a new printer service, with defaults coming from service iFrom.
1740 ***************************************************************************/
1742 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1744 const char *comment = "From Printcap";
1745 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1750 /* note that we do NOT default the availability flag to true - */
1751 /* we take it from the default service passed. This allows all */
1752 /* dynamic printers to be disabled by disabling the [printers] */
1753 /* entry (if/when the 'available' keyword is implemented!). */
1755 /* the printer name is set to the service name. */
1756 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1757 string_set(&ServicePtrs[i]->comment, comment);
1759 /* set the browseable flag from the gloabl default */
1760 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1762 /* Printers cannot be read_only. */
1763 ServicePtrs[i]->bRead_only = false;
1764 /* No share modes on printer services. */
1765 ServicePtrs[i]->bShareModes = false;
1766 /* No oplocks on printer services. */
1767 ServicePtrs[i]->bOpLocks = false;
1768 /* Printer services must be printable. */
1769 ServicePtrs[i]->bPrint_ok = true;
1771 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1777 /***************************************************************************
1778 Check whether the given parameter name is valid.
1779 Parametric options (names containing a colon) are considered valid.
1780 ***************************************************************************/
1782 bool lp_parameter_is_valid(const char *pszParmName)
1784 return ((map_parameter(pszParmName) != -1) ||
1785 (strchr(pszParmName, ':') != NULL));
1788 /***************************************************************************
1789 Check whether the given name is the name of a global parameter.
1790 Returns true for strings belonging to parameters of class
1791 P_GLOBAL, false for all other strings, also for parametric options
1792 and strings not belonging to any option.
1793 ***************************************************************************/
1795 bool lp_parameter_is_global(const char *pszParmName)
1797 int num = map_parameter(pszParmName);
1800 return (parm_table[num].p_class == P_GLOBAL);
1806 /**************************************************************************
1807 Check whether the given name is the canonical name of a parameter.
1808 Returns false if it is not a valid parameter Name.
1809 For parametric options, true is returned.
1810 **************************************************************************/
1812 bool lp_parameter_is_canonical(const char *parm_name)
1814 if (!lp_parameter_is_valid(parm_name)) {
1818 return (map_parameter(parm_name) ==
1819 map_parameter_canonical(parm_name, NULL));
1822 /**************************************************************************
1823 Determine the canonical name for a parameter.
1824 Indicate when it is an inverse (boolean) synonym instead of a
1826 **************************************************************************/
1828 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1833 if (!lp_parameter_is_valid(parm_name)) {
1838 num = map_parameter_canonical(parm_name, inverse);
1840 /* parametric option */
1841 *canon_parm = parm_name;
1843 *canon_parm = parm_table[num].label;
1850 /**************************************************************************
1851 Determine the canonical name for a parameter.
1852 Turn the value given into the inverse boolean expression when
1853 the synonym is an invers boolean synonym.
1855 Return true if parm_name is a valid parameter name and
1856 in case it is an invers boolean synonym, if the val string could
1857 successfully be converted to the reverse bool.
1858 Return false in all other cases.
1859 **************************************************************************/
1861 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1863 const char **canon_parm,
1864 const char **canon_val)
1869 if (!lp_parameter_is_valid(parm_name)) {
1875 num = map_parameter_canonical(parm_name, &inverse);
1877 /* parametric option */
1878 *canon_parm = parm_name;
1881 *canon_parm = parm_table[num].label;
1883 if (!lp_invert_boolean(val, canon_val)) {
1895 /***************************************************************************
1896 Map a parameter's string representation to something we can use.
1897 Returns false if the parameter string is not recognised, else TRUE.
1898 ***************************************************************************/
1900 static int map_parameter(const char *pszParmName)
1904 if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
1907 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1908 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1911 /* Warn only if it isn't parametric option */
1912 if (strchr(pszParmName, ':') == NULL)
1913 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1914 /* We do return 'fail' for parametric options as well because they are
1915 stored in different storage
1920 /***************************************************************************
1921 Map a parameter's string representation to the index of the canonical
1922 form of the parameter (it might be a synonym).
1923 Returns -1 if the parameter string is not recognised.
1924 ***************************************************************************/
1926 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1928 int parm_num, canon_num;
1929 bool loc_inverse = false;
1931 parm_num = map_parameter(pszParmName);
1932 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1933 /* invalid, parametric or no canidate for synonyms ... */
1937 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1938 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1939 parm_num = canon_num;
1945 if (inverse != NULL) {
1946 *inverse = loc_inverse;
1951 /***************************************************************************
1952 return true if parameter number parm1 is a synonym of parameter
1953 number parm2 (parm2 being the principal name).
1954 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1956 ***************************************************************************/
1958 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
1960 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
1961 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
1962 (parm_table[parm1].flags & FLAG_HIDE) &&
1963 !(parm_table[parm2].flags & FLAG_HIDE))
1965 if (inverse != NULL) {
1966 if ((parm_table[parm1].type == P_BOOLREV) &&
1967 (parm_table[parm2].type == P_BOOL))
1979 /***************************************************************************
1980 Show one parameter's name, type, [values,] and flags.
1981 (helper functions for show_parameter_list)
1982 ***************************************************************************/
1984 static void show_parameter(int parmIndex)
1986 int enumIndex, flagIndex;
1991 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
1992 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
1994 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
1995 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
1997 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
1998 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
1999 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2001 printf("%s=%s", parm_table[parmIndex].label,
2002 type[parm_table[parmIndex].type]);
2003 if (parm_table[parmIndex].type == P_ENUM) {
2006 parm_table[parmIndex].enum_list[enumIndex].name;
2010 enumIndex ? "|" : "",
2011 parm_table[parmIndex].enum_list[enumIndex].name);
2016 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2017 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2020 flag_names[flagIndex]);
2025 /* output synonyms */
2027 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2028 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2029 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2030 parm_table[parmIndex2].label);
2031 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2033 printf(" (synonyms: ");
2038 printf("%s%s", parm_table[parmIndex2].label,
2039 inverse ? "[i]" : "");
2049 /***************************************************************************
2050 Show all parameter's name, type, [values,] and flags.
2051 ***************************************************************************/
2053 void show_parameter_list(void)
2055 int classIndex, parmIndex;
2056 const char *section_names[] = { "local", "global", NULL};
2058 for (classIndex=0; section_names[classIndex]; classIndex++) {
2059 printf("[%s]\n", section_names[classIndex]);
2060 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2061 if (parm_table[parmIndex].p_class == classIndex) {
2062 show_parameter(parmIndex);
2068 /***************************************************************************
2069 Check if a given string correctly represents a boolean value.
2070 ***************************************************************************/
2072 bool lp_string_is_valid_boolean(const char *parm_value)
2074 return set_boolean(parm_value, NULL);
2077 /***************************************************************************
2078 Get the standard string representation of a boolean value ("yes" or "no")
2079 ***************************************************************************/
2081 static const char *get_boolean(bool bool_value)
2083 static const char *yes_str = "yes";
2084 static const char *no_str = "no";
2086 return (bool_value ? yes_str : no_str);
2089 /***************************************************************************
2090 Provide the string of the negated boolean value associated to the boolean
2091 given as a string. Returns false if the passed string does not correctly
2092 represent a boolean.
2093 ***************************************************************************/
2095 bool lp_invert_boolean(const char *str, const char **inverse_str)
2099 if (!set_boolean(str, &val)) {
2103 *inverse_str = get_boolean(!val);
2107 /***************************************************************************
2108 Provide the canonical string representation of a boolean value given
2109 as a string. Return true on success, false if the string given does
2110 not correctly represent a boolean.
2111 ***************************************************************************/
2113 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2117 if (!set_boolean(str, &val)) {
2121 *canon_str = get_boolean(val);
2125 /***************************************************************************
2126 Find a service by name. Otherwise works like get_service.
2127 ***************************************************************************/
2129 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2136 if (ServiceHash == NULL) {
2140 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2142 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2145 if (NT_STATUS_IS_OK(status) &&
2146 (data.dptr != NULL) &&
2147 (data.dsize == sizeof(iService)))
2149 iService = *(int *)data.dptr;
2152 TALLOC_FREE(canon_name);
2154 if ((iService != -1) && (LP_SNUM_OK(iService))
2155 && (pserviceDest != NULL)) {
2156 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2162 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2163 struct loadparm_service *lp_service(const char *pszServiceName)
2165 int iService = getservicebyname(pszServiceName, NULL);
2166 if (iService == -1 || !LP_SNUM_OK(iService)) {
2169 return ServicePtrs[iService];
2172 struct loadparm_service *lp_servicebynum(int snum)
2174 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2177 return ServicePtrs[snum];
2180 struct loadparm_service *lp_default_loadparm_service()
2186 /***************************************************************************
2187 Copy a service structure to another.
2188 If pcopymapDest is NULL then copy all fields
2189 ***************************************************************************/
2192 * Add a parametric option to a parmlist_entry,
2193 * replacing old value, if already present.
2195 static void set_param_opt(struct parmlist_entry **opt_list,
2196 const char *opt_name,
2197 const char *opt_value,
2200 struct parmlist_entry *new_opt, *opt;
2203 if (opt_list == NULL) {
2210 /* Traverse destination */
2212 /* If we already have same option, override it */
2213 if (strwicmp(opt->key, opt_name) == 0) {
2214 if ((opt->priority & FLAG_CMDLINE) &&
2215 !(priority & FLAG_CMDLINE)) {
2216 /* it's been marked as not to be
2220 string_free(&opt->value);
2221 TALLOC_FREE(opt->list);
2222 opt->value = SMB_STRDUP(opt_value);
2223 opt->priority = priority;
2230 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2231 new_opt->key = SMB_STRDUP(opt_name);
2232 new_opt->value = SMB_STRDUP(opt_value);
2233 new_opt->list = NULL;
2234 new_opt->priority = priority;
2235 DLIST_ADD(*opt_list, new_opt);
2239 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2240 struct bitmap *pcopymapDest)
2243 bool bcopyall = (pcopymapDest == NULL);
2244 struct parmlist_entry *data;
2246 for (i = 0; parm_table[i].label; i++)
2247 if (parm_table[i].p_class == P_LOCAL &&
2248 (bcopyall || bitmap_query(pcopymapDest,i))) {
2249 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2250 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2252 switch (parm_table[i].type) {
2255 *(bool *)dest_ptr = *(bool *)src_ptr;
2262 *(int *)dest_ptr = *(int *)src_ptr;
2266 *(char *)dest_ptr = *(char *)src_ptr;
2270 string_set((char **)dest_ptr,
2276 char *upper_string = strupper_talloc(talloc_tos(),
2278 string_set((char **)dest_ptr,
2280 TALLOC_FREE(upper_string);
2284 TALLOC_FREE(*((char ***)dest_ptr));
2285 *((char ***)dest_ptr) = str_list_copy(NULL,
2286 *(const char ***)src_ptr);
2294 init_copymap(pserviceDest);
2295 if (pserviceSource->copymap)
2296 bitmap_copy(pserviceDest->copymap,
2297 pserviceSource->copymap);
2300 data = pserviceSource->param_opt;
2302 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2307 /***************************************************************************
2308 Check a service for consistency. Return false if the service is in any way
2309 incomplete or faulty, else true.
2310 ***************************************************************************/
2312 bool service_ok(int iService)
2317 if (ServicePtrs[iService]->szService[0] == '\0') {
2318 DEBUG(0, ("The following message indicates an internal error:\n"));
2319 DEBUG(0, ("No service name in service entry.\n"));
2323 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2324 /* I can't see why you'd want a non-printable printer service... */
2325 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2326 if (!ServicePtrs[iService]->bPrint_ok) {
2327 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2328 ServicePtrs[iService]->szService));
2329 ServicePtrs[iService]->bPrint_ok = true;
2331 /* [printers] service must also be non-browsable. */
2332 if (ServicePtrs[iService]->bBrowseable)
2333 ServicePtrs[iService]->bBrowseable = false;
2336 if (ServicePtrs[iService]->szPath[0] == '\0' &&
2337 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2338 ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2340 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2341 ServicePtrs[iService]->szService));
2342 ServicePtrs[iService]->bAvailable = false;
2345 /* If a service is flagged unavailable, log the fact at level 1. */
2346 if (!ServicePtrs[iService]->bAvailable)
2347 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2348 ServicePtrs[iService]->szService));
2353 static struct smbconf_ctx *lp_smbconf_ctx(void)
2356 static struct smbconf_ctx *conf_ctx = NULL;
2358 if (conf_ctx == NULL) {
2359 err = smbconf_init(NULL, &conf_ctx, "registry:");
2360 if (!SBC_ERROR_IS_OK(err)) {
2361 DEBUG(1, ("error initializing registry configuration: "
2362 "%s\n", sbcErrorString(err)));
2370 static bool process_smbconf_service(struct smbconf_service *service)
2375 if (service == NULL) {
2379 ret = do_section(service->name, NULL);
2383 for (count = 0; count < service->num_params; count++) {
2384 ret = do_parameter(service->param_names[count],
2385 service->param_values[count],
2391 if (iServiceIndex >= 0) {
2392 return service_ok(iServiceIndex);
2398 * load a service from registry and activate it
2400 bool process_registry_service(const char *service_name)
2403 struct smbconf_service *service = NULL;
2404 TALLOC_CTX *mem_ctx = talloc_stackframe();
2405 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2408 if (conf_ctx == NULL) {
2412 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2414 if (!smbconf_share_exists(conf_ctx, service_name)) {
2416 * Registry does not contain data for this service (yet),
2417 * but make sure lp_load doesn't return false.
2423 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2424 if (!SBC_ERROR_IS_OK(err)) {
2428 ret = process_smbconf_service(service);
2434 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2437 TALLOC_FREE(mem_ctx);
2442 * process_registry_globals
2444 static bool process_registry_globals(void)
2448 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2450 ret = do_parameter("registry shares", "yes", NULL);
2455 return process_registry_service(GLOBAL_NAME);
2458 bool process_registry_shares(void)
2462 struct smbconf_service **service = NULL;
2463 uint32_t num_shares = 0;
2464 TALLOC_CTX *mem_ctx = talloc_stackframe();
2465 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2468 if (conf_ctx == NULL) {
2472 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2473 if (!SBC_ERROR_IS_OK(err)) {
2479 for (count = 0; count < num_shares; count++) {
2480 if (strequal(service[count]->name, GLOBAL_NAME)) {
2483 ret = process_smbconf_service(service[count]);
2490 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2493 TALLOC_FREE(mem_ctx);
2498 * reload those shares from registry that are already
2499 * activated in the services array.
2501 static bool reload_registry_shares(void)
2506 for (i = 0; i < iNumServices; i++) {
2511 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2515 ret = process_registry_service(ServicePtrs[i]->szService);
2526 #define MAX_INCLUDE_DEPTH 100
2528 static uint8_t include_depth;
2530 static struct file_lists {
2531 struct file_lists *next;
2535 } *file_lists = NULL;
2537 /*******************************************************************
2538 Keep a linked list of all config files so we know when one has changed
2539 it's date and needs to be reloaded.
2540 ********************************************************************/
2542 static void add_to_file_list(const char *fname, const char *subfname)
2544 struct file_lists *f = file_lists;
2547 if (f->name && !strcmp(f->name, fname))
2553 f = SMB_MALLOC_P(struct file_lists);
2556 f->next = file_lists;
2557 f->name = SMB_STRDUP(fname);
2562 f->subfname = SMB_STRDUP(subfname);
2569 f->modtime = file_modtime(subfname);
2571 time_t t = file_modtime(subfname);
2579 * Free the file lists
2581 static void free_file_list(void)
2583 struct file_lists *f;
2584 struct file_lists *next;
2589 SAFE_FREE( f->name );
2590 SAFE_FREE( f->subfname );
2599 * Utility function for outsiders to check if we're running on registry.
2601 bool lp_config_backend_is_registry(void)
2603 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2607 * Utility function to check if the config backend is FILE.
2609 bool lp_config_backend_is_file(void)
2611 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2614 /*******************************************************************
2615 Check if a config file has changed date.
2616 ********************************************************************/
2618 bool lp_file_list_changed(void)
2620 struct file_lists *f = file_lists;
2622 DEBUG(6, ("lp_file_list_changed()\n"));
2627 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2628 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2630 if (conf_ctx == NULL) {
2633 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2636 DEBUGADD(6, ("registry config changed\n"));
2641 n2 = talloc_sub_basic(talloc_tos(),
2642 get_current_username(),
2643 current_user_info.domain,
2648 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2649 f->name, n2, ctime(&f->modtime)));
2651 mod_time = file_modtime(n2);
2654 ((f->modtime != mod_time) ||
2655 (f->subfname == NULL) ||
2656 (strcmp(n2, f->subfname) != 0)))
2659 ("file %s modified: %s\n", n2,
2661 f->modtime = mod_time;
2662 SAFE_FREE(f->subfname);
2663 f->subfname = SMB_STRDUP(n2);
2676 * Initialize iconv conversion descriptors.
2678 * This is called the first time it is needed, and also called again
2679 * every time the configuration is reloaded, because the charset or
2680 * codepage might have changed.
2682 static void init_iconv(void)
2684 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2686 true, global_iconv_handle);
2689 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2691 if (strcmp(*ptr, pszParmValue) != 0) {
2692 string_set(ptr, pszParmValue);
2698 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2700 bool is_utf8 = false;
2701 size_t len = strlen(pszParmValue);
2703 if (len == 4 || len == 5) {
2704 /* Don't use StrCaseCmp here as we don't want to
2705 initialize iconv. */
2706 if ((toupper_m(pszParmValue[0]) == 'U') &&
2707 (toupper_m(pszParmValue[1]) == 'T') &&
2708 (toupper_m(pszParmValue[2]) == 'F')) {
2710 if (pszParmValue[3] == '8') {
2714 if (pszParmValue[3] == '-' &&
2715 pszParmValue[4] == '8') {
2722 if (strcmp(*ptr, pszParmValue) != 0) {
2724 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2725 "be UTF8, using (default value) %s instead.\n",
2726 DEFAULT_DOS_CHARSET));
2727 pszParmValue = DEFAULT_DOS_CHARSET;
2729 string_set(ptr, pszParmValue);
2735 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2738 char *realm = strupper_talloc(talloc_tos(), pszParmValue);
2739 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2741 ret &= string_set(&Globals.szRealm, pszParmValue);
2742 ret &= string_set(&Globals.szRealm_upper, realm);
2743 ret &= string_set(&Globals.szRealm_lower, dnsdomain);
2749 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2751 TALLOC_FREE(Globals.szNetbiosAliases);
2752 Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2753 return set_netbios_aliases(Globals.szNetbiosAliases);
2756 /***************************************************************************
2757 Handle the include operation.
2758 ***************************************************************************/
2759 static bool bAllowIncludeRegistry = true;
2761 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2765 if (include_depth >= MAX_INCLUDE_DEPTH) {
2766 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2771 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2772 if (!bAllowIncludeRegistry) {
2775 if (bInGlobalSection) {
2778 ret = process_registry_globals();
2782 DEBUG(1, ("\"include = registry\" only effective "
2783 "in %s section\n", GLOBAL_NAME));
2788 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2789 current_user_info.domain,
2792 add_to_file_list(pszParmValue, fname);
2794 string_set(ptr, fname);
2796 if (file_exist(fname)) {
2799 ret = pm_process(fname, do_section, do_parameter, NULL);
2805 DEBUG(2, ("Can't find include file %s\n", fname));
2810 /***************************************************************************
2811 Handle the interpretation of the copy parameter.
2812 ***************************************************************************/
2814 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2818 struct loadparm_service serviceTemp;
2820 string_set(ptr, pszParmValue);
2822 init_service(&serviceTemp);
2826 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2828 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2829 if (iTemp == iServiceIndex) {
2830 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2832 copy_service(ServicePtrs[iServiceIndex],
2834 ServicePtrs[iServiceIndex]->copymap);
2838 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2842 free_service(&serviceTemp);
2846 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2848 Globals.ldap_debug_level = lp_int(pszParmValue);
2849 init_ldap_debugging();
2853 /***************************************************************************
2854 Handle idmap/non unix account uid and gid allocation parameters. The format of these
2859 idmap uid = 1000-1999
2862 We only do simple parsing checks here. The strings are parsed into useful
2863 structures in the idmap daemon code.
2865 ***************************************************************************/
2867 /* Some lp_ routines to return idmap [ug]id information */
2869 static uid_t idmap_uid_low, idmap_uid_high;
2870 static gid_t idmap_gid_low, idmap_gid_high;
2872 bool lp_idmap_uid(uid_t *low, uid_t *high)
2874 if (idmap_uid_low == 0 || idmap_uid_high == 0)
2878 *low = idmap_uid_low;
2881 *high = idmap_uid_high;
2886 bool lp_idmap_gid(gid_t *low, gid_t *high)
2888 if (idmap_gid_low == 0 || idmap_gid_high == 0)
2892 *low = idmap_gid_low;
2895 *high = idmap_gid_high;
2900 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2902 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2907 /* Do some simple checks on "idmap [ug]id" parameter values */
2909 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2911 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2916 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2918 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2923 /***************************************************************************
2924 Handle the DEBUG level list.
2925 ***************************************************************************/
2927 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2929 string_set(ptr, pszParmValueIn);
2930 return debug_parse_levels(pszParmValueIn);
2933 /***************************************************************************
2934 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2935 ***************************************************************************/
2937 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2939 const char *suffix_string;
2941 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2942 Globals.szLdapSuffix );
2943 if ( !suffix_string ) {
2944 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2948 return suffix_string;
2951 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2953 if (Globals.szLdapMachineSuffix[0])
2954 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
2956 return lp_string(ctx, Globals.szLdapSuffix);
2959 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
2961 if (Globals.szLdapUserSuffix[0])
2962 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
2964 return lp_string(ctx, Globals.szLdapSuffix);
2967 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
2969 if (Globals.szLdapGroupSuffix[0])
2970 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
2972 return lp_string(ctx, Globals.szLdapSuffix);
2975 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
2977 if (Globals.szLdapIdmapSuffix[0])
2978 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
2980 return lp_string(ctx, Globals.szLdapSuffix);
2983 /****************************************************************************
2984 set the value for a P_ENUM
2985 ***************************************************************************/
2987 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
2992 for (i = 0; parm->enum_list[i].name; i++) {
2993 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
2994 *ptr = parm->enum_list[i].value;
2998 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
2999 pszParmValue, parm->label));
3002 /***************************************************************************
3003 ***************************************************************************/
3005 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3007 static int parm_num = -1;
3008 struct loadparm_service *s;
3010 if ( parm_num == -1 )
3011 parm_num = map_parameter( "printing" );
3013 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3018 s = ServicePtrs[snum];
3020 init_printer_values( s );
3026 /***************************************************************************
3027 Initialise a copymap.
3028 ***************************************************************************/
3030 static void init_copymap(struct loadparm_service *pservice)
3034 TALLOC_FREE(pservice->copymap);
3036 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3037 if (!pservice->copymap)
3039 ("Couldn't allocate copymap!! (size %d)\n",
3040 (int)NUMPARAMETERS));
3042 for (i = 0; i < NUMPARAMETERS; i++)
3043 bitmap_set(pservice->copymap, i);
3047 return the parameter pointer for a parameter
3049 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3051 if (service == NULL) {
3052 if (parm->p_class == P_LOCAL)
3053 return (void *)(((char *)&sDefault)+parm->offset);
3054 else if (parm->p_class == P_GLOBAL)
3055 return (void *)(((char *)&Globals)+parm->offset);
3058 return (void *)(((char *)service) + parm->offset);
3062 /***************************************************************************
3063 Return the local pointer to a parameter given the service number and parameter
3064 ***************************************************************************/
3066 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3068 return lp_parm_ptr(ServicePtrs[snum], parm);
3071 /***************************************************************************
3072 Process a parameter for a particular service number. If snum < 0
3073 then assume we are in the globals.
3074 ***************************************************************************/
3076 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3079 void *parm_ptr = NULL; /* where we are going to store the result */
3080 struct parmlist_entry **opt_list;
3082 parmnum = map_parameter(pszParmName);
3085 if (strchr(pszParmName, ':') == NULL) {
3086 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3092 * We've got a parametric option
3095 opt_list = (snum < 0)
3096 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3097 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3102 /* if it's already been set by the command line, then we don't
3104 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3108 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3109 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3113 /* we might point at a service, the default service or a global */
3115 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3117 if (parm_table[parmnum].p_class == P_GLOBAL) {
3119 ("Global parameter %s found in service section!\n",
3123 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3127 if (!ServicePtrs[snum]->copymap)
3128 init_copymap(ServicePtrs[snum]);
3130 /* this handles the aliases - set the copymap for other entries with
3131 the same data pointer */
3132 for (i = 0; parm_table[i].label; i++) {
3133 if ((parm_table[i].offset == parm_table[parmnum].offset)
3134 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3135 bitmap_clear(ServicePtrs[snum]->copymap, i);
3140 /* if it is a special case then go ahead */
3141 if (parm_table[parmnum].special) {
3142 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3146 /* now switch on the type of variable it is */
3147 switch (parm_table[parmnum].type)
3150 *(bool *)parm_ptr = lp_bool(pszParmValue);
3154 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3158 *(int *)parm_ptr = lp_int(pszParmValue);
3162 *(char *)parm_ptr = *pszParmValue;
3166 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3168 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3175 if (conv_str_size_error(pszParmValue, &val)) {
3176 if (val <= INT_MAX) {
3177 *(int *)parm_ptr = (int)val;
3182 DEBUG(0,("lp_do_parameter(%s): value is not "
3183 "a valid size specifier!\n", pszParmValue));
3189 TALLOC_FREE(*((char ***)parm_ptr));
3190 *(char ***)parm_ptr = str_list_make_v3(
3191 NULL, pszParmValue, NULL);
3195 string_set((char **)parm_ptr, pszParmValue);
3200 char *upper_string = strupper_talloc(talloc_tos(),
3202 string_set((char **)parm_ptr, upper_string);
3203 TALLOC_FREE(upper_string);
3207 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3216 /***************************************************************************
3217 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3218 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3219 ***************************************************************************/
3221 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3224 parmnum = map_parameter(pszParmName);
3226 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3227 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3230 parm_table[parmnum].flags |= FLAG_CMDLINE;
3232 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3233 * be grouped in the table, so we don't have to search the
3236 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3237 && parm_table[i].p_class == parm_table[parmnum].p_class;
3239 parm_table[i].flags |= FLAG_CMDLINE;
3241 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3242 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3243 parm_table[i].flags |= FLAG_CMDLINE;
3247 store_lp_set_cmdline(pszParmName, pszParmValue);
3252 /* it might be parametric */
3253 if (strchr(pszParmName, ':') != NULL) {
3254 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3256 store_lp_set_cmdline(pszParmName, pszParmValue);
3261 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3265 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3267 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3270 /***************************************************************************
3271 Process a parameter.
3272 ***************************************************************************/
3274 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3277 if (!bInGlobalSection && bGlobalOnly)
3280 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3282 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3283 pszParmName, pszParmValue));
3287 set a option from the commandline in 'a=b' format. Use to support --option
3289 bool lp_set_option(const char *option)
3294 s = talloc_strdup(NULL, option);
3307 /* skip white spaces after the = sign */
3310 } while (*p == ' ');
3312 ret = lp_set_cmdline(s, p);
3317 /**************************************************************************
3318 Print a parameter of the specified type.
3319 ***************************************************************************/
3321 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3323 /* For the seperation of lists values that we print below */
3324 const char *list_sep = ", ";
3329 for (i = 0; p->enum_list[i].name; i++) {
3330 if (*(int *)ptr == p->enum_list[i].value) {
3332 p->enum_list[i].name);
3339 fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3343 fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3348 fprintf(f, "%d", *(int *)ptr);
3352 fprintf(f, "%c", *(char *)ptr);
3356 int val = *(int *)ptr;
3360 fprintf(f, "0%o", val);
3369 if ((char ***)ptr && *(char ***)ptr) {
3370 char **list = *(char ***)ptr;
3371 for (; *list; list++) {
3372 /* surround strings with whitespace in double quotes */
3373 if (*(list+1) == NULL) {
3374 /* last item, no extra separator */
3377 if ( strchr_m( *list, ' ' ) ) {
3378 fprintf(f, "\"%s\"%s", *list, list_sep);
3380 fprintf(f, "%s%s", *list, list_sep);
3388 if (*(char **)ptr) {
3389 fprintf(f, "%s", *(char **)ptr);
3397 /***************************************************************************
3398 Check if two parameters are equal.
3399 ***************************************************************************/
3401 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3406 return (*((bool *)ptr1) == *((bool *)ptr2));
3412 return (*((int *)ptr1) == *((int *)ptr2));
3415 return (*((char *)ptr1) == *((char *)ptr2));
3419 return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3424 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3429 return (p1 == p2 || strequal(p1, p2));
3437 /***************************************************************************
3438 Initialize any local varients in the sDefault table.
3439 ***************************************************************************/
3441 void init_locals(void)
3446 /***************************************************************************
3447 Process a new section (service). At this stage all sections are services.
3448 Later we'll have special sections that permit server parameters to be set.
3449 Returns true on success, false on failure.
3450 ***************************************************************************/
3452 static bool do_section(const char *pszSectionName, void *userdata)
3455 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3456 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3459 /* if we were in a global section then do the local inits */
3460 if (bInGlobalSection && !isglobal)
3463 /* if we've just struck a global section, note the fact. */
3464 bInGlobalSection = isglobal;
3466 /* check for multiple global sections */
3467 if (bInGlobalSection) {
3468 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3472 if (!bInGlobalSection && bGlobalOnly)
3475 /* if we have a current service, tidy it up before moving on */
3478 if (iServiceIndex >= 0)
3479 bRetval = service_ok(iServiceIndex);
3481 /* if all is still well, move to the next record in the services array */
3483 /* We put this here to avoid an odd message order if messages are */
3484 /* issued by the post-processing of a previous section. */
3485 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3487 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3488 if (iServiceIndex < 0) {
3489 DEBUG(0, ("Failed to add a new service\n"));
3492 /* Clean all parametric options for service */
3493 /* They will be added during parsing again */
3494 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3501 /***************************************************************************
3502 Determine if a partcular base parameter is currentl set to the default value.
3503 ***************************************************************************/
3505 static bool is_default(int i)
3507 if (!defaults_saved)
3509 switch (parm_table[i].type) {
3512 return str_list_equal((const char **)parm_table[i].def.lvalue,
3513 *(const char ***)lp_parm_ptr(NULL,
3517 return strequal(parm_table[i].def.svalue,
3518 *(char **)lp_parm_ptr(NULL,
3522 return parm_table[i].def.bvalue ==
3523 *(bool *)lp_parm_ptr(NULL,
3526 return parm_table[i].def.cvalue ==
3527 *(char *)lp_parm_ptr(NULL,
3533 return parm_table[i].def.ivalue ==
3534 *(int *)lp_parm_ptr(NULL,
3542 /***************************************************************************
3543 Display the contents of the global structure.
3544 ***************************************************************************/
3546 static void dump_globals(FILE *f)
3549 struct parmlist_entry *data;
3551 fprintf(f, "[global]\n");
3553 for (i = 0; parm_table[i].label; i++)
3554 if (parm_table[i].p_class == P_GLOBAL &&
3555 !(parm_table[i].flags & FLAG_META) &&
3556 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3557 if (defaults_saved && is_default(i))
3559 fprintf(f, "\t%s = ", parm_table[i].label);
3560 print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3565 if (Globals.param_opt != NULL) {
3566 data = Globals.param_opt;
3568 fprintf(f, "\t%s = %s\n", data->key, data->value);
3575 /***************************************************************************
3576 Return true if a local parameter is currently set to the global default.
3577 ***************************************************************************/
3579 bool lp_is_default(int snum, struct parm_struct *parm)
3581 return equal_parameter(parm->type,
3582 lp_parm_ptr(ServicePtrs[snum], parm),
3583 lp_parm_ptr(NULL, parm));
3586 /***************************************************************************
3587 Display the contents of a single services record.
3588 ***************************************************************************/
3590 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3593 struct parmlist_entry *data;
3595 if (pService != &sDefault)
3596 fprintf(f, "[%s]\n", pService->szService);
3598 for (i = 0; parm_table[i].label; i++) {
3600 if (parm_table[i].p_class == P_LOCAL &&
3601 !(parm_table[i].flags & FLAG_META) &&
3602 (*parm_table[i].label != '-') &&
3603 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3605 if (pService == &sDefault) {
3606 if (defaults_saved && is_default(i))
3609 if (equal_parameter(parm_table[i].type,
3610 lp_parm_ptr(pService, &parm_table[i]),
3611 lp_parm_ptr(NULL, &parm_table[i])))
3615 fprintf(f, "\t%s = ", parm_table[i].label);
3616 print_parameter(&parm_table[i],
3617 lp_parm_ptr(pService, &parm_table[i]),
3623 if (pService->param_opt != NULL) {
3624 data = pService->param_opt;
3626 fprintf(f, "\t%s = %s\n", data->key, data->value);
3632 /***************************************************************************
3633 Display the contents of a parameter of a single services record.
3634 ***************************************************************************/
3636 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3639 bool result = false;
3642 fstring local_parm_name;
3644 const char *parm_opt_value;
3646 /* check for parametrical option */
3647 fstrcpy( local_parm_name, parm_name);
3648 parm_opt = strchr( local_parm_name, ':');
3653 if (strlen(parm_opt)) {
3654 parm_opt_value = lp_parm_const_string( snum,
3655 local_parm_name, parm_opt, NULL);
3656 if (parm_opt_value) {
3657 printf( "%s\n", parm_opt_value);
3664 /* check for a key and print the value */
3671 for (i = 0; parm_table[i].label; i++) {
3672 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3673 !(parm_table[i].flags & FLAG_META) &&
3674 (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3675 (*parm_table[i].label != '-') &&
3676 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3681 ptr = lp_parm_ptr(NULL,
3684 ptr = lp_parm_ptr(ServicePtrs[snum],
3688 print_parameter(&parm_table[i],
3699 /***************************************************************************
3700 Return info about the requested parameter (given as a string).
3701 Return NULL when the string is not a valid parameter name.
3702 ***************************************************************************/
3704 struct parm_struct *lp_get_parameter(const char *param_name)
3706 int num = map_parameter(param_name);
3712 return &parm_table[num];
3715 /***************************************************************************
3716 Return info about the next parameter in a service.
3717 snum==GLOBAL_SECTION_SNUM gives the globals.
3718 Return NULL when out of parameters.
3719 ***************************************************************************/
3721 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3724 /* do the globals */
3725 for (; parm_table[*i].label; (*i)++) {
3726 if (parm_table[*i].p_class == P_SEPARATOR)
3727 return &parm_table[(*i)++];
3729 if ((*parm_table[*i].label == '-'))
3733 && (parm_table[*i].offset ==
3734 parm_table[(*i) - 1].offset)
3735 && (parm_table[*i].p_class ==
3736 parm_table[(*i) - 1].p_class))
3739 if (is_default(*i) && !allparameters)
3742 return &parm_table[(*i)++];
3745 struct loadparm_service *pService = ServicePtrs[snum];
3747 for (; parm_table[*i].label; (*i)++) {
3748 if (parm_table[*i].p_class == P_SEPARATOR)
3749 return &parm_table[(*i)++];
3751 if (parm_table[*i].p_class == P_LOCAL &&
3752 (*parm_table[*i].label != '-') &&
3754 (parm_table[*i].offset !=
3755 parm_table[(*i) - 1].offset)))
3757 if (allparameters ||
3758 !equal_parameter(parm_table[*i].type,
3759 lp_parm_ptr(pService,
3764 return &parm_table[(*i)++];
3775 /***************************************************************************
3776 Display the contents of a single copy structure.
3777 ***************************************************************************/
3778 static void dump_copy_map(bool *pcopymap)
3784 printf("\n\tNon-Copied parameters:\n");
3786 for (i = 0; parm_table[i].label; i++)
3787 if (parm_table[i].p_class == P_LOCAL &&
3788 parm_table[i].ptr && !pcopymap[i] &&
3789 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3791 printf("\t\t%s\n", parm_table[i].label);
3796 /***************************************************************************
3797 Return TRUE if the passed service number is within range.
3798 ***************************************************************************/
3800 bool lp_snum_ok(int iService)
3802 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3805 /***************************************************************************
3806 Auto-load some home services.
3807 ***************************************************************************/
3809 static void lp_add_auto_services(char *str)
3819 s = SMB_STRDUP(str);
3823 homes = lp_servicenumber(HOMES_NAME);
3825 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3826 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3829 if (lp_servicenumber(p) >= 0)
3832 home = get_user_home_dir(talloc_tos(), p);
3834 if (home && home[0] && homes >= 0)
3835 lp_add_home(p, homes, p, home);
3842 /***************************************************************************
3843 Auto-load one printer.
3844 ***************************************************************************/
3846 void lp_add_one_printer(const char *name, const char *comment,
3847 const char *location, void *pdata)
3849 int printers = lp_servicenumber(PRINTERS_NAME);
3852 if (lp_servicenumber(name) < 0) {
3853 lp_add_printer(name, printers);
3854 if ((i = lp_servicenumber(name)) >= 0) {
3855 string_set(&ServicePtrs[i]->comment, comment);
3856 ServicePtrs[i]->autoloaded = true;
3861 /***************************************************************************
3862 Have we loaded a services file yet?
3863 ***************************************************************************/
3865 bool lp_loaded(void)
3870 /***************************************************************************
3871 Unload unused services.
3872 ***************************************************************************/
3874 void lp_killunused(struct smbd_server_connection *sconn,
3875 bool (*snumused) (struct smbd_server_connection *, int))
3878 for (i = 0; i < iNumServices; i++) {
3882 /* don't kill autoloaded or usershare services */
3883 if ( ServicePtrs[i]->autoloaded ||
3884 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3888 if (!snumused || !snumused(sconn, i)) {
3889 free_service_byindex(i);
3895 * Kill all except autoloaded and usershare services - convenience wrapper
3897 void lp_kill_all_services(void)
3899 lp_killunused(NULL, NULL);
3902 /***************************************************************************
3904 ***************************************************************************/
3906 void lp_killservice(int iServiceIn)
3908 if (VALID(iServiceIn)) {
3909 free_service_byindex(iServiceIn);
3913 /***************************************************************************
3914 Save the curent values of all global and sDefault parameters into the
3915 defaults union. This allows swat and testparm to show only the
3916 changed (ie. non-default) parameters.
3917 ***************************************************************************/
3919 static void lp_save_defaults(void)
3922 for (i = 0; parm_table[i].label; i++) {
3923 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3924 && parm_table[i].p_class == parm_table[i - 1].p_class)
3926 switch (parm_table[i].type) {
3929 parm_table[i].def.lvalue = str_list_copy(
3930 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3934 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3938 parm_table[i].def.bvalue =
3939 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3942 parm_table[i].def.cvalue =
3943 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3949 parm_table[i].def.ivalue =
3950 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3956 defaults_saved = true;
3959 /***********************************************************
3960 If we should send plaintext/LANMAN passwords in the clinet
3961 ************************************************************/
3963 static void set_allowed_client_auth(void)
3965 if (Globals.bClientNTLMv2Auth) {
3966 Globals.bClientLanManAuth = false;
3968 if (!Globals.bClientLanManAuth) {
3969 Globals.bClientPlaintextAuth = false;
3973 /***************************************************************************
3975 The following code allows smbd to read a user defined share file.
3976 Yes, this is my intent. Yes, I'm comfortable with that...
3978 THE FOLLOWING IS SECURITY CRITICAL CODE.
3980 It washes your clothes, it cleans your house, it guards you while you sleep...
3981 Do not f%^k with it....
3982 ***************************************************************************/
3984 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3986 /***************************************************************************
3987 Check allowed stat state of a usershare file.
3988 Ensure we print out who is dicking with us so the admin can
3989 get their sorry ass fired.
3990 ***************************************************************************/
3992 static bool check_usershare_stat(const char *fname,
3993 const SMB_STRUCT_STAT *psbuf)
3995 if (!S_ISREG(psbuf->st_ex_mode)) {
3996 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3997 "not a regular file\n",
3998 fname, (unsigned int)psbuf->st_ex_uid ));
4002 /* Ensure this doesn't have the other write bit set. */
4003 if (psbuf->st_ex_mode & S_IWOTH) {
4004 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4005 "public write. Refusing to allow as a usershare file.\n",
4006 fname, (unsigned int)psbuf->st_ex_uid ));
4010 /* Should be 10k or less. */
4011 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4012 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4013 "too large (%u) to be a user share file.\n",
4014 fname, (unsigned int)psbuf->st_ex_uid,
4015 (unsigned int)psbuf->st_ex_size ));
4022 /***************************************************************************
4023 Parse the contents of a usershare file.
4024 ***************************************************************************/
4026 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4027 SMB_STRUCT_STAT *psbuf,
4028 const char *servicename,
4032 char **pp_sharepath,
4034 char **pp_cp_servicename,
4035 struct security_descriptor **ppsd,
4038 const char **prefixallowlist = lp_usershare_prefix_allow_list();
4039 const char **prefixdenylist = lp_usershare_prefix_deny_list();
4042 SMB_STRUCT_STAT sbuf;
4043 char *sharepath = NULL;
4044 char *comment = NULL;
4046 *pp_sharepath = NULL;
4049 *pallow_guest = false;
4052 return USERSHARE_MALFORMED_FILE;
4055 if (strcmp(lines[0], "#VERSION 1") == 0) {
4057 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4060 return USERSHARE_MALFORMED_FILE;
4063 return USERSHARE_BAD_VERSION;
4066 if (strncmp(lines[1], "path=", 5) != 0) {
4067 return USERSHARE_MALFORMED_PATH;
4070 sharepath = talloc_strdup(ctx, &lines[1][5]);
4072 return USERSHARE_POSIX_ERR;
4074 trim_string(sharepath, " ", " ");
4076 if (strncmp(lines[2], "comment=", 8) != 0) {
4077 return USERSHARE_MALFORMED_COMMENT_DEF;
4080 comment = talloc_strdup(ctx, &lines[2][8]);
4082 return USERSHARE_POSIX_ERR;
4084 trim_string(comment, " ", " ");
4085 trim_char(comment, '"', '"');
4087 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4088 return USERSHARE_MALFORMED_ACL_DEF;
4091 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4092 return USERSHARE_ACL_ERR;
4096 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4097 return USERSHARE_MALFORMED_ACL_DEF;
4099 if (lines[4][9] == 'y') {
4100 *pallow_guest = true;
4103 /* Backwards compatible extension to file version #2. */
4105 if (strncmp(lines[5], "sharename=", 10) != 0) {
4106 return USERSHARE_MALFORMED_SHARENAME_DEF;
4108 if (!strequal(&lines[5][10], servicename)) {
4109 return USERSHARE_BAD_SHARENAME;
4111 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4112 if (!*pp_cp_servicename) {
4113 return USERSHARE_POSIX_ERR;
4118 if (*pp_cp_servicename == NULL) {
4119 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4120 if (!*pp_cp_servicename) {
4121 return USERSHARE_POSIX_ERR;
4125 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4126 /* Path didn't change, no checks needed. */
4127 *pp_sharepath = sharepath;
4128 *pp_comment = comment;
4129 return USERSHARE_OK;
4132 /* The path *must* be absolute. */
4133 if (sharepath[0] != '/') {
4134 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4135 servicename, sharepath));
4136 return USERSHARE_PATH_NOT_ABSOLUTE;
4139 /* If there is a usershare prefix deny list ensure one of these paths
4140 doesn't match the start of the user given path. */
4141 if (prefixdenylist) {
4143 for ( i=0; prefixdenylist[i]; i++ ) {
4144 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4145 servicename, i, prefixdenylist[i], sharepath ));
4146 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4147 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4148 "usershare prefix deny list entries.\n",
4149 servicename, sharepath));
4150 return USERSHARE_PATH_IS_DENIED;
4155 /* If there is a usershare prefix allow list ensure one of these paths
4156 does match the start of the user given path. */
4158 if (prefixallowlist) {
4160 for ( i=0; prefixallowlist[i]; i++ ) {
4161 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4162 servicename, i, prefixallowlist[i], sharepath ));
4163 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4167 if (prefixallowlist[i] == NULL) {
4168 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4169 "usershare prefix allow list entries.\n",
4170 servicename, sharepath));
4171 return USERSHARE_PATH_NOT_ALLOWED;
4175 /* Ensure this is pointing to a directory. */
4176 dp = opendir(sharepath);
4179 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4180 servicename, sharepath));
4181 return USERSHARE_PATH_NOT_DIRECTORY;
4184 /* Ensure the owner of the usershare file has permission to share
4187 if (sys_stat(sharepath, &sbuf, false) == -1) {
4188 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4189 servicename, sharepath, strerror(errno) ));
4191 return USERSHARE_POSIX_ERR;
4196 if (!S_ISDIR(sbuf.st_ex_mode)) {
4197 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4198 servicename, sharepath ));
4199 return USERSHARE_PATH_NOT_DIRECTORY;
4202 /* Check if sharing is restricted to owner-only. */
4203 /* psbuf is the stat of the usershare definition file,
4204 sbuf is the stat of the target directory to be shared. */
4206 if (lp_usershare_owner_only()) {
4207 /* root can share anything. */
4208 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4209 return USERSHARE_PATH_NOT_ALLOWED;
4213 *pp_sharepath = sharepath;
4214 *pp_comment = comment;
4215 return USERSHARE_OK;
4218 /***************************************************************************
4219 Deal with a usershare file.
4222 -1 - Bad name, invalid contents.
4223 - service name already existed and not a usershare, problem
4224 with permissions to share directory etc.
4225 ***************************************************************************/
4227 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4229 SMB_STRUCT_STAT sbuf;
4230 SMB_STRUCT_STAT lsbuf;
4232 char *sharepath = NULL;
4233 char *comment = NULL;
4234 char *cp_service_name = NULL;
4235 char **lines = NULL;
4239 TALLOC_CTX *ctx = talloc_stackframe();
4240 struct security_descriptor *psd = NULL;
4241 bool guest_ok = false;
4242 char *canon_name = NULL;
4243 bool added_service = false;
4246 /* Ensure share name doesn't contain invalid characters. */
4247 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4248 DEBUG(0,("process_usershare_file: share name %s contains "
4249 "invalid characters (any of %s)\n",
4250 file_name, INVALID_SHARENAME_CHARS ));
4254 canon_name = canonicalize_servicename(ctx, file_name);
4259 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4264 /* Minimize the race condition by doing an lstat before we
4265 open and fstat. Ensure this isn't a symlink link. */
4267 if (sys_lstat(fname, &lsbuf, false) != 0) {
4268 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4269 fname, strerror(errno) ));
4273 /* This must be a regular file, not a symlink, directory or
4274 other strange filetype. */
4275 if (!check_usershare_stat(fname, &lsbuf)) {
4283 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4288 if (NT_STATUS_IS_OK(status) &&
4289 (data.dptr != NULL) &&
4290 (data.dsize == sizeof(iService))) {
4291 memcpy(&iService, data.dptr, sizeof(iService));
4295 if (iService != -1 &&
4296 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4297 &lsbuf.st_ex_mtime) == 0) {
4298 /* Nothing changed - Mark valid and return. */
4299 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4301 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4306 /* Try and open the file read only - no symlinks allowed. */
4308 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4310 fd = open(fname, O_RDONLY, 0);
4314 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4315 fname, strerror(errno) ));
4319 /* Now fstat to be *SURE* it's a regular file. */
4320 if (sys_fstat(fd, &sbuf, false) != 0) {
4322 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4323 fname, strerror(errno) ));
4327 /* Is it the same dev/inode as was lstated ? */
4328 if (!check_same_stat(&lsbuf, &sbuf)) {
4330 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4331 "Symlink spoofing going on ?\n", fname ));
4335 /* This must be a regular file, not a symlink, directory or
4336 other strange filetype. */
4337 if (!check_usershare_stat(fname, &sbuf)) {
4341 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4344 if (lines == NULL) {
4345 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4346 fname, (unsigned int)sbuf.st_ex_uid ));
4350 if (parse_usershare_file(ctx, &sbuf, file_name,
4351 iService, lines, numlines, &sharepath,
4352 &comment, &cp_service_name,
4353 &psd, &guest_ok) != USERSHARE_OK) {
4357 /* Everything ok - add the service possibly using a template. */
4359 const struct loadparm_service *sp = &sDefault;
4360 if (snum_template != -1) {
4361 sp = ServicePtrs[snum_template];
4364 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4365 DEBUG(0, ("process_usershare_file: Failed to add "
4366 "new service %s\n", cp_service_name));
4370 added_service = true;
4372 /* Read only is controlled by usershare ACL below. */
4373 ServicePtrs[iService]->bRead_only = false;
4376 /* Write the ACL of the new/modified share. */
4377 if (!set_share_security(canon_name, psd)) {
4378 DEBUG(0, ("process_usershare_file: Failed to set share "
4379 "security for user share %s\n",
4384 /* If from a template it may be marked invalid. */
4385 ServicePtrs[iService]->valid = true;
4387 /* Set the service as a valid usershare. */
4388 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4390 /* Set guest access. */
4391 if (lp_usershare_allow_guests()) {
4392 ServicePtrs[iService]->bGuest_ok = guest_ok;
4395 /* And note when it was loaded. */
4396 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4397 string_set(&ServicePtrs[iService]->szPath, sharepath);
4398 string_set(&ServicePtrs[iService]->comment, comment);
4404 if (ret == -1 && iService != -1 && added_service) {
4405 lp_remove_service(iService);
4413 /***************************************************************************
4414 Checks if a usershare entry has been modified since last load.
4415 ***************************************************************************/
4417 static bool usershare_exists(int iService, struct timespec *last_mod)
4419 SMB_STRUCT_STAT lsbuf;
4420 const char *usersharepath = Globals.szUsersharePath;
4423 if (asprintf(&fname, "%s/%s",
4425 ServicePtrs[iService]->szService) < 0) {
4429 if (sys_lstat(fname, &lsbuf, false) != 0) {
4434 if (!S_ISREG(lsbuf.st_ex_mode)) {
4440 *last_mod = lsbuf.st_ex_mtime;
4444 /***************************************************************************
4445 Load a usershare service by name. Returns a valid servicenumber or -1.
4446 ***************************************************************************/
4448 int load_usershare_service(const char *servicename)
4450 SMB_STRUCT_STAT sbuf;
4451 const char *usersharepath = Globals.szUsersharePath;
4452 int max_user_shares = Globals.iUsershareMaxShares;
4453 int snum_template = -1;
4455 if (*usersharepath == 0 || max_user_shares == 0) {
4459 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4460 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4461 usersharepath, strerror(errno) ));
4465 if (!S_ISDIR(sbuf.st_ex_mode)) {
4466 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4472 * This directory must be owned by root, and have the 't' bit set.
4473 * It also must not be writable by "other".
4477 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4479 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4481 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4482 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4487 /* Ensure the template share exists if it's set. */
4488 if (Globals.szUsershareTemplateShare[0]) {
4489 /* We can't use lp_servicenumber here as we are recommending that
4490 template shares have -valid=false set. */
4491 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4492 if (ServicePtrs[snum_template]->szService &&
4493 strequal(ServicePtrs[snum_template]->szService,
4494 Globals.szUsershareTemplateShare)) {
4499 if (snum_template == -1) {
4500 DEBUG(0,("load_usershare_service: usershare template share %s "
4501 "does not exist.\n",
4502 Globals.szUsershareTemplateShare ));
4507 return process_usershare_file(usersharepath, servicename, snum_template);
4510 /***************************************************************************
4511 Load all user defined shares from the user share directory.
4512 We only do this if we're enumerating the share list.
4513 This is the function that can delete usershares that have
4515 ***************************************************************************/
4517 int load_usershare_shares(struct smbd_server_connection *sconn,
4518 bool (*snumused) (struct smbd_server_connection *, int))
4521 SMB_STRUCT_STAT sbuf;
4523 int num_usershares = 0;
4524 int max_user_shares = Globals.iUsershareMaxShares;
4525 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4526 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4527 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4529 int snum_template = -1;
4530 const char *usersharepath = Globals.szUsersharePath;
4531 int ret = lp_numservices();
4532 TALLOC_CTX *tmp_ctx;
4534 if (max_user_shares == 0 || *usersharepath == '\0') {
4535 return lp_numservices();
4538 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4539 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4540 usersharepath, strerror(errno) ));
4545 * This directory must be owned by root, and have the 't' bit set.
4546 * It also must not be writable by "other".
4550 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4552 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4554 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4555 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4560 /* Ensure the template share exists if it's set. */
4561 if (Globals.szUsershareTemplateShare[0]) {
4562 /* We can't use lp_servicenumber here as we are recommending that
4563 template shares have -valid=false set. */
4564 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4565 if (ServicePtrs[snum_template]->szService &&
4566 strequal(ServicePtrs[snum_template]->szService,
4567 Globals.szUsershareTemplateShare)) {
4572 if (snum_template == -1) {
4573 DEBUG(0,("load_usershare_shares: usershare template share %s "
4574 "does not exist.\n",
4575 Globals.szUsershareTemplateShare ));
4580 /* Mark all existing usershares as pending delete. */
4581 for (iService = iNumServices - 1; iService >= 0; iService--) {
4582 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4583 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4587 dp = opendir(usersharepath);
4589 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4590 usersharepath, strerror(errno) ));
4594 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4596 num_dir_entries++ ) {
4598 const char *n = de->d_name;
4600 /* Ignore . and .. */
4602 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4608 /* Temporary file used when creating a share. */
4609 num_tmp_dir_entries++;
4612 /* Allow 20% tmp entries. */
4613 if (num_tmp_dir_entries > allowed_tmp_entries) {
4614 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4615 "in directory %s\n",
4616 num_tmp_dir_entries, usersharepath));
4620 r = process_usershare_file(usersharepath, n, snum_template);
4622 /* Update the services count. */
4624 if (num_usershares >= max_user_shares) {
4625 DEBUG(0,("load_usershare_shares: max user shares reached "
4626 "on file %s in directory %s\n",
4627 n, usersharepath ));
4630 } else if (r == -1) {
4631 num_bad_dir_entries++;
4634 /* Allow 20% bad entries. */
4635 if (num_bad_dir_entries > allowed_bad_entries) {
4636 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4637 "in directory %s\n",
4638 num_bad_dir_entries, usersharepath));
4642 /* Allow 20% bad entries. */
4643 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4644 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4645 "in directory %s\n",
4646 num_dir_entries, usersharepath));
4653 /* Sweep through and delete any non-refreshed usershares that are
4654 not currently in use. */
4655 tmp_ctx = talloc_stackframe();
4656 for (iService = iNumServices - 1; iService >= 0; iService--) {
4657 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4660 if (snumused && snumused(sconn, iService)) {
4664 servname = lp_servicename(tmp_ctx, iService);
4666 /* Remove from the share ACL db. */
4667 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4669 delete_share_security(servname);
4670 free_service_byindex(iService);
4673 talloc_free(tmp_ctx);
4675 return lp_numservices();
4678 /********************************************************
4679 Destroy global resources allocated in this file
4680 ********************************************************/
4682 void gfree_loadparm(void)
4688 /* Free resources allocated to services */
4690 for ( i = 0; i < iNumServices; i++ ) {
4692 free_service_byindex(i);
4696 SAFE_FREE( ServicePtrs );
4699 /* Now release all resources allocated to global
4700 parameters and the default service */
4702 free_global_parameters();
4706 /***************************************************************************
4707 Allow client apps to specify that they are a client
4708 ***************************************************************************/
4709 static void lp_set_in_client(bool b)
4715 /***************************************************************************
4716 Determine if we're running in a client app
4717 ***************************************************************************/
4718 static bool lp_is_in_client(void)
4723 /***************************************************************************
4724 Load the services array from the services file. Return true on success,
4726 ***************************************************************************/
4728 static bool lp_load_ex(const char *pszFname,
4732 bool initialize_globals,
4733 bool allow_include_registry,
4734 bool load_all_shares)
4741 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4743 bInGlobalSection = true;
4744 bGlobalOnly = global_only;
4745 bAllowIncludeRegistry = allow_include_registry;
4747 init_globals(initialize_globals);
4751 if (save_defaults) {
4756 if (!initialize_globals) {
4757 free_param_opts(&Globals.param_opt);
4758 apply_lp_set_cmdline();
4761 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4763 /* We get sections first, so have to start 'behind' to make up */
4766 if (lp_config_backend_is_file()) {
4767 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4768 current_user_info.domain,
4771 smb_panic("lp_load_ex: out of memory");
4774 add_to_file_list(pszFname, n2);
4776 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4779 /* finish up the last section */
4780 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4782 if (iServiceIndex >= 0) {
4783 bRetval = service_ok(iServiceIndex);
4787 if (lp_config_backend_is_registry()) {
4788 /* config backend changed to registry in config file */
4790 * We need to use this extra global variable here to
4791 * survive restart: init_globals uses this as a default
4792 * for ConfigBackend. Otherwise, init_globals would
4793 * send us into an endless loop here.
4795 config_backend = CONFIG_BACKEND_REGISTRY;
4797 DEBUG(1, ("lp_load_ex: changing to config backend "
4800 lp_kill_all_services();
4801 return lp_load_ex(pszFname, global_only, save_defaults,
4802 add_ipc, initialize_globals,
4803 allow_include_registry,
4806 } else if (lp_config_backend_is_registry()) {
4807 bRetval = process_registry_globals();
4809 DEBUG(0, ("Illegal config backend given: %d\n",
4810 lp_config_backend()));
4814 if (bRetval && lp_registry_shares()) {
4815 if (load_all_shares) {
4816 bRetval = process_registry_shares();
4818 bRetval = reload_registry_shares();
4823 char *serv = lp_auto_services(talloc_tos());
4824 lp_add_auto_services(serv);
4829 /* When 'restrict anonymous = 2' guest connections to ipc$
4831 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4832 if ( lp_enable_asu_support() ) {
4833 lp_add_ipc("ADMIN$", false);
4837 set_allowed_client_auth();
4839 if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4840 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4841 lp_passwordserver()));
4846 /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4847 /* if bWINSsupport is true and we are in the client */
4848 if (lp_is_in_client() && Globals.bWINSsupport) {
4849 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4854 fault_configure(smb_panic_s3);
4856 bAllowIncludeRegistry = true;
4861 bool lp_load(const char *pszFname,
4865 bool initialize_globals)
4867 return lp_load_ex(pszFname,
4872 true, /* allow_include_registry */
4873 false); /* load_all_shares*/
4876 bool lp_load_initial_only(const char *pszFname)
4878 return lp_load_ex(pszFname,
4879 true, /* global only */
4880 false, /* save_defaults */
4881 false, /* add_ipc */
4882 true, /* initialize_globals */
4883 false, /* allow_include_registry */
4884 false); /* load_all_shares*/
4888 * most common lp_load wrapper, loading only the globals
4890 bool lp_load_global(const char *file_name)
4892 return lp_load_ex(file_name,
4893 true, /* global_only */
4894 false, /* save_defaults */
4895 false, /* add_ipc */
4896 true, /* initialize_globals */
4897 true, /* allow_include_registry */
4898 false); /* load_all_shares*/
4902 * lp_load wrapper, especially for clients
4904 bool lp_load_client(const char *file_name)
4906 lp_set_in_client(true);
4908 return lp_load_global(file_name);
4912 * lp_load wrapper, loading only globals, but intended
4913 * for subsequent calls, not reinitializing the globals
4916 bool lp_load_global_no_reinit(const char *file_name)
4918 return lp_load_ex(file_name,
4919 true, /* global_only */
4920 false, /* save_defaults */
4921 false, /* add_ipc */
4922 false, /* initialize_globals */
4923 true, /* allow_include_registry */
4924 false); /* load_all_shares*/
4928 * lp_load wrapper, especially for clients, no reinitialization
4930 bool lp_load_client_no_reinit(const char *file_name)
4932 lp_set_in_client(true);
4934 return lp_load_global_no_reinit(file_name);
4937 bool lp_load_with_registry_shares(const char *pszFname,
4941 bool initialize_globals)
4943 return lp_load_ex(pszFname,
4948 true, /* allow_include_registry */
4949 true); /* load_all_shares*/
4952 /***************************************************************************
4953 Return the max number of services.
4954 ***************************************************************************/
4956 int lp_numservices(void)
4958 return (iNumServices);
4961 /***************************************************************************
4962 Display the contents of the services array in human-readable form.
4963 ***************************************************************************/
4965 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4970 defaults_saved = false;
4974 dump_a_service(&sDefault, f);
4976 for (iService = 0; iService < maxtoprint; iService++) {
4978 lp_dump_one(f, show_defaults, iService);
4982 /***************************************************************************
4983 Display the contents of one service in human-readable form.
4984 ***************************************************************************/
4986 void lp_dump_one(FILE * f, bool show_defaults, int snum)
4989 if (ServicePtrs[snum]->szService[0] == '\0')
4991 dump_a_service(ServicePtrs[snum], f);
4995 /***************************************************************************
4996 Return the number of the service with the given name, or -1 if it doesn't
4997 exist. Note that this is a DIFFERENT ANIMAL from the internal function
4998 getservicebyname()! This works ONLY if all services have been loaded, and
4999 does not copy the found service.
5000 ***************************************************************************/
5002 int lp_servicenumber(const char *pszServiceName)
5005 fstring serviceName;
5007 if (!pszServiceName) {
5008 return GLOBAL_SECTION_SNUM;
5011 for (iService = iNumServices - 1; iService >= 0; iService--) {
5012 if (VALID(iService) && ServicePtrs[iService]->szService) {
5014 * The substitution here is used to support %U is
5017 fstrcpy(serviceName, ServicePtrs[iService]->szService);
5018 standard_sub_basic(get_current_username(),
5019 current_user_info.domain,
5020 serviceName,sizeof(serviceName));
5021 if (strequal(serviceName, pszServiceName)) {
5027 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5028 struct timespec last_mod;
5030 if (!usershare_exists(iService, &last_mod)) {
5031 /* Remove the share security tdb entry for it. */
5032 delete_share_security(lp_servicename(talloc_tos(), iService));
5033 /* Remove it from the array. */
5034 free_service_byindex(iService);
5035 /* Doesn't exist anymore. */
5036 return GLOBAL_SECTION_SNUM;
5039 /* Has it been modified ? If so delete and reload. */
5040 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5042 /* Remove it from the array. */
5043 free_service_byindex(iService);
5044 /* and now reload it. */
5045 iService = load_usershare_service(pszServiceName);
5050 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5051 return GLOBAL_SECTION_SNUM;
5057 /*******************************************************************
5058 A useful volume label function.
5059 ********************************************************************/
5061 const char *volume_label(TALLOC_CTX *ctx, int snum)
5064 const char *label = lp_volume(ctx, snum);
5066 label = lp_servicename(ctx, snum);
5069 /* This returns a 33 byte guarenteed null terminated string. */
5070 ret = talloc_strndup(ctx, label, 32);
5077 /*******************************************************************
5078 Get the default server type we will announce as via nmbd.
5079 ********************************************************************/
5081 int lp_default_server_announce(void)
5083 int default_server_announce = 0;
5084 default_server_announce |= SV_TYPE_WORKSTATION;
5085 default_server_announce |= SV_TYPE_SERVER;
5086 default_server_announce |= SV_TYPE_SERVER_UNIX;
5088 /* note that the flag should be set only if we have a
5089 printer service but nmbd doesn't actually load the
5090 services so we can't tell --jerry */
5092 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5094 default_server_announce |= SV_TYPE_SERVER_NT;
5095 default_server_announce |= SV_TYPE_NT;
5097 switch (lp_server_role()) {
5098 case ROLE_DOMAIN_MEMBER:
5099 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5101 case ROLE_DOMAIN_PDC:
5102 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5104 case ROLE_DOMAIN_BDC:
5105 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5107 case ROLE_STANDALONE:
5111 if (lp_time_server())
5112 default_server_announce |= SV_TYPE_TIME_SOURCE;
5114 if (lp_host_msdfs())
5115 default_server_announce |= SV_TYPE_DFS_SERVER;
5117 return default_server_announce;
5120 /***********************************************************
5121 If we are PDC then prefer us as DMB
5122 ************************************************************/
5124 bool lp_domain_master(void)
5126 if (Globals.domain_master == Auto)
5127 return (lp_server_role() == ROLE_DOMAIN_PDC);
5129 return (bool)Globals.domain_master;
5132 /***********************************************************
5133 If we are PDC then prefer us as DMB
5134 ************************************************************/
5136 static bool lp_domain_master_true_or_auto(void)
5138 if (Globals.domain_master) /* auto or yes */
5144 /***********************************************************
5145 If we are DMB then prefer us as LMB
5146 ************************************************************/
5148 bool lp_preferred_master(void)
5150 if (Globals.iPreferredMaster == Auto)
5151 return (lp_local_master() && lp_domain_master());
5153 return (bool)Globals.iPreferredMaster;
5156 /*******************************************************************
5158 ********************************************************************/
5160 void lp_remove_service(int snum)
5162 ServicePtrs[snum]->valid = false;
5163 invalid_services[num_invalid_services++] = snum;
5166 /*******************************************************************
5168 ********************************************************************/
5170 void lp_copy_service(int snum, const char *new_name)
5172 do_section(new_name, NULL);
5174 snum = lp_servicenumber(new_name);
5176 char *name = lp_servicename(talloc_tos(), snum);
5177 lp_do_parameter(snum, "copy", name);
5182 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5184 const char *ret = lp__printername(talloc_tos(), snum);
5185 if (ret == NULL || *ret == '\0') {
5186 ret = lp_const_servicename(snum);
5193 /***********************************************************
5194 Allow daemons such as winbindd to fix their logfile name.
5195 ************************************************************/
5197 void lp_set_logfile(const char *name)
5199 string_set(&Globals.logfile, name);
5200 debug_set_logfile(name);
5203 /*******************************************************************
5204 Return the max print jobs per queue.
5205 ********************************************************************/
5207 int lp_maxprintjobs(int snum)
5209 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5210 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5211 maxjobs = PRINT_MAX_JOBID - 1;
5216 const char *lp_printcapname(void)
5218 if ((Globals.szPrintcapname != NULL) &&
5219 (Globals.szPrintcapname[0] != '\0'))
5220 return Globals.szPrintcapname;
5222 if (sDefault.iPrinting == PRINT_CUPS) {
5230 if (sDefault.iPrinting == PRINT_BSD)
5231 return "/etc/printcap";
5233 return PRINTCAP_NAME;
5236 static uint32 spoolss_state;
5238 bool lp_disable_spoolss( void )
5240 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5241 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5243 return spoolss_state == SVCCTL_STOPPED ? true : false;
5246 void lp_set_spoolss_state( uint32 state )
5248 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5250 spoolss_state = state;
5253 uint32 lp_get_spoolss_state( void )
5255 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5258 /*******************************************************************
5259 Ensure we don't use sendfile if server smb signing is active.
5260 ********************************************************************/
5262 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5264 bool sign_active = false;
5266 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5267 if (get_Protocol() < PROTOCOL_NT1) {
5270 if (signing_state) {
5271 sign_active = smb_signing_is_active(signing_state);
5273 return (lp__use_sendfile(snum) &&
5274 (get_remote_arch() != RA_WIN95) &&
5278 /*******************************************************************
5279 Turn off sendfile if we find the underlying OS doesn't support it.
5280 ********************************************************************/
5282 void set_use_sendfile(int snum, bool val)
5284 if (LP_SNUM_OK(snum))
5285 ServicePtrs[snum]->bUseSendfile = val;
5287 sDefault.bUseSendfile = val;
5290 /*******************************************************************
5291 Turn off storing DOS attributes if this share doesn't support it.
5292 ********************************************************************/
5294 void set_store_dos_attributes(int snum, bool val)
5296 if (!LP_SNUM_OK(snum))
5298 ServicePtrs[(snum)]->bStoreDosAttributes = val;
5301 void lp_set_mangling_method(const char *new_method)
5303 string_set(&Globals.szManglingMethod, new_method);
5306 /*******************************************************************
5307 Global state for POSIX pathname processing.
5308 ********************************************************************/
5310 static bool posix_pathnames;
5312 bool lp_posix_pathnames(void)
5314 return posix_pathnames;
5317 /*******************************************************************
5318 Change everything needed to ensure POSIX pathname processing (currently
5320 ********************************************************************/
5322 void lp_set_posix_pathnames(void)
5324 posix_pathnames = true;
5327 /*******************************************************************
5328 Global state for POSIX lock processing - CIFS unix extensions.
5329 ********************************************************************/
5331 bool posix_default_lock_was_set;
5332 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5334 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5336 if (posix_default_lock_was_set) {
5337 return posix_cifsx_locktype;
5339 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5343 /*******************************************************************
5344 ********************************************************************/
5346 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5348 posix_default_lock_was_set = true;
5349 posix_cifsx_locktype = val;
5352 int lp_min_receive_file_size(void)
5354 if (Globals.iminreceivefile < 0) {
5357 return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5360 /*******************************************************************
5361 Safe wide links checks.
5362 This helper function always verify the validity of wide links,
5363 even after a configuration file reload.
5364 ********************************************************************/
5366 static bool lp_widelinks_internal(int snum)
5368 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5369 sDefault.bWidelinks);
5372 void widelinks_warning(int snum)
5374 if (lp_allow_insecure_widelinks()) {
5378 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5379 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5380 "These parameters are incompatible. "
5381 "Wide links will be disabled for this share.\n",
5382 lp_servicename(talloc_tos(), snum) ));
5386 bool lp_widelinks(int snum)
5388 /* wide links is always incompatible with unix extensions */
5389 if (lp_unix_extensions()) {
5391 * Unless we have "allow insecure widelinks"
5394 if (!lp_allow_insecure_widelinks()) {
5399 return lp_widelinks_internal(snum);
5402 bool lp_writeraw(void)
5404 if (lp_async_smb_echo_handler()) {
5407 return lp__writeraw();
5410 bool lp_readraw(void)
5412 if (lp_async_smb_echo_handler()) {
5415 return lp__readraw();
5418 int lp_server_role(void)
5420 return lp_find_server_role(lp__server_role(),
5422 lp__domain_logons(),
5423 lp_domain_master_true_or_auto());
5426 int lp_security(void)
5428 return lp_find_security(lp__server_role(),