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"
72 #ifdef HAVE_SYS_SYSCTL_H
73 #include <sys/sysctl.h>
76 #ifdef HAVE_HTTPCONNECTENCRYPT
77 #include <cups/http.h>
80 #ifdef CLUSTER_SUPPORT
81 #include "ctdb_private.h"
86 extern userdom_struct current_user_info;
88 /* the special value for the include parameter
89 * to be interpreted not as a file name but to
90 * trigger loading of the global smb.conf options
92 #ifndef INCLUDE_REGISTRY_NAME
93 #define INCLUDE_REGISTRY_NAME "registry"
96 static bool in_client = false; /* Not in the client by default */
97 static struct smbconf_csn conf_last_csn;
99 static int config_backend = CONFIG_BACKEND_FILE;
101 /* some helpful bits */
102 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
103 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
105 #define USERSHARE_VALID 1
106 #define USERSHARE_PENDING_DELETE 2
108 static bool defaults_saved = false;
110 #define LOADPARM_EXTRA_GLOBALS \
111 struct parmlist_entry *param_opt; \
114 int iminreceivefile; \
115 char *szPrintcapname; \
117 int iPreferredMaster; \
118 char *szLdapMachineSuffix; \
119 char *szLdapUserSuffix; \
120 char *szLdapIdmapSuffix; \
121 char *szLdapGroupSuffix; \
124 char *szUsershareTemplateShare; \
127 int winbindMaxDomainConnections; \
128 int ismb2_max_credits; \
130 char *tls_certfile; \
134 char *panic_action; \
135 int bPreferredMaster;
137 #include "param/param_global.h"
139 static struct loadparm_global Globals;
141 /* This is a default service used to prime a services structure */
142 static struct loadparm_service sDefault =
147 .usershare_last_mod = {0, 0},
151 .szInvalidUsers = NULL,
152 .szValidUsers = NULL,
153 .szAdminUsers = NULL,
158 .szRootPreExec = NULL,
159 .szRootPostExec = NULL,
160 .szCupsOptions = NULL,
161 .szPrintcommand = NULL,
162 .szLpqcommand = NULL,
163 .szLprmcommand = NULL,
164 .szLppausecommand = NULL,
165 .szLpresumecommand = NULL,
166 .szQueuepausecommand = NULL,
167 .szQueueresumecommand = NULL,
168 .szPrintername = NULL,
169 .szPrintjobUsername = NULL,
170 .szDontdescend = NULL,
171 .szHostsallow = NULL,
173 .szMagicScript = NULL,
174 .szMagicOutput = NULL,
177 .szVetoOplockFiles = NULL,
185 .szVfsObjects = NULL,
186 .szMSDfsProxy = NULL,
187 .szAioWriteBehind = NULL,
190 .iMaxPrintJobs = 1000,
191 .iMaxReportedPrintJobs = 0,
192 .iWriteCacheSize = 0,
193 .iCreate_mask = 0744,
194 .iCreate_force_mode = 0,
195 .iSecurity_mask = 0777,
196 .iSecurity_force_mode = 0,
198 .iDir_force_mode = 0,
199 .iDir_Security_mask = 0777,
200 .iDir_Security_force_mode = 0,
201 .iMaxConnections = 0,
202 .iDefaultCase = CASE_LOWER,
203 .iPrinting = DEFAULT_PRINTING,
204 .iOplockContentionLimit = 2,
207 .iDfreeCacheTime = 0,
208 .bPreexecClose = false,
209 .bRootpreexecClose = false,
210 .iCaseSensitive = Auto,
211 .bCasePreserve = true,
212 .bShortCasePreserve = true,
213 .bHideDotFiles = true,
214 .bHideSpecialFiles = false,
215 .bHideUnReadable = false,
216 .bHideUnWriteableFiles = false,
218 .bAccessBasedShareEnum = false,
222 .bGuest_only = false,
223 .bAdministrative_share = false,
226 .bPrintNotifyBackchannel = true,
227 .bMap_system = false,
228 .bMap_hidden = false,
229 .bMap_archive = true,
230 .bStoreDosAttributes = false,
231 .bDmapiSupport = false,
233 .iStrictLocking = Auto,
234 .bPosixLocking = true,
237 .bKernelOplocks = false,
238 .bLevel2OpLocks = true,
240 .bMangledNames = true,
243 .bSyncAlways = false,
244 .bStrictAllocate = false,
245 .bStrictSync = false,
248 .bDeleteReadonly = false,
249 .bFakeOplocks = false,
250 .bDeleteVetoFiles = false,
251 .bDosFilemode = false,
252 .bDosFiletimes = true,
253 .bDosFiletimeResolution = false,
254 .bFakeDirCreateTimes = false,
255 .bBlockingLocks = true,
256 .bInheritPerms = false,
257 .bInheritACLS = false,
258 .bInheritOwner = false,
260 .bUseClientDriver = false,
261 .bDefaultDevmode = true,
262 .bForcePrintername = false,
263 .bNTAclSupport = true,
264 .bForceUnknownAclUser = false,
265 .bUseSendfile = false,
266 .bProfileAcls = false,
267 .bMap_acl_inherit = false,
270 .bAclCheckPermissions = true,
271 .bAclMapFullControl = true,
272 .bAclGroupControl = false,
273 .bChangeNotify = true,
274 .bKernelChangeNotify = true,
275 .iallocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
278 .iMap_readonly = MAP_READONLY_YES,
279 #ifdef BROKEN_DIRECTORY_HANDLING
280 .iDirectoryNameCacheSize = 0,
282 .iDirectoryNameCacheSize = 100,
284 .ismb_encrypt = Auto,
289 /* local variables */
290 static struct loadparm_service **ServicePtrs = NULL;
291 static int iNumServices = 0;
292 static int iServiceIndex = 0;
293 static struct db_context *ServiceHash;
294 static int *invalid_services = NULL;
295 static int num_invalid_services = 0;
296 static bool bInGlobalSection = true;
297 static bool bGlobalOnly = false;
299 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
301 /* prototypes for the special type handlers */
302 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
303 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
304 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
305 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
306 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
307 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
308 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
309 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
310 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
311 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
312 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
313 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
315 /* these are parameter handlers which are not needed in the
319 #define handle_logfile NULL
321 static void set_allowed_client_auth(void);
323 static void add_to_file_list(const char *fname, const char *subfname);
324 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
325 static void free_param_opts(struct parmlist_entry **popts);
327 #include "lib/param/param_table.c"
329 /***************************************************************************
330 Initialise the sDefault parameter structure for the printer values.
331 ***************************************************************************/
333 static void init_printer_values(struct loadparm_service *pService)
335 /* choose defaults depending on the type of printing */
336 switch (pService->iPrinting) {
341 string_set(&pService->szLpqcommand, "lpq -P'%p'");
342 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
343 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
348 string_set(&pService->szLpqcommand, "lpq -P'%p'");
349 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
350 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
351 string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
352 string_set(&pService->szQueueresumecommand, "lpc start '%p'");
353 string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
354 string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
360 /* set the lpq command to contain the destination printer
361 name only. This is used by cups_queue_get() */
362 string_set(&pService->szLpqcommand, "%p");
363 string_set(&pService->szLprmcommand, "");
364 string_set(&pService->szPrintcommand, "");
365 string_set(&pService->szLppausecommand, "");
366 string_set(&pService->szLpresumecommand, "");
367 string_set(&pService->szQueuepausecommand, "");
368 string_set(&pService->szQueueresumecommand, "");
370 string_set(&pService->szLpqcommand, "lpq -P'%p'");
371 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
372 string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
373 string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
374 string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
375 string_set(&pService->szQueuepausecommand, "disable '%p'");
376 string_set(&pService->szQueueresumecommand, "enable '%p'");
377 #endif /* HAVE_CUPS */
382 string_set(&pService->szLpqcommand, "lpstat -o%p");
383 string_set(&pService->szLprmcommand, "cancel %p-%j");
384 string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
385 string_set(&pService->szQueuepausecommand, "disable %p");
386 string_set(&pService->szQueueresumecommand, "enable %p");
388 string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
389 string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
394 string_set(&pService->szLpqcommand, "lpq -P%p");
395 string_set(&pService->szLprmcommand, "lprm -P%p %j");
396 string_set(&pService->szPrintcommand, "lp -r -P%p %s");
399 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST) || defined(ENABLE_BUILD_FARM_HACKS)
404 TALLOC_CTX *tmp_ctx = talloc_stackframe();
407 tdbfile = talloc_asprintf(
408 tmp_ctx, "tdbfile=%s",
409 lp_parm_const_string(-1, "vlp", "tdbfile",
411 if (tdbfile == NULL) {
412 tdbfile="tdbfile=/tmp/vlp.tdb";
415 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
417 string_set(&pService->szPrintcommand,
418 tmp ? tmp : "vlp print %p %s");
420 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
422 string_set(&pService->szLpqcommand,
423 tmp ? tmp : "vlp lpq %p");
425 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
427 string_set(&pService->szLprmcommand,
428 tmp ? tmp : "vlp lprm %p %j");
430 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
432 string_set(&pService->szLppausecommand,
433 tmp ? tmp : "vlp lppause %p %j");
435 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
437 string_set(&pService->szLpresumecommand,
438 tmp ? tmp : "vlp lpresume %p %j");
440 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
442 string_set(&pService->szQueuepausecommand,
443 tmp ? tmp : "vlp queuepause %p");
445 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
447 string_set(&pService->szQueueresumecommand,
448 tmp ? tmp : "vlp queueresume %p");
449 TALLOC_FREE(tmp_ctx);
453 #endif /* DEVELOPER */
458 * Function to return the default value for the maximum number of open
459 * file descriptors permitted. This function tries to consult the
460 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
461 * the smaller of those.
463 static int max_open_files(void)
465 int sysctl_max = MAX_OPEN_FILES;
466 int rlimit_max = MAX_OPEN_FILES;
468 #ifdef HAVE_SYSCTLBYNAME
470 size_t size = sizeof(sysctl_max);
471 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
476 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
482 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
483 rlimit_max = rl.rlim_cur;
485 #if defined(RLIM_INFINITY)
486 if(rl.rlim_cur == RLIM_INFINITY)
487 rlimit_max = MAX_OPEN_FILES;
492 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
493 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
494 "minimum Windows limit (%d)\n",
496 MIN_OPEN_FILES_WINDOWS));
497 sysctl_max = MIN_OPEN_FILES_WINDOWS;
500 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
501 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
502 "minimum Windows limit (%d)\n",
504 MIN_OPEN_FILES_WINDOWS));
505 rlimit_max = MIN_OPEN_FILES_WINDOWS;
508 return MIN(sysctl_max, rlimit_max);
512 * Common part of freeing allocated data for one parameter.
514 static void free_one_parameter_common(void *parm_ptr,
515 struct parm_struct parm)
517 if ((parm.type == P_STRING) ||
518 (parm.type == P_USTRING))
520 string_free((char**)parm_ptr);
521 } else if (parm.type == P_LIST) {
522 TALLOC_FREE(*((char***)parm_ptr));
527 * Free the allocated data for one parameter for a share
528 * given as a service struct.
530 static void free_one_parameter(struct loadparm_service *service,
531 struct parm_struct parm)
535 if (parm.p_class != P_LOCAL) {
539 parm_ptr = lp_parm_ptr(service, &parm);
541 free_one_parameter_common(parm_ptr, parm);
545 * Free the allocated parameter data of a share given
546 * as a service struct.
548 static void free_parameters(struct loadparm_service *service)
552 for (i=0; parm_table[i].label; i++) {
553 free_one_parameter(service, parm_table[i]);
558 * Free the allocated data for one parameter for a given share
559 * specified by an snum.
561 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
566 parm_ptr = lp_parm_ptr(NULL, &parm);
567 } else if (parm.p_class != P_LOCAL) {
570 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
573 free_one_parameter_common(parm_ptr, parm);
577 * Free the allocated parameter data for a share specified
580 static void free_parameters_by_snum(int snum)
584 for (i=0; parm_table[i].label; i++) {
585 free_one_parameter_by_snum(snum, parm_table[i]);
590 * Free the allocated global parameters.
592 static void free_global_parameters(void)
594 free_param_opts(&Globals.param_opt);
595 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
598 static int map_parameter(const char *pszParmName);
600 struct lp_stored_option {
601 struct lp_stored_option *prev, *next;
606 static struct lp_stored_option *stored_options;
609 save options set by lp_set_cmdline() into a list. This list is
610 re-applied when we do a globals reset, so that cmdline set options
611 are sticky across reloads of smb.conf
613 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
615 struct lp_stored_option *entry, *entry_next;
616 for (entry = stored_options; entry != NULL; entry = entry_next) {
617 entry_next = entry->next;
618 if (strcmp(pszParmName, entry->label) == 0) {
619 DLIST_REMOVE(stored_options, entry);
625 entry = talloc(NULL, struct lp_stored_option);
630 entry->label = talloc_strdup(entry, pszParmName);
636 entry->value = talloc_strdup(entry, pszParmValue);
642 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
647 static bool apply_lp_set_cmdline(void)
649 struct lp_stored_option *entry = NULL;
650 for (entry = stored_options; entry != NULL; entry = entry->next) {
651 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
652 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
653 entry->label, entry->value));
660 /***************************************************************************
661 Initialise the global parameter structure.
662 ***************************************************************************/
664 static void init_globals(bool reinit_globals)
666 static bool done_init = false;
670 /* If requested to initialize only once and we've already done it... */
671 if (!reinit_globals && done_init) {
672 /* ... then we have nothing more to do */
677 /* The logfile can be set before this is invoked. Free it if so. */
678 if (Globals.logfile != NULL) {
679 string_free(&Globals.logfile);
680 Globals.logfile = NULL;
684 free_global_parameters();
687 /* This memset and the free_global_parameters() above will
688 * wipe out smb.conf options set with lp_set_cmdline(). The
689 * apply_lp_set_cmdline() call puts these values back in the
690 * table once the defaults are set */
691 ZERO_STRUCT(Globals);
693 for (i = 0; parm_table[i].label; i++) {
694 if ((parm_table[i].type == P_STRING ||
695 parm_table[i].type == P_USTRING))
697 string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
702 string_set(&sDefault.fstype, FSTYPE_STRING);
703 string_set(&sDefault.szPrintjobUsername, "%U");
705 init_printer_values(&sDefault);
708 DEBUG(3, ("Initialising global parameters\n"));
710 /* Must manually force to upper case here, as this does not go via the handler */
711 string_set(&Globals.szNetbiosName, myhostname_upper());
713 string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
714 string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
716 /* use the new 'hash2' method by default, with a prefix of 1 */
717 string_set(&Globals.szManglingMethod, "hash2");
718 Globals.mangle_prefix = 1;
720 string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
722 /* using UTF8 by default allows us to support all chars */
723 string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
725 /* Use codepage 850 as a default for the dos character set */
726 string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
729 * Allow the default PASSWD_CHAT to be overridden in local.h.
731 string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
733 string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
735 string_set(&Globals.szPasswdProgram, "");
736 string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
737 string_set(&Globals.szStateDir, get_dyn_STATEDIR());
738 string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
739 string_set(&Globals.szPidDir, get_dyn_PIDDIR());
740 string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
742 * By default support explicit binding to broadcast
745 Globals.bNmbdBindExplicitBroadcast = true;
747 if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
748 smb_panic("init_globals: ENOMEM");
750 string_set(&Globals.szServerString, s);
753 string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
756 string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
758 string_set(&Globals.szLogonDrive, "");
759 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
760 string_set(&Globals.szLogonHome, "\\\\%N\\%U");
761 string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
763 Globals.szNameResolveOrder = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
764 string_set(&Globals.szPasswordServer, "*");
766 Globals.AlgorithmicRidBase = BASE_RID;
768 Globals.bLoadPrinters = true;
769 Globals.PrintcapCacheTime = 750; /* 12.5 minutes */
771 Globals.ConfigBackend = config_backend;
772 Globals.server_role = ROLE_AUTO;
774 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
775 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
776 Globals.max_xmit = 0x4104;
777 Globals.max_mux = 50; /* This is *needed* for profile support. */
778 Globals.lpqcachetime = 30; /* changed to handle large print servers better -- jerry */
779 Globals.bDisableSpoolss = false;
780 Globals.iMaxSmbdProcesses = 0;/* no limit specified */
781 Globals.pwordlevel = 0;
782 Globals.unamelevel = 0;
783 Globals.deadtime = 0;
784 Globals.getwd_cache = true;
785 Globals.bLargeReadwrite = true;
786 Globals.max_log_size = 5000;
787 Globals.max_open_files = max_open_files();
788 Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
789 Globals.srv_maxprotocol = PROTOCOL_SMB2_10;
790 Globals.srv_minprotocol = PROTOCOL_LANMAN1;
791 Globals.security = SEC_USER;
792 Globals.bEncryptPasswords = true;
793 Globals.clientSchannel = Auto;
794 Globals.serverSchannel = Auto;
795 Globals.bReadRaw = true;
796 Globals.bWriteRaw = true;
797 Globals.bNullPasswords = false;
798 Globals.bObeyPamRestrictions = false;
800 Globals.bSyslogOnly = false;
801 Globals.bTimestampLogs = true;
802 string_set(&Globals.loglevel, "0");
803 Globals.bDebugPrefixTimestamp = false;
804 Globals.bDebugHiresTimestamp = true;
805 Globals.bDebugPid = false;
806 Globals.bDebugUid = false;
807 Globals.bDebugClass = false;
808 Globals.bEnableCoreFiles = true;
809 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
810 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
811 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
812 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
813 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
814 Globals.lm_interval = 60;
815 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
816 Globals.bNISHomeMap = false;
817 #ifdef WITH_NISPLUS_HOME
818 string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
820 string_set(&Globals.szNISHomeMapName, "auto.home");
823 Globals.bTimeServer = false;
824 Globals.bBindInterfacesOnly = false;
825 Globals.bUnixPasswdSync = false;
826 Globals.bPamPasswordChange = false;
827 Globals.bPasswdChatDebug = false;
828 Globals.iPasswdChatTimeout = 2; /* 2 second default. */
829 Globals.bNTPipeSupport = true; /* Do NT pipes by default. */
830 Globals.bNTStatusSupport = true; /* Use NT status by default. */
831 Globals.bStatCache = true; /* use stat cache by default */
832 Globals.iMaxStatCacheSize = 256; /* 256k by default */
833 Globals.restrict_anonymous = 0;
834 Globals.bClientLanManAuth = false; /* Do NOT use the LanMan hash if it is available */
835 Globals.bClientPlaintextAuth = false; /* Do NOT use a plaintext password even if is requested by the server */
836 Globals.bLanmanAuth = false; /* Do NOT use the LanMan hash, even if it is supplied */
837 Globals.bNTLMAuth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
838 Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
839 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
841 Globals.map_to_guest = 0; /* By Default, "Never" */
842 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
843 Globals.enhanced_browsing = true;
844 Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
845 #ifdef MMAP_BLACKLIST
846 Globals.bUseMmap = false;
848 Globals.bUseMmap = true;
850 Globals.bUnicode = true;
851 Globals.bUnixExtensions = true;
852 Globals.bResetOnZeroVC = false;
853 Globals.bLogWriteableFilesOnExit = false;
854 Globals.bCreateKrb5Conf = true;
855 Globals.winbindMaxDomainConnections = 1;
857 /* hostname lookups can be very expensive and are broken on
858 a large number of sites (tridge) */
859 Globals.bHostnameLookups = false;
861 string_set(&Globals.passdb_backend, "tdbsam");
862 string_set(&Globals.szLdapSuffix, "");
863 string_set(&Globals.szLdapMachineSuffix, "");
864 string_set(&Globals.szLdapUserSuffix, "");
865 string_set(&Globals.szLdapGroupSuffix, "");
866 string_set(&Globals.szLdapIdmapSuffix, "");
868 string_set(&Globals.szLdapAdminDn, "");
869 Globals.ldap_ssl = LDAP_SSL_START_TLS;
870 Globals.ldap_ssl_ads = false;
871 Globals.ldap_deref = -1;
872 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
873 Globals.ldap_delete_dn = false;
874 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
875 Globals.ldap_follow_referral = Auto;
876 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
877 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
878 Globals.ldap_page_size = LDAP_PAGE_SIZE;
880 Globals.ldap_debug_level = 0;
881 Globals.ldap_debug_threshold = 10;
883 /* This is what we tell the afs client. in reality we set the token
884 * to never expire, though, when this runs out the afs client will
885 * forget the token. Set to 0 to get NEVERDATE.*/
886 Globals.iAfsTokenLifetime = 604800;
887 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
889 /* these parameters are set to defaults that are more appropriate
890 for the increasing samba install base:
892 as a member of the workgroup, that will possibly become a
893 _local_ master browser (lm = true). this is opposed to a forced
894 local master browser startup (pm = true).
896 doesn't provide WINS server service by default (wsupp = false),
897 and doesn't provide domain master browser services by default, either.
901 Globals.bMsAddPrinterWizard = true;
902 Globals.os_level = 20;
903 Globals.bLocalMaster = true;
904 Globals.domain_master = Auto; /* depending on bDomainLogons */
905 Globals.bDomainLogons = false;
906 Globals.bBrowseList = true;
907 Globals.bWINSsupport = false;
908 Globals.bWINSproxy = false;
910 TALLOC_FREE(Globals.szInitLogonDelayedHosts);
911 Globals.InitLogonDelay = 100; /* 100 ms default delay */
913 Globals.bWINSdnsProxy = true;
915 Globals.bAllowTrustedDomains = true;
916 string_set(&Globals.szIdmapBackend, "tdb");
918 string_set(&Globals.szTemplateShell, "/bin/false");
919 string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
920 string_set(&Globals.szWinbindSeparator, "\\");
922 string_set(&Globals.szCupsServer, "");
923 string_set(&Globals.szIPrintServer, "");
925 #ifdef CLUSTER_SUPPORT
926 string_set(&Globals.ctdbdSocket, CTDB_PATH);
928 string_set(&Globals.ctdbdSocket, "");
931 Globals.szClusterAddresses = NULL;
932 Globals.clustering = false;
933 Globals.ctdb_timeout = 0;
934 Globals.ctdb_locktime_warn_threshold = 0;
936 Globals.winbind_cache_time = 300; /* 5 minutes */
937 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
938 Globals.winbind_max_clients = 200;
939 Globals.bWinbindEnumUsers = false;
940 Globals.bWinbindEnumGroups = false;
941 Globals.bWinbindUseDefaultDomain = false;
942 Globals.bWinbindTrustedDomainsOnly = false;
943 Globals.bWinbindNestedGroups = true;
944 Globals.winbind_expand_groups = 1;
945 Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
946 Globals.bWinbindRefreshTickets = false;
947 Globals.bWinbindOfflineLogon = false;
949 Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
950 Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
952 Globals.bPassdbExpandExplicit = false;
954 Globals.name_cache_timeout = 660; /* In seconds */
956 Globals.bUseSpnego = true;
957 Globals.bClientUseSpnego = true;
959 Globals.client_signing = SMB_SIGNING_DEFAULT;
960 Globals.server_signing = SMB_SIGNING_DEFAULT;
962 Globals.bDeferSharingViolations = true;
963 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
965 Globals.bEnablePrivileges = true;
966 Globals.bHostMSDfs = true;
967 Globals.bASUSupport = false;
969 /* User defined shares. */
970 if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
971 smb_panic("init_globals: ENOMEM");
973 string_set(&Globals.szUsersharePath, s);
975 string_set(&Globals.szUsershareTemplateShare, "");
976 Globals.iUsershareMaxShares = 0;
977 /* By default disallow sharing of directories not owned by the sharer. */
978 Globals.bUsershareOwnerOnly = true;
979 /* By default disallow guest access to usershares. */
980 Globals.bUsershareAllowGuests = false;
982 Globals.iKeepalive = DEFAULT_KEEPALIVE;
984 /* By default no shares out of the registry */
985 Globals.bRegistryShares = false;
987 Globals.iminreceivefile = 0;
989 Globals.bMapUntrustedToDomain = false;
990 Globals.bMulticastDnsRegister = true;
992 Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
993 Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
994 Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
995 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
997 string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
999 /* Now put back the settings that were set with lp_set_cmdline() */
1000 apply_lp_set_cmdline();
1003 /*******************************************************************
1004 Convenience routine to grab string parameters into talloced memory
1005 and run standard_sub_basic on them. The buffers can be written to by
1006 callers without affecting the source string.
1007 ********************************************************************/
1009 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1013 /* The follow debug is useful for tracking down memory problems
1014 especially if you have an inner loop that is calling a lp_*()
1015 function that returns a string. Perhaps this debug should be
1016 present all the time? */
1019 DEBUG(10, ("lp_string(%s)\n", s));
1025 ret = talloc_sub_basic(ctx,
1026 get_current_username(),
1027 current_user_info.domain,
1029 if (trim_char(ret, '\"', '\"')) {
1030 if (strchr(ret,'\"') != NULL) {
1032 ret = talloc_sub_basic(ctx,
1033 get_current_username(),
1034 current_user_info.domain,
1042 In this section all the functions that are used to access the
1043 parameters from the rest of the program are defined
1046 #define FN_GLOBAL_STRING(fn_name,ptr) \
1047 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1048 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1049 const char *lp_ ## fn_name(void) {return(*(const char **)(&Globals.ptr) ? *(const char **)(&Globals.ptr) : "");}
1050 #define FN_GLOBAL_LIST(fn_name,ptr) \
1051 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1052 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1053 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1054 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1055 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1056 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1057 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1059 #define FN_LOCAL_STRING(fn_name,val) \
1060 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));}
1061 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1062 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1063 #define FN_LOCAL_LIST(fn_name,val) \
1064 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1065 #define FN_LOCAL_BOOL(fn_name,val) \
1066 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1067 #define FN_LOCAL_INTEGER(fn_name,val) \
1068 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1070 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1071 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1072 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1073 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1074 #define FN_LOCAL_CHAR(fn_name,val) \
1075 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1078 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1079 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1081 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1082 * build process or in smb.conf, we use that value. Otherwise they
1083 * default to the value of lp_lockdir(). */
1084 const char *lp_statedir(void) {
1085 if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1086 (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1087 return(*(char **)(&Globals.szStateDir) ?
1088 *(char **)(&Globals.szStateDir) : "");
1090 return(*(char **)(&Globals.szLockDir) ?
1091 *(char **)(&Globals.szLockDir) : "");
1093 const char *lp_cachedir(void) {
1094 if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1095 (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1096 return(*(char **)(&Globals.szCacheDir) ?
1097 *(char **)(&Globals.szCacheDir) : "");
1099 return(*(char **)(&Globals.szLockDir) ?
1100 *(char **)(&Globals.szLockDir) : "");
1102 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1103 winbindMaxDomainConnections)
1105 int lp_winbind_max_domain_connections(void)
1107 if (lp_winbind_offline_logon() &&
1108 lp_winbind_max_domain_connections_int() > 1) {
1109 DEBUG(1, ("offline logons active, restricting max domain "
1110 "connections to 1\n"));
1113 return MAX(1, lp_winbind_max_domain_connections_int());
1116 int lp_smb2_max_credits(void)
1118 if (Globals.ismb2_max_credits == 0) {
1119 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1121 return Globals.ismb2_max_credits;
1123 int lp_cups_encrypt(void)
1126 #ifdef HAVE_HTTPCONNECTENCRYPT
1127 switch (Globals.CupsEncrypt) {
1129 result = HTTP_ENCRYPT_REQUIRED;
1132 result = HTTP_ENCRYPT_ALWAYS;
1135 result = HTTP_ENCRYPT_NEVER;
1142 /* These functions remain in source3/param for now */
1144 FN_GLOBAL_STRING(configfile, szConfigFile)
1146 #include "lib/param/param_functions.c"
1148 FN_LOCAL_STRING(servicename, szService)
1149 FN_LOCAL_CONST_STRING(const_servicename, szService)
1151 /* local prototypes */
1153 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1154 static const char *get_boolean(bool bool_value);
1155 static int getservicebyname(const char *pszServiceName,
1156 struct loadparm_service *pserviceDest);
1157 static void copy_service(struct loadparm_service *pserviceDest,
1158 struct loadparm_service *pserviceSource,
1159 struct bitmap *pcopymapDest);
1160 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1162 static bool do_section(const char *pszSectionName, void *userdata);
1163 static void init_copymap(struct loadparm_service *pservice);
1164 static bool hash_a_service(const char *name, int number);
1165 static void free_service_byindex(int iService);
1166 static void show_parameter(int parmIndex);
1167 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1170 * This is a helper function for parametrical options support. It returns a
1171 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1172 * parametrical functions are quite simple
1174 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1177 bool global_section = false;
1179 struct parmlist_entry *data;
1181 if (service == NULL) {
1182 data = Globals.param_opt;
1183 global_section = true;
1185 data = service->param_opt;
1188 if (asprintf(¶m_key, "%s:%s", type, option) == -1) {
1189 DEBUG(0,("asprintf failed!\n"));
1194 if (strwicmp(data->key, param_key) == 0) {
1195 string_free(¶m_key);
1201 if (!global_section) {
1202 /* Try to fetch the same option but from globals */
1203 /* but only if we are not already working with Globals */
1204 data = Globals.param_opt;
1206 if (strwicmp(data->key, param_key) == 0) {
1207 string_free(¶m_key);
1214 string_free(¶m_key);
1220 * This is a helper function for parametrical options support. It returns a
1221 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1222 * parametrical functions are quite simple
1224 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1227 if (snum >= iNumServices) return NULL;
1230 return get_parametrics_by_service(NULL, type, option);
1232 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1237 #define MISSING_PARAMETER(name) \
1238 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1240 /*******************************************************************
1241 convenience routine to return int parameters.
1242 ********************************************************************/
1243 static int lp_int(const char *s)
1247 MISSING_PARAMETER(lp_int);
1251 return (int)strtol(s, NULL, 0);
1254 /*******************************************************************
1255 convenience routine to return unsigned long parameters.
1256 ********************************************************************/
1257 static unsigned long lp_ulong(const char *s)
1261 MISSING_PARAMETER(lp_ulong);
1265 return strtoul(s, NULL, 0);
1268 /*******************************************************************
1269 convenience routine to return boolean parameters.
1270 ********************************************************************/
1271 static bool lp_bool(const char *s)
1276 MISSING_PARAMETER(lp_bool);
1280 if (!set_boolean(s, &ret)) {
1281 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1288 /*******************************************************************
1289 convenience routine to return enum parameters.
1290 ********************************************************************/
1291 static int lp_enum(const char *s,const struct enum_list *_enum)
1295 if (!s || !*s || !_enum) {
1296 MISSING_PARAMETER(lp_enum);
1300 for (i=0; _enum[i].name; i++) {
1301 if (strequal(_enum[i].name,s))
1302 return _enum[i].value;
1305 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1309 #undef MISSING_PARAMETER
1311 /* Return parametric option from a given service. Type is a part of option before ':' */
1312 /* Parametric option has following syntax: 'Type: option = value' */
1313 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1315 struct parmlist_entry *data = get_parametrics(snum, type, option);
1317 if (data == NULL||data->value==NULL) {
1319 return lp_string(ctx, def);
1325 return lp_string(ctx, data->value);
1328 /* Return parametric option from a given service. Type is a part of option before ':' */
1329 /* Parametric option has following syntax: 'Type: option = value' */
1330 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1332 struct parmlist_entry *data = get_parametrics(snum, type, option);
1334 if (data == NULL||data->value==NULL)
1340 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1342 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1344 if (data == NULL||data->value==NULL)
1351 /* Return parametric option from a given service. Type is a part of option before ':' */
1352 /* Parametric option has following syntax: 'Type: option = value' */
1354 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1356 struct parmlist_entry *data = get_parametrics(snum, type, option);
1358 if (data == NULL||data->value==NULL)
1359 return (const char **)def;
1361 if (data->list==NULL) {
1362 data->list = str_list_make_v3(NULL, data->value, NULL);
1365 return (const char **)data->list;
1368 /* Return parametric option from a given service. Type is a part of option before ':' */
1369 /* Parametric option has following syntax: 'Type: option = value' */
1371 int lp_parm_int(int snum, const char *type, const char *option, int def)
1373 struct parmlist_entry *data = get_parametrics(snum, type, option);
1375 if (data && data->value && *data->value)
1376 return lp_int(data->value);
1381 /* Return parametric option from a given service. Type is a part of option before ':' */
1382 /* Parametric option has following syntax: 'Type: option = value' */
1384 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1386 struct parmlist_entry *data = get_parametrics(snum, type, option);
1388 if (data && data->value && *data->value)
1389 return lp_ulong(data->value);
1394 /* Return parametric option from a given service. Type is a part of option before ':' */
1395 /* Parametric option has following syntax: 'Type: option = value' */
1397 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1399 struct parmlist_entry *data = get_parametrics(snum, type, option);
1401 if (data && data->value && *data->value)
1402 return lp_bool(data->value);
1407 /* Return parametric option from a given service. Type is a part of option before ':' */
1408 /* Parametric option has following syntax: 'Type: option = value' */
1410 int lp_parm_enum(int snum, const char *type, const char *option,
1411 const struct enum_list *_enum, int def)
1413 struct parmlist_entry *data = get_parametrics(snum, type, option);
1415 if (data && data->value && *data->value && _enum)
1416 return lp_enum(data->value, _enum);
1422 /***************************************************************************
1423 Initialise a service to the defaults.
1424 ***************************************************************************/
1426 static void init_service(struct loadparm_service *pservice)
1428 memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1429 copy_service(pservice, &sDefault, NULL);
1434 * free a param_opts structure.
1435 * param_opts handling should be moved to talloc;
1436 * then this whole functions reduces to a TALLOC_FREE().
1439 static void free_param_opts(struct parmlist_entry **popts)
1441 struct parmlist_entry *opt, *next_opt;
1443 if (popts == NULL) {
1447 if (*popts != NULL) {
1448 DEBUG(5, ("Freeing parametrics:\n"));
1451 while (opt != NULL) {
1452 string_free(&opt->key);
1453 string_free(&opt->value);
1454 TALLOC_FREE(opt->list);
1455 next_opt = opt->next;
1462 /***************************************************************************
1463 Free the dynamically allocated parts of a service struct.
1464 ***************************************************************************/
1466 static void free_service(struct loadparm_service *pservice)
1471 if (pservice->szService)
1472 DEBUG(5, ("free_service: Freeing service %s\n",
1473 pservice->szService));
1475 free_parameters(pservice);
1477 string_free(&pservice->szService);
1478 TALLOC_FREE(pservice->copymap);
1480 free_param_opts(&pservice->param_opt);
1482 ZERO_STRUCTP(pservice);
1486 /***************************************************************************
1487 remove a service indexed in the ServicePtrs array from the ServiceHash
1488 and free the dynamically allocated parts
1489 ***************************************************************************/
1491 static void free_service_byindex(int idx)
1493 if ( !LP_SNUM_OK(idx) )
1496 ServicePtrs[idx]->valid = false;
1497 invalid_services[num_invalid_services++] = idx;
1499 /* we have to cleanup the hash record */
1501 if (ServicePtrs[idx]->szService) {
1502 char *canon_name = canonicalize_servicename(
1504 ServicePtrs[idx]->szService );
1506 dbwrap_delete_bystring(ServiceHash, canon_name );
1507 TALLOC_FREE(canon_name);
1510 free_service(ServicePtrs[idx]);
1513 /***************************************************************************
1514 Add a new service to the services array initialising it with the given
1516 ***************************************************************************/
1518 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1521 struct loadparm_service tservice;
1522 int num_to_alloc = iNumServices + 1;
1524 tservice = *pservice;
1526 /* it might already exist */
1528 i = getservicebyname(name, NULL);
1534 /* find an invalid one */
1536 if (num_invalid_services > 0) {
1537 i = invalid_services[--num_invalid_services];
1540 /* if not, then create one */
1541 if (i == iNumServices) {
1542 struct loadparm_service **tsp;
1545 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1547 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1551 ServicePtrs[iNumServices] = SMB_MALLOC_P(struct loadparm_service);
1552 if (!ServicePtrs[iNumServices]) {
1553 DEBUG(0,("add_a_service: out of memory!\n"));
1558 /* enlarge invalid_services here for now... */
1559 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
1561 if (tinvalid == NULL) {
1562 DEBUG(0,("add_a_service: failed to enlarge "
1563 "invalid_services!\n"));
1566 invalid_services = tinvalid;
1568 free_service_byindex(i);
1571 ServicePtrs[i]->valid = true;
1573 init_service(ServicePtrs[i]);
1574 copy_service(ServicePtrs[i], &tservice, NULL);
1576 string_set(&ServicePtrs[i]->szService, name);
1578 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1579 i, ServicePtrs[i]->szService));
1581 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1588 /***************************************************************************
1589 Convert a string to uppercase and remove whitespaces.
1590 ***************************************************************************/
1592 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1597 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1601 result = talloc_strdup(ctx, src);
1602 SMB_ASSERT(result != NULL);
1608 /***************************************************************************
1609 Add a name/index pair for the services array to the hash table.
1610 ***************************************************************************/
1612 static bool hash_a_service(const char *name, int idx)
1616 if ( !ServiceHash ) {
1617 DEBUG(10,("hash_a_service: creating servicehash\n"));
1618 ServiceHash = db_open_rbt(NULL);
1619 if ( !ServiceHash ) {
1620 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1625 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1628 canon_name = canonicalize_servicename(talloc_tos(), name );
1630 dbwrap_store_bystring(ServiceHash, canon_name,
1631 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1634 TALLOC_FREE(canon_name);
1639 /***************************************************************************
1640 Add a new home service, with the specified home directory, defaults coming
1642 ***************************************************************************/
1644 bool lp_add_home(const char *pszHomename, int iDefaultService,
1645 const char *user, const char *pszHomedir)
1649 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1650 pszHomedir[0] == '\0') {
1654 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1659 if (!(*(ServicePtrs[iDefaultService]->szPath))
1660 || strequal(ServicePtrs[iDefaultService]->szPath,
1661 lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1662 string_set(&ServicePtrs[i]->szPath, pszHomedir);
1665 if (!(*(ServicePtrs[i]->comment))) {
1666 char *comment = NULL;
1667 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1670 string_set(&ServicePtrs[i]->comment, comment);
1674 /* set the browseable flag from the global default */
1676 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1677 ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
1679 ServicePtrs[i]->autoloaded = true;
1681 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1682 user, ServicePtrs[i]->szPath ));
1687 /***************************************************************************
1688 Add a new service, based on an old one.
1689 ***************************************************************************/
1691 int lp_add_service(const char *pszService, int iDefaultService)
1693 if (iDefaultService < 0) {
1694 return add_a_service(&sDefault, pszService);
1697 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1700 /***************************************************************************
1701 Add the IPC service.
1702 ***************************************************************************/
1704 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1706 char *comment = NULL;
1707 int i = add_a_service(&sDefault, ipc_name);
1712 if (asprintf(&comment, "IPC Service (%s)",
1713 Globals.szServerString) < 0) {
1717 string_set(&ServicePtrs[i]->szPath, tmpdir());
1718 string_set(&ServicePtrs[i]->szUsername, "");
1719 string_set(&ServicePtrs[i]->comment, comment);
1720 string_set(&ServicePtrs[i]->fstype, "IPC");
1721 ServicePtrs[i]->iMaxConnections = 0;
1722 ServicePtrs[i]->bAvailable = true;
1723 ServicePtrs[i]->bRead_only = true;
1724 ServicePtrs[i]->bGuest_only = false;
1725 ServicePtrs[i]->bAdministrative_share = true;
1726 ServicePtrs[i]->bGuest_ok = guest_ok;
1727 ServicePtrs[i]->bPrint_ok = false;
1728 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1730 DEBUG(3, ("adding IPC service\n"));
1736 /***************************************************************************
1737 Add a new printer service, with defaults coming from service iFrom.
1738 ***************************************************************************/
1740 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1742 const char *comment = "From Printcap";
1743 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1748 /* note that we do NOT default the availability flag to true - */
1749 /* we take it from the default service passed. This allows all */
1750 /* dynamic printers to be disabled by disabling the [printers] */
1751 /* entry (if/when the 'available' keyword is implemented!). */
1753 /* the printer name is set to the service name. */
1754 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1755 string_set(&ServicePtrs[i]->comment, comment);
1757 /* set the browseable flag from the gloabl default */
1758 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1760 /* Printers cannot be read_only. */
1761 ServicePtrs[i]->bRead_only = false;
1762 /* No share modes on printer services. */
1763 ServicePtrs[i]->bShareModes = false;
1764 /* No oplocks on printer services. */
1765 ServicePtrs[i]->bOpLocks = false;
1766 /* Printer services must be printable. */
1767 ServicePtrs[i]->bPrint_ok = true;
1769 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1775 /***************************************************************************
1776 Check whether the given parameter name is valid.
1777 Parametric options (names containing a colon) are considered valid.
1778 ***************************************************************************/
1780 bool lp_parameter_is_valid(const char *pszParmName)
1782 return ((map_parameter(pszParmName) != -1) ||
1783 (strchr(pszParmName, ':') != NULL));
1786 /***************************************************************************
1787 Check whether the given name is the name of a global parameter.
1788 Returns true for strings belonging to parameters of class
1789 P_GLOBAL, false for all other strings, also for parametric options
1790 and strings not belonging to any option.
1791 ***************************************************************************/
1793 bool lp_parameter_is_global(const char *pszParmName)
1795 int num = map_parameter(pszParmName);
1798 return (parm_table[num].p_class == P_GLOBAL);
1804 /**************************************************************************
1805 Check whether the given name is the canonical name of a parameter.
1806 Returns false if it is not a valid parameter Name.
1807 For parametric options, true is returned.
1808 **************************************************************************/
1810 bool lp_parameter_is_canonical(const char *parm_name)
1812 if (!lp_parameter_is_valid(parm_name)) {
1816 return (map_parameter(parm_name) ==
1817 map_parameter_canonical(parm_name, NULL));
1820 /**************************************************************************
1821 Determine the canonical name for a parameter.
1822 Indicate when it is an inverse (boolean) synonym instead of a
1824 **************************************************************************/
1826 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1831 if (!lp_parameter_is_valid(parm_name)) {
1836 num = map_parameter_canonical(parm_name, inverse);
1838 /* parametric option */
1839 *canon_parm = parm_name;
1841 *canon_parm = parm_table[num].label;
1848 /**************************************************************************
1849 Determine the canonical name for a parameter.
1850 Turn the value given into the inverse boolean expression when
1851 the synonym is an invers boolean synonym.
1853 Return true if parm_name is a valid parameter name and
1854 in case it is an invers boolean synonym, if the val string could
1855 successfully be converted to the reverse bool.
1856 Return false in all other cases.
1857 **************************************************************************/
1859 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1861 const char **canon_parm,
1862 const char **canon_val)
1867 if (!lp_parameter_is_valid(parm_name)) {
1873 num = map_parameter_canonical(parm_name, &inverse);
1875 /* parametric option */
1876 *canon_parm = parm_name;
1879 *canon_parm = parm_table[num].label;
1881 if (!lp_invert_boolean(val, canon_val)) {
1893 /***************************************************************************
1894 Map a parameter's string representation to something we can use.
1895 Returns false if the parameter string is not recognised, else TRUE.
1896 ***************************************************************************/
1898 static int map_parameter(const char *pszParmName)
1902 if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
1905 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1906 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1909 /* Warn only if it isn't parametric option */
1910 if (strchr(pszParmName, ':') == NULL)
1911 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1912 /* We do return 'fail' for parametric options as well because they are
1913 stored in different storage
1918 /***************************************************************************
1919 Map a parameter's string representation to the index of the canonical
1920 form of the parameter (it might be a synonym).
1921 Returns -1 if the parameter string is not recognised.
1922 ***************************************************************************/
1924 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1926 int parm_num, canon_num;
1927 bool loc_inverse = false;
1929 parm_num = map_parameter(pszParmName);
1930 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1931 /* invalid, parametric or no canidate for synonyms ... */
1935 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1936 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1937 parm_num = canon_num;
1943 if (inverse != NULL) {
1944 *inverse = loc_inverse;
1949 /***************************************************************************
1950 return true if parameter number parm1 is a synonym of parameter
1951 number parm2 (parm2 being the principal name).
1952 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1954 ***************************************************************************/
1956 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
1958 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
1959 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
1960 (parm_table[parm1].flags & FLAG_HIDE) &&
1961 !(parm_table[parm2].flags & FLAG_HIDE))
1963 if (inverse != NULL) {
1964 if ((parm_table[parm1].type == P_BOOLREV) &&
1965 (parm_table[parm2].type == P_BOOL))
1977 /***************************************************************************
1978 Show one parameter's name, type, [values,] and flags.
1979 (helper functions for show_parameter_list)
1980 ***************************************************************************/
1982 static void show_parameter(int parmIndex)
1984 int enumIndex, flagIndex;
1989 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
1990 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
1992 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
1993 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
1995 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
1996 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
1997 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
1999 printf("%s=%s", parm_table[parmIndex].label,
2000 type[parm_table[parmIndex].type]);
2001 if (parm_table[parmIndex].type == P_ENUM) {
2004 parm_table[parmIndex].enum_list[enumIndex].name;
2008 enumIndex ? "|" : "",
2009 parm_table[parmIndex].enum_list[enumIndex].name);
2014 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2015 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2018 flag_names[flagIndex]);
2023 /* output synonyms */
2025 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2026 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2027 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2028 parm_table[parmIndex2].label);
2029 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2031 printf(" (synonyms: ");
2036 printf("%s%s", parm_table[parmIndex2].label,
2037 inverse ? "[i]" : "");
2047 /***************************************************************************
2048 Show all parameter's name, type, [values,] and flags.
2049 ***************************************************************************/
2051 void show_parameter_list(void)
2053 int classIndex, parmIndex;
2054 const char *section_names[] = { "local", "global", NULL};
2056 for (classIndex=0; section_names[classIndex]; classIndex++) {
2057 printf("[%s]\n", section_names[classIndex]);
2058 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2059 if (parm_table[parmIndex].p_class == classIndex) {
2060 show_parameter(parmIndex);
2066 /***************************************************************************
2067 Check if a given string correctly represents a boolean value.
2068 ***************************************************************************/
2070 bool lp_string_is_valid_boolean(const char *parm_value)
2072 return set_boolean(parm_value, NULL);
2075 /***************************************************************************
2076 Get the standard string representation of a boolean value ("yes" or "no")
2077 ***************************************************************************/
2079 static const char *get_boolean(bool bool_value)
2081 static const char *yes_str = "yes";
2082 static const char *no_str = "no";
2084 return (bool_value ? yes_str : no_str);
2087 /***************************************************************************
2088 Provide the string of the negated boolean value associated to the boolean
2089 given as a string. Returns false if the passed string does not correctly
2090 represent a boolean.
2091 ***************************************************************************/
2093 bool lp_invert_boolean(const char *str, const char **inverse_str)
2097 if (!set_boolean(str, &val)) {
2101 *inverse_str = get_boolean(!val);
2105 /***************************************************************************
2106 Provide the canonical string representation of a boolean value given
2107 as a string. Return true on success, false if the string given does
2108 not correctly represent a boolean.
2109 ***************************************************************************/
2111 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2115 if (!set_boolean(str, &val)) {
2119 *canon_str = get_boolean(val);
2123 /***************************************************************************
2124 Find a service by name. Otherwise works like get_service.
2125 ***************************************************************************/
2127 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2134 if (ServiceHash == NULL) {
2138 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2140 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2143 if (NT_STATUS_IS_OK(status) &&
2144 (data.dptr != NULL) &&
2145 (data.dsize == sizeof(iService)))
2147 iService = *(int *)data.dptr;
2150 TALLOC_FREE(canon_name);
2152 if ((iService != -1) && (LP_SNUM_OK(iService))
2153 && (pserviceDest != NULL)) {
2154 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2160 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2161 struct loadparm_service *lp_service(const char *pszServiceName)
2163 int iService = getservicebyname(pszServiceName, NULL);
2164 if (iService == -1 || !LP_SNUM_OK(iService)) {
2167 return ServicePtrs[iService];
2170 struct loadparm_service *lp_servicebynum(int snum)
2172 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2175 return ServicePtrs[snum];
2178 struct loadparm_service *lp_default_loadparm_service()
2184 /***************************************************************************
2185 Copy a service structure to another.
2186 If pcopymapDest is NULL then copy all fields
2187 ***************************************************************************/
2190 * Add a parametric option to a parmlist_entry,
2191 * replacing old value, if already present.
2193 static void set_param_opt(struct parmlist_entry **opt_list,
2194 const char *opt_name,
2195 const char *opt_value,
2198 struct parmlist_entry *new_opt, *opt;
2201 if (opt_list == NULL) {
2208 /* Traverse destination */
2210 /* If we already have same option, override it */
2211 if (strwicmp(opt->key, opt_name) == 0) {
2212 if ((opt->priority & FLAG_CMDLINE) &&
2213 !(priority & FLAG_CMDLINE)) {
2214 /* it's been marked as not to be
2218 string_free(&opt->value);
2219 TALLOC_FREE(opt->list);
2220 opt->value = SMB_STRDUP(opt_value);
2221 opt->priority = priority;
2228 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2229 new_opt->key = SMB_STRDUP(opt_name);
2230 new_opt->value = SMB_STRDUP(opt_value);
2231 new_opt->list = NULL;
2232 new_opt->priority = priority;
2233 DLIST_ADD(*opt_list, new_opt);
2237 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2238 struct bitmap *pcopymapDest)
2241 bool bcopyall = (pcopymapDest == NULL);
2242 struct parmlist_entry *data;
2244 for (i = 0; parm_table[i].label; i++)
2245 if (parm_table[i].p_class == P_LOCAL &&
2246 (bcopyall || bitmap_query(pcopymapDest,i))) {
2247 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2248 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2250 switch (parm_table[i].type) {
2253 *(bool *)dest_ptr = *(bool *)src_ptr;
2260 *(int *)dest_ptr = *(int *)src_ptr;
2264 *(char *)dest_ptr = *(char *)src_ptr;
2268 string_set((char **)dest_ptr,
2274 char *upper_string = strupper_talloc(talloc_tos(),
2276 string_set((char **)dest_ptr,
2278 TALLOC_FREE(upper_string);
2282 TALLOC_FREE(*((char ***)dest_ptr));
2283 *((char ***)dest_ptr) = str_list_copy(NULL,
2284 *(const char ***)src_ptr);
2292 init_copymap(pserviceDest);
2293 if (pserviceSource->copymap)
2294 bitmap_copy(pserviceDest->copymap,
2295 pserviceSource->copymap);
2298 data = pserviceSource->param_opt;
2300 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2305 /***************************************************************************
2306 Check a service for consistency. Return false if the service is in any way
2307 incomplete or faulty, else true.
2308 ***************************************************************************/
2310 bool service_ok(int iService)
2315 if (ServicePtrs[iService]->szService[0] == '\0') {
2316 DEBUG(0, ("The following message indicates an internal error:\n"));
2317 DEBUG(0, ("No service name in service entry.\n"));
2321 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2322 /* I can't see why you'd want a non-printable printer service... */
2323 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2324 if (!ServicePtrs[iService]->bPrint_ok) {
2325 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2326 ServicePtrs[iService]->szService));
2327 ServicePtrs[iService]->bPrint_ok = true;
2329 /* [printers] service must also be non-browsable. */
2330 if (ServicePtrs[iService]->bBrowseable)
2331 ServicePtrs[iService]->bBrowseable = false;
2334 if (ServicePtrs[iService]->szPath[0] == '\0' &&
2335 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2336 ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2338 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2339 ServicePtrs[iService]->szService));
2340 ServicePtrs[iService]->bAvailable = false;
2343 /* If a service is flagged unavailable, log the fact at level 1. */
2344 if (!ServicePtrs[iService]->bAvailable)
2345 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2346 ServicePtrs[iService]->szService));
2351 static struct smbconf_ctx *lp_smbconf_ctx(void)
2354 static struct smbconf_ctx *conf_ctx = NULL;
2356 if (conf_ctx == NULL) {
2357 err = smbconf_init(NULL, &conf_ctx, "registry:");
2358 if (!SBC_ERROR_IS_OK(err)) {
2359 DEBUG(1, ("error initializing registry configuration: "
2360 "%s\n", sbcErrorString(err)));
2368 static bool process_smbconf_service(struct smbconf_service *service)
2373 if (service == NULL) {
2377 ret = do_section(service->name, NULL);
2381 for (count = 0; count < service->num_params; count++) {
2382 ret = do_parameter(service->param_names[count],
2383 service->param_values[count],
2389 if (iServiceIndex >= 0) {
2390 return service_ok(iServiceIndex);
2396 * load a service from registry and activate it
2398 bool process_registry_service(const char *service_name)
2401 struct smbconf_service *service = NULL;
2402 TALLOC_CTX *mem_ctx = talloc_stackframe();
2403 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2406 if (conf_ctx == NULL) {
2410 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2412 if (!smbconf_share_exists(conf_ctx, service_name)) {
2414 * Registry does not contain data for this service (yet),
2415 * but make sure lp_load doesn't return false.
2421 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2422 if (!SBC_ERROR_IS_OK(err)) {
2426 ret = process_smbconf_service(service);
2432 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2435 TALLOC_FREE(mem_ctx);
2440 * process_registry_globals
2442 static bool process_registry_globals(void)
2446 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2448 ret = do_parameter("registry shares", "yes", NULL);
2453 return process_registry_service(GLOBAL_NAME);
2456 bool process_registry_shares(void)
2460 struct smbconf_service **service = NULL;
2461 uint32_t num_shares = 0;
2462 TALLOC_CTX *mem_ctx = talloc_stackframe();
2463 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2466 if (conf_ctx == NULL) {
2470 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2471 if (!SBC_ERROR_IS_OK(err)) {
2477 for (count = 0; count < num_shares; count++) {
2478 if (strequal(service[count]->name, GLOBAL_NAME)) {
2481 ret = process_smbconf_service(service[count]);
2488 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2491 TALLOC_FREE(mem_ctx);
2496 * reload those shares from registry that are already
2497 * activated in the services array.
2499 static bool reload_registry_shares(void)
2504 for (i = 0; i < iNumServices; i++) {
2509 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2513 ret = process_registry_service(ServicePtrs[i]->szService);
2524 #define MAX_INCLUDE_DEPTH 100
2526 static uint8_t include_depth;
2528 static struct file_lists {
2529 struct file_lists *next;
2533 } *file_lists = NULL;
2535 /*******************************************************************
2536 Keep a linked list of all config files so we know when one has changed
2537 it's date and needs to be reloaded.
2538 ********************************************************************/
2540 static void add_to_file_list(const char *fname, const char *subfname)
2542 struct file_lists *f = file_lists;
2545 if (f->name && !strcmp(f->name, fname))
2551 f = SMB_MALLOC_P(struct file_lists);
2554 f->next = file_lists;
2555 f->name = SMB_STRDUP(fname);
2560 f->subfname = SMB_STRDUP(subfname);
2567 f->modtime = file_modtime(subfname);
2569 time_t t = file_modtime(subfname);
2577 * Free the file lists
2579 static void free_file_list(void)
2581 struct file_lists *f;
2582 struct file_lists *next;
2587 SAFE_FREE( f->name );
2588 SAFE_FREE( f->subfname );
2597 * Utility function for outsiders to check if we're running on registry.
2599 bool lp_config_backend_is_registry(void)
2601 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2605 * Utility function to check if the config backend is FILE.
2607 bool lp_config_backend_is_file(void)
2609 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2612 /*******************************************************************
2613 Check if a config file has changed date.
2614 ********************************************************************/
2616 bool lp_file_list_changed(void)
2618 struct file_lists *f = file_lists;
2620 DEBUG(6, ("lp_file_list_changed()\n"));
2625 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2626 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2628 if (conf_ctx == NULL) {
2631 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2634 DEBUGADD(6, ("registry config changed\n"));
2639 n2 = talloc_sub_basic(talloc_tos(),
2640 get_current_username(),
2641 current_user_info.domain,
2646 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2647 f->name, n2, ctime(&f->modtime)));
2649 mod_time = file_modtime(n2);
2652 ((f->modtime != mod_time) ||
2653 (f->subfname == NULL) ||
2654 (strcmp(n2, f->subfname) != 0)))
2657 ("file %s modified: %s\n", n2,
2659 f->modtime = mod_time;
2660 SAFE_FREE(f->subfname);
2661 f->subfname = SMB_STRDUP(n2);
2674 * Initialize iconv conversion descriptors.
2676 * This is called the first time it is needed, and also called again
2677 * every time the configuration is reloaded, because the charset or
2678 * codepage might have changed.
2680 static void init_iconv(void)
2682 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2684 true, global_iconv_handle);
2687 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2689 if (strcmp(*ptr, pszParmValue) != 0) {
2690 string_set(ptr, pszParmValue);
2696 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2698 bool is_utf8 = false;
2699 size_t len = strlen(pszParmValue);
2701 if (len == 4 || len == 5) {
2702 /* Don't use StrCaseCmp here as we don't want to
2703 initialize iconv. */
2704 if ((toupper_m(pszParmValue[0]) == 'U') &&
2705 (toupper_m(pszParmValue[1]) == 'T') &&
2706 (toupper_m(pszParmValue[2]) == 'F')) {
2708 if (pszParmValue[3] == '8') {
2712 if (pszParmValue[3] == '-' &&
2713 pszParmValue[4] == '8') {
2720 if (strcmp(*ptr, pszParmValue) != 0) {
2722 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2723 "be UTF8, using (default value) %s instead.\n",
2724 DEFAULT_DOS_CHARSET));
2725 pszParmValue = DEFAULT_DOS_CHARSET;
2727 string_set(ptr, pszParmValue);
2733 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2736 char *realm = strupper_talloc(talloc_tos(), pszParmValue);
2737 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2739 ret &= string_set(&Globals.szRealm, pszParmValue);
2740 ret &= string_set(&Globals.szRealm_upper, realm);
2741 ret &= string_set(&Globals.szRealm_lower, dnsdomain);
2747 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2749 TALLOC_FREE(Globals.szNetbiosAliases);
2750 Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2751 return set_netbios_aliases(Globals.szNetbiosAliases);
2754 /***************************************************************************
2755 Handle the include operation.
2756 ***************************************************************************/
2757 static bool bAllowIncludeRegistry = true;
2759 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2763 if (include_depth >= MAX_INCLUDE_DEPTH) {
2764 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2769 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2770 if (!bAllowIncludeRegistry) {
2773 if (bInGlobalSection) {
2776 ret = process_registry_globals();
2780 DEBUG(1, ("\"include = registry\" only effective "
2781 "in %s section\n", GLOBAL_NAME));
2786 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2787 current_user_info.domain,
2790 add_to_file_list(pszParmValue, fname);
2792 string_set(ptr, fname);
2794 if (file_exist(fname)) {
2797 ret = pm_process(fname, do_section, do_parameter, NULL);
2803 DEBUG(2, ("Can't find include file %s\n", fname));
2808 /***************************************************************************
2809 Handle the interpretation of the copy parameter.
2810 ***************************************************************************/
2812 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2816 struct loadparm_service serviceTemp;
2818 string_set(ptr, pszParmValue);
2820 init_service(&serviceTemp);
2824 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2826 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2827 if (iTemp == iServiceIndex) {
2828 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2830 copy_service(ServicePtrs[iServiceIndex],
2832 ServicePtrs[iServiceIndex]->copymap);
2836 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2840 free_service(&serviceTemp);
2844 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2846 Globals.ldap_debug_level = lp_int(pszParmValue);
2847 init_ldap_debugging();
2851 /***************************************************************************
2852 Handle idmap/non unix account uid and gid allocation parameters. The format of these
2857 idmap uid = 1000-1999
2860 We only do simple parsing checks here. The strings are parsed into useful
2861 structures in the idmap daemon code.
2863 ***************************************************************************/
2865 /* Some lp_ routines to return idmap [ug]id information */
2867 static uid_t idmap_uid_low, idmap_uid_high;
2868 static gid_t idmap_gid_low, idmap_gid_high;
2870 bool lp_idmap_uid(uid_t *low, uid_t *high)
2872 if (idmap_uid_low == 0 || idmap_uid_high == 0)
2876 *low = idmap_uid_low;
2879 *high = idmap_uid_high;
2884 bool lp_idmap_gid(gid_t *low, gid_t *high)
2886 if (idmap_gid_low == 0 || idmap_gid_high == 0)
2890 *low = idmap_gid_low;
2893 *high = idmap_gid_high;
2898 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2900 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2905 /* Do some simple checks on "idmap [ug]id" parameter values */
2907 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2909 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2914 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2916 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2921 /***************************************************************************
2922 Handle the DEBUG level list.
2923 ***************************************************************************/
2925 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2927 string_set(ptr, pszParmValueIn);
2928 return debug_parse_levels(pszParmValueIn);
2931 /***************************************************************************
2932 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2933 ***************************************************************************/
2935 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2937 const char *suffix_string;
2939 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2940 Globals.szLdapSuffix );
2941 if ( !suffix_string ) {
2942 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2946 return suffix_string;
2949 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2951 if (Globals.szLdapMachineSuffix[0])
2952 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
2954 return lp_string(ctx, Globals.szLdapSuffix);
2957 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
2959 if (Globals.szLdapUserSuffix[0])
2960 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
2962 return lp_string(ctx, Globals.szLdapSuffix);
2965 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
2967 if (Globals.szLdapGroupSuffix[0])
2968 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
2970 return lp_string(ctx, Globals.szLdapSuffix);
2973 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
2975 if (Globals.szLdapIdmapSuffix[0])
2976 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
2978 return lp_string(ctx, Globals.szLdapSuffix);
2981 /****************************************************************************
2982 set the value for a P_ENUM
2983 ***************************************************************************/
2985 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
2990 for (i = 0; parm->enum_list[i].name; i++) {
2991 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
2992 *ptr = parm->enum_list[i].value;
2996 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
2997 pszParmValue, parm->label));
3000 /***************************************************************************
3001 ***************************************************************************/
3003 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3005 static int parm_num = -1;
3006 struct loadparm_service *s;
3008 if ( parm_num == -1 )
3009 parm_num = map_parameter( "printing" );
3011 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3016 s = ServicePtrs[snum];
3018 init_printer_values( s );
3024 /***************************************************************************
3025 Initialise a copymap.
3026 ***************************************************************************/
3028 static void init_copymap(struct loadparm_service *pservice)
3032 TALLOC_FREE(pservice->copymap);
3034 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3035 if (!pservice->copymap)
3037 ("Couldn't allocate copymap!! (size %d)\n",
3038 (int)NUMPARAMETERS));
3040 for (i = 0; i < NUMPARAMETERS; i++)
3041 bitmap_set(pservice->copymap, i);
3045 return the parameter pointer for a parameter
3047 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3049 if (service == NULL) {
3050 if (parm->p_class == P_LOCAL)
3051 return (void *)(((char *)&sDefault)+parm->offset);
3052 else if (parm->p_class == P_GLOBAL)
3053 return (void *)(((char *)&Globals)+parm->offset);
3056 return (void *)(((char *)service) + parm->offset);
3060 /***************************************************************************
3061 Return the local pointer to a parameter given the service number and parameter
3062 ***************************************************************************/
3064 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3066 return lp_parm_ptr(ServicePtrs[snum], parm);
3069 /***************************************************************************
3070 Process a parameter for a particular service number. If snum < 0
3071 then assume we are in the globals.
3072 ***************************************************************************/
3074 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3077 void *parm_ptr = NULL; /* where we are going to store the result */
3078 struct parmlist_entry **opt_list;
3080 parmnum = map_parameter(pszParmName);
3083 if (strchr(pszParmName, ':') == NULL) {
3084 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3090 * We've got a parametric option
3093 opt_list = (snum < 0)
3094 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3095 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3100 /* if it's already been set by the command line, then we don't
3102 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3106 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3107 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3111 /* we might point at a service, the default service or a global */
3113 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3115 if (parm_table[parmnum].p_class == P_GLOBAL) {
3117 ("Global parameter %s found in service section!\n",
3121 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3125 if (!ServicePtrs[snum]->copymap)
3126 init_copymap(ServicePtrs[snum]);
3128 /* this handles the aliases - set the copymap for other entries with
3129 the same data pointer */
3130 for (i = 0; parm_table[i].label; i++) {
3131 if ((parm_table[i].offset == parm_table[parmnum].offset)
3132 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3133 bitmap_clear(ServicePtrs[snum]->copymap, i);
3138 /* if it is a special case then go ahead */
3139 if (parm_table[parmnum].special) {
3140 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3144 /* now switch on the type of variable it is */
3145 switch (parm_table[parmnum].type)
3148 *(bool *)parm_ptr = lp_bool(pszParmValue);
3152 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3156 *(int *)parm_ptr = lp_int(pszParmValue);
3160 *(char *)parm_ptr = *pszParmValue;
3164 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3166 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3173 if (conv_str_size_error(pszParmValue, &val)) {
3174 if (val <= INT_MAX) {
3175 *(int *)parm_ptr = (int)val;
3180 DEBUG(0,("lp_do_parameter(%s): value is not "
3181 "a valid size specifier!\n", pszParmValue));
3187 TALLOC_FREE(*((char ***)parm_ptr));
3188 *(char ***)parm_ptr = str_list_make_v3(
3189 NULL, pszParmValue, NULL);
3193 string_set((char **)parm_ptr, pszParmValue);
3198 char *upper_string = strupper_talloc(talloc_tos(),
3200 string_set((char **)parm_ptr, upper_string);
3201 TALLOC_FREE(upper_string);
3205 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3214 /***************************************************************************
3215 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3216 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3217 ***************************************************************************/
3219 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3222 parmnum = map_parameter(pszParmName);
3224 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3225 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3228 parm_table[parmnum].flags |= FLAG_CMDLINE;
3230 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3231 * be grouped in the table, so we don't have to search the
3234 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3235 && parm_table[i].p_class == parm_table[parmnum].p_class;
3237 parm_table[i].flags |= FLAG_CMDLINE;
3239 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3240 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3241 parm_table[i].flags |= FLAG_CMDLINE;
3245 store_lp_set_cmdline(pszParmName, pszParmValue);
3250 /* it might be parametric */
3251 if (strchr(pszParmName, ':') != NULL) {
3252 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3254 store_lp_set_cmdline(pszParmName, pszParmValue);
3259 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3263 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3265 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3268 /***************************************************************************
3269 Process a parameter.
3270 ***************************************************************************/
3272 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3275 if (!bInGlobalSection && bGlobalOnly)
3278 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3280 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3281 pszParmName, pszParmValue));
3285 set a option from the commandline in 'a=b' format. Use to support --option
3287 bool lp_set_option(const char *option)
3292 s = talloc_strdup(NULL, option);
3305 /* skip white spaces after the = sign */
3308 } while (*p == ' ');
3310 ret = lp_set_cmdline(s, p);
3315 /**************************************************************************
3316 Print a parameter of the specified type.
3317 ***************************************************************************/
3319 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3321 /* For the seperation of lists values that we print below */
3322 const char *list_sep = ", ";
3327 for (i = 0; p->enum_list[i].name; i++) {
3328 if (*(int *)ptr == p->enum_list[i].value) {
3330 p->enum_list[i].name);
3337 fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3341 fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3346 fprintf(f, "%d", *(int *)ptr);
3350 fprintf(f, "%c", *(char *)ptr);
3354 int val = *(int *)ptr;
3358 fprintf(f, "0%o", val);
3367 if ((char ***)ptr && *(char ***)ptr) {
3368 char **list = *(char ***)ptr;
3369 for (; *list; list++) {
3370 /* surround strings with whitespace in double quotes */
3371 if (*(list+1) == NULL) {
3372 /* last item, no extra separator */
3375 if ( strchr_m( *list, ' ' ) ) {
3376 fprintf(f, "\"%s\"%s", *list, list_sep);
3378 fprintf(f, "%s%s", *list, list_sep);
3386 if (*(char **)ptr) {
3387 fprintf(f, "%s", *(char **)ptr);
3395 /***************************************************************************
3396 Check if two parameters are equal.
3397 ***************************************************************************/
3399 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3404 return (*((bool *)ptr1) == *((bool *)ptr2));
3410 return (*((int *)ptr1) == *((int *)ptr2));
3413 return (*((char *)ptr1) == *((char *)ptr2));
3417 return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3422 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3427 return (p1 == p2 || strequal(p1, p2));
3435 /***************************************************************************
3436 Initialize any local varients in the sDefault table.
3437 ***************************************************************************/
3439 void init_locals(void)
3444 /***************************************************************************
3445 Process a new section (service). At this stage all sections are services.
3446 Later we'll have special sections that permit server parameters to be set.
3447 Returns true on success, false on failure.
3448 ***************************************************************************/
3450 static bool do_section(const char *pszSectionName, void *userdata)
3453 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3454 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3457 /* if we were in a global section then do the local inits */
3458 if (bInGlobalSection && !isglobal)
3461 /* if we've just struck a global section, note the fact. */
3462 bInGlobalSection = isglobal;
3464 /* check for multiple global sections */
3465 if (bInGlobalSection) {
3466 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3470 if (!bInGlobalSection && bGlobalOnly)
3473 /* if we have a current service, tidy it up before moving on */
3476 if (iServiceIndex >= 0)
3477 bRetval = service_ok(iServiceIndex);
3479 /* if all is still well, move to the next record in the services array */
3481 /* We put this here to avoid an odd message order if messages are */
3482 /* issued by the post-processing of a previous section. */
3483 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3485 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3486 if (iServiceIndex < 0) {
3487 DEBUG(0, ("Failed to add a new service\n"));
3490 /* Clean all parametric options for service */
3491 /* They will be added during parsing again */
3492 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3499 /***************************************************************************
3500 Determine if a partcular base parameter is currentl set to the default value.
3501 ***************************************************************************/
3503 static bool is_default(int i)
3505 if (!defaults_saved)
3507 switch (parm_table[i].type) {
3510 return str_list_equal((const char **)parm_table[i].def.lvalue,
3511 *(const char ***)lp_parm_ptr(NULL,
3515 return strequal(parm_table[i].def.svalue,
3516 *(char **)lp_parm_ptr(NULL,
3520 return parm_table[i].def.bvalue ==
3521 *(bool *)lp_parm_ptr(NULL,
3524 return parm_table[i].def.cvalue ==
3525 *(char *)lp_parm_ptr(NULL,
3531 return parm_table[i].def.ivalue ==
3532 *(int *)lp_parm_ptr(NULL,
3540 /***************************************************************************
3541 Display the contents of the global structure.
3542 ***************************************************************************/
3544 static void dump_globals(FILE *f)
3547 struct parmlist_entry *data;
3549 fprintf(f, "[global]\n");
3551 for (i = 0; parm_table[i].label; i++)
3552 if (parm_table[i].p_class == P_GLOBAL &&
3553 !(parm_table[i].flags & FLAG_META) &&
3554 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3555 if (defaults_saved && is_default(i))
3557 fprintf(f, "\t%s = ", parm_table[i].label);
3558 print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3563 if (Globals.param_opt != NULL) {
3564 data = Globals.param_opt;
3566 fprintf(f, "\t%s = %s\n", data->key, data->value);
3573 /***************************************************************************
3574 Return true if a local parameter is currently set to the global default.
3575 ***************************************************************************/
3577 bool lp_is_default(int snum, struct parm_struct *parm)
3579 return equal_parameter(parm->type,
3580 lp_parm_ptr(ServicePtrs[snum], parm),
3581 lp_parm_ptr(NULL, parm));
3584 /***************************************************************************
3585 Display the contents of a single services record.
3586 ***************************************************************************/
3588 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3591 struct parmlist_entry *data;
3593 if (pService != &sDefault)
3594 fprintf(f, "[%s]\n", pService->szService);
3596 for (i = 0; parm_table[i].label; i++) {
3598 if (parm_table[i].p_class == P_LOCAL &&
3599 !(parm_table[i].flags & FLAG_META) &&
3600 (*parm_table[i].label != '-') &&
3601 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3603 if (pService == &sDefault) {
3604 if (defaults_saved && is_default(i))
3607 if (equal_parameter(parm_table[i].type,
3608 lp_parm_ptr(pService, &parm_table[i]),
3609 lp_parm_ptr(NULL, &parm_table[i])))
3613 fprintf(f, "\t%s = ", parm_table[i].label);
3614 print_parameter(&parm_table[i],
3615 lp_parm_ptr(pService, &parm_table[i]),
3621 if (pService->param_opt != NULL) {
3622 data = pService->param_opt;
3624 fprintf(f, "\t%s = %s\n", data->key, data->value);
3630 /***************************************************************************
3631 Display the contents of a parameter of a single services record.
3632 ***************************************************************************/
3634 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3637 bool result = false;
3640 fstring local_parm_name;
3642 const char *parm_opt_value;
3644 /* check for parametrical option */
3645 fstrcpy( local_parm_name, parm_name);
3646 parm_opt = strchr( local_parm_name, ':');
3651 if (strlen(parm_opt)) {
3652 parm_opt_value = lp_parm_const_string( snum,
3653 local_parm_name, parm_opt, NULL);
3654 if (parm_opt_value) {
3655 printf( "%s\n", parm_opt_value);
3662 /* check for a key and print the value */
3669 for (i = 0; parm_table[i].label; i++) {
3670 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3671 !(parm_table[i].flags & FLAG_META) &&
3672 (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3673 (*parm_table[i].label != '-') &&
3674 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3679 ptr = lp_parm_ptr(NULL,
3682 ptr = lp_parm_ptr(ServicePtrs[snum],
3686 print_parameter(&parm_table[i],
3697 /***************************************************************************
3698 Return info about the requested parameter (given as a string).
3699 Return NULL when the string is not a valid parameter name.
3700 ***************************************************************************/
3702 struct parm_struct *lp_get_parameter(const char *param_name)
3704 int num = map_parameter(param_name);
3710 return &parm_table[num];
3713 /***************************************************************************
3714 Return info about the next parameter in a service.
3715 snum==GLOBAL_SECTION_SNUM gives the globals.
3716 Return NULL when out of parameters.
3717 ***************************************************************************/
3719 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3722 /* do the globals */
3723 for (; parm_table[*i].label; (*i)++) {
3724 if (parm_table[*i].p_class == P_SEPARATOR)
3725 return &parm_table[(*i)++];
3727 if ((*parm_table[*i].label == '-'))
3731 && (parm_table[*i].offset ==
3732 parm_table[(*i) - 1].offset)
3733 && (parm_table[*i].p_class ==
3734 parm_table[(*i) - 1].p_class))
3737 if (is_default(*i) && !allparameters)
3740 return &parm_table[(*i)++];
3743 struct loadparm_service *pService = ServicePtrs[snum];
3745 for (; parm_table[*i].label; (*i)++) {
3746 if (parm_table[*i].p_class == P_SEPARATOR)
3747 return &parm_table[(*i)++];
3749 if (parm_table[*i].p_class == P_LOCAL &&
3750 (*parm_table[*i].label != '-') &&
3752 (parm_table[*i].offset !=
3753 parm_table[(*i) - 1].offset)))
3755 if (allparameters ||
3756 !equal_parameter(parm_table[*i].type,
3757 lp_parm_ptr(pService,
3762 return &parm_table[(*i)++];
3773 /***************************************************************************
3774 Display the contents of a single copy structure.
3775 ***************************************************************************/
3776 static void dump_copy_map(bool *pcopymap)
3782 printf("\n\tNon-Copied parameters:\n");
3784 for (i = 0; parm_table[i].label; i++)
3785 if (parm_table[i].p_class == P_LOCAL &&
3786 parm_table[i].ptr && !pcopymap[i] &&
3787 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3789 printf("\t\t%s\n", parm_table[i].label);
3794 /***************************************************************************
3795 Return TRUE if the passed service number is within range.
3796 ***************************************************************************/
3798 bool lp_snum_ok(int iService)
3800 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3803 /***************************************************************************
3804 Auto-load some home services.
3805 ***************************************************************************/
3807 static void lp_add_auto_services(char *str)
3817 s = SMB_STRDUP(str);
3821 homes = lp_servicenumber(HOMES_NAME);
3823 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3824 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3827 if (lp_servicenumber(p) >= 0)
3830 home = get_user_home_dir(talloc_tos(), p);
3832 if (home && home[0] && homes >= 0)
3833 lp_add_home(p, homes, p, home);
3840 /***************************************************************************
3841 Auto-load one printer.
3842 ***************************************************************************/
3844 void lp_add_one_printer(const char *name, const char *comment,
3845 const char *location, void *pdata)
3847 int printers = lp_servicenumber(PRINTERS_NAME);
3850 if (lp_servicenumber(name) < 0) {
3851 lp_add_printer(name, printers);
3852 if ((i = lp_servicenumber(name)) >= 0) {
3853 string_set(&ServicePtrs[i]->comment, comment);
3854 ServicePtrs[i]->autoloaded = true;
3859 /***************************************************************************
3860 Have we loaded a services file yet?
3861 ***************************************************************************/
3863 bool lp_loaded(void)
3868 /***************************************************************************
3869 Unload unused services.
3870 ***************************************************************************/
3872 void lp_killunused(struct smbd_server_connection *sconn,
3873 bool (*snumused) (struct smbd_server_connection *, int))
3876 for (i = 0; i < iNumServices; i++) {
3880 /* don't kill autoloaded or usershare services */
3881 if ( ServicePtrs[i]->autoloaded ||
3882 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3886 if (!snumused || !snumused(sconn, i)) {
3887 free_service_byindex(i);
3893 * Kill all except autoloaded and usershare services - convenience wrapper
3895 void lp_kill_all_services(void)
3897 lp_killunused(NULL, NULL);
3900 /***************************************************************************
3902 ***************************************************************************/
3904 void lp_killservice(int iServiceIn)
3906 if (VALID(iServiceIn)) {
3907 free_service_byindex(iServiceIn);
3911 /***************************************************************************
3912 Save the curent values of all global and sDefault parameters into the
3913 defaults union. This allows swat and testparm to show only the
3914 changed (ie. non-default) parameters.
3915 ***************************************************************************/
3917 static void lp_save_defaults(void)
3920 for (i = 0; parm_table[i].label; i++) {
3921 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3922 && parm_table[i].p_class == parm_table[i - 1].p_class)
3924 switch (parm_table[i].type) {
3927 parm_table[i].def.lvalue = str_list_copy(
3928 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3932 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3936 parm_table[i].def.bvalue =
3937 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3940 parm_table[i].def.cvalue =
3941 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3947 parm_table[i].def.ivalue =
3948 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3954 defaults_saved = true;
3957 /***********************************************************
3958 If we should send plaintext/LANMAN passwords in the clinet
3959 ************************************************************/
3961 static void set_allowed_client_auth(void)
3963 if (Globals.bClientNTLMv2Auth) {
3964 Globals.bClientLanManAuth = false;
3966 if (!Globals.bClientLanManAuth) {
3967 Globals.bClientPlaintextAuth = false;
3971 /***************************************************************************
3973 The following code allows smbd to read a user defined share file.
3974 Yes, this is my intent. Yes, I'm comfortable with that...
3976 THE FOLLOWING IS SECURITY CRITICAL CODE.
3978 It washes your clothes, it cleans your house, it guards you while you sleep...
3979 Do not f%^k with it....
3980 ***************************************************************************/
3982 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3984 /***************************************************************************
3985 Check allowed stat state of a usershare file.
3986 Ensure we print out who is dicking with us so the admin can
3987 get their sorry ass fired.
3988 ***************************************************************************/
3990 static bool check_usershare_stat(const char *fname,
3991 const SMB_STRUCT_STAT *psbuf)
3993 if (!S_ISREG(psbuf->st_ex_mode)) {
3994 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3995 "not a regular file\n",
3996 fname, (unsigned int)psbuf->st_ex_uid ));
4000 /* Ensure this doesn't have the other write bit set. */
4001 if (psbuf->st_ex_mode & S_IWOTH) {
4002 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4003 "public write. Refusing to allow as a usershare file.\n",
4004 fname, (unsigned int)psbuf->st_ex_uid ));
4008 /* Should be 10k or less. */
4009 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4010 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4011 "too large (%u) to be a user share file.\n",
4012 fname, (unsigned int)psbuf->st_ex_uid,
4013 (unsigned int)psbuf->st_ex_size ));
4020 /***************************************************************************
4021 Parse the contents of a usershare file.
4022 ***************************************************************************/
4024 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4025 SMB_STRUCT_STAT *psbuf,
4026 const char *servicename,
4030 char **pp_sharepath,
4032 char **pp_cp_servicename,
4033 struct security_descriptor **ppsd,
4036 const char **prefixallowlist = lp_usershare_prefix_allow_list();
4037 const char **prefixdenylist = lp_usershare_prefix_deny_list();
4040 SMB_STRUCT_STAT sbuf;
4041 char *sharepath = NULL;
4042 char *comment = NULL;
4044 *pp_sharepath = NULL;
4047 *pallow_guest = false;
4050 return USERSHARE_MALFORMED_FILE;
4053 if (strcmp(lines[0], "#VERSION 1") == 0) {
4055 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4058 return USERSHARE_MALFORMED_FILE;
4061 return USERSHARE_BAD_VERSION;
4064 if (strncmp(lines[1], "path=", 5) != 0) {
4065 return USERSHARE_MALFORMED_PATH;
4068 sharepath = talloc_strdup(ctx, &lines[1][5]);
4070 return USERSHARE_POSIX_ERR;
4072 trim_string(sharepath, " ", " ");
4074 if (strncmp(lines[2], "comment=", 8) != 0) {
4075 return USERSHARE_MALFORMED_COMMENT_DEF;
4078 comment = talloc_strdup(ctx, &lines[2][8]);
4080 return USERSHARE_POSIX_ERR;
4082 trim_string(comment, " ", " ");
4083 trim_char(comment, '"', '"');
4085 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4086 return USERSHARE_MALFORMED_ACL_DEF;
4089 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4090 return USERSHARE_ACL_ERR;
4094 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4095 return USERSHARE_MALFORMED_ACL_DEF;
4097 if (lines[4][9] == 'y') {
4098 *pallow_guest = true;
4101 /* Backwards compatible extension to file version #2. */
4103 if (strncmp(lines[5], "sharename=", 10) != 0) {
4104 return USERSHARE_MALFORMED_SHARENAME_DEF;
4106 if (!strequal(&lines[5][10], servicename)) {
4107 return USERSHARE_BAD_SHARENAME;
4109 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4110 if (!*pp_cp_servicename) {
4111 return USERSHARE_POSIX_ERR;
4116 if (*pp_cp_servicename == NULL) {
4117 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4118 if (!*pp_cp_servicename) {
4119 return USERSHARE_POSIX_ERR;
4123 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4124 /* Path didn't change, no checks needed. */
4125 *pp_sharepath = sharepath;
4126 *pp_comment = comment;
4127 return USERSHARE_OK;
4130 /* The path *must* be absolute. */
4131 if (sharepath[0] != '/') {
4132 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4133 servicename, sharepath));
4134 return USERSHARE_PATH_NOT_ABSOLUTE;
4137 /* If there is a usershare prefix deny list ensure one of these paths
4138 doesn't match the start of the user given path. */
4139 if (prefixdenylist) {
4141 for ( i=0; prefixdenylist[i]; i++ ) {
4142 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4143 servicename, i, prefixdenylist[i], sharepath ));
4144 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4145 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4146 "usershare prefix deny list entries.\n",
4147 servicename, sharepath));
4148 return USERSHARE_PATH_IS_DENIED;
4153 /* If there is a usershare prefix allow list ensure one of these paths
4154 does match the start of the user given path. */
4156 if (prefixallowlist) {
4158 for ( i=0; prefixallowlist[i]; i++ ) {
4159 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4160 servicename, i, prefixallowlist[i], sharepath ));
4161 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4165 if (prefixallowlist[i] == NULL) {
4166 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4167 "usershare prefix allow list entries.\n",
4168 servicename, sharepath));
4169 return USERSHARE_PATH_NOT_ALLOWED;
4173 /* Ensure this is pointing to a directory. */
4174 dp = opendir(sharepath);
4177 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4178 servicename, sharepath));
4179 return USERSHARE_PATH_NOT_DIRECTORY;
4182 /* Ensure the owner of the usershare file has permission to share
4185 if (sys_stat(sharepath, &sbuf, false) == -1) {
4186 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4187 servicename, sharepath, strerror(errno) ));
4189 return USERSHARE_POSIX_ERR;
4194 if (!S_ISDIR(sbuf.st_ex_mode)) {
4195 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4196 servicename, sharepath ));
4197 return USERSHARE_PATH_NOT_DIRECTORY;
4200 /* Check if sharing is restricted to owner-only. */
4201 /* psbuf is the stat of the usershare definition file,
4202 sbuf is the stat of the target directory to be shared. */
4204 if (lp_usershare_owner_only()) {
4205 /* root can share anything. */
4206 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4207 return USERSHARE_PATH_NOT_ALLOWED;
4211 *pp_sharepath = sharepath;
4212 *pp_comment = comment;
4213 return USERSHARE_OK;
4216 /***************************************************************************
4217 Deal with a usershare file.
4220 -1 - Bad name, invalid contents.
4221 - service name already existed and not a usershare, problem
4222 with permissions to share directory etc.
4223 ***************************************************************************/
4225 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4227 SMB_STRUCT_STAT sbuf;
4228 SMB_STRUCT_STAT lsbuf;
4230 char *sharepath = NULL;
4231 char *comment = NULL;
4232 char *cp_service_name = NULL;
4233 char **lines = NULL;
4237 TALLOC_CTX *ctx = talloc_stackframe();
4238 struct security_descriptor *psd = NULL;
4239 bool guest_ok = false;
4240 char *canon_name = NULL;
4241 bool added_service = false;
4244 /* Ensure share name doesn't contain invalid characters. */
4245 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4246 DEBUG(0,("process_usershare_file: share name %s contains "
4247 "invalid characters (any of %s)\n",
4248 file_name, INVALID_SHARENAME_CHARS ));
4252 canon_name = canonicalize_servicename(ctx, file_name);
4257 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4262 /* Minimize the race condition by doing an lstat before we
4263 open and fstat. Ensure this isn't a symlink link. */
4265 if (sys_lstat(fname, &lsbuf, false) != 0) {
4266 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4267 fname, strerror(errno) ));
4271 /* This must be a regular file, not a symlink, directory or
4272 other strange filetype. */
4273 if (!check_usershare_stat(fname, &lsbuf)) {
4281 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4286 if (NT_STATUS_IS_OK(status) &&
4287 (data.dptr != NULL) &&
4288 (data.dsize == sizeof(iService))) {
4289 memcpy(&iService, data.dptr, sizeof(iService));
4293 if (iService != -1 &&
4294 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4295 &lsbuf.st_ex_mtime) == 0) {
4296 /* Nothing changed - Mark valid and return. */
4297 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4299 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4304 /* Try and open the file read only - no symlinks allowed. */
4306 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4308 fd = open(fname, O_RDONLY, 0);
4312 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4313 fname, strerror(errno) ));
4317 /* Now fstat to be *SURE* it's a regular file. */
4318 if (sys_fstat(fd, &sbuf, false) != 0) {
4320 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4321 fname, strerror(errno) ));
4325 /* Is it the same dev/inode as was lstated ? */
4326 if (!check_same_stat(&lsbuf, &sbuf)) {
4328 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4329 "Symlink spoofing going on ?\n", fname ));
4333 /* This must be a regular file, not a symlink, directory or
4334 other strange filetype. */
4335 if (!check_usershare_stat(fname, &sbuf)) {
4339 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4342 if (lines == NULL) {
4343 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4344 fname, (unsigned int)sbuf.st_ex_uid ));
4348 if (parse_usershare_file(ctx, &sbuf, file_name,
4349 iService, lines, numlines, &sharepath,
4350 &comment, &cp_service_name,
4351 &psd, &guest_ok) != USERSHARE_OK) {
4355 /* Everything ok - add the service possibly using a template. */
4357 const struct loadparm_service *sp = &sDefault;
4358 if (snum_template != -1) {
4359 sp = ServicePtrs[snum_template];
4362 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4363 DEBUG(0, ("process_usershare_file: Failed to add "
4364 "new service %s\n", cp_service_name));
4368 added_service = true;
4370 /* Read only is controlled by usershare ACL below. */
4371 ServicePtrs[iService]->bRead_only = false;
4374 /* Write the ACL of the new/modified share. */
4375 if (!set_share_security(canon_name, psd)) {
4376 DEBUG(0, ("process_usershare_file: Failed to set share "
4377 "security for user share %s\n",
4382 /* If from a template it may be marked invalid. */
4383 ServicePtrs[iService]->valid = true;
4385 /* Set the service as a valid usershare. */
4386 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4388 /* Set guest access. */
4389 if (lp_usershare_allow_guests()) {
4390 ServicePtrs[iService]->bGuest_ok = guest_ok;
4393 /* And note when it was loaded. */
4394 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4395 string_set(&ServicePtrs[iService]->szPath, sharepath);
4396 string_set(&ServicePtrs[iService]->comment, comment);
4402 if (ret == -1 && iService != -1 && added_service) {
4403 lp_remove_service(iService);
4411 /***************************************************************************
4412 Checks if a usershare entry has been modified since last load.
4413 ***************************************************************************/
4415 static bool usershare_exists(int iService, struct timespec *last_mod)
4417 SMB_STRUCT_STAT lsbuf;
4418 const char *usersharepath = Globals.szUsersharePath;
4421 if (asprintf(&fname, "%s/%s",
4423 ServicePtrs[iService]->szService) < 0) {
4427 if (sys_lstat(fname, &lsbuf, false) != 0) {
4432 if (!S_ISREG(lsbuf.st_ex_mode)) {
4438 *last_mod = lsbuf.st_ex_mtime;
4442 /***************************************************************************
4443 Load a usershare service by name. Returns a valid servicenumber or -1.
4444 ***************************************************************************/
4446 int load_usershare_service(const char *servicename)
4448 SMB_STRUCT_STAT sbuf;
4449 const char *usersharepath = Globals.szUsersharePath;
4450 int max_user_shares = Globals.iUsershareMaxShares;
4451 int snum_template = -1;
4453 if (*usersharepath == 0 || max_user_shares == 0) {
4457 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4458 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4459 usersharepath, strerror(errno) ));
4463 if (!S_ISDIR(sbuf.st_ex_mode)) {
4464 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4470 * This directory must be owned by root, and have the 't' bit set.
4471 * It also must not be writable by "other".
4475 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4477 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4479 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4480 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4485 /* Ensure the template share exists if it's set. */
4486 if (Globals.szUsershareTemplateShare[0]) {
4487 /* We can't use lp_servicenumber here as we are recommending that
4488 template shares have -valid=false set. */
4489 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4490 if (ServicePtrs[snum_template]->szService &&
4491 strequal(ServicePtrs[snum_template]->szService,
4492 Globals.szUsershareTemplateShare)) {
4497 if (snum_template == -1) {
4498 DEBUG(0,("load_usershare_service: usershare template share %s "
4499 "does not exist.\n",
4500 Globals.szUsershareTemplateShare ));
4505 return process_usershare_file(usersharepath, servicename, snum_template);
4508 /***************************************************************************
4509 Load all user defined shares from the user share directory.
4510 We only do this if we're enumerating the share list.
4511 This is the function that can delete usershares that have
4513 ***************************************************************************/
4515 int load_usershare_shares(struct smbd_server_connection *sconn,
4516 bool (*snumused) (struct smbd_server_connection *, int))
4519 SMB_STRUCT_STAT sbuf;
4521 int num_usershares = 0;
4522 int max_user_shares = Globals.iUsershareMaxShares;
4523 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4524 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4525 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4527 int snum_template = -1;
4528 const char *usersharepath = Globals.szUsersharePath;
4529 int ret = lp_numservices();
4530 TALLOC_CTX *tmp_ctx;
4532 if (max_user_shares == 0 || *usersharepath == '\0') {
4533 return lp_numservices();
4536 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4537 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4538 usersharepath, strerror(errno) ));
4543 * This directory must be owned by root, and have the 't' bit set.
4544 * It also must not be writable by "other".
4548 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4550 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4552 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4553 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4558 /* Ensure the template share exists if it's set. */
4559 if (Globals.szUsershareTemplateShare[0]) {
4560 /* We can't use lp_servicenumber here as we are recommending that
4561 template shares have -valid=false set. */
4562 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4563 if (ServicePtrs[snum_template]->szService &&
4564 strequal(ServicePtrs[snum_template]->szService,
4565 Globals.szUsershareTemplateShare)) {
4570 if (snum_template == -1) {
4571 DEBUG(0,("load_usershare_shares: usershare template share %s "
4572 "does not exist.\n",
4573 Globals.szUsershareTemplateShare ));
4578 /* Mark all existing usershares as pending delete. */
4579 for (iService = iNumServices - 1; iService >= 0; iService--) {
4580 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4581 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4585 dp = opendir(usersharepath);
4587 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4588 usersharepath, strerror(errno) ));
4592 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4594 num_dir_entries++ ) {
4596 const char *n = de->d_name;
4598 /* Ignore . and .. */
4600 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4606 /* Temporary file used when creating a share. */
4607 num_tmp_dir_entries++;
4610 /* Allow 20% tmp entries. */
4611 if (num_tmp_dir_entries > allowed_tmp_entries) {
4612 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4613 "in directory %s\n",
4614 num_tmp_dir_entries, usersharepath));
4618 r = process_usershare_file(usersharepath, n, snum_template);
4620 /* Update the services count. */
4622 if (num_usershares >= max_user_shares) {
4623 DEBUG(0,("load_usershare_shares: max user shares reached "
4624 "on file %s in directory %s\n",
4625 n, usersharepath ));
4628 } else if (r == -1) {
4629 num_bad_dir_entries++;
4632 /* Allow 20% bad entries. */
4633 if (num_bad_dir_entries > allowed_bad_entries) {
4634 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4635 "in directory %s\n",
4636 num_bad_dir_entries, usersharepath));
4640 /* Allow 20% bad entries. */
4641 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4642 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4643 "in directory %s\n",
4644 num_dir_entries, usersharepath));
4651 /* Sweep through and delete any non-refreshed usershares that are
4652 not currently in use. */
4653 tmp_ctx = talloc_stackframe();
4654 for (iService = iNumServices - 1; iService >= 0; iService--) {
4655 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4658 if (snumused && snumused(sconn, iService)) {
4662 servname = lp_servicename(tmp_ctx, iService);
4664 /* Remove from the share ACL db. */
4665 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4667 delete_share_security(servname);
4668 free_service_byindex(iService);
4671 talloc_free(tmp_ctx);
4673 return lp_numservices();
4676 /********************************************************
4677 Destroy global resources allocated in this file
4678 ********************************************************/
4680 void gfree_loadparm(void)
4686 /* Free resources allocated to services */
4688 for ( i = 0; i < iNumServices; i++ ) {
4690 free_service_byindex(i);
4694 SAFE_FREE( ServicePtrs );
4697 /* Now release all resources allocated to global
4698 parameters and the default service */
4700 free_global_parameters();
4704 /***************************************************************************
4705 Allow client apps to specify that they are a client
4706 ***************************************************************************/
4707 static void lp_set_in_client(bool b)
4713 /***************************************************************************
4714 Determine if we're running in a client app
4715 ***************************************************************************/
4716 static bool lp_is_in_client(void)
4721 /***************************************************************************
4722 Load the services array from the services file. Return true on success,
4724 ***************************************************************************/
4726 static bool lp_load_ex(const char *pszFname,
4730 bool initialize_globals,
4731 bool allow_include_registry,
4732 bool load_all_shares)
4739 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4741 bInGlobalSection = true;
4742 bGlobalOnly = global_only;
4743 bAllowIncludeRegistry = allow_include_registry;
4745 init_globals(initialize_globals);
4749 if (save_defaults) {
4754 if (!initialize_globals) {
4755 free_param_opts(&Globals.param_opt);
4756 apply_lp_set_cmdline();
4759 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4761 /* We get sections first, so have to start 'behind' to make up */
4764 if (lp_config_backend_is_file()) {
4765 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4766 current_user_info.domain,
4769 smb_panic("lp_load_ex: out of memory");
4772 add_to_file_list(pszFname, n2);
4774 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4777 /* finish up the last section */
4778 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4780 if (iServiceIndex >= 0) {
4781 bRetval = service_ok(iServiceIndex);
4785 if (lp_config_backend_is_registry()) {
4786 /* config backend changed to registry in config file */
4788 * We need to use this extra global variable here to
4789 * survive restart: init_globals uses this as a default
4790 * for ConfigBackend. Otherwise, init_globals would
4791 * send us into an endless loop here.
4793 config_backend = CONFIG_BACKEND_REGISTRY;
4795 DEBUG(1, ("lp_load_ex: changing to config backend "
4798 lp_kill_all_services();
4799 return lp_load_ex(pszFname, global_only, save_defaults,
4800 add_ipc, initialize_globals,
4801 allow_include_registry,
4804 } else if (lp_config_backend_is_registry()) {
4805 bRetval = process_registry_globals();
4807 DEBUG(0, ("Illegal config backend given: %d\n",
4808 lp_config_backend()));
4812 if (bRetval && lp_registry_shares()) {
4813 if (load_all_shares) {
4814 bRetval = process_registry_shares();
4816 bRetval = reload_registry_shares();
4821 char *serv = lp_auto_services(talloc_tos());
4822 lp_add_auto_services(serv);
4827 /* When 'restrict anonymous = 2' guest connections to ipc$
4829 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4830 if ( lp_enable_asu_support() ) {
4831 lp_add_ipc("ADMIN$", false);
4835 set_allowed_client_auth();
4837 if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4838 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4839 lp_passwordserver()));
4844 /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4845 /* if bWINSsupport is true and we are in the client */
4846 if (lp_is_in_client() && Globals.bWINSsupport) {
4847 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4852 fault_configure(smb_panic_s3);
4854 bAllowIncludeRegistry = true;
4859 bool lp_load(const char *pszFname,
4863 bool initialize_globals)
4865 return lp_load_ex(pszFname,
4870 true, /* allow_include_registry */
4871 false); /* load_all_shares*/
4874 bool lp_load_initial_only(const char *pszFname)
4876 return lp_load_ex(pszFname,
4877 true, /* global only */
4878 false, /* save_defaults */
4879 false, /* add_ipc */
4880 true, /* initialize_globals */
4881 false, /* allow_include_registry */
4882 false); /* load_all_shares*/
4886 * most common lp_load wrapper, loading only the globals
4888 bool lp_load_global(const char *file_name)
4890 return lp_load_ex(file_name,
4891 true, /* global_only */
4892 false, /* save_defaults */
4893 false, /* add_ipc */
4894 true, /* initialize_globals */
4895 true, /* allow_include_registry */
4896 false); /* load_all_shares*/
4900 * lp_load wrapper, especially for clients
4902 bool lp_load_client(const char *file_name)
4904 lp_set_in_client(true);
4906 return lp_load_global(file_name);
4910 * lp_load wrapper, loading only globals, but intended
4911 * for subsequent calls, not reinitializing the globals
4914 bool lp_load_global_no_reinit(const char *file_name)
4916 return lp_load_ex(file_name,
4917 true, /* global_only */
4918 false, /* save_defaults */
4919 false, /* add_ipc */
4920 false, /* initialize_globals */
4921 true, /* allow_include_registry */
4922 false); /* load_all_shares*/
4926 * lp_load wrapper, especially for clients, no reinitialization
4928 bool lp_load_client_no_reinit(const char *file_name)
4930 lp_set_in_client(true);
4932 return lp_load_global_no_reinit(file_name);
4935 bool lp_load_with_registry_shares(const char *pszFname,
4939 bool initialize_globals)
4941 return lp_load_ex(pszFname,
4946 true, /* allow_include_registry */
4947 true); /* load_all_shares*/
4950 /***************************************************************************
4951 Return the max number of services.
4952 ***************************************************************************/
4954 int lp_numservices(void)
4956 return (iNumServices);
4959 /***************************************************************************
4960 Display the contents of the services array in human-readable form.
4961 ***************************************************************************/
4963 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4968 defaults_saved = false;
4972 dump_a_service(&sDefault, f);
4974 for (iService = 0; iService < maxtoprint; iService++) {
4976 lp_dump_one(f, show_defaults, iService);
4980 /***************************************************************************
4981 Display the contents of one service in human-readable form.
4982 ***************************************************************************/
4984 void lp_dump_one(FILE * f, bool show_defaults, int snum)
4987 if (ServicePtrs[snum]->szService[0] == '\0')
4989 dump_a_service(ServicePtrs[snum], f);
4993 /***************************************************************************
4994 Return the number of the service with the given name, or -1 if it doesn't
4995 exist. Note that this is a DIFFERENT ANIMAL from the internal function
4996 getservicebyname()! This works ONLY if all services have been loaded, and
4997 does not copy the found service.
4998 ***************************************************************************/
5000 int lp_servicenumber(const char *pszServiceName)
5003 fstring serviceName;
5005 if (!pszServiceName) {
5006 return GLOBAL_SECTION_SNUM;
5009 for (iService = iNumServices - 1; iService >= 0; iService--) {
5010 if (VALID(iService) && ServicePtrs[iService]->szService) {
5012 * The substitution here is used to support %U is
5015 fstrcpy(serviceName, ServicePtrs[iService]->szService);
5016 standard_sub_basic(get_current_username(),
5017 current_user_info.domain,
5018 serviceName,sizeof(serviceName));
5019 if (strequal(serviceName, pszServiceName)) {
5025 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5026 struct timespec last_mod;
5028 if (!usershare_exists(iService, &last_mod)) {
5029 /* Remove the share security tdb entry for it. */
5030 delete_share_security(lp_servicename(talloc_tos(), iService));
5031 /* Remove it from the array. */
5032 free_service_byindex(iService);
5033 /* Doesn't exist anymore. */
5034 return GLOBAL_SECTION_SNUM;
5037 /* Has it been modified ? If so delete and reload. */
5038 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5040 /* Remove it from the array. */
5041 free_service_byindex(iService);
5042 /* and now reload it. */
5043 iService = load_usershare_service(pszServiceName);
5048 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5049 return GLOBAL_SECTION_SNUM;
5055 /*******************************************************************
5056 A useful volume label function.
5057 ********************************************************************/
5059 const char *volume_label(TALLOC_CTX *ctx, int snum)
5062 const char *label = lp_volume(ctx, snum);
5064 label = lp_servicename(ctx, snum);
5067 /* This returns a 33 byte guarenteed null terminated string. */
5068 ret = talloc_strndup(ctx, label, 32);
5075 /*******************************************************************
5076 Get the default server type we will announce as via nmbd.
5077 ********************************************************************/
5079 int lp_default_server_announce(void)
5081 int default_server_announce = 0;
5082 default_server_announce |= SV_TYPE_WORKSTATION;
5083 default_server_announce |= SV_TYPE_SERVER;
5084 default_server_announce |= SV_TYPE_SERVER_UNIX;
5086 /* note that the flag should be set only if we have a
5087 printer service but nmbd doesn't actually load the
5088 services so we can't tell --jerry */
5090 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5092 default_server_announce |= SV_TYPE_SERVER_NT;
5093 default_server_announce |= SV_TYPE_NT;
5095 switch (lp_server_role()) {
5096 case ROLE_DOMAIN_MEMBER:
5097 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5099 case ROLE_DOMAIN_PDC:
5100 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5102 case ROLE_DOMAIN_BDC:
5103 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5105 case ROLE_STANDALONE:
5109 if (lp_time_server())
5110 default_server_announce |= SV_TYPE_TIME_SOURCE;
5112 if (lp_host_msdfs())
5113 default_server_announce |= SV_TYPE_DFS_SERVER;
5115 return default_server_announce;
5118 /***********************************************************
5119 If we are PDC then prefer us as DMB
5120 ************************************************************/
5122 bool lp_domain_master(void)
5124 if (Globals.domain_master == Auto)
5125 return (lp_server_role() == ROLE_DOMAIN_PDC);
5127 return (bool)Globals.domain_master;
5130 /***********************************************************
5131 If we are PDC then prefer us as DMB
5132 ************************************************************/
5134 static bool lp_domain_master_true_or_auto(void)
5136 if (Globals.domain_master) /* auto or yes */
5142 /***********************************************************
5143 If we are DMB then prefer us as LMB
5144 ************************************************************/
5146 bool lp_preferred_master(void)
5148 if (Globals.iPreferredMaster == Auto)
5149 return (lp_local_master() && lp_domain_master());
5151 return (bool)Globals.iPreferredMaster;
5154 /*******************************************************************
5156 ********************************************************************/
5158 void lp_remove_service(int snum)
5160 ServicePtrs[snum]->valid = false;
5161 invalid_services[num_invalid_services++] = snum;
5164 /*******************************************************************
5166 ********************************************************************/
5168 void lp_copy_service(int snum, const char *new_name)
5170 do_section(new_name, NULL);
5172 snum = lp_servicenumber(new_name);
5174 char *name = lp_servicename(talloc_tos(), snum);
5175 lp_do_parameter(snum, "copy", name);
5180 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5182 const char *ret = lp__printername(talloc_tos(), snum);
5183 if (ret == NULL || *ret == '\0') {
5184 ret = lp_const_servicename(snum);
5191 /***********************************************************
5192 Allow daemons such as winbindd to fix their logfile name.
5193 ************************************************************/
5195 void lp_set_logfile(const char *name)
5197 string_set(&Globals.logfile, name);
5198 debug_set_logfile(name);
5201 /*******************************************************************
5202 Return the max print jobs per queue.
5203 ********************************************************************/
5205 int lp_maxprintjobs(int snum)
5207 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5208 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5209 maxjobs = PRINT_MAX_JOBID - 1;
5214 const char *lp_printcapname(void)
5216 if ((Globals.szPrintcapname != NULL) &&
5217 (Globals.szPrintcapname[0] != '\0'))
5218 return Globals.szPrintcapname;
5220 if (sDefault.iPrinting == PRINT_CUPS) {
5228 if (sDefault.iPrinting == PRINT_BSD)
5229 return "/etc/printcap";
5231 return PRINTCAP_NAME;
5234 static uint32 spoolss_state;
5236 bool lp_disable_spoolss( void )
5238 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5239 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5241 return spoolss_state == SVCCTL_STOPPED ? true : false;
5244 void lp_set_spoolss_state( uint32 state )
5246 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5248 spoolss_state = state;
5251 uint32 lp_get_spoolss_state( void )
5253 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5256 /*******************************************************************
5257 Ensure we don't use sendfile if server smb signing is active.
5258 ********************************************************************/
5260 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5262 bool sign_active = false;
5264 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5265 if (get_Protocol() < PROTOCOL_NT1) {
5268 if (signing_state) {
5269 sign_active = smb_signing_is_active(signing_state);
5271 return (lp__use_sendfile(snum) &&
5272 (get_remote_arch() != RA_WIN95) &&
5276 /*******************************************************************
5277 Turn off sendfile if we find the underlying OS doesn't support it.
5278 ********************************************************************/
5280 void set_use_sendfile(int snum, bool val)
5282 if (LP_SNUM_OK(snum))
5283 ServicePtrs[snum]->bUseSendfile = val;
5285 sDefault.bUseSendfile = val;
5288 /*******************************************************************
5289 Turn off storing DOS attributes if this share doesn't support it.
5290 ********************************************************************/
5292 void set_store_dos_attributes(int snum, bool val)
5294 if (!LP_SNUM_OK(snum))
5296 ServicePtrs[(snum)]->bStoreDosAttributes = val;
5299 void lp_set_mangling_method(const char *new_method)
5301 string_set(&Globals.szManglingMethod, new_method);
5304 /*******************************************************************
5305 Global state for POSIX pathname processing.
5306 ********************************************************************/
5308 static bool posix_pathnames;
5310 bool lp_posix_pathnames(void)
5312 return posix_pathnames;
5315 /*******************************************************************
5316 Change everything needed to ensure POSIX pathname processing (currently
5318 ********************************************************************/
5320 void lp_set_posix_pathnames(void)
5322 posix_pathnames = true;
5325 /*******************************************************************
5326 Global state for POSIX lock processing - CIFS unix extensions.
5327 ********************************************************************/
5329 bool posix_default_lock_was_set;
5330 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5332 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5334 if (posix_default_lock_was_set) {
5335 return posix_cifsx_locktype;
5337 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5341 /*******************************************************************
5342 ********************************************************************/
5344 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5346 posix_default_lock_was_set = true;
5347 posix_cifsx_locktype = val;
5350 int lp_min_receive_file_size(void)
5352 if (Globals.iminreceivefile < 0) {
5355 return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5358 /*******************************************************************
5359 Safe wide links checks.
5360 This helper function always verify the validity of wide links,
5361 even after a configuration file reload.
5362 ********************************************************************/
5364 static bool lp_widelinks_internal(int snum)
5366 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5367 sDefault.bWidelinks);
5370 void widelinks_warning(int snum)
5372 if (lp_allow_insecure_widelinks()) {
5376 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5377 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5378 "These parameters are incompatible. "
5379 "Wide links will be disabled for this share.\n",
5380 lp_servicename(talloc_tos(), snum) ));
5384 bool lp_widelinks(int snum)
5386 /* wide links is always incompatible with unix extensions */
5387 if (lp_unix_extensions()) {
5389 * Unless we have "allow insecure widelinks"
5392 if (!lp_allow_insecure_widelinks()) {
5397 return lp_widelinks_internal(snum);
5400 bool lp_writeraw(void)
5402 if (lp_async_smb_echo_handler()) {
5405 return lp__writeraw();
5408 bool lp_readraw(void)
5410 if (lp_async_smb_echo_handler()) {
5413 return lp__readraw();
5416 int lp_server_role(void)
5418 return lp_find_server_role(lp__server_role(),
5420 lp__domain_logons(),
5421 lp_domain_master_true_or_auto());
5424 int lp_security(void)
5426 return lp_find_security(lp__server_role(),