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"
60 #include "lib/smbconf/smbconf.h"
61 #include "lib/smbconf/smbconf_init.h"
62 #include "lib/param/loadparm.h"
65 #include "../librpc/gen_ndr/svcctl.h"
67 #include "../libcli/smb/smb_signing.h"
68 #include "dbwrap/dbwrap.h"
69 #include "dbwrap/dbwrap_rbt.h"
70 #include "../lib/util/bitmap.h"
71 #include "../source4/dns_server/dns_update.h"
73 #ifdef HAVE_SYS_SYSCTL_H
74 #include <sys/sysctl.h>
77 #ifdef HAVE_HTTPCONNECTENCRYPT
78 #include <cups/http.h>
81 #ifdef CLUSTER_SUPPORT
82 #include "ctdb_private.h"
87 extern userdom_struct current_user_info;
89 /* the special value for the include parameter
90 * to be interpreted not as a file name but to
91 * trigger loading of the global smb.conf options
93 #ifndef INCLUDE_REGISTRY_NAME
94 #define INCLUDE_REGISTRY_NAME "registry"
97 static bool in_client = false; /* Not in the client by default */
98 static struct smbconf_csn conf_last_csn;
100 #define CONFIG_BACKEND_FILE 0
101 #define CONFIG_BACKEND_REGISTRY 1
103 static int config_backend = CONFIG_BACKEND_FILE;
105 /* some helpful bits */
106 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
107 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
109 #define USERSHARE_VALID 1
110 #define USERSHARE_PENDING_DELETE 2
112 static bool defaults_saved = false;
114 #define LOADPARM_EXTRA_GLOBALS \
115 struct parmlist_entry *param_opt; \
118 int iminreceivefile; \
119 char *szPrintcapname; \
121 int iPreferredMaster; \
123 char *szLdapMachineSuffix; \
124 char *szLdapUserSuffix; \
125 char *szLdapIdmapSuffix; \
126 char *szLdapGroupSuffix; \
129 char *szSocketAddress; \
130 char *szUsershareTemplateShare; \
133 int winbindMaxDomainConnections; \
134 int ismb2_max_credits;
136 #include "param/param_global.h"
138 static struct loadparm_global Globals;
140 /* This is a default service used to prime a services structure */
141 static struct loadparm_service sDefault =
146 .usershare_last_mod = {0, 0},
150 .szInvalidUsers = NULL,
151 .szValidUsers = NULL,
152 .szAdminUsers = NULL,
157 .szRootPreExec = NULL,
158 .szRootPostExec = NULL,
159 .szCupsOptions = NULL,
160 .szPrintcommand = NULL,
161 .szLpqcommand = NULL,
162 .szLprmcommand = NULL,
163 .szLppausecommand = NULL,
164 .szLpresumecommand = NULL,
165 .szQueuepausecommand = NULL,
166 .szQueueresumecommand = NULL,
167 .szPrintername = NULL,
168 .szPrintjobUsername = NULL,
169 .szDontdescend = NULL,
170 .szHostsallow = NULL,
172 .szMagicScript = NULL,
173 .szMagicOutput = NULL,
176 .szVetoOplockFiles = NULL,
184 .szVfsObjects = NULL,
185 .szMSDfsProxy = NULL,
186 .szAioWriteBehind = NULL,
189 .iMaxPrintJobs = 1000,
190 .iMaxReportedPrintJobs = 0,
191 .iWriteCacheSize = 0,
192 .iCreate_mask = 0744,
193 .iCreate_force_mode = 0,
194 .iSecurity_mask = 0777,
195 .iSecurity_force_mode = 0,
197 .iDir_force_mode = 0,
198 .iDir_Security_mask = 0777,
199 .iDir_Security_force_mode = 0,
200 .iMaxConnections = 0,
201 .iDefaultCase = CASE_LOWER,
202 .iPrinting = DEFAULT_PRINTING,
203 .iOplockContentionLimit = 2,
206 .iDfreeCacheTime = 0,
207 .bPreexecClose = false,
208 .bRootpreexecClose = false,
209 .iCaseSensitive = Auto,
210 .bCasePreserve = true,
211 .bShortCasePreserve = true,
212 .bHideDotFiles = true,
213 .bHideSpecialFiles = false,
214 .bHideUnReadable = false,
215 .bHideUnWriteableFiles = false,
217 .bAccessBasedShareEnum = false,
221 .bGuest_only = false,
222 .bAdministrative_share = false,
225 .bPrintNotifyBackchannel = true,
226 .bMap_system = false,
227 .bMap_hidden = false,
228 .bMap_archive = true,
229 .bStoreDosAttributes = false,
230 .bDmapiSupport = false,
232 .iStrictLocking = Auto,
233 .bPosixLocking = true,
236 .bKernelOplocks = false,
237 .bLevel2OpLocks = true,
239 .bMangledNames = true,
242 .bSyncAlways = false,
243 .bStrictAllocate = false,
244 .bStrictSync = false,
247 .bDeleteReadonly = false,
248 .bFakeOplocks = false,
249 .bDeleteVetoFiles = false,
250 .bDosFilemode = false,
251 .bDosFiletimes = true,
252 .bDosFiletimeResolution = false,
253 .bFakeDirCreateTimes = false,
254 .bBlockingLocks = true,
255 .bInheritPerms = false,
256 .bInheritACLS = false,
257 .bInheritOwner = false,
259 .bUseClientDriver = false,
260 .bDefaultDevmode = true,
261 .bForcePrintername = false,
262 .bNTAclSupport = true,
263 .bForceUnknownAclUser = false,
264 .bUseSendfile = false,
265 .bProfileAcls = false,
266 .bMap_acl_inherit = false,
269 .bAclCheckPermissions = true,
270 .bAclMapFullControl = true,
271 .bAclGroupControl = false,
272 .bChangeNotify = true,
273 .bKernelChangeNotify = true,
274 .iallocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
277 .iMap_readonly = MAP_READONLY_YES,
278 #ifdef BROKEN_DIRECTORY_HANDLING
279 .iDirectoryNameCacheSize = 0,
281 .iDirectoryNameCacheSize = 100,
283 .ismb_encrypt = Auto,
288 /* local variables */
289 static struct loadparm_service **ServicePtrs = NULL;
290 static int iNumServices = 0;
291 static int iServiceIndex = 0;
292 static struct db_context *ServiceHash;
293 static int *invalid_services = NULL;
294 static int num_invalid_services = 0;
295 static bool bInGlobalSection = true;
296 static bool bGlobalOnly = false;
298 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
300 /* prototypes for the special type handlers */
301 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
302 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
303 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
304 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
305 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
306 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
307 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
308 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
309 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
310 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
311 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
312 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
314 static void set_allowed_client_auth(void);
316 static void add_to_file_list(const char *fname, const char *subfname);
317 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
318 static void free_param_opts(struct parmlist_entry **popts);
320 #include "lib/param/param_enums.c"
322 static const struct enum_list enum_printing[] = {
323 {PRINT_SYSV, "sysv"},
325 {PRINT_HPUX, "hpux"},
329 {PRINT_LPRNG, "lprng"},
330 {PRINT_CUPS, "cups"},
331 {PRINT_IPRINT, "iprint"},
333 {PRINT_LPROS2, "os2"},
334 #if defined(DEVELOPER) || defined(ENABLE_BUILD_FARM_HACKS)
335 {PRINT_TEST, "test"},
337 #endif /* DEVELOPER */
341 static const struct enum_list enum_ldap_sasl_wrapping[] = {
343 {ADS_AUTH_SASL_SIGN, "sign"},
344 {ADS_AUTH_SASL_SEAL, "seal"},
348 static const struct enum_list enum_ldap_ssl[] = {
349 {LDAP_SSL_OFF, "no"},
350 {LDAP_SSL_OFF, "off"},
351 {LDAP_SSL_START_TLS, "start tls"},
352 {LDAP_SSL_START_TLS, "start_tls"},
356 /* LDAP Dereferencing Alias types */
357 #define SAMBA_LDAP_DEREF_NEVER 0
358 #define SAMBA_LDAP_DEREF_SEARCHING 1
359 #define SAMBA_LDAP_DEREF_FINDING 2
360 #define SAMBA_LDAP_DEREF_ALWAYS 3
362 static const struct enum_list enum_ldap_deref[] = {
363 {SAMBA_LDAP_DEREF_NEVER, "never"},
364 {SAMBA_LDAP_DEREF_SEARCHING, "searching"},
365 {SAMBA_LDAP_DEREF_FINDING, "finding"},
366 {SAMBA_LDAP_DEREF_ALWAYS, "always"},
370 static const struct enum_list enum_ldap_passwd_sync[] = {
371 {LDAP_PASSWD_SYNC_OFF, "no"},
372 {LDAP_PASSWD_SYNC_OFF, "off"},
373 {LDAP_PASSWD_SYNC_ON, "yes"},
374 {LDAP_PASSWD_SYNC_ON, "on"},
375 {LDAP_PASSWD_SYNC_ONLY, "only"},
379 static const struct enum_list enum_map_readonly[] = {
380 {MAP_READONLY_NO, "no"},
381 {MAP_READONLY_NO, "false"},
382 {MAP_READONLY_NO, "0"},
383 {MAP_READONLY_YES, "yes"},
384 {MAP_READONLY_YES, "true"},
385 {MAP_READONLY_YES, "1"},
386 {MAP_READONLY_PERMISSIONS, "permissions"},
387 {MAP_READONLY_PERMISSIONS, "perms"},
391 static const struct enum_list enum_case[] = {
392 {CASE_LOWER, "lower"},
393 {CASE_UPPER, "upper"},
398 /* ACL compatibility options. */
399 static const struct enum_list enum_acl_compat_vals[] = {
400 { ACL_COMPAT_AUTO, "auto" },
401 { ACL_COMPAT_WINNT, "winnt" },
402 { ACL_COMPAT_WIN2K, "win2k" },
407 Do you want session setups at user level security with a invalid
408 password to be rejected or allowed in as guest? WinNT rejects them
409 but it can be a pain as it means "net view" needs to use a password
411 You have 3 choices in the setting of map_to_guest:
413 "Never" means session setups with an invalid password
414 are rejected. This is the default.
416 "Bad User" means session setups with an invalid password
417 are rejected, unless the username does not exist, in which case it
418 is treated as a guest login
420 "Bad Password" means session setups with an invalid password
421 are treated as a guest login
423 Note that map_to_guest only has an effect in user or server
427 static const struct enum_list enum_map_to_guest[] = {
428 {NEVER_MAP_TO_GUEST, "Never"},
429 {MAP_TO_GUEST_ON_BAD_USER, "Bad User"},
430 {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"},
431 {MAP_TO_GUEST_ON_BAD_UID, "Bad Uid"},
435 /* Config backend options */
437 static const struct enum_list enum_config_backend[] = {
438 {CONFIG_BACKEND_FILE, "file"},
439 {CONFIG_BACKEND_REGISTRY, "registry"},
443 /* ADS kerberos ticket verification options */
445 static const struct enum_list enum_kerberos_method[] = {
446 {KERBEROS_VERIFY_SECRETS, "default"},
447 {KERBEROS_VERIFY_SECRETS, "secrets only"},
448 {KERBEROS_VERIFY_SYSTEM_KEYTAB, "system keytab"},
449 {KERBEROS_VERIFY_DEDICATED_KEYTAB, "dedicated keytab"},
450 {KERBEROS_VERIFY_SECRETS_AND_KEYTAB, "secrets and keytab"},
454 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
456 * The FLAG_HIDE is explicit. Parameters set this way do NOT appear in any edit
457 * screen in SWAT. This is used to exclude parameters as well as to squash all
458 * parameters that have been duplicated by pseudonyms.
460 * NOTE: To display a parameter in BASIC view set FLAG_BASIC
461 * Any parameter that does NOT have FLAG_ADVANCED will not disply at all
462 * Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in
465 * NOTE2: Handling of duplicated (synonym) parameters:
466 * Only the first occurance of a parameter should be enabled by FLAG_BASIC
467 * and/or FLAG_ADVANCED. All duplicates following the first mention should be
468 * set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred
469 * name first, and all synonyms must follow it with the FLAG_HIDE attribute.
472 #define GLOBAL_VAR(name) offsetof(struct loadparm_global, name)
473 #define LOCAL_VAR(name) offsetof(struct loadparm_service, name)
475 static struct parm_struct parm_table[] = {
476 {N_("Base Options"), P_SEP, P_SEPARATOR},
479 .label = "dos charset",
482 .offset = GLOBAL_VAR(dos_charset),
483 .special = handle_dos_charset,
485 .flags = FLAG_ADVANCED
488 .label = "unix charset",
491 .offset = GLOBAL_VAR(unix_charset),
492 .special = handle_charset,
494 .flags = FLAG_ADVANCED
500 .offset = LOCAL_VAR(comment),
503 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT
509 .offset = LOCAL_VAR(szPath),
512 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
515 .label = "directory",
518 .offset = LOCAL_VAR(szPath),
524 .label = "workgroup",
527 .offset = GLOBAL_VAR(szWorkgroup),
530 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
536 .offset = GLOBAL_VAR(szRealm),
537 .special = handle_realm,
539 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
542 .label = "netbios name",
545 .offset = GLOBAL_VAR(szNetbiosName),
548 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
551 .label = "netbios aliases",
554 .offset = GLOBAL_VAR(szNetbiosAliases),
555 .special = handle_netbios_aliases,
557 .flags = FLAG_ADVANCED,
560 .label = "netbios scope",
563 .offset = GLOBAL_VAR(szNetbiosScope),
566 .flags = FLAG_ADVANCED,
569 .label = "server string",
572 .offset = GLOBAL_VAR(szServerString),
575 .flags = FLAG_BASIC | FLAG_ADVANCED,
578 .label = "interfaces",
581 .offset = GLOBAL_VAR(szInterfaces),
584 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
587 .label = "bind interfaces only",
590 .offset = GLOBAL_VAR(bBindInterfacesOnly),
593 .flags = FLAG_ADVANCED | FLAG_WIZARD,
596 .label = "config backend",
599 .offset = GLOBAL_VAR(ConfigBackend),
601 .enum_list = enum_config_backend,
602 .flags = FLAG_HIDE|FLAG_ADVANCED|FLAG_META,
605 .label = "server role",
608 .offset = GLOBAL_VAR(ServerRole),
610 .enum_list = enum_server_role,
611 .flags = FLAG_BASIC | FLAG_ADVANCED,
614 {N_("Security Options"), P_SEP, P_SEPARATOR},
620 .offset = GLOBAL_VAR(security),
622 .enum_list = enum_security,
623 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
626 .label = "auth methods",
629 .offset = GLOBAL_VAR(AuthMethods),
632 .flags = FLAG_ADVANCED,
635 .label = "encrypt passwords",
638 .offset = GLOBAL_VAR(bEncryptPasswords),
641 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
644 .label = "client schannel",
647 .offset = GLOBAL_VAR(clientSchannel),
649 .enum_list = enum_bool_auto,
650 .flags = FLAG_BASIC | FLAG_ADVANCED,
653 .label = "server schannel",
656 .offset = GLOBAL_VAR(serverSchannel),
658 .enum_list = enum_bool_auto,
659 .flags = FLAG_BASIC | FLAG_ADVANCED,
662 .label = "allow trusted domains",
665 .offset = GLOBAL_VAR(bAllowTrustedDomains),
668 .flags = FLAG_ADVANCED,
671 .label = "map to guest",
674 .offset = GLOBAL_VAR(map_to_guest),
676 .enum_list = enum_map_to_guest,
677 .flags = FLAG_ADVANCED,
680 .label = "null passwords",
683 .offset = GLOBAL_VAR(bNullPasswords),
686 .flags = FLAG_ADVANCED | FLAG_DEPRECATED,
689 .label = "obey pam restrictions",
692 .offset = GLOBAL_VAR(bObeyPamRestrictions),
695 .flags = FLAG_ADVANCED,
698 .label = "password server",
701 .offset = GLOBAL_VAR(szPasswordServer),
704 .flags = FLAG_ADVANCED | FLAG_WIZARD,
707 .label = "smb passwd file",
710 .offset = GLOBAL_VAR(szSMBPasswdFile),
713 .flags = FLAG_ADVANCED,
716 .label = "private dir",
719 .offset = GLOBAL_VAR(szPrivateDir),
722 .flags = FLAG_ADVANCED,
725 .label = "private directory",
728 .offset = GLOBAL_VAR(szPrivateDir),
734 .label = "passdb backend",
737 .offset = GLOBAL_VAR(passdb_backend),
740 .flags = FLAG_ADVANCED | FLAG_WIZARD,
743 .label = "algorithmic rid base",
746 .offset = GLOBAL_VAR(AlgorithmicRidBase),
749 .flags = FLAG_ADVANCED,
752 .label = "root directory",
755 .offset = GLOBAL_VAR(szRootdir),
758 .flags = FLAG_ADVANCED,
764 .offset = GLOBAL_VAR(szRootdir),
773 .offset = GLOBAL_VAR(szRootdir),
779 .label = "guest account",
782 .offset = GLOBAL_VAR(szGuestaccount),
785 .flags = FLAG_BASIC | FLAG_ADVANCED,
788 .label = "enable privileges",
791 .offset = GLOBAL_VAR(bEnablePrivileges),
794 .flags = FLAG_ADVANCED | FLAG_DEPRECATED,
798 .label = "pam password change",
801 .offset = GLOBAL_VAR(bPamPasswordChange),
804 .flags = FLAG_ADVANCED,
807 .label = "passwd program",
810 .offset = GLOBAL_VAR(szPasswdProgram),
813 .flags = FLAG_ADVANCED,
816 .label = "passwd chat",
819 .offset = GLOBAL_VAR(szPasswdChat),
822 .flags = FLAG_ADVANCED,
825 .label = "passwd chat debug",
828 .offset = GLOBAL_VAR(bPasswdChatDebug),
831 .flags = FLAG_ADVANCED,
834 .label = "passwd chat timeout",
837 .offset = GLOBAL_VAR(iPasswdChatTimeout),
840 .flags = FLAG_ADVANCED,
843 .label = "check password script",
846 .offset = GLOBAL_VAR(szCheckPasswordScript),
849 .flags = FLAG_ADVANCED,
852 .label = "username map",
855 .offset = GLOBAL_VAR(szUsernameMap),
858 .flags = FLAG_ADVANCED,
861 .label = "password level",
864 .offset = GLOBAL_VAR(pwordlevel),
867 .flags = FLAG_ADVANCED | FLAG_DEPRECATED,
870 .label = "username level",
873 .offset = GLOBAL_VAR(unamelevel),
876 .flags = FLAG_ADVANCED,
879 .label = "unix password sync",
882 .offset = GLOBAL_VAR(bUnixPasswdSync),
885 .flags = FLAG_ADVANCED,
888 .label = "restrict anonymous",
891 .offset = GLOBAL_VAR(restrict_anonymous),
894 .flags = FLAG_ADVANCED,
897 .label = "lanman auth",
900 .offset = GLOBAL_VAR(bLanmanAuth),
903 .flags = FLAG_ADVANCED,
906 .label = "ntlm auth",
909 .offset = GLOBAL_VAR(bNTLMAuth),
912 .flags = FLAG_ADVANCED,
915 .label = "client NTLMv2 auth",
918 .offset = GLOBAL_VAR(bClientNTLMv2Auth),
921 .flags = FLAG_ADVANCED,
924 .label = "client lanman auth",
927 .offset = GLOBAL_VAR(bClientLanManAuth),
930 .flags = FLAG_ADVANCED,
933 .label = "client plaintext auth",
936 .offset = GLOBAL_VAR(bClientPlaintextAuth),
939 .flags = FLAG_ADVANCED,
942 .label = "client use spnego principal",
945 .offset = GLOBAL_VAR(client_use_spnego_principal),
948 .flags = FLAG_ADVANCED,
954 .offset = LOCAL_VAR(szUsername),
957 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE | FLAG_DEPRECATED,
963 .offset = LOCAL_VAR(szUsername),
972 .offset = LOCAL_VAR(szUsername),
978 .label = "invalid users",
981 .offset = LOCAL_VAR(szInvalidUsers),
984 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
987 .label = "valid users",
990 .offset = LOCAL_VAR(szValidUsers),
993 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
996 .label = "admin users",
999 .offset = LOCAL_VAR(szAdminUsers),
1002 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1005 .label = "read list",
1008 .offset = LOCAL_VAR(readlist),
1011 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1014 .label = "write list",
1017 .offset = LOCAL_VAR(writelist),
1020 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1023 .label = "force user",
1026 .offset = LOCAL_VAR(force_user),
1029 .flags = FLAG_ADVANCED | FLAG_SHARE,
1032 .label = "force group",
1035 .offset = LOCAL_VAR(force_group),
1038 .flags = FLAG_ADVANCED | FLAG_SHARE,
1044 .offset = LOCAL_VAR(force_group),
1047 .flags = FLAG_ADVANCED,
1050 .label = "read only",
1053 .offset = LOCAL_VAR(bRead_only),
1056 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE,
1059 .label = "write ok",
1062 .offset = LOCAL_VAR(bRead_only),
1068 .label = "writeable",
1071 .offset = LOCAL_VAR(bRead_only),
1077 .label = "writable",
1080 .offset = LOCAL_VAR(bRead_only),
1086 .label = "acl check permissions",
1089 .offset = LOCAL_VAR(bAclCheckPermissions),
1092 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE | FLAG_DEPRECATED,
1095 .label = "acl group control",
1098 .offset = LOCAL_VAR(bAclGroupControl),
1101 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1104 .label = "acl map full control",
1107 .offset = LOCAL_VAR(bAclMapFullControl),
1110 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1113 .label = "create mask",
1116 .offset = LOCAL_VAR(iCreate_mask),
1119 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1122 .label = "create mode",
1125 .offset = LOCAL_VAR(iCreate_mask),
1131 .label = "force create mode",
1134 .offset = LOCAL_VAR(iCreate_force_mode),
1137 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1140 .label = "security mask",
1143 .offset = LOCAL_VAR(iSecurity_mask),
1146 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1149 .label = "force security mode",
1152 .offset = LOCAL_VAR(iSecurity_force_mode),
1155 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1158 .label = "directory mask",
1161 .offset = LOCAL_VAR(iDir_mask),
1164 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1167 .label = "directory mode",
1170 .offset = LOCAL_VAR(iDir_mask),
1173 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
1176 .label = "force directory mode",
1179 .offset = LOCAL_VAR(iDir_force_mode),
1182 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1185 .label = "directory security mask",
1188 .offset = LOCAL_VAR(iDir_Security_mask),
1191 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1194 .label = "force directory security mode",
1197 .offset = LOCAL_VAR(iDir_Security_force_mode),
1200 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1203 .label = "force unknown acl user",
1206 .offset = LOCAL_VAR(bForceUnknownAclUser),
1209 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1212 .label = "inherit permissions",
1215 .offset = LOCAL_VAR(bInheritPerms),
1218 .flags = FLAG_ADVANCED | FLAG_SHARE,
1221 .label = "inherit acls",
1224 .offset = LOCAL_VAR(bInheritACLS),
1227 .flags = FLAG_ADVANCED | FLAG_SHARE,
1230 .label = "inherit owner",
1233 .offset = LOCAL_VAR(bInheritOwner),
1236 .flags = FLAG_ADVANCED | FLAG_SHARE,
1239 .label = "guest only",
1242 .offset = LOCAL_VAR(bGuest_only),
1245 .flags = FLAG_ADVANCED | FLAG_SHARE,
1248 .label = "only guest",
1251 .offset = LOCAL_VAR(bGuest_only),
1257 .label = "administrative share",
1260 .offset = LOCAL_VAR(bAdministrative_share),
1263 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1267 .label = "guest ok",
1270 .offset = LOCAL_VAR(bGuest_ok),
1273 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1279 .offset = LOCAL_VAR(bGuest_ok),
1285 .label = "only user",
1288 .offset = LOCAL_VAR(bOnlyUser),
1291 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED,
1294 .label = "hosts allow",
1297 .offset = LOCAL_VAR(szHostsallow),
1300 .flags = FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1303 .label = "allow hosts",
1306 .offset = LOCAL_VAR(szHostsallow),
1312 .label = "hosts deny",
1315 .offset = LOCAL_VAR(szHostsdeny),
1318 .flags = FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1321 .label = "deny hosts",
1324 .offset = LOCAL_VAR(szHostsdeny),
1330 .label = "preload modules",
1332 .p_class = P_GLOBAL,
1333 .offset = GLOBAL_VAR(szPreloadModules),
1336 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
1339 .label = "dedicated keytab file",
1341 .p_class = P_GLOBAL,
1342 .offset = GLOBAL_VAR(szDedicatedKeytabFile),
1345 .flags = FLAG_ADVANCED,
1348 .label = "kerberos method",
1350 .p_class = P_GLOBAL,
1351 .offset = GLOBAL_VAR(iKerberosMethod),
1353 .enum_list = enum_kerberos_method,
1354 .flags = FLAG_ADVANCED,
1357 .label = "map untrusted to domain",
1359 .p_class = P_GLOBAL,
1360 .offset = GLOBAL_VAR(bMapUntrustedToDomain),
1363 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
1367 {N_("Logging Options"), P_SEP, P_SEPARATOR},
1370 .label = "log level",
1372 .p_class = P_GLOBAL,
1373 .offset = GLOBAL_VAR(szLogLevel),
1374 .special = handle_debug_list,
1376 .flags = FLAG_ADVANCED,
1379 .label = "debuglevel",
1381 .p_class = P_GLOBAL,
1382 .offset = GLOBAL_VAR(szLogLevel),
1383 .special = handle_debug_list,
1390 .p_class = P_GLOBAL,
1391 .offset = GLOBAL_VAR(syslog),
1394 .flags = FLAG_ADVANCED,
1397 .label = "syslog only",
1399 .p_class = P_GLOBAL,
1400 .offset = GLOBAL_VAR(bSyslogOnly),
1403 .flags = FLAG_ADVANCED,
1406 .label = "log file",
1408 .p_class = P_GLOBAL,
1409 .offset = GLOBAL_VAR(logfile),
1412 .flags = FLAG_ADVANCED,
1415 .label = "max log size",
1417 .p_class = P_GLOBAL,
1418 .offset = GLOBAL_VAR(max_log_size),
1421 .flags = FLAG_ADVANCED,
1424 .label = "debug timestamp",
1426 .p_class = P_GLOBAL,
1427 .offset = GLOBAL_VAR(bTimestampLogs),
1430 .flags = FLAG_ADVANCED,
1433 .label = "timestamp logs",
1435 .p_class = P_GLOBAL,
1436 .offset = GLOBAL_VAR(bTimestampLogs),
1439 .flags = FLAG_ADVANCED,
1442 .label = "debug prefix timestamp",
1444 .p_class = P_GLOBAL,
1445 .offset = GLOBAL_VAR(bDebugPrefixTimestamp),
1448 .flags = FLAG_ADVANCED,
1451 .label = "debug hires timestamp",
1453 .p_class = P_GLOBAL,
1454 .offset = GLOBAL_VAR(bDebugHiresTimestamp),
1457 .flags = FLAG_ADVANCED,
1460 .label = "debug pid",
1462 .p_class = P_GLOBAL,
1463 .offset = GLOBAL_VAR(bDebugPid),
1466 .flags = FLAG_ADVANCED,
1469 .label = "debug uid",
1471 .p_class = P_GLOBAL,
1472 .offset = GLOBAL_VAR(bDebugUid),
1475 .flags = FLAG_ADVANCED,
1478 .label = "debug class",
1480 .p_class = P_GLOBAL,
1481 .offset = GLOBAL_VAR(bDebugClass),
1484 .flags = FLAG_ADVANCED,
1487 .label = "enable core files",
1489 .p_class = P_GLOBAL,
1490 .offset = GLOBAL_VAR(bEnableCoreFiles),
1493 .flags = FLAG_ADVANCED,
1496 {N_("Protocol Options"), P_SEP, P_SEPARATOR},
1499 .label = "allocation roundup size",
1502 .offset = LOCAL_VAR(iallocation_roundup_size),
1505 .flags = FLAG_ADVANCED,
1508 .label = "aio read size",
1511 .offset = LOCAL_VAR(iAioReadSize),
1514 .flags = FLAG_ADVANCED,
1517 .label = "aio write size",
1520 .offset = LOCAL_VAR(iAioWriteSize),
1523 .flags = FLAG_ADVANCED,
1526 .label = "aio write behind",
1529 .offset = LOCAL_VAR(szAioWriteBehind),
1532 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1535 .label = "smb ports",
1537 .p_class = P_GLOBAL,
1538 .offset = GLOBAL_VAR(smb_ports),
1541 .flags = FLAG_ADVANCED,
1544 .label = "large readwrite",
1546 .p_class = P_GLOBAL,
1547 .offset = GLOBAL_VAR(bLargeReadwrite),
1550 .flags = FLAG_ADVANCED,
1553 .label = "server max protocol",
1555 .p_class = P_GLOBAL,
1556 .offset = GLOBAL_VAR(srv_maxprotocol),
1558 .enum_list = enum_protocol,
1559 .flags = FLAG_ADVANCED,
1562 .label = "max protocol",
1564 .p_class = P_GLOBAL,
1565 .offset = GLOBAL_VAR(srv_maxprotocol),
1567 .enum_list = enum_protocol,
1568 .flags = FLAG_ADVANCED,
1571 .label = "protocol",
1573 .p_class = P_GLOBAL,
1574 .offset = GLOBAL_VAR(srv_maxprotocol),
1576 .enum_list = enum_protocol,
1577 .flags = FLAG_ADVANCED,
1580 .label = "server min protocol",
1582 .p_class = P_GLOBAL,
1583 .offset = GLOBAL_VAR(srv_minprotocol),
1585 .enum_list = enum_protocol,
1586 .flags = FLAG_ADVANCED,
1589 .label = "min protocol",
1591 .p_class = P_GLOBAL,
1592 .offset = GLOBAL_VAR(srv_minprotocol),
1594 .enum_list = enum_protocol,
1595 .flags = FLAG_ADVANCED,
1598 .label = "min receivefile size",
1600 .p_class = P_GLOBAL,
1601 .offset = GLOBAL_VAR(iminreceivefile),
1604 .flags = FLAG_ADVANCED,
1607 .label = "read raw",
1609 .p_class = P_GLOBAL,
1610 .offset = GLOBAL_VAR(bReadRaw),
1613 .flags = FLAG_ADVANCED,
1616 .label = "write raw",
1618 .p_class = P_GLOBAL,
1619 .offset = GLOBAL_VAR(bWriteRaw),
1622 .flags = FLAG_ADVANCED,
1625 .label = "disable netbios",
1627 .p_class = P_GLOBAL,
1628 .offset = GLOBAL_VAR(bDisableNetbios),
1631 .flags = FLAG_ADVANCED,
1634 .label = "reset on zero vc",
1636 .p_class = P_GLOBAL,
1637 .offset = GLOBAL_VAR(bResetOnZeroVC),
1640 .flags = FLAG_ADVANCED,
1643 .label = "log writeable files on exit",
1645 .p_class = P_GLOBAL,
1646 .offset = GLOBAL_VAR(bLogWriteableFilesOnExit),
1649 .flags = FLAG_ADVANCED,
1652 .label = "acl compatibility",
1654 .p_class = P_GLOBAL,
1655 .offset = GLOBAL_VAR(iAclCompat),
1657 .enum_list = enum_acl_compat_vals,
1658 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1661 .label = "defer sharing violations",
1663 .p_class = P_GLOBAL,
1664 .offset = GLOBAL_VAR(bDeferSharingViolations),
1667 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
1670 .label = "ea support",
1673 .offset = LOCAL_VAR(bEASupport),
1676 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1679 .label = "nt acl support",
1682 .offset = LOCAL_VAR(bNTAclSupport),
1685 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1688 .label = "nt pipe support",
1690 .p_class = P_GLOBAL,
1691 .offset = GLOBAL_VAR(bNTPipeSupport),
1694 .flags = FLAG_ADVANCED,
1697 .label = "nt status support",
1699 .p_class = P_GLOBAL,
1700 .offset = GLOBAL_VAR(bNTStatusSupport),
1703 .flags = FLAG_ADVANCED,
1706 .label = "profile acls",
1709 .offset = LOCAL_VAR(bProfileAcls),
1712 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1715 .label = "map acl inherit",
1718 .offset = LOCAL_VAR(bMap_acl_inherit),
1721 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1724 .label = "afs share",
1727 .offset = LOCAL_VAR(bAfs_Share),
1730 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1735 .p_class = P_GLOBAL,
1736 .offset = GLOBAL_VAR(max_mux),
1739 .flags = FLAG_ADVANCED,
1742 .label = "max xmit",
1744 .p_class = P_GLOBAL,
1745 .offset = GLOBAL_VAR(max_xmit),
1748 .flags = FLAG_ADVANCED,
1751 .label = "name resolve order",
1753 .p_class = P_GLOBAL,
1754 .offset = GLOBAL_VAR(szNameResolveOrder),
1757 .flags = FLAG_ADVANCED | FLAG_WIZARD,
1762 .p_class = P_GLOBAL,
1763 .offset = GLOBAL_VAR(max_ttl),
1766 .flags = FLAG_ADVANCED,
1769 .label = "max wins ttl",
1771 .p_class = P_GLOBAL,
1772 .offset = GLOBAL_VAR(max_wins_ttl),
1775 .flags = FLAG_ADVANCED,
1778 .label = "min wins ttl",
1780 .p_class = P_GLOBAL,
1781 .offset = GLOBAL_VAR(min_wins_ttl),
1784 .flags = FLAG_ADVANCED,
1787 .label = "time server",
1789 .p_class = P_GLOBAL,
1790 .offset = GLOBAL_VAR(bTimeServer),
1793 .flags = FLAG_ADVANCED,
1796 .label = "unix extensions",
1798 .p_class = P_GLOBAL,
1799 .offset = GLOBAL_VAR(bUnixExtensions),
1802 .flags = FLAG_ADVANCED,
1805 .label = "use spnego",
1807 .p_class = P_GLOBAL,
1808 .offset = GLOBAL_VAR(bUseSpnego),
1811 .flags = FLAG_ADVANCED | FLAG_DEPRECATED,
1814 .label = "client signing",
1816 .p_class = P_GLOBAL,
1817 .offset = GLOBAL_VAR(client_signing),
1819 .enum_list = enum_smb_signing_vals,
1820 .flags = FLAG_ADVANCED,
1823 .label = "server signing",
1825 .p_class = P_GLOBAL,
1826 .offset = GLOBAL_VAR(server_signing),
1828 .enum_list = enum_smb_signing_vals,
1829 .flags = FLAG_ADVANCED,
1832 .label = "smb encrypt",
1835 .offset = LOCAL_VAR(ismb_encrypt),
1837 .enum_list = enum_smb_signing_vals,
1838 .flags = FLAG_ADVANCED,
1841 .label = "client use spnego",
1843 .p_class = P_GLOBAL,
1844 .offset = GLOBAL_VAR(bClientUseSpnego),
1847 .flags = FLAG_ADVANCED,
1850 .label = "client ldap sasl wrapping",
1852 .p_class = P_GLOBAL,
1853 .offset = GLOBAL_VAR(client_ldap_sasl_wrapping),
1855 .enum_list = enum_ldap_sasl_wrapping,
1856 .flags = FLAG_ADVANCED,
1859 .label = "enable asu support",
1861 .p_class = P_GLOBAL,
1862 .offset = GLOBAL_VAR(bASUSupport),
1865 .flags = FLAG_ADVANCED,
1868 .label = "svcctl list",
1870 .p_class = P_GLOBAL,
1871 .offset = GLOBAL_VAR(szServicesList),
1874 .flags = FLAG_ADVANCED,
1877 {N_("Tuning Options"), P_SEP, P_SEPARATOR},
1880 .label = "block size",
1883 .offset = LOCAL_VAR(iBlock_size),
1886 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1889 .label = "deadtime",
1891 .p_class = P_GLOBAL,
1892 .offset = GLOBAL_VAR(deadtime),
1895 .flags = FLAG_ADVANCED,
1898 .label = "getwd cache",
1900 .p_class = P_GLOBAL,
1901 .offset = GLOBAL_VAR(getwd_cache),
1904 .flags = FLAG_ADVANCED,
1907 .label = "keepalive",
1909 .p_class = P_GLOBAL,
1910 .offset = GLOBAL_VAR(iKeepalive),
1913 .flags = FLAG_ADVANCED,
1916 .label = "change notify",
1919 .offset = LOCAL_VAR(bChangeNotify),
1922 .flags = FLAG_ADVANCED | FLAG_SHARE,
1925 .label = "directory name cache size",
1928 .offset = LOCAL_VAR(iDirectoryNameCacheSize),
1931 .flags = FLAG_ADVANCED | FLAG_SHARE,
1934 .label = "kernel change notify",
1937 .offset = LOCAL_VAR(bKernelChangeNotify),
1940 .flags = FLAG_ADVANCED | FLAG_SHARE,
1943 .label = "lpq cache time",
1945 .p_class = P_GLOBAL,
1946 .offset = GLOBAL_VAR(lpqcachetime),
1949 .flags = FLAG_ADVANCED,
1952 .label = "max smbd processes",
1954 .p_class = P_GLOBAL,
1955 .offset = GLOBAL_VAR(iMaxSmbdProcesses),
1958 .flags = FLAG_ADVANCED,
1961 .label = "max connections",
1964 .offset = LOCAL_VAR(iMaxConnections),
1967 .flags = FLAG_ADVANCED | FLAG_SHARE,
1970 .label = "paranoid server security",
1972 .p_class = P_GLOBAL,
1973 .offset = GLOBAL_VAR(paranoid_server_security),
1976 .flags = FLAG_ADVANCED,
1979 .label = "max disk size",
1981 .p_class = P_GLOBAL,
1982 .offset = GLOBAL_VAR(maxdisksize),
1985 .flags = FLAG_ADVANCED,
1988 .label = "max open files",
1990 .p_class = P_GLOBAL,
1991 .offset = GLOBAL_VAR(max_open_files),
1994 .flags = FLAG_ADVANCED,
1997 .label = "min print space",
2000 .offset = LOCAL_VAR(iMinPrintSpace),
2003 .flags = FLAG_ADVANCED | FLAG_PRINT,
2006 .label = "socket options",
2008 .p_class = P_GLOBAL,
2009 .offset = GLOBAL_VAR(socket_options),
2012 .flags = FLAG_ADVANCED,
2015 .label = "strict allocate",
2018 .offset = LOCAL_VAR(bStrictAllocate),
2021 .flags = FLAG_ADVANCED | FLAG_SHARE,
2024 .label = "strict sync",
2027 .offset = LOCAL_VAR(bStrictSync),
2030 .flags = FLAG_ADVANCED | FLAG_SHARE,
2033 .label = "sync always",
2036 .offset = LOCAL_VAR(bSyncAlways),
2039 .flags = FLAG_ADVANCED | FLAG_SHARE,
2042 .label = "use mmap",
2044 .p_class = P_GLOBAL,
2045 .offset = GLOBAL_VAR(bUseMmap),
2048 .flags = FLAG_ADVANCED,
2051 .label = "use sendfile",
2054 .offset = LOCAL_VAR(bUseSendfile),
2057 .flags = FLAG_ADVANCED | FLAG_SHARE,
2060 .label = "hostname lookups",
2062 .p_class = P_GLOBAL,
2063 .offset = GLOBAL_VAR(bHostnameLookups),
2066 .flags = FLAG_ADVANCED,
2069 .label = "write cache size",
2072 .offset = LOCAL_VAR(iWriteCacheSize),
2075 .flags = FLAG_ADVANCED | FLAG_SHARE,
2078 .label = "name cache timeout",
2080 .p_class = P_GLOBAL,
2081 .offset = GLOBAL_VAR(name_cache_timeout),
2084 .flags = FLAG_ADVANCED,
2087 .label = "ctdbd socket",
2089 .p_class = P_GLOBAL,
2090 .offset = GLOBAL_VAR(ctdbdSocket),
2093 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
2096 .label = "cluster addresses",
2098 .p_class = P_GLOBAL,
2099 .offset = GLOBAL_VAR(szClusterAddresses),
2102 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
2105 .label = "clustering",
2107 .p_class = P_GLOBAL,
2108 .offset = GLOBAL_VAR(clustering),
2111 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
2114 .label = "ctdb timeout",
2116 .p_class = P_GLOBAL,
2117 .offset = GLOBAL_VAR(ctdb_timeout),
2120 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
2123 .label = "ctdb locktime warn threshold",
2125 .p_class = P_GLOBAL,
2126 .offset = GLOBAL_VAR(ctdb_locktime_warn_threshold),
2129 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
2132 .label = "smb2 max read",
2134 .p_class = P_GLOBAL,
2135 .offset = GLOBAL_VAR(ismb2_max_read),
2138 .flags = FLAG_ADVANCED,
2141 .label = "smb2 max write",
2143 .p_class = P_GLOBAL,
2144 .offset = GLOBAL_VAR(ismb2_max_write),
2147 .flags = FLAG_ADVANCED,
2150 .label = "smb2 max trans",
2152 .p_class = P_GLOBAL,
2153 .offset = GLOBAL_VAR(ismb2_max_trans),
2156 .flags = FLAG_ADVANCED,
2159 .label = "smb2 max credits",
2161 .p_class = P_GLOBAL,
2162 .offset = GLOBAL_VAR(ismb2_max_credits),
2165 .flags = FLAG_ADVANCED,
2168 {N_("Printing Options"), P_SEP, P_SEPARATOR},
2171 .label = "max reported print jobs",
2174 .offset = LOCAL_VAR(iMaxReportedPrintJobs),
2177 .flags = FLAG_ADVANCED | FLAG_PRINT,
2180 .label = "max print jobs",
2183 .offset = LOCAL_VAR(iMaxPrintJobs),
2186 .flags = FLAG_ADVANCED | FLAG_PRINT,
2189 .label = "load printers",
2191 .p_class = P_GLOBAL,
2192 .offset = GLOBAL_VAR(bLoadPrinters),
2195 .flags = FLAG_ADVANCED | FLAG_PRINT,
2198 .label = "printcap cache time",
2200 .p_class = P_GLOBAL,
2201 .offset = GLOBAL_VAR(PrintcapCacheTime),
2204 .flags = FLAG_ADVANCED | FLAG_PRINT,
2207 .label = "printcap name",
2209 .p_class = P_GLOBAL,
2210 .offset = GLOBAL_VAR(szPrintcapname),
2213 .flags = FLAG_ADVANCED | FLAG_PRINT,
2216 .label = "printcap",
2218 .p_class = P_GLOBAL,
2219 .offset = GLOBAL_VAR(szPrintcapname),
2225 .label = "printable",
2228 .offset = LOCAL_VAR(bPrint_ok),
2231 .flags = FLAG_ADVANCED | FLAG_PRINT,
2234 .label = "print notify backchannel",
2237 .offset = LOCAL_VAR(bPrintNotifyBackchannel),
2240 .flags = FLAG_ADVANCED,
2243 .label = "print ok",
2246 .offset = LOCAL_VAR(bPrint_ok),
2252 .label = "printing",
2255 .offset = LOCAL_VAR(iPrinting),
2256 .special = handle_printing,
2257 .enum_list = enum_printing,
2258 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2261 .label = "cups options",
2264 .offset = LOCAL_VAR(szCupsOptions),
2267 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2270 .label = "cups server",
2272 .p_class = P_GLOBAL,
2273 .offset = GLOBAL_VAR(szCupsServer),
2276 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2279 .label = "cups encrypt",
2281 .p_class = P_GLOBAL,
2282 .offset = GLOBAL_VAR(CupsEncrypt),
2284 .enum_list = enum_bool_auto,
2285 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2289 .label = "cups connection timeout",
2291 .p_class = P_GLOBAL,
2292 .offset = GLOBAL_VAR(cups_connection_timeout),
2295 .flags = FLAG_ADVANCED,
2298 .label = "iprint server",
2300 .p_class = P_GLOBAL,
2301 .offset = GLOBAL_VAR(szIPrintServer),
2304 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2307 .label = "print command",
2310 .offset = LOCAL_VAR(szPrintcommand),
2313 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2316 .label = "disable spoolss",
2318 .p_class = P_GLOBAL,
2319 .offset = GLOBAL_VAR(bDisableSpoolss),
2322 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2325 .label = "enable spoolss",
2327 .p_class = P_GLOBAL,
2328 .offset = GLOBAL_VAR(bDisableSpoolss),
2334 .label = "lpq command",
2337 .offset = LOCAL_VAR(szLpqcommand),
2340 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2343 .label = "lprm command",
2346 .offset = LOCAL_VAR(szLprmcommand),
2349 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2352 .label = "lppause command",
2355 .offset = LOCAL_VAR(szLppausecommand),
2358 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2361 .label = "lpresume command",
2364 .offset = LOCAL_VAR(szLpresumecommand),
2367 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2370 .label = "queuepause command",
2373 .offset = LOCAL_VAR(szQueuepausecommand),
2376 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2379 .label = "queueresume command",
2382 .offset = LOCAL_VAR(szQueueresumecommand),
2385 .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2388 .label = "addport command",
2390 .p_class = P_GLOBAL,
2391 .offset = GLOBAL_VAR(szAddPortCommand),
2394 .flags = FLAG_ADVANCED,
2397 .label = "enumports command",
2399 .p_class = P_GLOBAL,
2400 .offset = GLOBAL_VAR(szEnumPortsCommand),
2403 .flags = FLAG_ADVANCED,
2406 .label = "addprinter command",
2408 .p_class = P_GLOBAL,
2409 .offset = GLOBAL_VAR(szAddPrinterCommand),
2412 .flags = FLAG_ADVANCED,
2415 .label = "deleteprinter command",
2417 .p_class = P_GLOBAL,
2418 .offset = GLOBAL_VAR(szDeletePrinterCommand),
2421 .flags = FLAG_ADVANCED,
2424 .label = "show add printer wizard",
2426 .p_class = P_GLOBAL,
2427 .offset = GLOBAL_VAR(bMsAddPrinterWizard),
2430 .flags = FLAG_ADVANCED,
2433 .label = "os2 driver map",
2435 .p_class = P_GLOBAL,
2436 .offset = GLOBAL_VAR(szOs2DriverMap),
2439 .flags = FLAG_ADVANCED,
2443 .label = "printer name",
2446 .offset = LOCAL_VAR(szPrintername),
2449 .flags = FLAG_ADVANCED | FLAG_PRINT,
2455 .offset = LOCAL_VAR(szPrintername),
2461 .label = "use client driver",
2464 .offset = LOCAL_VAR(bUseClientDriver),
2467 .flags = FLAG_ADVANCED | FLAG_PRINT,
2470 .label = "default devmode",
2473 .offset = LOCAL_VAR(bDefaultDevmode),
2476 .flags = FLAG_ADVANCED | FLAG_PRINT,
2479 .label = "force printername",
2482 .offset = LOCAL_VAR(bForcePrintername),
2485 .flags = FLAG_ADVANCED | FLAG_PRINT,
2488 .label = "printjob username",
2491 .offset = LOCAL_VAR(szPrintjobUsername),
2494 .flags = FLAG_ADVANCED | FLAG_PRINT,
2497 {N_("Filename Handling"), P_SEP, P_SEPARATOR},
2500 .label = "mangling method",
2502 .p_class = P_GLOBAL,
2503 .offset = GLOBAL_VAR(szManglingMethod),
2506 .flags = FLAG_ADVANCED,
2509 .label = "mangle prefix",
2511 .p_class = P_GLOBAL,
2512 .offset = GLOBAL_VAR(mangle_prefix),
2515 .flags = FLAG_ADVANCED,
2519 .label = "default case",
2522 .offset = LOCAL_VAR(iDefaultCase),
2524 .enum_list = enum_case,
2525 .flags = FLAG_ADVANCED | FLAG_SHARE,
2528 .label = "case sensitive",
2531 .offset = LOCAL_VAR(iCaseSensitive),
2533 .enum_list = enum_bool_auto,
2534 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2537 .label = "casesignames",
2540 .offset = LOCAL_VAR(iCaseSensitive),
2542 .enum_list = enum_bool_auto,
2543 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_HIDE,
2546 .label = "preserve case",
2549 .offset = LOCAL_VAR(bCasePreserve),
2552 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2555 .label = "short preserve case",
2558 .offset = LOCAL_VAR(bShortCasePreserve),
2561 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2564 .label = "mangling char",
2567 .offset = LOCAL_VAR(magic_char),
2570 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2573 .label = "hide dot files",
2576 .offset = LOCAL_VAR(bHideDotFiles),
2579 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2582 .label = "hide special files",
2585 .offset = LOCAL_VAR(bHideSpecialFiles),
2588 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2591 .label = "hide unreadable",
2594 .offset = LOCAL_VAR(bHideUnReadable),
2597 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2600 .label = "hide unwriteable files",
2603 .offset = LOCAL_VAR(bHideUnWriteableFiles),
2606 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2609 .label = "delete veto files",
2612 .offset = LOCAL_VAR(bDeleteVetoFiles),
2615 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2618 .label = "veto files",
2621 .offset = LOCAL_VAR(szVetoFiles),
2624 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2627 .label = "hide files",
2630 .offset = LOCAL_VAR(szHideFiles),
2633 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2636 .label = "veto oplock files",
2639 .offset = LOCAL_VAR(szVetoOplockFiles),
2642 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2645 .label = "map archive",
2648 .offset = LOCAL_VAR(bMap_archive),
2651 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2654 .label = "map hidden",
2657 .offset = LOCAL_VAR(bMap_hidden),
2660 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2663 .label = "map system",
2666 .offset = LOCAL_VAR(bMap_system),
2669 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2672 .label = "map readonly",
2675 .offset = LOCAL_VAR(iMap_readonly),
2677 .enum_list = enum_map_readonly,
2678 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2681 .label = "mangled names",
2684 .offset = LOCAL_VAR(bMangledNames),
2687 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2690 .label = "max stat cache size",
2692 .p_class = P_GLOBAL,
2693 .offset = GLOBAL_VAR(iMaxStatCacheSize),
2696 .flags = FLAG_ADVANCED,
2699 .label = "stat cache",
2701 .p_class = P_GLOBAL,
2702 .offset = GLOBAL_VAR(bStatCache),
2705 .flags = FLAG_ADVANCED,
2708 .label = "store dos attributes",
2711 .offset = LOCAL_VAR(bStoreDosAttributes),
2714 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2717 .label = "dmapi support",
2720 .offset = LOCAL_VAR(bDmapiSupport),
2723 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2727 {N_("Domain Options"), P_SEP, P_SEPARATOR},
2730 .label = "machine password timeout",
2732 .p_class = P_GLOBAL,
2733 .offset = GLOBAL_VAR(machine_password_timeout),
2736 .flags = FLAG_ADVANCED | FLAG_WIZARD,
2739 {N_("Logon Options"), P_SEP, P_SEPARATOR},
2742 .label = "add user script",
2744 .p_class = P_GLOBAL,
2745 .offset = GLOBAL_VAR(szAddUserScript),
2748 .flags = FLAG_ADVANCED,
2751 .label = "rename user script",
2753 .p_class = P_GLOBAL,
2754 .offset = GLOBAL_VAR(szRenameUserScript),
2757 .flags = FLAG_ADVANCED,
2760 .label = "delete user script",
2762 .p_class = P_GLOBAL,
2763 .offset = GLOBAL_VAR(szDelUserScript),
2766 .flags = FLAG_ADVANCED,
2769 .label = "add group script",
2771 .p_class = P_GLOBAL,
2772 .offset = GLOBAL_VAR(szAddGroupScript),
2775 .flags = FLAG_ADVANCED,
2778 .label = "delete group script",
2780 .p_class = P_GLOBAL,
2781 .offset = GLOBAL_VAR(szDelGroupScript),
2784 .flags = FLAG_ADVANCED,
2787 .label = "add user to group script",
2789 .p_class = P_GLOBAL,
2790 .offset = GLOBAL_VAR(szAddUserToGroupScript),
2793 .flags = FLAG_ADVANCED,
2796 .label = "delete user from group script",
2798 .p_class = P_GLOBAL,
2799 .offset = GLOBAL_VAR(szDelUserFromGroupScript),
2802 .flags = FLAG_ADVANCED,
2805 .label = "set primary group script",
2807 .p_class = P_GLOBAL,
2808 .offset = GLOBAL_VAR(szSetPrimaryGroupScript),
2811 .flags = FLAG_ADVANCED,
2814 .label = "add machine script",
2816 .p_class = P_GLOBAL,
2817 .offset = GLOBAL_VAR(szAddMachineScript),
2820 .flags = FLAG_ADVANCED,
2823 .label = "shutdown script",
2825 .p_class = P_GLOBAL,
2826 .offset = GLOBAL_VAR(szShutdownScript),
2829 .flags = FLAG_ADVANCED,
2832 .label = "abort shutdown script",
2834 .p_class = P_GLOBAL,
2835 .offset = GLOBAL_VAR(szAbortShutdownScript),
2838 .flags = FLAG_ADVANCED,
2841 .label = "username map script",
2843 .p_class = P_GLOBAL,
2844 .offset = GLOBAL_VAR(szUsernameMapScript),
2847 .flags = FLAG_ADVANCED,
2850 .label = "username map cache time",
2852 .p_class = P_GLOBAL,
2853 .offset = GLOBAL_VAR(iUsernameMapCacheTime),
2856 .flags = FLAG_ADVANCED,
2859 .label = "logon script",
2861 .p_class = P_GLOBAL,
2862 .offset = GLOBAL_VAR(szLogonScript),
2865 .flags = FLAG_ADVANCED,
2868 .label = "logon path",
2870 .p_class = P_GLOBAL,
2871 .offset = GLOBAL_VAR(szLogonPath),
2874 .flags = FLAG_ADVANCED,
2877 .label = "logon drive",
2879 .p_class = P_GLOBAL,
2880 .offset = GLOBAL_VAR(szLogonDrive),
2883 .flags = FLAG_ADVANCED,
2886 .label = "logon home",
2888 .p_class = P_GLOBAL,
2889 .offset = GLOBAL_VAR(szLogonHome),
2892 .flags = FLAG_ADVANCED,
2895 .label = "domain logons",
2897 .p_class = P_GLOBAL,
2898 .offset = GLOBAL_VAR(bDomainLogons),
2901 .flags = FLAG_ADVANCED,
2905 .label = "init logon delayed hosts",
2907 .p_class = P_GLOBAL,
2908 .offset = GLOBAL_VAR(szInitLogonDelayedHosts),
2911 .flags = FLAG_ADVANCED,
2915 .label = "init logon delay",
2917 .p_class = P_GLOBAL,
2918 .offset = GLOBAL_VAR(InitLogonDelay),
2921 .flags = FLAG_ADVANCED,
2925 {N_("Browse Options"), P_SEP, P_SEPARATOR},
2928 .label = "os level",
2930 .p_class = P_GLOBAL,
2931 .offset = GLOBAL_VAR(os_level),
2934 .flags = FLAG_BASIC | FLAG_ADVANCED,
2937 .label = "lm announce",
2939 .p_class = P_GLOBAL,
2940 .offset = GLOBAL_VAR(lm_announce),
2942 .enum_list = enum_bool_auto,
2943 .flags = FLAG_ADVANCED,
2946 .label = "lm interval",
2948 .p_class = P_GLOBAL,
2949 .offset = GLOBAL_VAR(lm_interval),
2952 .flags = FLAG_ADVANCED,
2955 .label = "preferred master",
2957 .p_class = P_GLOBAL,
2958 .offset = GLOBAL_VAR(iPreferredMaster),
2960 .enum_list = enum_bool_auto,
2961 .flags = FLAG_BASIC | FLAG_ADVANCED,
2964 .label = "prefered master",
2966 .p_class = P_GLOBAL,
2967 .offset = GLOBAL_VAR(iPreferredMaster),
2969 .enum_list = enum_bool_auto,
2973 .label = "local master",
2975 .p_class = P_GLOBAL,
2976 .offset = GLOBAL_VAR(bLocalMaster),
2979 .flags = FLAG_BASIC | FLAG_ADVANCED,
2982 .label = "domain master",
2984 .p_class = P_GLOBAL,
2985 .offset = GLOBAL_VAR(iDomainMaster),
2987 .enum_list = enum_bool_auto,
2988 .flags = FLAG_BASIC | FLAG_ADVANCED,
2991 .label = "browse list",
2993 .p_class = P_GLOBAL,
2994 .offset = GLOBAL_VAR(bBrowseList),
2997 .flags = FLAG_ADVANCED,
3000 .label = "browseable",
3003 .offset = LOCAL_VAR(bBrowseable),
3006 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3009 .label = "browsable",
3012 .offset = LOCAL_VAR(bBrowseable),
3018 .label = "access based share enum",
3021 .offset = LOCAL_VAR(bAccessBasedShareEnum),
3024 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE
3027 .label = "enhanced browsing",
3029 .p_class = P_GLOBAL,
3030 .offset = GLOBAL_VAR(enhanced_browsing),
3033 .flags = FLAG_ADVANCED,
3036 {N_("WINS Options"), P_SEP, P_SEPARATOR},
3039 .label = "dns proxy",
3041 .p_class = P_GLOBAL,
3042 .offset = GLOBAL_VAR(bWINSdnsProxy),
3045 .flags = FLAG_ADVANCED,
3048 .label = "wins proxy",
3050 .p_class = P_GLOBAL,
3051 .offset = GLOBAL_VAR(bWINSproxy),
3054 .flags = FLAG_ADVANCED,
3057 .label = "wins server",
3059 .p_class = P_GLOBAL,
3060 .offset = GLOBAL_VAR(szWINSservers),
3063 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
3066 .label = "wins support",
3068 .p_class = P_GLOBAL,
3069 .offset = GLOBAL_VAR(bWINSsupport),
3072 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
3075 .label = "wins hook",
3077 .p_class = P_GLOBAL,
3078 .offset = GLOBAL_VAR(szWINSHook),
3081 .flags = FLAG_ADVANCED,
3084 {N_("Locking Options"), P_SEP, P_SEPARATOR},
3087 .label = "blocking locks",
3090 .offset = LOCAL_VAR(bBlockingLocks),
3093 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3096 .label = "csc policy",
3099 .offset = LOCAL_VAR(iCSCPolicy),
3101 .enum_list = enum_csc_policy,
3102 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3105 .label = "fake oplocks",
3108 .offset = LOCAL_VAR(bFakeOplocks),
3111 .flags = FLAG_ADVANCED | FLAG_SHARE,
3114 .label = "kernel oplocks",
3117 .offset = LOCAL_VAR(bKernelOplocks),
3120 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3126 .offset = LOCAL_VAR(bLocking),
3129 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3132 .label = "lock spin time",
3134 .p_class = P_GLOBAL,
3135 .offset = GLOBAL_VAR(iLockSpinTime),
3138 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
3144 .offset = LOCAL_VAR(bOpLocks),
3147 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3150 .label = "level2 oplocks",
3153 .offset = LOCAL_VAR(bLevel2OpLocks),
3156 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3159 .label = "oplock break wait time",
3161 .p_class = P_GLOBAL,
3162 .offset = GLOBAL_VAR(oplock_break_wait_time),
3165 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
3168 .label = "oplock contention limit",
3171 .offset = LOCAL_VAR(iOplockContentionLimit),
3174 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3177 .label = "posix locking",
3180 .offset = LOCAL_VAR(bPosixLocking),
3183 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3186 .label = "strict locking",
3189 .offset = LOCAL_VAR(iStrictLocking),
3191 .enum_list = enum_bool_auto,
3192 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3195 {N_("Ldap Options"), P_SEP, P_SEPARATOR},
3198 .label = "ldap admin dn",
3200 .p_class = P_GLOBAL,
3201 .offset = GLOBAL_VAR(szLdapAdminDn),
3204 .flags = FLAG_ADVANCED,
3207 .label = "ldap delete dn",
3209 .p_class = P_GLOBAL,
3210 .offset = GLOBAL_VAR(ldap_delete_dn),
3213 .flags = FLAG_ADVANCED,
3216 .label = "ldap group suffix",
3218 .p_class = P_GLOBAL,
3219 .offset = GLOBAL_VAR(szLdapGroupSuffix),
3222 .flags = FLAG_ADVANCED,
3225 .label = "ldap idmap suffix",
3227 .p_class = P_GLOBAL,
3228 .offset = GLOBAL_VAR(szLdapIdmapSuffix),
3231 .flags = FLAG_ADVANCED,
3234 .label = "ldap machine suffix",
3236 .p_class = P_GLOBAL,
3237 .offset = GLOBAL_VAR(szLdapMachineSuffix),
3240 .flags = FLAG_ADVANCED,
3243 .label = "ldap passwd sync",
3245 .p_class = P_GLOBAL,
3246 .offset = GLOBAL_VAR(ldap_passwd_sync),
3248 .enum_list = enum_ldap_passwd_sync,
3249 .flags = FLAG_ADVANCED,
3252 .label = "ldap password sync",
3254 .p_class = P_GLOBAL,
3255 .offset = GLOBAL_VAR(ldap_passwd_sync),
3257 .enum_list = enum_ldap_passwd_sync,
3261 .label = "ldap replication sleep",
3263 .p_class = P_GLOBAL,
3264 .offset = GLOBAL_VAR(ldap_replication_sleep),
3267 .flags = FLAG_ADVANCED,
3270 .label = "ldap suffix",
3272 .p_class = P_GLOBAL,
3273 .offset = GLOBAL_VAR(szLdapSuffix),
3276 .flags = FLAG_ADVANCED,
3279 .label = "ldap ssl",
3281 .p_class = P_GLOBAL,
3282 .offset = GLOBAL_VAR(ldap_ssl),
3284 .enum_list = enum_ldap_ssl,
3285 .flags = FLAG_ADVANCED,
3288 .label = "ldap ssl ads",
3290 .p_class = P_GLOBAL,
3291 .offset = GLOBAL_VAR(ldap_ssl_ads),
3294 .flags = FLAG_ADVANCED,
3297 .label = "ldap deref",
3299 .p_class = P_GLOBAL,
3300 .offset = GLOBAL_VAR(ldap_deref),
3302 .enum_list = enum_ldap_deref,
3303 .flags = FLAG_ADVANCED,
3306 .label = "ldap follow referral",
3308 .p_class = P_GLOBAL,
3309 .offset = GLOBAL_VAR(ldap_follow_referral),
3311 .enum_list = enum_bool_auto,
3312 .flags = FLAG_ADVANCED,
3315 .label = "ldap timeout",
3317 .p_class = P_GLOBAL,
3318 .offset = GLOBAL_VAR(ldap_timeout),
3321 .flags = FLAG_ADVANCED,
3324 .label = "ldap connection timeout",
3326 .p_class = P_GLOBAL,
3327 .offset = GLOBAL_VAR(ldap_connection_timeout),
3330 .flags = FLAG_ADVANCED,
3333 .label = "ldap page size",
3335 .p_class = P_GLOBAL,
3336 .offset = GLOBAL_VAR(ldap_page_size),
3339 .flags = FLAG_ADVANCED,
3342 .label = "ldap user suffix",
3344 .p_class = P_GLOBAL,
3345 .offset = GLOBAL_VAR(szLdapUserSuffix),
3348 .flags = FLAG_ADVANCED,
3351 .label = "ldap debug level",
3353 .p_class = P_GLOBAL,
3354 .offset = GLOBAL_VAR(ldap_debug_level),
3355 .special = handle_ldap_debug_level,
3357 .flags = FLAG_ADVANCED,
3360 .label = "ldap debug threshold",
3362 .p_class = P_GLOBAL,
3363 .offset = GLOBAL_VAR(ldap_debug_threshold),
3366 .flags = FLAG_ADVANCED,
3369 {N_("EventLog Options"), P_SEP, P_SEPARATOR},
3372 .label = "eventlog list",
3374 .p_class = P_GLOBAL,
3375 .offset = GLOBAL_VAR(szEventLogs),
3378 .flags = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
3381 {N_("Miscellaneous Options"), P_SEP, P_SEPARATOR},
3384 .label = "add share command",
3386 .p_class = P_GLOBAL,
3387 .offset = GLOBAL_VAR(szAddShareCommand),
3390 .flags = FLAG_ADVANCED,
3393 .label = "change share command",
3395 .p_class = P_GLOBAL,
3396 .offset = GLOBAL_VAR(szChangeShareCommand),
3399 .flags = FLAG_ADVANCED,
3402 .label = "delete share command",
3404 .p_class = P_GLOBAL,
3405 .offset = GLOBAL_VAR(szDeleteShareCommand),
3408 .flags = FLAG_ADVANCED,
3411 .label = "config file",
3413 .p_class = P_GLOBAL,
3414 .offset = GLOBAL_VAR(szConfigFile),
3417 .flags = FLAG_HIDE|FLAG_META,
3422 .p_class = P_GLOBAL,
3423 .offset = GLOBAL_VAR(szAutoServices),
3426 .flags = FLAG_ADVANCED,
3429 .label = "auto services",
3431 .p_class = P_GLOBAL,
3432 .offset = GLOBAL_VAR(szAutoServices),
3435 .flags = FLAG_ADVANCED,
3438 .label = "lock directory",
3440 .p_class = P_GLOBAL,
3441 .offset = GLOBAL_VAR(szLockDir),
3444 .flags = FLAG_ADVANCED,
3447 .label = "lock dir",
3449 .p_class = P_GLOBAL,
3450 .offset = GLOBAL_VAR(szLockDir),
3456 .label = "state directory",
3458 .p_class = P_GLOBAL,
3459 .offset = GLOBAL_VAR(szStateDir),
3462 .flags = FLAG_ADVANCED,
3465 .label = "cache directory",
3467 .p_class = P_GLOBAL,
3468 .offset = GLOBAL_VAR(szCacheDir),
3471 .flags = FLAG_ADVANCED,
3474 .label = "pid directory",
3476 .p_class = P_GLOBAL,
3477 .offset = GLOBAL_VAR(szPidDir),
3480 .flags = FLAG_ADVANCED,
3484 .label = "utmp directory",
3486 .p_class = P_GLOBAL,
3487 .offset = GLOBAL_VAR(szUtmpDir),
3490 .flags = FLAG_ADVANCED,
3493 .label = "wtmp directory",
3495 .p_class = P_GLOBAL,
3496 .offset = GLOBAL_VAR(szWtmpDir),
3499 .flags = FLAG_ADVANCED,
3504 .p_class = P_GLOBAL,
3505 .offset = GLOBAL_VAR(bUtmp),
3508 .flags = FLAG_ADVANCED,
3512 .label = "default service",
3514 .p_class = P_GLOBAL,
3515 .offset = GLOBAL_VAR(szDefaultService),
3518 .flags = FLAG_ADVANCED,
3523 .p_class = P_GLOBAL,
3524 .offset = GLOBAL_VAR(szDefaultService),
3527 .flags = FLAG_ADVANCED,
3530 .label = "message command",
3532 .p_class = P_GLOBAL,
3533 .offset = GLOBAL_VAR(szMsgCommand),
3536 .flags = FLAG_ADVANCED,
3539 .label = "dfree cache time",
3542 .offset = LOCAL_VAR(iDfreeCacheTime),
3545 .flags = FLAG_ADVANCED,
3548 .label = "dfree command",
3551 .offset = LOCAL_VAR(szDfree),
3554 .flags = FLAG_ADVANCED,
3557 .label = "get quota command",
3559 .p_class = P_GLOBAL,
3560 .offset = GLOBAL_VAR(szGetQuota),
3563 .flags = FLAG_ADVANCED,
3566 .label = "set quota command",
3568 .p_class = P_GLOBAL,
3569 .offset = GLOBAL_VAR(szSetQuota),
3572 .flags = FLAG_ADVANCED,
3575 .label = "remote announce",
3577 .p_class = P_GLOBAL,
3578 .offset = GLOBAL_VAR(szRemoteAnnounce),
3581 .flags = FLAG_ADVANCED,
3584 .label = "remote browse sync",
3586 .p_class = P_GLOBAL,
3587 .offset = GLOBAL_VAR(szRemoteBrowseSync),
3590 .flags = FLAG_ADVANCED,
3593 .label = "socket address",
3595 .p_class = P_GLOBAL,
3596 .offset = GLOBAL_VAR(szSocketAddress),
3599 .flags = FLAG_ADVANCED,
3602 .label = "nmbd bind explicit broadcast",
3604 .p_class = P_GLOBAL,
3605 .offset = GLOBAL_VAR(bNmbdBindExplicitBroadcast),
3608 .flags = FLAG_ADVANCED,
3611 .label = "homedir map",
3613 .p_class = P_GLOBAL,
3614 .offset = GLOBAL_VAR(szNISHomeMapName),
3617 .flags = FLAG_ADVANCED,
3620 .label = "afs username map",
3622 .p_class = P_GLOBAL,
3623 .offset = GLOBAL_VAR(szAfsUsernameMap),
3626 .flags = FLAG_ADVANCED,
3629 .label = "afs token lifetime",
3631 .p_class = P_GLOBAL,
3632 .offset = GLOBAL_VAR(iAfsTokenLifetime),
3635 .flags = FLAG_ADVANCED,
3638 .label = "log nt token command",
3640 .p_class = P_GLOBAL,
3641 .offset = GLOBAL_VAR(szLogNtTokenCommand),
3644 .flags = FLAG_ADVANCED,
3647 .label = "NIS homedir",
3649 .p_class = P_GLOBAL,
3650 .offset = GLOBAL_VAR(bNISHomeMap),
3653 .flags = FLAG_ADVANCED,
3659 .offset = LOCAL_VAR(valid),
3668 .offset = LOCAL_VAR(szCopy),
3669 .special = handle_copy,
3677 .offset = LOCAL_VAR(szInclude),
3678 .special = handle_include,
3680 .flags = FLAG_HIDE|FLAG_META,
3686 .offset = LOCAL_VAR(szPreExec),
3689 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3695 .offset = LOCAL_VAR(szPreExec),
3698 .flags = FLAG_ADVANCED,
3701 .label = "preexec close",
3704 .offset = LOCAL_VAR(bPreexecClose),
3707 .flags = FLAG_ADVANCED | FLAG_SHARE,
3710 .label = "postexec",
3713 .offset = LOCAL_VAR(szPostExec),
3716 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3719 .label = "root preexec",
3722 .offset = LOCAL_VAR(szRootPreExec),
3725 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3728 .label = "root preexec close",
3731 .offset = LOCAL_VAR(bRootpreexecClose),
3734 .flags = FLAG_ADVANCED | FLAG_SHARE,
3737 .label = "root postexec",
3740 .offset = LOCAL_VAR(szRootPostExec),
3743 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3746 .label = "available",
3749 .offset = LOCAL_VAR(bAvailable),
3752 .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3755 .label = "registry shares",
3757 .p_class = P_GLOBAL,
3758 .offset = GLOBAL_VAR(bRegistryShares),
3761 .flags = FLAG_ADVANCED,
3764 .label = "usershare allow guests",
3766 .p_class = P_GLOBAL,
3767 .offset = GLOBAL_VAR(bUsershareAllowGuests),
3770 .flags = FLAG_ADVANCED,
3773 .label = "usershare max shares",
3775 .p_class = P_GLOBAL,
3776 .offset = GLOBAL_VAR(iUsershareMaxShares),
3779 .flags = FLAG_ADVANCED,
3782 .label = "usershare owner only",
3784 .p_class = P_GLOBAL,
3785 .offset = GLOBAL_VAR(bUsershareOwnerOnly),
3788 .flags = FLAG_ADVANCED,
3791 .label = "usershare path",
3793 .p_class = P_GLOBAL,
3794 .offset = GLOBAL_VAR(szUsersharePath),
3797 .flags = FLAG_ADVANCED,
3800 .label = "usershare prefix allow list",
3802 .p_class = P_GLOBAL,
3803 .offset = GLOBAL_VAR(szUsersharePrefixAllowList),
3806 .flags = FLAG_ADVANCED,
3809 .label = "usershare prefix deny list",
3811 .p_class = P_GLOBAL,
3812 .offset = GLOBAL_VAR(szUsersharePrefixDenyList),
3815 .flags = FLAG_ADVANCED,
3818 .label = "usershare template share",
3820 .p_class = P_GLOBAL,
3821 .offset = GLOBAL_VAR(szUsershareTemplateShare),
3824 .flags = FLAG_ADVANCED,
3830 .offset = LOCAL_VAR(volume),
3833 .flags = FLAG_ADVANCED | FLAG_SHARE,
3839 .offset = LOCAL_VAR(fstype),
3842 .flags = FLAG_ADVANCED | FLAG_SHARE,
3845 .label = "set directory",
3848 .offset = LOCAL_VAR(bNo_set_dir),
3851 .flags = FLAG_ADVANCED | FLAG_SHARE,
3854 .label = "allow insecure wide links",
3856 .p_class = P_GLOBAL,
3857 .offset = GLOBAL_VAR(bAllowInsecureWidelinks),
3860 .flags = FLAG_ADVANCED,
3863 .label = "wide links",
3866 .offset = LOCAL_VAR(bWidelinks),
3869 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3872 .label = "follow symlinks",
3875 .offset = LOCAL_VAR(bSymlinks),
3878 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3881 .label = "dont descend",
3884 .offset = LOCAL_VAR(szDontdescend),
3887 .flags = FLAG_ADVANCED | FLAG_SHARE,
3890 .label = "magic script",
3893 .offset = LOCAL_VAR(szMagicScript),
3896 .flags = FLAG_ADVANCED | FLAG_SHARE,
3899 .label = "magic output",
3902 .offset = LOCAL_VAR(szMagicOutput),
3905 .flags = FLAG_ADVANCED | FLAG_SHARE,
3908 .label = "delete readonly",
3911 .offset = LOCAL_VAR(bDeleteReadonly),
3914 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3917 .label = "dos filemode",
3920 .offset = LOCAL_VAR(bDosFilemode),
3923 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3926 .label = "dos filetimes",
3929 .offset = LOCAL_VAR(bDosFiletimes),
3932 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3935 .label = "dos filetime resolution",
3938 .offset = LOCAL_VAR(bDosFiletimeResolution),
3941 .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3944 .label = "fake directory create times",
3947 .offset = LOCAL_VAR(bFakeDirCreateTimes),
3950 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
3953 .label = "async smb echo handler",
3955 .p_class = P_GLOBAL,
3956 .offset = GLOBAL_VAR(bAsyncSMBEchoHandler),
3959 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
3962 .label = "multicast dns register",
3964 .p_class = P_GLOBAL,
3965 .offset = GLOBAL_VAR(bMulticastDnsRegister),
3968 .flags = FLAG_ADVANCED | FLAG_GLOBAL,
3971 .label = "panic action",
3973 .p_class = P_GLOBAL,
3974 .offset = GLOBAL_VAR(szPanicAction),
3977 .flags = FLAG_ADVANCED,
3980 .label = "perfcount module",
3982 .p_class = P_GLOBAL,
3983 .offset = GLOBAL_VAR(szSMBPerfcountModule),
3986 .flags = FLAG_ADVANCED,
3989 {N_("VFS module options"), P_SEP, P_SEPARATOR},
3992 .label = "vfs objects",
3995 .offset = LOCAL_VAR(szVfsObjects),
3998 .flags = FLAG_ADVANCED | FLAG_SHARE,
4001 .label = "vfs object",
4004 .offset = LOCAL_VAR(szVfsObjects),
4011 {N_("MSDFS options"), P_SEP, P_SEPARATOR},
4014 .label = "msdfs root",
4017 .offset = LOCAL_VAR(bMSDfsRoot),
4020 .flags = FLAG_ADVANCED | FLAG_SHARE,
4023 .label = "msdfs proxy",
4026 .offset = LOCAL_VAR(szMSDfsProxy),
4029 .flags = FLAG_ADVANCED | FLAG_SHARE,
4032 .label = "host msdfs",
4034 .p_class = P_GLOBAL,
4035 .offset = GLOBAL_VAR(bHostMSDfs),
4038 .flags = FLAG_ADVANCED,
4041 {N_("Winbind options"), P_SEP, P_SEPARATOR},
4044 .label = "passdb expand explicit",
4046 .p_class = P_GLOBAL,
4047 .offset = GLOBAL_VAR(bPassdbExpandExplicit),
4050 .flags = FLAG_ADVANCED,
4053 .label = "idmap backend",
4055 .p_class = P_GLOBAL,
4056 .offset = GLOBAL_VAR(szIdmapBackend),
4057 .special = handle_idmap_backend,
4059 .flags = FLAG_ADVANCED | FLAG_DEPRECATED,
4062 .label = "idmap cache time",
4064 .p_class = P_GLOBAL,
4065 .offset = GLOBAL_VAR(iIdmapCacheTime),
4068 .flags = FLAG_ADVANCED,
4071 .label = "idmap negative cache time",
4073 .p_class = P_GLOBAL,
4074 .offset = GLOBAL_VAR(iIdmapNegativeCacheTime),
4077 .flags = FLAG_ADVANCED,
4080 .label = "idmap uid",
4082 .p_class = P_GLOBAL,
4083 .offset = GLOBAL_VAR(szIdmapUID),
4084 .special = handle_idmap_uid,
4086 .flags = FLAG_ADVANCED | FLAG_DEPRECATED,
4089 .label = "winbind uid",
4091 .p_class = P_GLOBAL,
4092 .offset = GLOBAL_VAR(szIdmapUID),
4093 .special = handle_idmap_uid,
4098 .label = "idmap gid",
4100 .p_class = P_GLOBAL,
4101 .offset = GLOBAL_VAR(szIdmapGID),
4102 .special = handle_idmap_gid,
4104 .flags = FLAG_ADVANCED | FLAG_DEPRECATED,
4107 .label = "winbind gid",
4109 .p_class = P_GLOBAL,
4110 .offset = GLOBAL_VAR(szIdmapGID),
4111 .special = handle_idmap_gid,
4116 .label = "template homedir",
4118 .p_class = P_GLOBAL,
4119 .offset = GLOBAL_VAR(szTemplateHomedir),
4122 .flags = FLAG_ADVANCED,
4125 .label = "template shell",
4127 .p_class = P_GLOBAL,
4128 .offset = GLOBAL_VAR(szTemplateShell),
4131 .flags = FLAG_ADVANCED,
4134 .label = "winbind separator",
4136 .p_class = P_GLOBAL,
4137 .offset = GLOBAL_VAR(szWinbindSeparator),
4140 .flags = FLAG_ADVANCED,
4143 .label = "winbind cache time",
4145 .p_class = P_GLOBAL,
4146 .offset = GLOBAL_VAR(winbind_cache_time),
4149 .flags = FLAG_ADVANCED,
4152 .label = "winbind reconnect delay",
4154 .p_class = P_GLOBAL,
4155 .offset = GLOBAL_VAR(winbind_reconnect_delay),
4158 .flags = FLAG_ADVANCED,
4161 .label = "winbind max clients",
4163 .p_class = P_GLOBAL,
4164 .offset = GLOBAL_VAR(winbind_max_clients),
4167 .flags = FLAG_ADVANCED,
4170 .label = "winbind enum users",
4172 .p_class = P_GLOBAL,
4173 .offset = GLOBAL_VAR(bWinbindEnumUsers),
4176 .flags = FLAG_ADVANCED,
4179 .label = "winbind enum groups",
4181 .p_class = P_GLOBAL,
4182 .offset = GLOBAL_VAR(bWinbindEnumGroups),
4185 .flags = FLAG_ADVANCED,
4188 .label = "winbind use default domain",
4190 .p_class = P_GLOBAL,
4191 .offset = GLOBAL_VAR(bWinbindUseDefaultDomain),
4194 .flags = FLAG_ADVANCED,
4197 .label = "winbind trusted domains only",
4199 .p_class = P_GLOBAL,
4200 .offset = GLOBAL_VAR(bWinbindTrustedDomainsOnly),
4203 .flags = FLAG_ADVANCED,
4206 .label = "winbind nested groups",
4208 .p_class = P_GLOBAL,
4209 .offset = GLOBAL_VAR(bWinbindNestedGroups),
4212 .flags = FLAG_ADVANCED,
4215 .label = "winbind expand groups",
4217 .p_class = P_GLOBAL,
4218 .offset = GLOBAL_VAR(winbind_expand_groups),
4221 .flags = FLAG_ADVANCED,
4224 .label = "winbind nss info",
4226 .p_class = P_GLOBAL,
4227 .offset = GLOBAL_VAR(szWinbindNssInfo),
4230 .flags = FLAG_ADVANCED,
4233 .label = "winbind refresh tickets",
4235 .p_class = P_GLOBAL,
4236 .offset = GLOBAL_VAR(bWinbindRefreshTickets),
4239 .flags = FLAG_ADVANCED,
4242 .label = "winbind offline logon",
4244 .p_class = P_GLOBAL,
4245 .offset = GLOBAL_VAR(bWinbindOfflineLogon),
4248 .flags = FLAG_ADVANCED,
4251 .label = "winbind normalize names",
4253 .p_class = P_GLOBAL,
4254 .offset = GLOBAL_VAR(bWinbindNormalizeNames),
4257 .flags = FLAG_ADVANCED,
4260 .label = "winbind rpc only",
4262 .p_class = P_GLOBAL,
4263 .offset = GLOBAL_VAR(bWinbindRpcOnly),
4266 .flags = FLAG_ADVANCED,
4269 .label = "create krb5 conf",
4271 .p_class = P_GLOBAL,
4272 .offset = GLOBAL_VAR(bCreateKrb5Conf),
4275 .flags = FLAG_ADVANCED,
4278 .label = "ncalrpc dir",
4280 .p_class = P_GLOBAL,
4281 .offset = GLOBAL_VAR(ncalrpc_dir),
4284 .flags = FLAG_ADVANCED,
4287 .label = "winbind max domain connections",
4289 .p_class = P_GLOBAL,
4290 .offset = GLOBAL_VAR(winbindMaxDomainConnections),
4293 .flags = FLAG_ADVANCED,
4296 {NULL, P_BOOL, P_NONE, 0, NULL, NULL, 0}
4299 /***************************************************************************
4300 Initialise the sDefault parameter structure for the printer values.
4301 ***************************************************************************/
4303 static void init_printer_values(struct loadparm_service *pService)
4305 /* choose defaults depending on the type of printing */
4306 switch (pService->iPrinting) {
4311 string_set(&pService->szLpqcommand, "lpq -P'%p'");
4312 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
4313 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
4318 string_set(&pService->szLpqcommand, "lpq -P'%p'");
4319 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
4320 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
4321 string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
4322 string_set(&pService->szQueueresumecommand, "lpc start '%p'");
4323 string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
4324 string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
4330 /* set the lpq command to contain the destination printer
4331 name only. This is used by cups_queue_get() */
4332 string_set(&pService->szLpqcommand, "%p");
4333 string_set(&pService->szLprmcommand, "");
4334 string_set(&pService->szPrintcommand, "");
4335 string_set(&pService->szLppausecommand, "");
4336 string_set(&pService->szLpresumecommand, "");
4337 string_set(&pService->szQueuepausecommand, "");
4338 string_set(&pService->szQueueresumecommand, "");
4340 string_set(&pService->szLpqcommand, "lpq -P'%p'");
4341 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
4342 string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
4343 string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
4344 string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
4345 string_set(&pService->szQueuepausecommand, "disable '%p'");
4346 string_set(&pService->szQueueresumecommand, "enable '%p'");
4347 #endif /* HAVE_CUPS */
4352 string_set(&pService->szLpqcommand, "lpstat -o%p");
4353 string_set(&pService->szLprmcommand, "cancel %p-%j");
4354 string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
4355 string_set(&pService->szQueuepausecommand, "disable %p");
4356 string_set(&pService->szQueueresumecommand, "enable %p");
4358 string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
4359 string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
4364 string_set(&pService->szLpqcommand, "lpq -P%p");
4365 string_set(&pService->szLprmcommand, "lprm -P%p %j");
4366 string_set(&pService->szPrintcommand, "lp -r -P%p %s");
4369 #if defined(DEVELOPER) || defined(ENABLE_BUILD_FARM_HACKS)
4373 const char *tdbfile;
4374 TALLOC_CTX *tmp_ctx = talloc_stackframe();
4377 tdbfile = talloc_asprintf(
4378 tmp_ctx, "tdbfile=%s",
4379 lp_parm_const_string(-1, "vlp", "tdbfile",
4381 if (tdbfile == NULL) {
4382 tdbfile="tdbfile=/tmp/vlp.tdb";
4385 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
4387 string_set(&pService->szPrintcommand,
4388 tmp ? tmp : "vlp print %p %s");
4390 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
4392 string_set(&pService->szLpqcommand,
4393 tmp ? tmp : "vlp lpq %p");
4395 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
4397 string_set(&pService->szLprmcommand,
4398 tmp ? tmp : "vlp lprm %p %j");
4400 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
4402 string_set(&pService->szLppausecommand,
4403 tmp ? tmp : "vlp lppause %p %j");
4405 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
4407 string_set(&pService->szLpresumecommand,
4408 tmp ? tmp : "vlp lpresume %p %j");
4410 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
4412 string_set(&pService->szQueuepausecommand,
4413 tmp ? tmp : "vlp queuepause %p");
4415 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
4417 string_set(&pService->szQueueresumecommand,
4418 tmp ? tmp : "vlp queueresume %p");
4419 TALLOC_FREE(tmp_ctx);
4423 #endif /* DEVELOPER */
4428 * Function to return the default value for the maximum number of open
4429 * file descriptors permitted. This function tries to consult the
4430 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
4431 * the smaller of those.
4433 static int max_open_files(void)
4435 int sysctl_max = MAX_OPEN_FILES;
4436 int rlimit_max = MAX_OPEN_FILES;
4438 #ifdef HAVE_SYSCTLBYNAME
4440 size_t size = sizeof(sysctl_max);
4441 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
4446 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
4452 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
4453 rlimit_max = rl.rlim_cur;
4455 #if defined(RLIM_INFINITY)
4456 if(rl.rlim_cur == RLIM_INFINITY)
4457 rlimit_max = MAX_OPEN_FILES;
4462 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
4463 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
4464 "minimum Windows limit (%d)\n",
4466 MIN_OPEN_FILES_WINDOWS));
4467 sysctl_max = MIN_OPEN_FILES_WINDOWS;
4470 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
4471 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
4472 "minimum Windows limit (%d)\n",
4474 MIN_OPEN_FILES_WINDOWS));
4475 rlimit_max = MIN_OPEN_FILES_WINDOWS;
4478 return MIN(sysctl_max, rlimit_max);
4482 * Common part of freeing allocated data for one parameter.
4484 static void free_one_parameter_common(void *parm_ptr,
4485 struct parm_struct parm)
4487 if ((parm.type == P_STRING) ||
4488 (parm.type == P_USTRING))
4490 string_free((char**)parm_ptr);
4491 } else if (parm.type == P_LIST) {
4492 TALLOC_FREE(*((char***)parm_ptr));
4497 * Free the allocated data for one parameter for a share
4498 * given as a service struct.
4500 static void free_one_parameter(struct loadparm_service *service,
4501 struct parm_struct parm)
4505 if (parm.p_class != P_LOCAL) {
4509 parm_ptr = lp_parm_ptr(service, &parm);
4511 free_one_parameter_common(parm_ptr, parm);
4515 * Free the allocated parameter data of a share given
4516 * as a service struct.
4518 static void free_parameters(struct loadparm_service *service)
4522 for (i=0; parm_table[i].label; i++) {
4523 free_one_parameter(service, parm_table[i]);
4528 * Free the allocated data for one parameter for a given share
4529 * specified by an snum.
4531 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
4536 parm_ptr = lp_parm_ptr(NULL, &parm);
4537 } else if (parm.p_class != P_LOCAL) {
4540 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
4543 free_one_parameter_common(parm_ptr, parm);
4547 * Free the allocated parameter data for a share specified
4550 static void free_parameters_by_snum(int snum)
4554 for (i=0; parm_table[i].label; i++) {
4555 free_one_parameter_by_snum(snum, parm_table[i]);
4560 * Free the allocated global parameters.
4562 static void free_global_parameters(void)
4564 free_param_opts(&Globals.param_opt);
4565 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
4568 static int map_parameter(const char *pszParmName);
4570 struct lp_stored_option {
4571 struct lp_stored_option *prev, *next;
4576 static struct lp_stored_option *stored_options;
4579 save options set by lp_set_cmdline() into a list. This list is
4580 re-applied when we do a globals reset, so that cmdline set options
4581 are sticky across reloads of smb.conf
4583 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
4585 struct lp_stored_option *entry, *entry_next;
4586 for (entry = stored_options; entry != NULL; entry = entry_next) {
4587 entry_next = entry->next;
4588 if (strcmp(pszParmName, entry->label) == 0) {
4589 DLIST_REMOVE(stored_options, entry);
4595 entry = talloc(NULL, struct lp_stored_option);
4600 entry->label = talloc_strdup(entry, pszParmName);
4601 if (!entry->label) {
4606 entry->value = talloc_strdup(entry, pszParmValue);
4607 if (!entry->value) {
4612 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
4617 static bool apply_lp_set_cmdline(void)
4619 struct lp_stored_option *entry = NULL;
4620 for (entry = stored_options; entry != NULL; entry = entry->next) {
4621 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
4622 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
4623 entry->label, entry->value));
4630 /***************************************************************************
4631 Initialise the global parameter structure.
4632 ***************************************************************************/
4634 static void init_globals(bool reinit_globals)
4636 static bool done_init = false;
4640 /* If requested to initialize only once and we've already done it... */
4641 if (!reinit_globals && done_init) {
4642 /* ... then we have nothing more to do */
4647 /* The logfile can be set before this is invoked. Free it if so. */
4648 if (Globals.logfile != NULL) {
4649 string_free(&Globals.logfile);
4650 Globals.logfile = NULL;
4654 free_global_parameters();
4657 /* This memset and the free_global_parameters() above will
4658 * wipe out smb.conf options set with lp_set_cmdline(). The
4659 * apply_lp_set_cmdline() call puts these values back in the
4660 * table once the defaults are set */
4661 ZERO_STRUCT(Globals);
4663 for (i = 0; parm_table[i].label; i++) {
4664 if ((parm_table[i].type == P_STRING ||
4665 parm_table[i].type == P_USTRING))
4667 string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
4672 string_set(&sDefault.fstype, FSTYPE_STRING);
4673 string_set(&sDefault.szPrintjobUsername, "%U");
4675 init_printer_values(&sDefault);
4678 DEBUG(3, ("Initialising global parameters\n"));
4680 /* Must manually force to upper case here, as this does not go via the handler */
4681 string_set(&Globals.szNetbiosName, myhostname_upper());
4683 string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
4684 string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
4686 /* use the new 'hash2' method by default, with a prefix of 1 */
4687 string_set(&Globals.szManglingMethod, "hash2");
4688 Globals.mangle_prefix = 1;
4690 string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
4692 /* using UTF8 by default allows us to support all chars */
4693 string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
4695 /* Use codepage 850 as a default for the dos character set */
4696 string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
4699 * Allow the default PASSWD_CHAT to be overridden in local.h.
4701 string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
4703 string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
4705 string_set(&Globals.szPasswdProgram, "");
4706 string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
4707 string_set(&Globals.szStateDir, get_dyn_STATEDIR());
4708 string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
4709 string_set(&Globals.szPidDir, get_dyn_PIDDIR());
4710 string_set(&Globals.szSocketAddress, "0.0.0.0");
4712 * By default support explicit binding to broadcast
4715 Globals.bNmbdBindExplicitBroadcast = true;
4717 if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
4718 smb_panic("init_globals: ENOMEM");
4720 string_set(&Globals.szServerString, s);
4723 string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
4726 string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
4728 string_set(&Globals.szLogonDrive, "");
4729 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
4730 string_set(&Globals.szLogonHome, "\\\\%N\\%U");
4731 string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
4733 string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast");
4734 string_set(&Globals.szPasswordServer, "*");
4736 Globals.AlgorithmicRidBase = BASE_RID;
4738 Globals.bLoadPrinters = true;
4739 Globals.PrintcapCacheTime = 750; /* 12.5 minutes */
4741 Globals.ConfigBackend = config_backend;
4742 Globals.ServerRole = ROLE_AUTO;
4744 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
4745 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
4746 Globals.max_xmit = 0x4104;
4747 Globals.max_mux = 50; /* This is *needed* for profile support. */
4748 Globals.lpqcachetime = 30; /* changed to handle large print servers better -- jerry */
4749 Globals.bDisableSpoolss = false;
4750 Globals.iMaxSmbdProcesses = 0;/* no limit specified */
4751 Globals.pwordlevel = 0;
4752 Globals.unamelevel = 0;
4753 Globals.deadtime = 0;
4754 Globals.getwd_cache = true;
4755 Globals.bLargeReadwrite = true;
4756 Globals.max_log_size = 5000;
4757 Globals.max_open_files = max_open_files();
4758 Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
4759 Globals.srv_maxprotocol = PROTOCOL_SMB2_10;
4760 Globals.srv_minprotocol = PROTOCOL_LANMAN1;
4761 Globals.security = SEC_USER;
4762 Globals.paranoid_server_security = true;
4763 Globals.bEncryptPasswords = true;
4764 Globals.clientSchannel = Auto;
4765 Globals.serverSchannel = Auto;
4766 Globals.bReadRaw = true;
4767 Globals.bWriteRaw = true;
4768 Globals.bNullPasswords = false;
4769 Globals.bObeyPamRestrictions = false;
4771 Globals.bSyslogOnly = false;
4772 Globals.bTimestampLogs = true;
4773 string_set(&Globals.szLogLevel, "0");
4774 Globals.bDebugPrefixTimestamp = false;
4775 Globals.bDebugHiresTimestamp = true;
4776 Globals.bDebugPid = false;
4777 Globals.bDebugUid = false;
4778 Globals.bDebugClass = false;
4779 Globals.bEnableCoreFiles = true;
4780 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
4781 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
4782 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
4783 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
4784 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
4785 Globals.lm_interval = 60;
4786 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
4787 Globals.bNISHomeMap = false;
4788 #ifdef WITH_NISPLUS_HOME
4789 string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
4791 string_set(&Globals.szNISHomeMapName, "auto.home");
4794 Globals.bTimeServer = false;
4795 Globals.bBindInterfacesOnly = false;
4796 Globals.bUnixPasswdSync = false;
4797 Globals.bPamPasswordChange = false;
4798 Globals.bPasswdChatDebug = false;
4799 Globals.iPasswdChatTimeout = 2; /* 2 second default. */
4800 Globals.bNTPipeSupport = true; /* Do NT pipes by default. */
4801 Globals.bNTStatusSupport = true; /* Use NT status by default. */
4802 Globals.bStatCache = true; /* use stat cache by default */
4803 Globals.iMaxStatCacheSize = 256; /* 256k by default */
4804 Globals.restrict_anonymous = 0;
4805 Globals.bClientLanManAuth = false; /* Do NOT use the LanMan hash if it is available */
4806 Globals.bClientPlaintextAuth = false; /* Do NOT use a plaintext password even if is requested by the server */
4807 Globals.bLanmanAuth = false; /* Do NOT use the LanMan hash, even if it is supplied */
4808 Globals.bNTLMAuth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
4809 Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
4810 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
4812 Globals.map_to_guest = 0; /* By Default, "Never" */
4813 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
4814 Globals.enhanced_browsing = true;
4815 Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
4816 #ifdef MMAP_BLACKLIST
4817 Globals.bUseMmap = false;
4819 Globals.bUseMmap = true;
4821 Globals.bUnixExtensions = true;
4822 Globals.bResetOnZeroVC = false;
4823 Globals.bLogWriteableFilesOnExit = false;
4824 Globals.bCreateKrb5Conf = true;
4825 Globals.winbindMaxDomainConnections = 1;
4827 /* hostname lookups can be very expensive and are broken on
4828 a large number of sites (tridge) */
4829 Globals.bHostnameLookups = false;
4831 string_set(&Globals.passdb_backend, "tdbsam");
4832 string_set(&Globals.szLdapSuffix, "");
4833 string_set(&Globals.szLdapMachineSuffix, "");
4834 string_set(&Globals.szLdapUserSuffix, "");
4835 string_set(&Globals.szLdapGroupSuffix, "");
4836 string_set(&Globals.szLdapIdmapSuffix, "");
4838 string_set(&Globals.szLdapAdminDn, "");
4839 Globals.ldap_ssl = LDAP_SSL_START_TLS;
4840 Globals.ldap_ssl_ads = false;
4841 Globals.ldap_deref = -1;
4842 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
4843 Globals.ldap_delete_dn = false;
4844 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
4845 Globals.ldap_follow_referral = Auto;
4846 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
4847 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
4848 Globals.ldap_page_size = LDAP_PAGE_SIZE;
4850 Globals.ldap_debug_level = 0;
4851 Globals.ldap_debug_threshold = 10;
4853 /* This is what we tell the afs client. in reality we set the token
4854 * to never expire, though, when this runs out the afs client will
4855 * forget the token. Set to 0 to get NEVERDATE.*/
4856 Globals.iAfsTokenLifetime = 604800;
4857 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
4859 /* these parameters are set to defaults that are more appropriate
4860 for the increasing samba install base:
4862 as a member of the workgroup, that will possibly become a
4863 _local_ master browser (lm = true). this is opposed to a forced
4864 local master browser startup (pm = true).
4866 doesn't provide WINS server service by default (wsupp = false),
4867 and doesn't provide domain master browser services by default, either.
4871 Globals.bMsAddPrinterWizard = true;
4872 Globals.os_level = 20;
4873 Globals.bLocalMaster = true;
4874 Globals.iDomainMaster = Auto; /* depending on bDomainLogons */
4875 Globals.bDomainLogons = false;
4876 Globals.bBrowseList = true;
4877 Globals.bWINSsupport = false;
4878 Globals.bWINSproxy = false;
4880 TALLOC_FREE(Globals.szInitLogonDelayedHosts);
4881 Globals.InitLogonDelay = 100; /* 100 ms default delay */
4883 Globals.bWINSdnsProxy = true;
4885 Globals.bAllowTrustedDomains = true;
4886 string_set(&Globals.szIdmapBackend, "tdb");
4888 string_set(&Globals.szTemplateShell, "/bin/false");
4889 string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
4890 string_set(&Globals.szWinbindSeparator, "\\");
4892 string_set(&Globals.szCupsServer, "");
4893 string_set(&Globals.szIPrintServer, "");
4895 string_set(&Globals.ctdbdSocket, "");
4896 Globals.szClusterAddresses = NULL;
4897 Globals.clustering = false;
4898 Globals.ctdb_timeout = 0;
4899 Globals.ctdb_locktime_warn_threshold = 0;
4901 Globals.winbind_cache_time = 300; /* 5 minutes */
4902 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
4903 Globals.winbind_max_clients = 200;
4904 Globals.bWinbindEnumUsers = false;
4905 Globals.bWinbindEnumGroups = false;
4906 Globals.bWinbindUseDefaultDomain = false;
4907 Globals.bWinbindTrustedDomainsOnly = false;
4908 Globals.bWinbindNestedGroups = true;
4909 Globals.winbind_expand_groups = 1;
4910 Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
4911 Globals.bWinbindRefreshTickets = false;
4912 Globals.bWinbindOfflineLogon = false;
4914 Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
4915 Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
4917 Globals.bPassdbExpandExplicit = false;
4919 Globals.name_cache_timeout = 660; /* In seconds */
4921 Globals.bUseSpnego = true;
4922 Globals.bClientUseSpnego = true;
4924 Globals.client_signing = SMB_SIGNING_DEFAULT;
4925 Globals.server_signing = SMB_SIGNING_DEFAULT;
4927 Globals.bDeferSharingViolations = true;
4928 string_set(&Globals.smb_ports, SMB_PORTS);
4930 Globals.bEnablePrivileges = true;
4931 Globals.bHostMSDfs = true;
4932 Globals.bASUSupport = false;
4934 /* User defined shares. */
4935 if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
4936 smb_panic("init_globals: ENOMEM");
4938 string_set(&Globals.szUsersharePath, s);
4940 string_set(&Globals.szUsershareTemplateShare, "");
4941 Globals.iUsershareMaxShares = 0;
4942 /* By default disallow sharing of directories not owned by the sharer. */
4943 Globals.bUsershareOwnerOnly = true;
4944 /* By default disallow guest access to usershares. */
4945 Globals.bUsershareAllowGuests = false;
4947 Globals.iKeepalive = DEFAULT_KEEPALIVE;
4949 /* By default no shares out of the registry */
4950 Globals.bRegistryShares = false;
4952 Globals.iminreceivefile = 0;
4954 Globals.bMapUntrustedToDomain = false;
4955 Globals.bMulticastDnsRegister = true;
4957 Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
4958 Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
4959 Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
4960 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
4962 string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
4964 /* Now put back the settings that were set with lp_set_cmdline() */
4965 apply_lp_set_cmdline();
4968 /*******************************************************************
4969 Convenience routine to grab string parameters into talloced memory
4970 and run standard_sub_basic on them. The buffers can be written to by
4971 callers without affecting the source string.
4972 ********************************************************************/
4974 static char *lp_string(TALLOC_CTX *ctx, const char *s)
4978 /* The follow debug is useful for tracking down memory problems
4979 especially if you have an inner loop that is calling a lp_*()
4980 function that returns a string. Perhaps this debug should be
4981 present all the time? */
4984 DEBUG(10, ("lp_string(%s)\n", s));
4990 ret = talloc_sub_basic(ctx,
4991 get_current_username(),
4992 current_user_info.domain,
4994 if (trim_char(ret, '\"', '\"')) {
4995 if (strchr(ret,'\"') != NULL) {
4997 ret = talloc_sub_basic(ctx,
4998 get_current_username(),
4999 current_user_info.domain,
5007 In this section all the functions that are used to access the
5008 parameters from the rest of the program are defined
5011 #define FN_GLOBAL_STRING(fn_name,ptr) \
5012 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
5013 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
5014 const char *lp_ ## fn_name(void) {return(*(const char **)(&Globals.ptr) ? *(const char **)(&Globals.ptr) : "");}
5015 #define FN_GLOBAL_LIST(fn_name,ptr) \
5016 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
5017 #define FN_GLOBAL_BOOL(fn_name,ptr) \
5018 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
5019 #define FN_GLOBAL_CHAR(fn_name,ptr) \
5020 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
5021 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
5022 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
5024 #define FN_LOCAL_STRING(fn_name,val) \
5025 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));}
5026 #define FN_LOCAL_CONST_STRING(fn_name,val) \
5027 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
5028 #define FN_LOCAL_LIST(fn_name,val) \
5029 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5030 #define FN_LOCAL_BOOL(fn_name,val) \
5031 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5032 #define FN_LOCAL_INTEGER(fn_name,val) \
5033 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5035 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
5036 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5037 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
5038 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5039 #define FN_LOCAL_CHAR(fn_name,val) \
5040 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5043 static FN_GLOBAL_BOOL(domain_logons, bDomainLogons)
5044 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
5045 static FN_GLOBAL_BOOL(time_server, bTimeServer)
5046 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
5047 static FN_GLOBAL_CONST_STRING(_ctdbd_socket, ctdbdSocket)
5048 static FN_GLOBAL_INTEGER(_server_role, ServerRole)
5050 /* If lp_statedir() and lp_cachedir() are explicitely set during the
5051 * build process or in smb.conf, we use that value. Otherwise they
5052 * default to the value of lp_lockdir(). */
5053 const char *lp_statedir(void) {
5054 if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
5055 (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
5056 return(*(char **)(&Globals.szStateDir) ?
5057 *(char **)(&Globals.szStateDir) : "");
5059 return(*(char **)(&Globals.szLockDir) ?
5060 *(char **)(&Globals.szLockDir) : "");
5062 const char *lp_cachedir(void) {
5063 if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
5064 (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
5065 return(*(char **)(&Globals.szCacheDir) ?
5066 *(char **)(&Globals.szCacheDir) : "");
5068 return(*(char **)(&Globals.szLockDir) ?
5069 *(char **)(&Globals.szLockDir) : "");
5071 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
5072 winbindMaxDomainConnections)
5074 int lp_winbind_max_domain_connections(void)
5076 if (lp_winbind_offline_logon() &&
5077 lp_winbind_max_domain_connections_int() > 1) {
5078 DEBUG(1, ("offline logons active, restricting max domain "
5079 "connections to 1\n"));
5082 return MAX(1, lp_winbind_max_domain_connections_int());
5085 int lp_smb2_max_credits(void)
5087 if (Globals.ismb2_max_credits == 0) {
5088 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
5090 return Globals.ismb2_max_credits;
5092 int lp_cups_encrypt(void)
5095 #ifdef HAVE_HTTPCONNECTENCRYPT
5096 switch (Globals.CupsEncrypt) {
5098 result = HTTP_ENCRYPT_REQUIRED;
5101 result = HTTP_ENCRYPT_ALWAYS;
5104 result = HTTP_ENCRYPT_NEVER;
5111 /* These functions remain in source3/param for now */
5113 FN_GLOBAL_CONST_STRING(name_resolve_order, szNameResolveOrder)
5114 FN_GLOBAL_CONST_STRING(smb_ports, smb_ports)
5115 FN_GLOBAL_INTEGER(security, security)
5116 FN_GLOBAL_INTEGER(usershare_max_shares, iUsershareMaxShares)
5117 FN_GLOBAL_STRING(configfile, szConfigFile)
5119 #include "lib/param/param_functions.c"
5121 FN_LOCAL_STRING(servicename, szService)
5122 FN_LOCAL_CONST_STRING(const_servicename, szService)
5124 /* local prototypes */
5126 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
5127 static const char *get_boolean(bool bool_value);
5128 static int getservicebyname(const char *pszServiceName,
5129 struct loadparm_service *pserviceDest);
5130 static void copy_service(struct loadparm_service *pserviceDest,
5131 struct loadparm_service *pserviceSource,
5132 struct bitmap *pcopymapDest);
5133 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
5135 static bool do_section(const char *pszSectionName, void *userdata);
5136 static void init_copymap(struct loadparm_service *pservice);
5137 static bool hash_a_service(const char *name, int number);
5138 static void free_service_byindex(int iService);
5139 static void show_parameter(int parmIndex);
5140 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
5143 * This is a helper function for parametrical options support. It returns a
5144 * pointer to parametrical option value if it exists or NULL otherwise. Actual
5145 * parametrical functions are quite simple
5147 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
5150 bool global_section = false;
5152 struct parmlist_entry *data;
5154 if (service == NULL) {
5155 data = Globals.param_opt;
5156 global_section = true;
5158 data = service->param_opt;
5161 if (asprintf(¶m_key, "%s:%s", type, option) == -1) {
5162 DEBUG(0,("asprintf failed!\n"));
5167 if (strwicmp(data->key, param_key) == 0) {
5168 string_free(¶m_key);
5174 if (!global_section) {
5175 /* Try to fetch the same option but from globals */
5176 /* but only if we are not already working with Globals */
5177 data = Globals.param_opt;
5179 if (strwicmp(data->key, param_key) == 0) {
5180 string_free(¶m_key);
5187 string_free(¶m_key);
5193 * This is a helper function for parametrical options support. It returns a
5194 * pointer to parametrical option value if it exists or NULL otherwise. Actual
5195 * parametrical functions are quite simple
5197 static struct parmlist_entry *get_parametrics(int snum, const char *type,
5200 if (snum >= iNumServices) return NULL;
5203 return get_parametrics_by_service(NULL, type, option);
5205 return get_parametrics_by_service(ServicePtrs[snum], type, option);
5210 #define MISSING_PARAMETER(name) \
5211 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
5213 /*******************************************************************
5214 convenience routine to return int parameters.
5215 ********************************************************************/
5216 static int lp_int(const char *s)
5220 MISSING_PARAMETER(lp_int);
5224 return (int)strtol(s, NULL, 0);
5227 /*******************************************************************
5228 convenience routine to return unsigned long parameters.
5229 ********************************************************************/
5230 static unsigned long lp_ulong(const char *s)
5234 MISSING_PARAMETER(lp_ulong);
5238 return strtoul(s, NULL, 0);
5241 /*******************************************************************
5242 convenience routine to return boolean parameters.
5243 ********************************************************************/
5244 static bool lp_bool(const char *s)
5249 MISSING_PARAMETER(lp_bool);
5253 if (!set_boolean(s, &ret)) {
5254 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
5261 /*******************************************************************
5262 convenience routine to return enum parameters.
5263 ********************************************************************/
5264 static int lp_enum(const char *s,const struct enum_list *_enum)
5268 if (!s || !*s || !_enum) {
5269 MISSING_PARAMETER(lp_enum);
5273 for (i=0; _enum[i].name; i++) {
5274 if (strequal(_enum[i].name,s))
5275 return _enum[i].value;
5278 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
5282 #undef MISSING_PARAMETER
5284 /* Return parametric option from a given service. Type is a part of option before ':' */
5285 /* Parametric option has following syntax: 'Type: option = value' */
5286 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
5288 struct parmlist_entry *data = get_parametrics(snum, type, option);
5290 if (data == NULL||data->value==NULL) {
5292 return lp_string(ctx, def);
5298 return lp_string(ctx, data->value);
5301 /* Return parametric option from a given service. Type is a part of option before ':' */
5302 /* Parametric option has following syntax: 'Type: option = value' */
5303 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
5305 struct parmlist_entry *data = get_parametrics(snum, type, option);
5307 if (data == NULL||data->value==NULL)
5313 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
5315 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
5317 if (data == NULL||data->value==NULL)
5324 /* Return parametric option from a given service. Type is a part of option before ':' */
5325 /* Parametric option has following syntax: 'Type: option = value' */
5327 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
5329 struct parmlist_entry *data = get_parametrics(snum, type, option);
5331 if (data == NULL||data->value==NULL)
5332 return (const char **)def;
5334 if (data->list==NULL) {
5335 data->list = str_list_make_v3(NULL, data->value, NULL);
5338 return (const char **)data->list;
5341 /* Return parametric option from a given service. Type is a part of option before ':' */
5342 /* Parametric option has following syntax: 'Type: option = value' */
5344 int lp_parm_int(int snum, const char *type, const char *option, int def)
5346 struct parmlist_entry *data = get_parametrics(snum, type, option);
5348 if (data && data->value && *data->value)
5349 return lp_int(data->value);
5354 /* Return parametric option from a given service. Type is a part of option before ':' */
5355 /* Parametric option has following syntax: 'Type: option = value' */
5357 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
5359 struct parmlist_entry *data = get_parametrics(snum, type, option);
5361 if (data && data->value && *data->value)
5362 return lp_ulong(data->value);
5367 /* Return parametric option from a given service. Type is a part of option before ':' */
5368 /* Parametric option has following syntax: 'Type: option = value' */
5370 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
5372 struct parmlist_entry *data = get_parametrics(snum, type, option);
5374 if (data && data->value && *data->value)
5375 return lp_bool(data->value);
5380 /* Return parametric option from a given service. Type is a part of option before ':' */
5381 /* Parametric option has following syntax: 'Type: option = value' */
5383 int lp_parm_enum(int snum, const char *type, const char *option,
5384 const struct enum_list *_enum, int def)
5386 struct parmlist_entry *data = get_parametrics(snum, type, option);
5388 if (data && data->value && *data->value && _enum)
5389 return lp_enum(data->value, _enum);
5395 /***************************************************************************
5396 Initialise a service to the defaults.
5397 ***************************************************************************/
5399 static void init_service(struct loadparm_service *pservice)
5401 memset((char *)pservice, '\0', sizeof(struct loadparm_service));
5402 copy_service(pservice, &sDefault, NULL);
5407 * free a param_opts structure.
5408 * param_opts handling should be moved to talloc;
5409 * then this whole functions reduces to a TALLOC_FREE().
5412 static void free_param_opts(struct parmlist_entry **popts)
5414 struct parmlist_entry *opt, *next_opt;
5416 if (popts == NULL) {
5420 if (*popts != NULL) {
5421 DEBUG(5, ("Freeing parametrics:\n"));
5424 while (opt != NULL) {
5425 string_free(&opt->key);
5426 string_free(&opt->value);
5427 TALLOC_FREE(opt->list);
5428 next_opt = opt->next;
5435 /***************************************************************************
5436 Free the dynamically allocated parts of a service struct.
5437 ***************************************************************************/
5439 static void free_service(struct loadparm_service *pservice)
5444 if (pservice->szService)
5445 DEBUG(5, ("free_service: Freeing service %s\n",
5446 pservice->szService));
5448 free_parameters(pservice);
5450 string_free(&pservice->szService);
5451 TALLOC_FREE(pservice->copymap);
5453 free_param_opts(&pservice->param_opt);
5455 ZERO_STRUCTP(pservice);
5459 /***************************************************************************
5460 remove a service indexed in the ServicePtrs array from the ServiceHash
5461 and free the dynamically allocated parts
5462 ***************************************************************************/
5464 static void free_service_byindex(int idx)
5466 if ( !LP_SNUM_OK(idx) )
5469 ServicePtrs[idx]->valid = false;
5470 invalid_services[num_invalid_services++] = idx;
5472 /* we have to cleanup the hash record */
5474 if (ServicePtrs[idx]->szService) {
5475 char *canon_name = canonicalize_servicename(
5477 ServicePtrs[idx]->szService );
5479 dbwrap_delete_bystring(ServiceHash, canon_name );
5480 TALLOC_FREE(canon_name);
5483 free_service(ServicePtrs[idx]);
5486 /***************************************************************************
5487 Add a new service to the services array initialising it with the given
5489 ***************************************************************************/
5491 static int add_a_service(const struct loadparm_service *pservice, const char *name)
5494 struct loadparm_service tservice;
5495 int num_to_alloc = iNumServices + 1;
5497 tservice = *pservice;
5499 /* it might already exist */
5501 i = getservicebyname(name, NULL);
5507 /* find an invalid one */
5509 if (num_invalid_services > 0) {
5510 i = invalid_services[--num_invalid_services];
5513 /* if not, then create one */
5514 if (i == iNumServices) {
5515 struct loadparm_service **tsp;
5518 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
5520 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
5524 ServicePtrs[iNumServices] = SMB_MALLOC_P(struct loadparm_service);
5525 if (!ServicePtrs[iNumServices]) {
5526 DEBUG(0,("add_a_service: out of memory!\n"));
5531 /* enlarge invalid_services here for now... */
5532 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
5534 if (tinvalid == NULL) {
5535 DEBUG(0,("add_a_service: failed to enlarge "
5536 "invalid_services!\n"));
5539 invalid_services = tinvalid;
5541 free_service_byindex(i);
5544 ServicePtrs[i]->valid = true;
5546 init_service(ServicePtrs[i]);
5547 copy_service(ServicePtrs[i], &tservice, NULL);
5549 string_set(&ServicePtrs[i]->szService, name);
5551 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
5552 i, ServicePtrs[i]->szService));
5554 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
5561 /***************************************************************************
5562 Convert a string to uppercase and remove whitespaces.
5563 ***************************************************************************/
5565 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
5570 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
5574 result = talloc_strdup(ctx, src);
5575 SMB_ASSERT(result != NULL);
5581 /***************************************************************************
5582 Add a name/index pair for the services array to the hash table.
5583 ***************************************************************************/
5585 static bool hash_a_service(const char *name, int idx)
5589 if ( !ServiceHash ) {
5590 DEBUG(10,("hash_a_service: creating servicehash\n"));
5591 ServiceHash = db_open_rbt(NULL);
5592 if ( !ServiceHash ) {
5593 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
5598 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
5601 canon_name = canonicalize_servicename(talloc_tos(), name );
5603 dbwrap_store_bystring(ServiceHash, canon_name,
5604 make_tdb_data((uint8 *)&idx, sizeof(idx)),
5607 TALLOC_FREE(canon_name);
5612 /***************************************************************************
5613 Add a new home service, with the specified home directory, defaults coming
5615 ***************************************************************************/
5617 bool lp_add_home(const char *pszHomename, int iDefaultService,
5618 const char *user, const char *pszHomedir)
5622 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
5623 pszHomedir[0] == '\0') {
5627 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
5632 if (!(*(ServicePtrs[iDefaultService]->szPath))
5633 || strequal(ServicePtrs[iDefaultService]->szPath,
5634 lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
5635 string_set(&ServicePtrs[i]->szPath, pszHomedir);
5638 if (!(*(ServicePtrs[i]->comment))) {
5639 char *comment = NULL;
5640 if (asprintf(&comment, "Home directory of %s", user) < 0) {
5643 string_set(&ServicePtrs[i]->comment, comment);
5647 /* set the browseable flag from the global default */
5649 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5650 ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
5652 ServicePtrs[i]->autoloaded = true;
5654 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
5655 user, ServicePtrs[i]->szPath ));
5660 /***************************************************************************
5661 Add a new service, based on an old one.
5662 ***************************************************************************/
5664 int lp_add_service(const char *pszService, int iDefaultService)
5666 if (iDefaultService < 0) {
5667 return add_a_service(&sDefault, pszService);
5670 return (add_a_service(ServicePtrs[iDefaultService], pszService));
5673 /***************************************************************************
5674 Add the IPC service.
5675 ***************************************************************************/
5677 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
5679 char *comment = NULL;
5680 int i = add_a_service(&sDefault, ipc_name);
5685 if (asprintf(&comment, "IPC Service (%s)",
5686 Globals.szServerString) < 0) {
5690 string_set(&ServicePtrs[i]->szPath, tmpdir());
5691 string_set(&ServicePtrs[i]->szUsername, "");
5692 string_set(&ServicePtrs[i]->comment, comment);
5693 string_set(&ServicePtrs[i]->fstype, "IPC");
5694 ServicePtrs[i]->iMaxConnections = 0;
5695 ServicePtrs[i]->bAvailable = true;
5696 ServicePtrs[i]->bRead_only = true;
5697 ServicePtrs[i]->bGuest_only = false;
5698 ServicePtrs[i]->bAdministrative_share = true;
5699 ServicePtrs[i]->bGuest_ok = guest_ok;
5700 ServicePtrs[i]->bPrint_ok = false;
5701 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5703 DEBUG(3, ("adding IPC service\n"));
5709 /***************************************************************************
5710 Add a new printer service, with defaults coming from service iFrom.
5711 ***************************************************************************/
5713 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
5715 const char *comment = "From Printcap";
5716 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
5721 /* note that we do NOT default the availability flag to true - */
5722 /* we take it from the default service passed. This allows all */
5723 /* dynamic printers to be disabled by disabling the [printers] */
5724 /* entry (if/when the 'available' keyword is implemented!). */
5726 /* the printer name is set to the service name. */
5727 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
5728 string_set(&ServicePtrs[i]->comment, comment);
5730 /* set the browseable flag from the gloabl default */
5731 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5733 /* Printers cannot be read_only. */
5734 ServicePtrs[i]->bRead_only = false;
5735 /* No share modes on printer services. */
5736 ServicePtrs[i]->bShareModes = false;
5737 /* No oplocks on printer services. */
5738 ServicePtrs[i]->bOpLocks = false;
5739 /* Printer services must be printable. */
5740 ServicePtrs[i]->bPrint_ok = true;
5742 DEBUG(3, ("adding printer service %s\n", pszPrintername));
5748 /***************************************************************************
5749 Check whether the given parameter name is valid.
5750 Parametric options (names containing a colon) are considered valid.
5751 ***************************************************************************/
5753 bool lp_parameter_is_valid(const char *pszParmName)
5755 return ((map_parameter(pszParmName) != -1) ||
5756 (strchr(pszParmName, ':') != NULL));
5759 /***************************************************************************
5760 Check whether the given name is the name of a global parameter.
5761 Returns true for strings belonging to parameters of class
5762 P_GLOBAL, false for all other strings, also for parametric options
5763 and strings not belonging to any option.
5764 ***************************************************************************/
5766 bool lp_parameter_is_global(const char *pszParmName)
5768 int num = map_parameter(pszParmName);
5771 return (parm_table[num].p_class == P_GLOBAL);
5777 /**************************************************************************
5778 Check whether the given name is the canonical name of a parameter.
5779 Returns false if it is not a valid parameter Name.
5780 For parametric options, true is returned.
5781 **************************************************************************/
5783 bool lp_parameter_is_canonical(const char *parm_name)
5785 if (!lp_parameter_is_valid(parm_name)) {
5789 return (map_parameter(parm_name) ==
5790 map_parameter_canonical(parm_name, NULL));
5793 /**************************************************************************
5794 Determine the canonical name for a parameter.
5795 Indicate when it is an inverse (boolean) synonym instead of a
5797 **************************************************************************/
5799 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
5804 if (!lp_parameter_is_valid(parm_name)) {
5809 num = map_parameter_canonical(parm_name, inverse);
5811 /* parametric option */
5812 *canon_parm = parm_name;
5814 *canon_parm = parm_table[num].label;
5821 /**************************************************************************
5822 Determine the canonical name for a parameter.
5823 Turn the value given into the inverse boolean expression when
5824 the synonym is an invers boolean synonym.
5826 Return true if parm_name is a valid parameter name and
5827 in case it is an invers boolean synonym, if the val string could
5828 successfully be converted to the reverse bool.
5829 Return false in all other cases.
5830 **************************************************************************/
5832 bool lp_canonicalize_parameter_with_value(const char *parm_name,
5834 const char **canon_parm,
5835 const char **canon_val)
5840 if (!lp_parameter_is_valid(parm_name)) {
5846 num = map_parameter_canonical(parm_name, &inverse);
5848 /* parametric option */
5849 *canon_parm = parm_name;
5852 *canon_parm = parm_table[num].label;
5854 if (!lp_invert_boolean(val, canon_val)) {
5866 /***************************************************************************
5867 Map a parameter's string representation to something we can use.
5868 Returns false if the parameter string is not recognised, else TRUE.
5869 ***************************************************************************/
5871 static int map_parameter(const char *pszParmName)
5875 if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
5878 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
5879 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
5882 /* Warn only if it isn't parametric option */
5883 if (strchr(pszParmName, ':') == NULL)
5884 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
5885 /* We do return 'fail' for parametric options as well because they are
5886 stored in different storage
5891 /***************************************************************************
5892 Map a parameter's string representation to the index of the canonical
5893 form of the parameter (it might be a synonym).
5894 Returns -1 if the parameter string is not recognised.
5895 ***************************************************************************/
5897 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
5899 int parm_num, canon_num;
5900 bool loc_inverse = false;
5902 parm_num = map_parameter(pszParmName);
5903 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
5904 /* invalid, parametric or no canidate for synonyms ... */
5908 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
5909 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
5910 parm_num = canon_num;
5916 if (inverse != NULL) {
5917 *inverse = loc_inverse;
5922 /***************************************************************************
5923 return true if parameter number parm1 is a synonym of parameter
5924 number parm2 (parm2 being the principal name).
5925 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
5927 ***************************************************************************/
5929 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
5931 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
5932 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
5933 (parm_table[parm1].flags & FLAG_HIDE) &&
5934 !(parm_table[parm2].flags & FLAG_HIDE))
5936 if (inverse != NULL) {
5937 if ((parm_table[parm1].type == P_BOOLREV) &&
5938 (parm_table[parm2].type == P_BOOL))
5950 /***************************************************************************
5951 Show one parameter's name, type, [values,] and flags.
5952 (helper functions for show_parameter_list)
5953 ***************************************************************************/
5955 static void show_parameter(int parmIndex)
5957 int enumIndex, flagIndex;
5962 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
5963 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
5965 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
5966 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
5968 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
5969 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
5970 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
5972 printf("%s=%s", parm_table[parmIndex].label,
5973 type[parm_table[parmIndex].type]);
5974 if (parm_table[parmIndex].type == P_ENUM) {
5977 parm_table[parmIndex].enum_list[enumIndex].name;
5981 enumIndex ? "|" : "",
5982 parm_table[parmIndex].enum_list[enumIndex].name);
5987 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
5988 if (parm_table[parmIndex].flags & flags[flagIndex]) {
5991 flag_names[flagIndex]);
5996 /* output synonyms */
5998 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
5999 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
6000 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
6001 parm_table[parmIndex2].label);
6002 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
6004 printf(" (synonyms: ");
6009 printf("%s%s", parm_table[parmIndex2].label,
6010 inverse ? "[i]" : "");
6020 /***************************************************************************
6021 Show all parameter's name, type, [values,] and flags.
6022 ***************************************************************************/
6024 void show_parameter_list(void)
6026 int classIndex, parmIndex;
6027 const char *section_names[] = { "local", "global", NULL};
6029 for (classIndex=0; section_names[classIndex]; classIndex++) {
6030 printf("[%s]\n", section_names[classIndex]);
6031 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
6032 if (parm_table[parmIndex].p_class == classIndex) {
6033 show_parameter(parmIndex);
6039 /***************************************************************************
6040 Check if a given string correctly represents a boolean value.
6041 ***************************************************************************/
6043 bool lp_string_is_valid_boolean(const char *parm_value)
6045 return set_boolean(parm_value, NULL);
6048 /***************************************************************************
6049 Get the standard string representation of a boolean value ("yes" or "no")
6050 ***************************************************************************/
6052 static const char *get_boolean(bool bool_value)
6054 static const char *yes_str = "yes";
6055 static const char *no_str = "no";
6057 return (bool_value ? yes_str : no_str);
6060 /***************************************************************************
6061 Provide the string of the negated boolean value associated to the boolean
6062 given as a string. Returns false if the passed string does not correctly
6063 represent a boolean.
6064 ***************************************************************************/
6066 bool lp_invert_boolean(const char *str, const char **inverse_str)
6070 if (!set_boolean(str, &val)) {
6074 *inverse_str = get_boolean(!val);
6078 /***************************************************************************
6079 Provide the canonical string representation of a boolean value given
6080 as a string. Return true on success, false if the string given does
6081 not correctly represent a boolean.
6082 ***************************************************************************/
6084 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
6088 if (!set_boolean(str, &val)) {
6092 *canon_str = get_boolean(val);
6096 /***************************************************************************
6097 Find a service by name. Otherwise works like get_service.
6098 ***************************************************************************/
6100 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
6107 if (ServiceHash == NULL) {
6111 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
6113 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
6116 if (NT_STATUS_IS_OK(status) &&
6117 (data.dptr != NULL) &&
6118 (data.dsize == sizeof(iService)))
6120 iService = *(int *)data.dptr;
6123 TALLOC_FREE(canon_name);
6125 if ((iService != -1) && (LP_SNUM_OK(iService))
6126 && (pserviceDest != NULL)) {
6127 copy_service(pserviceDest, ServicePtrs[iService], NULL);
6133 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
6134 struct loadparm_service *lp_service(const char *pszServiceName)
6136 int iService = getservicebyname(pszServiceName, NULL);
6137 if (iService == -1 || !LP_SNUM_OK(iService)) {
6140 return ServicePtrs[iService];
6143 struct loadparm_service *lp_servicebynum(int snum)
6145 if ((snum == -1) || !LP_SNUM_OK(snum)) {
6148 return ServicePtrs[snum];
6151 struct loadparm_service *lp_default_loadparm_service()
6157 /***************************************************************************
6158 Copy a service structure to another.
6159 If pcopymapDest is NULL then copy all fields
6160 ***************************************************************************/
6163 * Add a parametric option to a parmlist_entry,
6164 * replacing old value, if already present.
6166 static void set_param_opt(struct parmlist_entry **opt_list,
6167 const char *opt_name,
6168 const char *opt_value,
6171 struct parmlist_entry *new_opt, *opt;
6174 if (opt_list == NULL) {
6181 /* Traverse destination */
6183 /* If we already have same option, override it */
6184 if (strwicmp(opt->key, opt_name) == 0) {
6185 if ((opt->priority & FLAG_CMDLINE) &&
6186 !(priority & FLAG_CMDLINE)) {
6187 /* it's been marked as not to be
6191 string_free(&opt->value);
6192 TALLOC_FREE(opt->list);
6193 opt->value = SMB_STRDUP(opt_value);
6194 opt->priority = priority;
6201 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
6202 new_opt->key = SMB_STRDUP(opt_name);
6203 new_opt->value = SMB_STRDUP(opt_value);
6204 new_opt->list = NULL;
6205 new_opt->priority = priority;
6206 DLIST_ADD(*opt_list, new_opt);
6210 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
6211 struct bitmap *pcopymapDest)
6214 bool bcopyall = (pcopymapDest == NULL);
6215 struct parmlist_entry *data;
6217 for (i = 0; parm_table[i].label; i++)
6218 if (parm_table[i].p_class == P_LOCAL &&
6219 (bcopyall || bitmap_query(pcopymapDest,i))) {
6220 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
6221 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
6223 switch (parm_table[i].type) {
6226 *(bool *)dest_ptr = *(bool *)src_ptr;
6233 *(int *)dest_ptr = *(int *)src_ptr;
6237 *(char *)dest_ptr = *(char *)src_ptr;
6241 string_set((char **)dest_ptr,
6247 char *upper_string = strupper_talloc(talloc_tos(),
6249 string_set((char **)dest_ptr,
6251 TALLOC_FREE(upper_string);
6255 TALLOC_FREE(*((char ***)dest_ptr));
6256 *((char ***)dest_ptr) = str_list_copy(NULL,
6257 *(const char ***)src_ptr);
6265 init_copymap(pserviceDest);
6266 if (pserviceSource->copymap)
6267 bitmap_copy(pserviceDest->copymap,
6268 pserviceSource->copymap);
6271 data = pserviceSource->param_opt;
6273 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
6278 /***************************************************************************
6279 Check a service for consistency. Return false if the service is in any way
6280 incomplete or faulty, else true.
6281 ***************************************************************************/
6283 bool service_ok(int iService)
6288 if (ServicePtrs[iService]->szService[0] == '\0') {
6289 DEBUG(0, ("The following message indicates an internal error:\n"));
6290 DEBUG(0, ("No service name in service entry.\n"));
6294 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
6295 /* I can't see why you'd want a non-printable printer service... */
6296 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
6297 if (!ServicePtrs[iService]->bPrint_ok) {
6298 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
6299 ServicePtrs[iService]->szService));
6300 ServicePtrs[iService]->bPrint_ok = true;
6302 /* [printers] service must also be non-browsable. */
6303 if (ServicePtrs[iService]->bBrowseable)
6304 ServicePtrs[iService]->bBrowseable = false;
6307 if (ServicePtrs[iService]->szPath[0] == '\0' &&
6308 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
6309 ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
6311 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
6312 ServicePtrs[iService]->szService));
6313 ServicePtrs[iService]->bAvailable = false;
6316 /* If a service is flagged unavailable, log the fact at level 1. */
6317 if (!ServicePtrs[iService]->bAvailable)
6318 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
6319 ServicePtrs[iService]->szService));
6324 static struct smbconf_ctx *lp_smbconf_ctx(void)
6327 static struct smbconf_ctx *conf_ctx = NULL;
6329 if (conf_ctx == NULL) {
6330 err = smbconf_init(NULL, &conf_ctx, "registry:");
6331 if (!SBC_ERROR_IS_OK(err)) {
6332 DEBUG(1, ("error initializing registry configuration: "
6333 "%s\n", sbcErrorString(err)));
6341 static bool process_smbconf_service(struct smbconf_service *service)
6346 if (service == NULL) {
6350 ret = do_section(service->name, NULL);
6354 for (count = 0; count < service->num_params; count++) {
6355 ret = do_parameter(service->param_names[count],
6356 service->param_values[count],
6362 if (iServiceIndex >= 0) {
6363 return service_ok(iServiceIndex);
6369 * load a service from registry and activate it
6371 bool process_registry_service(const char *service_name)
6374 struct smbconf_service *service = NULL;
6375 TALLOC_CTX *mem_ctx = talloc_stackframe();
6376 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6379 if (conf_ctx == NULL) {
6383 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
6385 if (!smbconf_share_exists(conf_ctx, service_name)) {
6387 * Registry does not contain data for this service (yet),
6388 * but make sure lp_load doesn't return false.
6394 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
6395 if (!SBC_ERROR_IS_OK(err)) {
6399 ret = process_smbconf_service(service);
6405 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6408 TALLOC_FREE(mem_ctx);
6413 * process_registry_globals
6415 static bool process_registry_globals(void)
6419 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
6421 ret = do_parameter("registry shares", "yes", NULL);
6426 return process_registry_service(GLOBAL_NAME);
6429 bool process_registry_shares(void)
6433 struct smbconf_service **service = NULL;
6434 uint32_t num_shares = 0;
6435 TALLOC_CTX *mem_ctx = talloc_stackframe();
6436 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6439 if (conf_ctx == NULL) {
6443 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
6444 if (!SBC_ERROR_IS_OK(err)) {
6450 for (count = 0; count < num_shares; count++) {
6451 if (strequal(service[count]->name, GLOBAL_NAME)) {
6454 ret = process_smbconf_service(service[count]);
6461 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6464 TALLOC_FREE(mem_ctx);
6469 * reload those shares from registry that are already
6470 * activated in the services array.
6472 static bool reload_registry_shares(void)
6477 for (i = 0; i < iNumServices; i++) {
6482 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
6486 ret = process_registry_service(ServicePtrs[i]->szService);
6497 #define MAX_INCLUDE_DEPTH 100
6499 static uint8_t include_depth;
6501 static struct file_lists {
6502 struct file_lists *next;
6506 } *file_lists = NULL;
6508 /*******************************************************************
6509 Keep a linked list of all config files so we know when one has changed
6510 it's date and needs to be reloaded.
6511 ********************************************************************/
6513 static void add_to_file_list(const char *fname, const char *subfname)
6515 struct file_lists *f = file_lists;
6518 if (f->name && !strcmp(f->name, fname))
6524 f = SMB_MALLOC_P(struct file_lists);
6527 f->next = file_lists;
6528 f->name = SMB_STRDUP(fname);
6533 f->subfname = SMB_STRDUP(subfname);
6540 f->modtime = file_modtime(subfname);
6542 time_t t = file_modtime(subfname);
6550 * Free the file lists
6552 static void free_file_list(void)
6554 struct file_lists *f;
6555 struct file_lists *next;
6560 SAFE_FREE( f->name );
6561 SAFE_FREE( f->subfname );
6570 * Utility function for outsiders to check if we're running on registry.
6572 bool lp_config_backend_is_registry(void)
6574 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
6578 * Utility function to check if the config backend is FILE.
6580 bool lp_config_backend_is_file(void)
6582 return (lp_config_backend() == CONFIG_BACKEND_FILE);
6585 /*******************************************************************
6586 Check if a config file has changed date.
6587 ********************************************************************/
6589 bool lp_file_list_changed(void)
6591 struct file_lists *f = file_lists;
6593 DEBUG(6, ("lp_file_list_changed()\n"));
6598 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
6599 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6601 if (conf_ctx == NULL) {
6604 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
6607 DEBUGADD(6, ("registry config changed\n"));
6612 n2 = talloc_sub_basic(talloc_tos(),
6613 get_current_username(),
6614 current_user_info.domain,
6619 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
6620 f->name, n2, ctime(&f->modtime)));
6622 mod_time = file_modtime(n2);
6625 ((f->modtime != mod_time) ||
6626 (f->subfname == NULL) ||
6627 (strcmp(n2, f->subfname) != 0)))
6630 ("file %s modified: %s\n", n2,
6632 f->modtime = mod_time;
6633 SAFE_FREE(f->subfname);
6634 f->subfname = SMB_STRDUP(n2);
6647 * Initialize iconv conversion descriptors.
6649 * This is called the first time it is needed, and also called again
6650 * every time the configuration is reloaded, because the charset or
6651 * codepage might have changed.
6653 static void init_iconv(void)
6655 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
6657 true, global_iconv_handle);
6660 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6662 if (strcmp(*ptr, pszParmValue) != 0) {
6663 string_set(ptr, pszParmValue);
6669 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6671 bool is_utf8 = false;
6672 size_t len = strlen(pszParmValue);
6674 if (len == 4 || len == 5) {
6675 /* Don't use StrCaseCmp here as we don't want to
6676 initialize iconv. */
6677 if ((toupper_m(pszParmValue[0]) == 'U') &&
6678 (toupper_m(pszParmValue[1]) == 'T') &&
6679 (toupper_m(pszParmValue[2]) == 'F')) {
6681 if (pszParmValue[3] == '8') {
6685 if (pszParmValue[3] == '-' &&
6686 pszParmValue[4] == '8') {
6693 if (strcmp(*ptr, pszParmValue) != 0) {
6695 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
6696 "be UTF8, using (default value) %s instead.\n",
6697 DEFAULT_DOS_CHARSET));
6698 pszParmValue = DEFAULT_DOS_CHARSET;
6700 string_set(ptr, pszParmValue);
6706 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6709 char *realm = strupper_talloc(talloc_tos(), pszParmValue);
6710 char *dnsdomain = strlower_talloc(realm, pszParmValue);
6712 ret &= string_set(&Globals.szRealm, pszParmValue);
6713 ret &= string_set(&Globals.szRealm_upper, realm);
6714 ret &= string_set(&Globals.szRealm_lower, dnsdomain);
6720 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6722 TALLOC_FREE(Globals.szNetbiosAliases);
6723 Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
6724 return set_netbios_aliases(Globals.szNetbiosAliases);
6727 /***************************************************************************
6728 Handle the include operation.
6729 ***************************************************************************/
6730 static bool bAllowIncludeRegistry = true;
6732 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6736 if (include_depth >= MAX_INCLUDE_DEPTH) {
6737 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
6742 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
6743 if (!bAllowIncludeRegistry) {
6746 if (bInGlobalSection) {
6749 ret = process_registry_globals();
6753 DEBUG(1, ("\"include = registry\" only effective "
6754 "in %s section\n", GLOBAL_NAME));
6759 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
6760 current_user_info.domain,
6763 add_to_file_list(pszParmValue, fname);
6765 string_set(ptr, fname);
6767 if (file_exist(fname)) {
6770 ret = pm_process(fname, do_section, do_parameter, NULL);
6776 DEBUG(2, ("Can't find include file %s\n", fname));
6781 /***************************************************************************
6782 Handle the interpretation of the copy parameter.
6783 ***************************************************************************/
6785 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6789 struct loadparm_service serviceTemp;
6791 string_set(ptr, pszParmValue);
6793 init_service(&serviceTemp);
6797 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
6799 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
6800 if (iTemp == iServiceIndex) {
6801 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
6803 copy_service(ServicePtrs[iServiceIndex],
6805 ServicePtrs[iServiceIndex]->copymap);
6809 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
6813 free_service(&serviceTemp);
6817 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6819 Globals.ldap_debug_level = lp_int(pszParmValue);
6820 init_ldap_debugging();
6824 /***************************************************************************
6825 Handle idmap/non unix account uid and gid allocation parameters. The format of these
6830 idmap uid = 1000-1999
6833 We only do simple parsing checks here. The strings are parsed into useful
6834 structures in the idmap daemon code.
6836 ***************************************************************************/
6838 /* Some lp_ routines to return idmap [ug]id information */
6840 static uid_t idmap_uid_low, idmap_uid_high;
6841 static gid_t idmap_gid_low, idmap_gid_high;
6843 bool lp_idmap_uid(uid_t *low, uid_t *high)
6845 if (idmap_uid_low == 0 || idmap_uid_high == 0)
6849 *low = idmap_uid_low;
6852 *high = idmap_uid_high;
6857 bool lp_idmap_gid(gid_t *low, gid_t *high)
6859 if (idmap_gid_low == 0 || idmap_gid_high == 0)
6863 *low = idmap_gid_low;
6866 *high = idmap_gid_high;
6871 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6873 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
6878 /* Do some simple checks on "idmap [ug]id" parameter values */
6880 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6882 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
6887 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6889 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
6894 /***************************************************************************
6895 Handle the DEBUG level list.
6896 ***************************************************************************/
6898 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
6900 string_set(ptr, pszParmValueIn);
6901 return debug_parse_levels(pszParmValueIn);
6904 /***************************************************************************
6905 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
6906 ***************************************************************************/
6908 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
6910 const char *suffix_string;
6912 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
6913 Globals.szLdapSuffix );
6914 if ( !suffix_string ) {
6915 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
6919 return suffix_string;
6922 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
6924 if (Globals.szLdapMachineSuffix[0])
6925 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
6927 return lp_string(ctx, Globals.szLdapSuffix);
6930 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
6932 if (Globals.szLdapUserSuffix[0])
6933 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
6935 return lp_string(ctx, Globals.szLdapSuffix);
6938 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
6940 if (Globals.szLdapGroupSuffix[0])
6941 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
6943 return lp_string(ctx, Globals.szLdapSuffix);
6946 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
6948 if (Globals.szLdapIdmapSuffix[0])
6949 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
6951 return lp_string(ctx, Globals.szLdapSuffix);
6954 /****************************************************************************
6955 set the value for a P_ENUM
6956 ***************************************************************************/
6958 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
6963 for (i = 0; parm->enum_list[i].name; i++) {
6964 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
6965 *ptr = parm->enum_list[i].value;
6969 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
6970 pszParmValue, parm->label));
6973 /***************************************************************************
6974 ***************************************************************************/
6976 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6978 static int parm_num = -1;
6979 struct loadparm_service *s;
6981 if ( parm_num == -1 )
6982 parm_num = map_parameter( "printing" );
6984 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
6989 s = ServicePtrs[snum];
6991 init_printer_values( s );
6997 /***************************************************************************
6998 Initialise a copymap.
6999 ***************************************************************************/
7001 static void init_copymap(struct loadparm_service *pservice)
7005 TALLOC_FREE(pservice->copymap);
7007 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
7008 if (!pservice->copymap)
7010 ("Couldn't allocate copymap!! (size %d)\n",
7011 (int)NUMPARAMETERS));
7013 for (i = 0; i < NUMPARAMETERS; i++)
7014 bitmap_set(pservice->copymap, i);
7018 return the parameter pointer for a parameter
7020 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
7022 if (service == NULL) {
7023 if (parm->p_class == P_LOCAL)
7024 return (void *)(((char *)&sDefault)+parm->offset);
7025 else if (parm->p_class == P_GLOBAL)
7026 return (void *)(((char *)&Globals)+parm->offset);
7029 return (void *)(((char *)service) + parm->offset);
7033 /***************************************************************************
7034 Return the local pointer to a parameter given the service number and parameter
7035 ***************************************************************************/
7037 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
7039 return lp_parm_ptr(ServicePtrs[snum], parm);
7042 /***************************************************************************
7043 Process a parameter for a particular service number. If snum < 0
7044 then assume we are in the globals.
7045 ***************************************************************************/
7047 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
7050 void *parm_ptr = NULL; /* where we are going to store the result */
7051 struct parmlist_entry **opt_list;
7053 parmnum = map_parameter(pszParmName);
7056 if (strchr(pszParmName, ':') == NULL) {
7057 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
7063 * We've got a parametric option
7066 opt_list = (snum < 0)
7067 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
7068 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
7073 /* if it's already been set by the command line, then we don't
7075 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
7079 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
7080 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
7084 /* we might point at a service, the default service or a global */
7086 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
7088 if (parm_table[parmnum].p_class == P_GLOBAL) {
7090 ("Global parameter %s found in service section!\n",
7094 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
7098 if (!ServicePtrs[snum]->copymap)
7099 init_copymap(ServicePtrs[snum]);
7101 /* this handles the aliases - set the copymap for other entries with
7102 the same data pointer */
7103 for (i = 0; parm_table[i].label; i++) {
7104 if ((parm_table[i].offset == parm_table[parmnum].offset)
7105 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
7106 bitmap_clear(ServicePtrs[snum]->copymap, i);
7111 /* if it is a special case then go ahead */
7112 if (parm_table[parmnum].special) {
7113 return parm_table[parmnum].special(NULL, snum, pszParmValue,
7117 /* now switch on the type of variable it is */
7118 switch (parm_table[parmnum].type)
7121 *(bool *)parm_ptr = lp_bool(pszParmValue);
7125 *(bool *)parm_ptr = !lp_bool(pszParmValue);
7129 *(int *)parm_ptr = lp_int(pszParmValue);
7133 *(char *)parm_ptr = *pszParmValue;
7137 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
7139 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
7146 if (conv_str_size_error(pszParmValue, &val)) {
7147 if (val <= INT_MAX) {
7148 *(int *)parm_ptr = (int)val;
7153 DEBUG(0,("lp_do_parameter(%s): value is not "
7154 "a valid size specifier!\n", pszParmValue));
7160 TALLOC_FREE(*((char ***)parm_ptr));
7161 *(char ***)parm_ptr = str_list_make_v3(
7162 NULL, pszParmValue, NULL);
7166 string_set((char **)parm_ptr, pszParmValue);
7171 char *upper_string = strupper_talloc(talloc_tos(),
7173 string_set((char **)parm_ptr, upper_string);
7174 TALLOC_FREE(upper_string);
7178 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
7187 /***************************************************************************
7188 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
7189 FLAG_CMDLINE won't be overridden by loads from smb.conf.
7190 ***************************************************************************/
7192 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
7195 parmnum = map_parameter(pszParmName);
7197 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
7198 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
7201 parm_table[parmnum].flags |= FLAG_CMDLINE;
7203 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
7204 * be grouped in the table, so we don't have to search the
7207 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
7208 && parm_table[i].p_class == parm_table[parmnum].p_class;
7210 parm_table[i].flags |= FLAG_CMDLINE;
7212 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
7213 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
7214 parm_table[i].flags |= FLAG_CMDLINE;
7218 store_lp_set_cmdline(pszParmName, pszParmValue);
7223 /* it might be parametric */
7224 if (strchr(pszParmName, ':') != NULL) {
7225 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
7227 store_lp_set_cmdline(pszParmName, pszParmValue);
7232 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
7236 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
7238 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
7241 /***************************************************************************
7242 Process a parameter.
7243 ***************************************************************************/
7245 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
7248 if (!bInGlobalSection && bGlobalOnly)
7251 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
7253 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
7254 pszParmName, pszParmValue));
7258 set a option from the commandline in 'a=b' format. Use to support --option
7260 bool lp_set_option(const char *option)
7265 s = talloc_strdup(NULL, option);
7278 /* skip white spaces after the = sign */
7281 } while (*p == ' ');
7283 ret = lp_set_cmdline(s, p);
7288 /**************************************************************************
7289 Print a parameter of the specified type.
7290 ***************************************************************************/
7292 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
7294 /* For the seperation of lists values that we print below */
7295 const char *list_sep = ", ";
7300 for (i = 0; p->enum_list[i].name; i++) {
7301 if (*(int *)ptr == p->enum_list[i].value) {
7303 p->enum_list[i].name);
7310 fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
7314 fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
7319 fprintf(f, "%d", *(int *)ptr);
7323 fprintf(f, "%c", *(char *)ptr);
7327 int val = *(int *)ptr;
7331 fprintf(f, "0%o", val);
7340 if ((char ***)ptr && *(char ***)ptr) {
7341 char **list = *(char ***)ptr;
7342 for (; *list; list++) {
7343 /* surround strings with whitespace in double quotes */
7344 if (*(list+1) == NULL) {
7345 /* last item, no extra separator */
7348 if ( strchr_m( *list, ' ' ) ) {
7349 fprintf(f, "\"%s\"%s", *list, list_sep);
7351 fprintf(f, "%s%s", *list, list_sep);
7359 if (*(char **)ptr) {
7360 fprintf(f, "%s", *(char **)ptr);
7368 /***************************************************************************
7369 Check if two parameters are equal.
7370 ***************************************************************************/
7372 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
7377 return (*((bool *)ptr1) == *((bool *)ptr2));
7383 return (*((int *)ptr1) == *((int *)ptr2));
7386 return (*((char *)ptr1) == *((char *)ptr2));
7390 return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
7395 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
7400 return (p1 == p2 || strequal(p1, p2));
7408 /***************************************************************************
7409 Initialize any local varients in the sDefault table.
7410 ***************************************************************************/
7412 void init_locals(void)
7417 /***************************************************************************
7418 Process a new section (service). At this stage all sections are services.
7419 Later we'll have special sections that permit server parameters to be set.
7420 Returns true on success, false on failure.
7421 ***************************************************************************/
7423 static bool do_section(const char *pszSectionName, void *userdata)
7426 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
7427 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
7430 /* if we were in a global section then do the local inits */
7431 if (bInGlobalSection && !isglobal)
7434 /* if we've just struck a global section, note the fact. */
7435 bInGlobalSection = isglobal;
7437 /* check for multiple global sections */
7438 if (bInGlobalSection) {
7439 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
7443 if (!bInGlobalSection && bGlobalOnly)
7446 /* if we have a current service, tidy it up before moving on */
7449 if (iServiceIndex >= 0)
7450 bRetval = service_ok(iServiceIndex);
7452 /* if all is still well, move to the next record in the services array */
7454 /* We put this here to avoid an odd message order if messages are */
7455 /* issued by the post-processing of a previous section. */
7456 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
7458 iServiceIndex = add_a_service(&sDefault, pszSectionName);
7459 if (iServiceIndex < 0) {
7460 DEBUG(0, ("Failed to add a new service\n"));
7463 /* Clean all parametric options for service */
7464 /* They will be added during parsing again */
7465 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
7472 /***************************************************************************
7473 Determine if a partcular base parameter is currentl set to the default value.
7474 ***************************************************************************/
7476 static bool is_default(int i)
7478 if (!defaults_saved)
7480 switch (parm_table[i].type) {
7483 return str_list_equal((const char **)parm_table[i].def.lvalue,
7484 *(const char ***)lp_parm_ptr(NULL,
7488 return strequal(parm_table[i].def.svalue,
7489 *(char **)lp_parm_ptr(NULL,
7493 return parm_table[i].def.bvalue ==
7494 *(bool *)lp_parm_ptr(NULL,
7497 return parm_table[i].def.cvalue ==
7498 *(char *)lp_parm_ptr(NULL,
7504 return parm_table[i].def.ivalue ==
7505 *(int *)lp_parm_ptr(NULL,
7513 /***************************************************************************
7514 Display the contents of the global structure.
7515 ***************************************************************************/
7517 static void dump_globals(FILE *f)
7520 struct parmlist_entry *data;
7522 fprintf(f, "[global]\n");
7524 for (i = 0; parm_table[i].label; i++)
7525 if (parm_table[i].p_class == P_GLOBAL &&
7526 !(parm_table[i].flags & FLAG_META) &&
7527 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
7528 if (defaults_saved && is_default(i))
7530 fprintf(f, "\t%s = ", parm_table[i].label);
7531 print_parameter(&parm_table[i], lp_parm_ptr(NULL,
7536 if (Globals.param_opt != NULL) {
7537 data = Globals.param_opt;
7539 fprintf(f, "\t%s = %s\n", data->key, data->value);
7546 /***************************************************************************
7547 Return true if a local parameter is currently set to the global default.
7548 ***************************************************************************/
7550 bool lp_is_default(int snum, struct parm_struct *parm)
7552 return equal_parameter(parm->type,
7553 lp_parm_ptr(ServicePtrs[snum], parm),
7554 lp_parm_ptr(NULL, parm));
7557 /***************************************************************************
7558 Display the contents of a single services record.
7559 ***************************************************************************/
7561 static void dump_a_service(struct loadparm_service *pService, FILE * f)
7564 struct parmlist_entry *data;
7566 if (pService != &sDefault)
7567 fprintf(f, "[%s]\n", pService->szService);
7569 for (i = 0; parm_table[i].label; i++) {
7571 if (parm_table[i].p_class == P_LOCAL &&
7572 !(parm_table[i].flags & FLAG_META) &&
7573 (*parm_table[i].label != '-') &&
7574 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
7576 if (pService == &sDefault) {
7577 if (defaults_saved && is_default(i))
7580 if (equal_parameter(parm_table[i].type,
7581 lp_parm_ptr(pService, &parm_table[i]),
7582 lp_parm_ptr(NULL, &parm_table[i])))
7586 fprintf(f, "\t%s = ", parm_table[i].label);
7587 print_parameter(&parm_table[i],
7588 lp_parm_ptr(pService, &parm_table[i]),
7594 if (pService->param_opt != NULL) {
7595 data = pService->param_opt;
7597 fprintf(f, "\t%s = %s\n", data->key, data->value);
7603 /***************************************************************************
7604 Display the contents of a parameter of a single services record.
7605 ***************************************************************************/
7607 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
7610 bool result = false;
7613 fstring local_parm_name;
7615 const char *parm_opt_value;
7617 /* check for parametrical option */
7618 fstrcpy( local_parm_name, parm_name);
7619 parm_opt = strchr( local_parm_name, ':');
7624 if (strlen(parm_opt)) {
7625 parm_opt_value = lp_parm_const_string( snum,
7626 local_parm_name, parm_opt, NULL);
7627 if (parm_opt_value) {
7628 printf( "%s\n", parm_opt_value);
7635 /* check for a key and print the value */
7642 for (i = 0; parm_table[i].label; i++) {
7643 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
7644 !(parm_table[i].flags & FLAG_META) &&
7645 (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
7646 (*parm_table[i].label != '-') &&
7647 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
7652 ptr = lp_parm_ptr(NULL,
7655 ptr = lp_parm_ptr(ServicePtrs[snum],
7659 print_parameter(&parm_table[i],
7670 /***************************************************************************
7671 Return info about the requested parameter (given as a string).
7672 Return NULL when the string is not a valid parameter name.
7673 ***************************************************************************/
7675 struct parm_struct *lp_get_parameter(const char *param_name)
7677 int num = map_parameter(param_name);
7683 return &parm_table[num];
7686 /***************************************************************************
7687 Return info about the next parameter in a service.
7688 snum==GLOBAL_SECTION_SNUM gives the globals.
7689 Return NULL when out of parameters.
7690 ***************************************************************************/
7692 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
7695 /* do the globals */
7696 for (; parm_table[*i].label; (*i)++) {
7697 if (parm_table[*i].p_class == P_SEPARATOR)
7698 return &parm_table[(*i)++];
7700 if ((*parm_table[*i].label == '-'))
7704 && (parm_table[*i].offset ==
7705 parm_table[(*i) - 1].offset)
7706 && (parm_table[*i].p_class ==
7707 parm_table[(*i) - 1].p_class))
7710 if (is_default(*i) && !allparameters)
7713 return &parm_table[(*i)++];
7716 struct loadparm_service *pService = ServicePtrs[snum];
7718 for (; parm_table[*i].label; (*i)++) {
7719 if (parm_table[*i].p_class == P_SEPARATOR)
7720 return &parm_table[(*i)++];
7722 if (parm_table[*i].p_class == P_LOCAL &&
7723 (*parm_table[*i].label != '-') &&
7725 (parm_table[*i].offset !=
7726 parm_table[(*i) - 1].offset)))
7728 if (allparameters ||
7729 !equal_parameter(parm_table[*i].type,
7730 lp_parm_ptr(pService,
7735 return &parm_table[(*i)++];
7746 /***************************************************************************
7747 Display the contents of a single copy structure.
7748 ***************************************************************************/
7749 static void dump_copy_map(bool *pcopymap)
7755 printf("\n\tNon-Copied parameters:\n");
7757 for (i = 0; parm_table[i].label; i++)
7758 if (parm_table[i].p_class == P_LOCAL &&
7759 parm_table[i].ptr && !pcopymap[i] &&
7760 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
7762 printf("\t\t%s\n", parm_table[i].label);
7767 /***************************************************************************
7768 Return TRUE if the passed service number is within range.
7769 ***************************************************************************/
7771 bool lp_snum_ok(int iService)
7773 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
7776 /***************************************************************************
7777 Auto-load some home services.
7778 ***************************************************************************/
7780 static void lp_add_auto_services(char *str)
7790 s = SMB_STRDUP(str);
7794 homes = lp_servicenumber(HOMES_NAME);
7796 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
7797 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
7800 if (lp_servicenumber(p) >= 0)
7803 home = get_user_home_dir(talloc_tos(), p);
7805 if (home && home[0] && homes >= 0)
7806 lp_add_home(p, homes, p, home);
7813 /***************************************************************************
7814 Auto-load one printer.
7815 ***************************************************************************/
7817 void lp_add_one_printer(const char *name, const char *comment,
7818 const char *location, void *pdata)
7820 int printers = lp_servicenumber(PRINTERS_NAME);
7823 if (lp_servicenumber(name) < 0) {
7824 lp_add_printer(name, printers);
7825 if ((i = lp_servicenumber(name)) >= 0) {
7826 string_set(&ServicePtrs[i]->comment, comment);
7827 ServicePtrs[i]->autoloaded = true;
7832 /***************************************************************************
7833 Have we loaded a services file yet?
7834 ***************************************************************************/
7836 bool lp_loaded(void)
7841 /***************************************************************************
7842 Unload unused services.
7843 ***************************************************************************/
7845 void lp_killunused(struct smbd_server_connection *sconn,
7846 bool (*snumused) (struct smbd_server_connection *, int))
7849 for (i = 0; i < iNumServices; i++) {
7853 /* don't kill autoloaded or usershare services */
7854 if ( ServicePtrs[i]->autoloaded ||
7855 ServicePtrs[i]->usershare == USERSHARE_VALID) {
7859 if (!snumused || !snumused(sconn, i)) {
7860 free_service_byindex(i);
7866 * Kill all except autoloaded and usershare services - convenience wrapper
7868 void lp_kill_all_services(void)
7870 lp_killunused(NULL, NULL);
7873 /***************************************************************************
7875 ***************************************************************************/
7877 void lp_killservice(int iServiceIn)
7879 if (VALID(iServiceIn)) {
7880 free_service_byindex(iServiceIn);
7884 /***************************************************************************
7885 Save the curent values of all global and sDefault parameters into the
7886 defaults union. This allows swat and testparm to show only the
7887 changed (ie. non-default) parameters.
7888 ***************************************************************************/
7890 static void lp_save_defaults(void)
7893 for (i = 0; parm_table[i].label; i++) {
7894 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
7895 && parm_table[i].p_class == parm_table[i - 1].p_class)
7897 switch (parm_table[i].type) {
7900 parm_table[i].def.lvalue = str_list_copy(
7901 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
7905 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
7909 parm_table[i].def.bvalue =
7910 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
7913 parm_table[i].def.cvalue =
7914 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
7920 parm_table[i].def.ivalue =
7921 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
7927 defaults_saved = true;
7930 /***********************************************************
7931 If we should send plaintext/LANMAN passwords in the clinet
7932 ************************************************************/
7934 static void set_allowed_client_auth(void)
7936 if (Globals.bClientNTLMv2Auth) {
7937 Globals.bClientLanManAuth = false;
7939 if (!Globals.bClientLanManAuth) {
7940 Globals.bClientPlaintextAuth = false;
7944 /***************************************************************************
7946 The following code allows smbd to read a user defined share file.
7947 Yes, this is my intent. Yes, I'm comfortable with that...
7949 THE FOLLOWING IS SECURITY CRITICAL CODE.
7951 It washes your clothes, it cleans your house, it guards you while you sleep...
7952 Do not f%^k with it....
7953 ***************************************************************************/
7955 #define MAX_USERSHARE_FILE_SIZE (10*1024)
7957 /***************************************************************************
7958 Check allowed stat state of a usershare file.
7959 Ensure we print out who is dicking with us so the admin can
7960 get their sorry ass fired.
7961 ***************************************************************************/
7963 static bool check_usershare_stat(const char *fname,
7964 const SMB_STRUCT_STAT *psbuf)
7966 if (!S_ISREG(psbuf->st_ex_mode)) {
7967 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
7968 "not a regular file\n",
7969 fname, (unsigned int)psbuf->st_ex_uid ));
7973 /* Ensure this doesn't have the other write bit set. */
7974 if (psbuf->st_ex_mode & S_IWOTH) {
7975 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
7976 "public write. Refusing to allow as a usershare file.\n",
7977 fname, (unsigned int)psbuf->st_ex_uid ));
7981 /* Should be 10k or less. */
7982 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
7983 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
7984 "too large (%u) to be a user share file.\n",
7985 fname, (unsigned int)psbuf->st_ex_uid,
7986 (unsigned int)psbuf->st_ex_size ));
7993 /***************************************************************************
7994 Parse the contents of a usershare file.
7995 ***************************************************************************/
7997 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
7998 SMB_STRUCT_STAT *psbuf,
7999 const char *servicename,
8003 char **pp_sharepath,
8005 char **pp_cp_servicename,
8006 struct security_descriptor **ppsd,
8009 const char **prefixallowlist = lp_usershare_prefix_allow_list();
8010 const char **prefixdenylist = lp_usershare_prefix_deny_list();
8013 SMB_STRUCT_STAT sbuf;
8014 char *sharepath = NULL;
8015 char *comment = NULL;
8017 *pp_sharepath = NULL;
8020 *pallow_guest = false;
8023 return USERSHARE_MALFORMED_FILE;
8026 if (strcmp(lines[0], "#VERSION 1") == 0) {
8028 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
8031 return USERSHARE_MALFORMED_FILE;
8034 return USERSHARE_BAD_VERSION;
8037 if (strncmp(lines[1], "path=", 5) != 0) {
8038 return USERSHARE_MALFORMED_PATH;
8041 sharepath = talloc_strdup(ctx, &lines[1][5]);
8043 return USERSHARE_POSIX_ERR;
8045 trim_string(sharepath, " ", " ");
8047 if (strncmp(lines[2], "comment=", 8) != 0) {
8048 return USERSHARE_MALFORMED_COMMENT_DEF;
8051 comment = talloc_strdup(ctx, &lines[2][8]);
8053 return USERSHARE_POSIX_ERR;
8055 trim_string(comment, " ", " ");
8056 trim_char(comment, '"', '"');
8058 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
8059 return USERSHARE_MALFORMED_ACL_DEF;
8062 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
8063 return USERSHARE_ACL_ERR;
8067 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
8068 return USERSHARE_MALFORMED_ACL_DEF;
8070 if (lines[4][9] == 'y') {
8071 *pallow_guest = true;
8074 /* Backwards compatible extension to file version #2. */
8076 if (strncmp(lines[5], "sharename=", 10) != 0) {
8077 return USERSHARE_MALFORMED_SHARENAME_DEF;
8079 if (!strequal(&lines[5][10], servicename)) {
8080 return USERSHARE_BAD_SHARENAME;
8082 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
8083 if (!*pp_cp_servicename) {
8084 return USERSHARE_POSIX_ERR;
8089 if (*pp_cp_servicename == NULL) {
8090 *pp_cp_servicename = talloc_strdup(ctx, servicename);
8091 if (!*pp_cp_servicename) {
8092 return USERSHARE_POSIX_ERR;
8096 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
8097 /* Path didn't change, no checks needed. */
8098 *pp_sharepath = sharepath;
8099 *pp_comment = comment;
8100 return USERSHARE_OK;
8103 /* The path *must* be absolute. */
8104 if (sharepath[0] != '/') {
8105 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
8106 servicename, sharepath));
8107 return USERSHARE_PATH_NOT_ABSOLUTE;
8110 /* If there is a usershare prefix deny list ensure one of these paths
8111 doesn't match the start of the user given path. */
8112 if (prefixdenylist) {
8114 for ( i=0; prefixdenylist[i]; i++ ) {
8115 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
8116 servicename, i, prefixdenylist[i], sharepath ));
8117 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
8118 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
8119 "usershare prefix deny list entries.\n",
8120 servicename, sharepath));
8121 return USERSHARE_PATH_IS_DENIED;
8126 /* If there is a usershare prefix allow list ensure one of these paths
8127 does match the start of the user given path. */
8129 if (prefixallowlist) {
8131 for ( i=0; prefixallowlist[i]; i++ ) {
8132 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
8133 servicename, i, prefixallowlist[i], sharepath ));
8134 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
8138 if (prefixallowlist[i] == NULL) {
8139 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
8140 "usershare prefix allow list entries.\n",
8141 servicename, sharepath));
8142 return USERSHARE_PATH_NOT_ALLOWED;
8146 /* Ensure this is pointing to a directory. */
8147 dp = opendir(sharepath);
8150 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8151 servicename, sharepath));
8152 return USERSHARE_PATH_NOT_DIRECTORY;
8155 /* Ensure the owner of the usershare file has permission to share
8158 if (sys_stat(sharepath, &sbuf, false) == -1) {
8159 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
8160 servicename, sharepath, strerror(errno) ));
8162 return USERSHARE_POSIX_ERR;
8167 if (!S_ISDIR(sbuf.st_ex_mode)) {
8168 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8169 servicename, sharepath ));
8170 return USERSHARE_PATH_NOT_DIRECTORY;
8173 /* Check if sharing is restricted to owner-only. */
8174 /* psbuf is the stat of the usershare definition file,
8175 sbuf is the stat of the target directory to be shared. */
8177 if (lp_usershare_owner_only()) {
8178 /* root can share anything. */
8179 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
8180 return USERSHARE_PATH_NOT_ALLOWED;
8184 *pp_sharepath = sharepath;
8185 *pp_comment = comment;
8186 return USERSHARE_OK;
8189 /***************************************************************************
8190 Deal with a usershare file.
8193 -1 - Bad name, invalid contents.
8194 - service name already existed and not a usershare, problem
8195 with permissions to share directory etc.
8196 ***************************************************************************/
8198 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
8200 SMB_STRUCT_STAT sbuf;
8201 SMB_STRUCT_STAT lsbuf;
8203 char *sharepath = NULL;
8204 char *comment = NULL;
8205 char *cp_service_name = NULL;
8206 char **lines = NULL;
8210 TALLOC_CTX *ctx = talloc_stackframe();
8211 struct security_descriptor *psd = NULL;
8212 bool guest_ok = false;
8213 char *canon_name = NULL;
8214 bool added_service = false;
8217 /* Ensure share name doesn't contain invalid characters. */
8218 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
8219 DEBUG(0,("process_usershare_file: share name %s contains "
8220 "invalid characters (any of %s)\n",
8221 file_name, INVALID_SHARENAME_CHARS ));
8225 canon_name = canonicalize_servicename(ctx, file_name);
8230 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
8235 /* Minimize the race condition by doing an lstat before we
8236 open and fstat. Ensure this isn't a symlink link. */
8238 if (sys_lstat(fname, &lsbuf, false) != 0) {
8239 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
8240 fname, strerror(errno) ));
8244 /* This must be a regular file, not a symlink, directory or
8245 other strange filetype. */
8246 if (!check_usershare_stat(fname, &lsbuf)) {
8254 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
8259 if (NT_STATUS_IS_OK(status) &&
8260 (data.dptr != NULL) &&
8261 (data.dsize == sizeof(iService))) {
8262 memcpy(&iService, data.dptr, sizeof(iService));
8266 if (iService != -1 &&
8267 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
8268 &lsbuf.st_ex_mtime) == 0) {
8269 /* Nothing changed - Mark valid and return. */
8270 DEBUG(10,("process_usershare_file: service %s not changed.\n",
8272 ServicePtrs[iService]->usershare = USERSHARE_VALID;
8277 /* Try and open the file read only - no symlinks allowed. */
8279 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
8281 fd = open(fname, O_RDONLY, 0);
8285 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
8286 fname, strerror(errno) ));
8290 /* Now fstat to be *SURE* it's a regular file. */
8291 if (sys_fstat(fd, &sbuf, false) != 0) {
8293 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
8294 fname, strerror(errno) ));
8298 /* Is it the same dev/inode as was lstated ? */
8299 if (!check_same_stat(&lsbuf, &sbuf)) {
8301 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
8302 "Symlink spoofing going on ?\n", fname ));
8306 /* This must be a regular file, not a symlink, directory or
8307 other strange filetype. */
8308 if (!check_usershare_stat(fname, &sbuf)) {
8312 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
8315 if (lines == NULL) {
8316 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
8317 fname, (unsigned int)sbuf.st_ex_uid ));
8321 if (parse_usershare_file(ctx, &sbuf, file_name,
8322 iService, lines, numlines, &sharepath,
8323 &comment, &cp_service_name,
8324 &psd, &guest_ok) != USERSHARE_OK) {
8328 /* Everything ok - add the service possibly using a template. */
8330 const struct loadparm_service *sp = &sDefault;
8331 if (snum_template != -1) {
8332 sp = ServicePtrs[snum_template];
8335 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
8336 DEBUG(0, ("process_usershare_file: Failed to add "
8337 "new service %s\n", cp_service_name));
8341 added_service = true;
8343 /* Read only is controlled by usershare ACL below. */
8344 ServicePtrs[iService]->bRead_only = false;
8347 /* Write the ACL of the new/modified share. */
8348 if (!set_share_security(canon_name, psd)) {
8349 DEBUG(0, ("process_usershare_file: Failed to set share "
8350 "security for user share %s\n",
8355 /* If from a template it may be marked invalid. */
8356 ServicePtrs[iService]->valid = true;
8358 /* Set the service as a valid usershare. */
8359 ServicePtrs[iService]->usershare = USERSHARE_VALID;
8361 /* Set guest access. */
8362 if (lp_usershare_allow_guests()) {
8363 ServicePtrs[iService]->bGuest_ok = guest_ok;
8366 /* And note when it was loaded. */
8367 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
8368 string_set(&ServicePtrs[iService]->szPath, sharepath);
8369 string_set(&ServicePtrs[iService]->comment, comment);
8375 if (ret == -1 && iService != -1 && added_service) {
8376 lp_remove_service(iService);
8384 /***************************************************************************
8385 Checks if a usershare entry has been modified since last load.
8386 ***************************************************************************/
8388 static bool usershare_exists(int iService, struct timespec *last_mod)
8390 SMB_STRUCT_STAT lsbuf;
8391 const char *usersharepath = Globals.szUsersharePath;
8394 if (asprintf(&fname, "%s/%s",
8396 ServicePtrs[iService]->szService) < 0) {
8400 if (sys_lstat(fname, &lsbuf, false) != 0) {
8405 if (!S_ISREG(lsbuf.st_ex_mode)) {
8411 *last_mod = lsbuf.st_ex_mtime;
8415 /***************************************************************************
8416 Load a usershare service by name. Returns a valid servicenumber or -1.
8417 ***************************************************************************/
8419 int load_usershare_service(const char *servicename)
8421 SMB_STRUCT_STAT sbuf;
8422 const char *usersharepath = Globals.szUsersharePath;
8423 int max_user_shares = Globals.iUsershareMaxShares;
8424 int snum_template = -1;
8426 if (*usersharepath == 0 || max_user_shares == 0) {
8430 if (sys_stat(usersharepath, &sbuf, false) != 0) {
8431 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
8432 usersharepath, strerror(errno) ));
8436 if (!S_ISDIR(sbuf.st_ex_mode)) {
8437 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
8443 * This directory must be owned by root, and have the 't' bit set.
8444 * It also must not be writable by "other".
8448 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
8450 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
8452 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
8453 "or does not have the sticky bit 't' set or is writable by anyone.\n",
8458 /* Ensure the template share exists if it's set. */
8459 if (Globals.szUsershareTemplateShare[0]) {
8460 /* We can't use lp_servicenumber here as we are recommending that
8461 template shares have -valid=false set. */
8462 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8463 if (ServicePtrs[snum_template]->szService &&
8464 strequal(ServicePtrs[snum_template]->szService,
8465 Globals.szUsershareTemplateShare)) {
8470 if (snum_template == -1) {
8471 DEBUG(0,("load_usershare_service: usershare template share %s "
8472 "does not exist.\n",
8473 Globals.szUsershareTemplateShare ));
8478 return process_usershare_file(usersharepath, servicename, snum_template);
8481 /***************************************************************************
8482 Load all user defined shares from the user share directory.
8483 We only do this if we're enumerating the share list.
8484 This is the function that can delete usershares that have
8486 ***************************************************************************/
8488 int load_usershare_shares(struct smbd_server_connection *sconn,
8489 bool (*snumused) (struct smbd_server_connection *, int))
8492 SMB_STRUCT_STAT sbuf;
8494 int num_usershares = 0;
8495 int max_user_shares = Globals.iUsershareMaxShares;
8496 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
8497 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
8498 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
8500 int snum_template = -1;
8501 const char *usersharepath = Globals.szUsersharePath;
8502 int ret = lp_numservices();
8503 TALLOC_CTX *tmp_ctx;
8505 if (max_user_shares == 0 || *usersharepath == '\0') {
8506 return lp_numservices();
8509 if (sys_stat(usersharepath, &sbuf, false) != 0) {
8510 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
8511 usersharepath, strerror(errno) ));
8516 * This directory must be owned by root, and have the 't' bit set.
8517 * It also must not be writable by "other".
8521 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
8523 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
8525 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
8526 "or does not have the sticky bit 't' set or is writable by anyone.\n",
8531 /* Ensure the template share exists if it's set. */
8532 if (Globals.szUsershareTemplateShare[0]) {
8533 /* We can't use lp_servicenumber here as we are recommending that
8534 template shares have -valid=false set. */
8535 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8536 if (ServicePtrs[snum_template]->szService &&
8537 strequal(ServicePtrs[snum_template]->szService,
8538 Globals.szUsershareTemplateShare)) {
8543 if (snum_template == -1) {
8544 DEBUG(0,("load_usershare_shares: usershare template share %s "
8545 "does not exist.\n",
8546 Globals.szUsershareTemplateShare ));
8551 /* Mark all existing usershares as pending delete. */
8552 for (iService = iNumServices - 1; iService >= 0; iService--) {
8553 if (VALID(iService) && ServicePtrs[iService]->usershare) {
8554 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
8558 dp = opendir(usersharepath);
8560 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
8561 usersharepath, strerror(errno) ));
8565 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
8567 num_dir_entries++ ) {
8569 const char *n = de->d_name;
8571 /* Ignore . and .. */
8573 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
8579 /* Temporary file used when creating a share. */
8580 num_tmp_dir_entries++;
8583 /* Allow 20% tmp entries. */
8584 if (num_tmp_dir_entries > allowed_tmp_entries) {
8585 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
8586 "in directory %s\n",
8587 num_tmp_dir_entries, usersharepath));
8591 r = process_usershare_file(usersharepath, n, snum_template);
8593 /* Update the services count. */
8595 if (num_usershares >= max_user_shares) {
8596 DEBUG(0,("load_usershare_shares: max user shares reached "
8597 "on file %s in directory %s\n",
8598 n, usersharepath ));
8601 } else if (r == -1) {
8602 num_bad_dir_entries++;
8605 /* Allow 20% bad entries. */
8606 if (num_bad_dir_entries > allowed_bad_entries) {
8607 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
8608 "in directory %s\n",
8609 num_bad_dir_entries, usersharepath));
8613 /* Allow 20% bad entries. */
8614 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
8615 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
8616 "in directory %s\n",
8617 num_dir_entries, usersharepath));
8624 /* Sweep through and delete any non-refreshed usershares that are
8625 not currently in use. */
8626 tmp_ctx = talloc_stackframe();
8627 for (iService = iNumServices - 1; iService >= 0; iService--) {
8628 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
8631 if (snumused && snumused(sconn, iService)) {
8635 servname = lp_servicename(tmp_ctx, iService);
8637 /* Remove from the share ACL db. */
8638 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
8640 delete_share_security(servname);
8641 free_service_byindex(iService);
8644 talloc_free(tmp_ctx);
8646 return lp_numservices();
8649 /********************************************************
8650 Destroy global resources allocated in this file
8651 ********************************************************/
8653 void gfree_loadparm(void)
8659 /* Free resources allocated to services */
8661 for ( i = 0; i < iNumServices; i++ ) {
8663 free_service_byindex(i);
8667 SAFE_FREE( ServicePtrs );
8670 /* Now release all resources allocated to global
8671 parameters and the default service */
8673 free_global_parameters();
8677 /***************************************************************************
8678 Allow client apps to specify that they are a client
8679 ***************************************************************************/
8680 static void lp_set_in_client(bool b)
8686 /***************************************************************************
8687 Determine if we're running in a client app
8688 ***************************************************************************/
8689 static bool lp_is_in_client(void)
8694 /***************************************************************************
8695 Load the services array from the services file. Return true on success,
8697 ***************************************************************************/
8699 static bool lp_load_ex(const char *pszFname,
8703 bool initialize_globals,
8704 bool allow_include_registry,
8705 bool load_all_shares)
8712 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
8714 bInGlobalSection = true;
8715 bGlobalOnly = global_only;
8716 bAllowIncludeRegistry = allow_include_registry;
8718 init_globals(initialize_globals);
8722 if (save_defaults) {
8727 if (!initialize_globals) {
8728 free_param_opts(&Globals.param_opt);
8729 apply_lp_set_cmdline();
8732 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
8734 /* We get sections first, so have to start 'behind' to make up */
8737 if (lp_config_backend_is_file()) {
8738 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
8739 current_user_info.domain,
8742 smb_panic("lp_load_ex: out of memory");
8745 add_to_file_list(pszFname, n2);
8747 bRetval = pm_process(n2, do_section, do_parameter, NULL);
8750 /* finish up the last section */
8751 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
8753 if (iServiceIndex >= 0) {
8754 bRetval = service_ok(iServiceIndex);
8758 if (lp_config_backend_is_registry()) {
8759 /* config backend changed to registry in config file */
8761 * We need to use this extra global variable here to
8762 * survive restart: init_globals uses this as a default
8763 * for ConfigBackend. Otherwise, init_globals would
8764 * send us into an endless loop here.
8766 config_backend = CONFIG_BACKEND_REGISTRY;
8768 DEBUG(1, ("lp_load_ex: changing to config backend "
8771 lp_kill_all_services();
8772 return lp_load_ex(pszFname, global_only, save_defaults,
8773 add_ipc, initialize_globals,
8774 allow_include_registry,
8777 } else if (lp_config_backend_is_registry()) {
8778 bRetval = process_registry_globals();
8780 DEBUG(0, ("Illegal config backend given: %d\n",
8781 lp_config_backend()));
8785 if (bRetval && lp_registry_shares()) {
8786 if (load_all_shares) {
8787 bRetval = process_registry_shares();
8789 bRetval = reload_registry_shares();
8794 char *serv = lp_auto_services(talloc_tos());
8795 lp_add_auto_services(serv);
8800 /* When 'restrict anonymous = 2' guest connections to ipc$
8802 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
8803 if ( lp_enable_asu_support() ) {
8804 lp_add_ipc("ADMIN$", false);
8808 set_allowed_client_auth();
8810 if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
8811 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
8812 lp_passwordserver()));
8817 /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
8818 /* if bWINSsupport is true and we are in the client */
8819 if (lp_is_in_client() && Globals.bWINSsupport) {
8820 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
8825 fault_configure(smb_panic_s3);
8827 bAllowIncludeRegistry = true;
8832 bool lp_load(const char *pszFname,
8836 bool initialize_globals)
8838 return lp_load_ex(pszFname,
8843 true, /* allow_include_registry */
8844 false); /* load_all_shares*/
8847 bool lp_load_initial_only(const char *pszFname)
8849 return lp_load_ex(pszFname,
8850 true, /* global only */
8851 false, /* save_defaults */
8852 false, /* add_ipc */
8853 true, /* initialize_globals */
8854 false, /* allow_include_registry */
8855 false); /* load_all_shares*/
8859 * most common lp_load wrapper, loading only the globals
8861 bool lp_load_global(const char *file_name)
8863 return lp_load_ex(file_name,
8864 true, /* global_only */
8865 false, /* save_defaults */
8866 false, /* add_ipc */
8867 true, /* initialize_globals */
8868 true, /* allow_include_registry */
8869 false); /* load_all_shares*/
8873 * lp_load wrapper, especially for clients
8875 bool lp_load_client(const char *file_name)
8877 lp_set_in_client(true);
8879 return lp_load_global(file_name);
8883 * lp_load wrapper, loading only globals, but intended
8884 * for subsequent calls, not reinitializing the globals
8887 bool lp_load_global_no_reinit(const char *file_name)
8889 return lp_load_ex(file_name,
8890 true, /* global_only */
8891 false, /* save_defaults */
8892 false, /* add_ipc */
8893 false, /* initialize_globals */
8894 true, /* allow_include_registry */
8895 false); /* load_all_shares*/
8899 * lp_load wrapper, especially for clients, no reinitialization
8901 bool lp_load_client_no_reinit(const char *file_name)
8903 lp_set_in_client(true);
8905 return lp_load_global_no_reinit(file_name);
8908 bool lp_load_with_registry_shares(const char *pszFname,
8912 bool initialize_globals)
8914 return lp_load_ex(pszFname,
8919 true, /* allow_include_registry */
8920 true); /* load_all_shares*/
8923 /***************************************************************************
8924 Return the max number of services.
8925 ***************************************************************************/
8927 int lp_numservices(void)
8929 return (iNumServices);
8932 /***************************************************************************
8933 Display the contents of the services array in human-readable form.
8934 ***************************************************************************/
8936 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
8941 defaults_saved = false;
8945 dump_a_service(&sDefault, f);
8947 for (iService = 0; iService < maxtoprint; iService++) {
8949 lp_dump_one(f, show_defaults, iService);
8953 /***************************************************************************
8954 Display the contents of one service in human-readable form.
8955 ***************************************************************************/
8957 void lp_dump_one(FILE * f, bool show_defaults, int snum)
8960 if (ServicePtrs[snum]->szService[0] == '\0')
8962 dump_a_service(ServicePtrs[snum], f);
8966 /***************************************************************************
8967 Return the number of the service with the given name, or -1 if it doesn't
8968 exist. Note that this is a DIFFERENT ANIMAL from the internal function
8969 getservicebyname()! This works ONLY if all services have been loaded, and
8970 does not copy the found service.
8971 ***************************************************************************/
8973 int lp_servicenumber(const char *pszServiceName)
8976 fstring serviceName;
8978 if (!pszServiceName) {
8979 return GLOBAL_SECTION_SNUM;
8982 for (iService = iNumServices - 1; iService >= 0; iService--) {
8983 if (VALID(iService) && ServicePtrs[iService]->szService) {
8985 * The substitution here is used to support %U is
8988 fstrcpy(serviceName, ServicePtrs[iService]->szService);
8989 standard_sub_basic(get_current_username(),
8990 current_user_info.domain,
8991 serviceName,sizeof(serviceName));
8992 if (strequal(serviceName, pszServiceName)) {
8998 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
8999 struct timespec last_mod;
9001 if (!usershare_exists(iService, &last_mod)) {
9002 /* Remove the share security tdb entry for it. */
9003 delete_share_security(lp_servicename(talloc_tos(), iService));
9004 /* Remove it from the array. */
9005 free_service_byindex(iService);
9006 /* Doesn't exist anymore. */
9007 return GLOBAL_SECTION_SNUM;
9010 /* Has it been modified ? If so delete and reload. */
9011 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
9013 /* Remove it from the array. */
9014 free_service_byindex(iService);
9015 /* and now reload it. */
9016 iService = load_usershare_service(pszServiceName);
9021 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
9022 return GLOBAL_SECTION_SNUM;
9028 /*******************************************************************
9029 A useful volume label function.
9030 ********************************************************************/
9032 const char *volume_label(TALLOC_CTX *ctx, int snum)
9035 const char *label = lp_volume(ctx, snum);
9037 label = lp_servicename(ctx, snum);
9040 /* This returns a 33 byte guarenteed null terminated string. */
9041 ret = talloc_strndup(ctx, label, 32);
9048 /*******************************************************************
9049 Get the default server type we will announce as via nmbd.
9050 ********************************************************************/
9052 int lp_default_server_announce(void)
9054 int default_server_announce = 0;
9055 default_server_announce |= SV_TYPE_WORKSTATION;
9056 default_server_announce |= SV_TYPE_SERVER;
9057 default_server_announce |= SV_TYPE_SERVER_UNIX;
9059 /* note that the flag should be set only if we have a
9060 printer service but nmbd doesn't actually load the
9061 services so we can't tell --jerry */
9063 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
9065 default_server_announce |= SV_TYPE_SERVER_NT;
9066 default_server_announce |= SV_TYPE_NT;
9068 switch (lp_server_role()) {
9069 case ROLE_DOMAIN_MEMBER:
9070 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
9072 case ROLE_DOMAIN_PDC:
9073 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
9075 case ROLE_DOMAIN_BDC:
9076 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
9078 case ROLE_STANDALONE:
9082 if (lp_time_server())
9083 default_server_announce |= SV_TYPE_TIME_SOURCE;
9085 if (lp_host_msdfs())
9086 default_server_announce |= SV_TYPE_DFS_SERVER;
9088 return default_server_announce;
9091 /***********************************************************
9092 If we are PDC then prefer us as DMB
9093 ************************************************************/
9095 bool lp_domain_master(void)
9097 if (Globals.iDomainMaster == Auto)
9098 return (lp_server_role() == ROLE_DOMAIN_PDC);
9100 return (bool)Globals.iDomainMaster;
9103 /***********************************************************
9104 If we are PDC then prefer us as DMB
9105 ************************************************************/
9107 static bool lp_domain_master_true_or_auto(void)
9109 if (Globals.iDomainMaster) /* auto or yes */
9115 /***********************************************************
9116 If we are DMB then prefer us as LMB
9117 ************************************************************/
9119 bool lp_preferred_master(void)
9121 if (Globals.iPreferredMaster == Auto)
9122 return (lp_local_master() && lp_domain_master());
9124 return (bool)Globals.iPreferredMaster;
9127 /*******************************************************************
9129 ********************************************************************/
9131 void lp_remove_service(int snum)
9133 ServicePtrs[snum]->valid = false;
9134 invalid_services[num_invalid_services++] = snum;
9137 /*******************************************************************
9139 ********************************************************************/
9141 void lp_copy_service(int snum, const char *new_name)
9143 do_section(new_name, NULL);
9145 snum = lp_servicenumber(new_name);
9147 char *name = lp_servicename(talloc_tos(), snum);
9148 lp_do_parameter(snum, "copy", name);
9154 /***********************************************************
9155 Set the global name resolution order (used in smbclient).
9156 ************************************************************/
9158 void lp_set_name_resolve_order(const char *new_order)
9160 string_set(&Globals.szNameResolveOrder, new_order);
9163 const char *lp_printername(TALLOC_CTX *ctx, int snum)
9165 const char *ret = lp__printername(talloc_tos(), snum);
9166 if (ret == NULL || *ret == '\0') {
9167 ret = lp_const_servicename(snum);
9174 /***********************************************************
9175 Allow daemons such as winbindd to fix their logfile name.
9176 ************************************************************/
9178 void lp_set_logfile(const char *name)
9180 string_set(&Globals.logfile, name);
9181 debug_set_logfile(name);
9184 /*******************************************************************
9185 Return the max print jobs per queue.
9186 ********************************************************************/
9188 int lp_maxprintjobs(int snum)
9190 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
9191 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
9192 maxjobs = PRINT_MAX_JOBID - 1;
9197 const char *lp_printcapname(void)
9199 if ((Globals.szPrintcapname != NULL) &&
9200 (Globals.szPrintcapname[0] != '\0'))
9201 return Globals.szPrintcapname;
9203 if (sDefault.iPrinting == PRINT_CUPS) {
9211 if (sDefault.iPrinting == PRINT_BSD)
9212 return "/etc/printcap";
9214 return PRINTCAP_NAME;
9217 static uint32 spoolss_state;
9219 bool lp_disable_spoolss( void )
9221 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
9222 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9224 return spoolss_state == SVCCTL_STOPPED ? true : false;
9227 void lp_set_spoolss_state( uint32 state )
9229 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
9231 spoolss_state = state;
9234 uint32 lp_get_spoolss_state( void )
9236 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9239 /*******************************************************************
9240 Ensure we don't use sendfile if server smb signing is active.
9241 ********************************************************************/
9243 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
9245 bool sign_active = false;
9247 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
9248 if (get_Protocol() < PROTOCOL_NT1) {
9251 if (signing_state) {
9252 sign_active = smb_signing_is_active(signing_state);
9254 return (lp__use_sendfile(snum) &&
9255 (get_remote_arch() != RA_WIN95) &&
9259 /*******************************************************************
9260 Turn off sendfile if we find the underlying OS doesn't support it.
9261 ********************************************************************/
9263 void set_use_sendfile(int snum, bool val)
9265 if (LP_SNUM_OK(snum))
9266 ServicePtrs[snum]->bUseSendfile = val;
9268 sDefault.bUseSendfile = val;
9271 /*******************************************************************
9272 Turn off storing DOS attributes if this share doesn't support it.
9273 ********************************************************************/
9275 void set_store_dos_attributes(int snum, bool val)
9277 if (!LP_SNUM_OK(snum))
9279 ServicePtrs[(snum)]->bStoreDosAttributes = val;
9282 void lp_set_mangling_method(const char *new_method)
9284 string_set(&Globals.szManglingMethod, new_method);
9287 /*******************************************************************
9288 Global state for POSIX pathname processing.
9289 ********************************************************************/
9291 static bool posix_pathnames;
9293 bool lp_posix_pathnames(void)
9295 return posix_pathnames;
9298 /*******************************************************************
9299 Change everything needed to ensure POSIX pathname processing (currently
9301 ********************************************************************/
9303 void lp_set_posix_pathnames(void)
9305 posix_pathnames = true;
9308 /*******************************************************************
9309 Global state for POSIX lock processing - CIFS unix extensions.
9310 ********************************************************************/
9312 bool posix_default_lock_was_set;
9313 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
9315 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
9317 if (posix_default_lock_was_set) {
9318 return posix_cifsx_locktype;
9320 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
9324 /*******************************************************************
9325 ********************************************************************/
9327 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
9329 posix_default_lock_was_set = true;
9330 posix_cifsx_locktype = val;
9333 int lp_min_receive_file_size(void)
9335 if (Globals.iminreceivefile < 0) {
9338 return MIN(Globals.iminreceivefile, BUFFER_SIZE);
9341 /*******************************************************************
9342 If socket address is an empty character string, it is necessary to
9343 define it as "0.0.0.0".
9344 ********************************************************************/
9346 const char *lp_socket_address(void)
9348 char *sock_addr = Globals.szSocketAddress;
9350 if (sock_addr[0] == '\0'){
9351 string_set(&Globals.szSocketAddress, "0.0.0.0");
9353 return Globals.szSocketAddress;
9356 /*******************************************************************
9357 Safe wide links checks.
9358 This helper function always verify the validity of wide links,
9359 even after a configuration file reload.
9360 ********************************************************************/
9362 static bool lp_widelinks_internal(int snum)
9364 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
9365 sDefault.bWidelinks);
9368 void widelinks_warning(int snum)
9370 if (lp_allow_insecure_widelinks()) {
9374 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
9375 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
9376 "These parameters are incompatible. "
9377 "Wide links will be disabled for this share.\n",
9378 lp_servicename(talloc_tos(), snum) ));
9382 bool lp_widelinks(int snum)
9384 /* wide links is always incompatible with unix extensions */
9385 if (lp_unix_extensions()) {
9387 * Unless we have "allow insecure widelinks"
9390 if (!lp_allow_insecure_widelinks()) {
9395 return lp_widelinks_internal(snum);
9398 bool lp_writeraw(void)
9400 if (lp_async_smb_echo_handler()) {
9403 return lp__writeraw();
9406 bool lp_readraw(void)
9408 if (lp_async_smb_echo_handler()) {
9411 return lp__readraw();
9414 int lp_server_role(void)
9416 return lp_find_server_role(lp__server_role(),
9419 lp_domain_master_true_or_auto());
9422 const char *lp_ctdbd_socket(void)
9424 const char *result = lp__ctdbd_socket();
9426 #ifdef CLUSTER_SUPPORT
9427 if ((result == NULL) || (*result == '\0')) {