2 Unix SMB/CIFS implementation.
3 Parameter loading functions
4 Copyright (C) Karl Auer 1993-1998
6 Largely re-written by Andrew Tridgell, September 1994
8 Copyright (C) Simo Sorce 2001
9 Copyright (C) Alexander Bokovoy 2002
10 Copyright (C) Stefan (metze) Metzmacher 2002
11 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12 Copyright (C) Michael Adam 2008
13 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14 Copyright (C) Andrew Bartlett 2011
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 3 of the License, or
19 (at your option) any later version.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
33 * This module provides suitable callback functions for the params
34 * module. It builds the internal table of service details which is
35 * then used by the rest of the server.
39 * 1) add it to the global or service structure definition
40 * 2) add it to the parm_table
41 * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42 * 4) If it's a global then initialise it in init_globals. If a local
43 * (ie. service) parameter then initialise it in the sDefault structure
47 * The configuration file is processed sequentially for speed. It is NOT
48 * accessed randomly as happens in 'real' Windows. For this reason, there
49 * is a fair bit of sequence-dependent code here - ie., code which assumes
50 * that certain things happen before others. In particular, the code which
51 * happens at the boundary between sections is delicately poised, so be
57 #include "system/filesys.h"
59 #include "lib/param/loadparm.h"
61 #include "lib/smbconf/smbconf.h"
62 #include "lib/smbconf/smbconf_init.h"
65 #include "../librpc/gen_ndr/svcctl.h"
67 #include "../libcli/smb/smb_signing.h"
68 #include "dbwrap/dbwrap.h"
69 #include "dbwrap/dbwrap_rbt.h"
70 #include "../lib/util/bitmap.h"
72 #ifdef HAVE_SYS_SYSCTL_H
73 #include <sys/sysctl.h>
76 #ifdef HAVE_HTTPCONNECTENCRYPT
77 #include <cups/http.h>
80 #ifdef CLUSTER_SUPPORT
81 #include "ctdb_private.h"
86 extern userdom_struct current_user_info;
88 /* the special value for the include parameter
89 * to be interpreted not as a file name but to
90 * trigger loading of the global smb.conf options
92 #ifndef INCLUDE_REGISTRY_NAME
93 #define INCLUDE_REGISTRY_NAME "registry"
96 static bool in_client = false; /* Not in the client by default */
97 static struct smbconf_csn conf_last_csn;
99 static int config_backend = CONFIG_BACKEND_FILE;
101 /* some helpful bits */
102 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
103 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
105 #define USERSHARE_VALID 1
106 #define USERSHARE_PENDING_DELETE 2
108 static bool defaults_saved = false;
110 #define LOADPARM_EXTRA_GLOBALS \
111 struct parmlist_entry *param_opt; \
114 int iminreceivefile; \
115 char *szPrintcapname; \
117 int iPreferredMaster; \
118 char *szLdapMachineSuffix; \
119 char *szLdapUserSuffix; \
120 char *szLdapIdmapSuffix; \
121 char *szLdapGroupSuffix; \
124 char *szUsershareTemplateShare; \
127 int winbindMaxDomainConnections; \
128 int ismb2_max_credits; \
130 char *tls_certfile; \
134 char *panic_action; \
135 int bPreferredMaster;
137 #include "param/param_global.h"
139 static struct loadparm_global Globals;
141 /* This is a default service used to prime a services structure */
142 static struct loadparm_service sDefault =
147 .usershare_last_mod = {0, 0},
151 .szInvalidUsers = NULL,
152 .szValidUsers = NULL,
153 .szAdminUsers = NULL,
158 .szRootPreExec = NULL,
159 .szRootPostExec = NULL,
160 .szCupsOptions = NULL,
161 .szPrintcommand = NULL,
162 .szLpqcommand = NULL,
163 .szLprmcommand = NULL,
164 .szLppausecommand = NULL,
165 .szLpresumecommand = NULL,
166 .szQueuepausecommand = NULL,
167 .szQueueresumecommand = NULL,
168 .szPrintername = NULL,
169 .szPrintjobUsername = NULL,
170 .szDontdescend = NULL,
171 .szHostsallow = NULL,
173 .szMagicScript = NULL,
174 .szMagicOutput = NULL,
177 .szVetoOplockFiles = NULL,
185 .szVfsObjects = NULL,
186 .szMSDfsProxy = NULL,
187 .szAioWriteBehind = NULL,
190 .iMaxPrintJobs = 1000,
191 .iMaxReportedPrintJobs = 0,
192 .iWriteCacheSize = 0,
193 .iCreate_mask = 0744,
194 .iCreate_force_mode = 0,
195 .iSecurity_mask = 0777,
196 .iSecurity_force_mode = 0,
198 .iDir_force_mode = 0,
199 .iDir_Security_mask = 0777,
200 .iDir_Security_force_mode = 0,
201 .iMaxConnections = 0,
202 .iDefaultCase = CASE_LOWER,
203 .iPrinting = DEFAULT_PRINTING,
204 .iOplockContentionLimit = 2,
207 .iDfreeCacheTime = 0,
208 .bPreexecClose = false,
209 .bRootpreexecClose = false,
210 .iCaseSensitive = Auto,
211 .bCasePreserve = true,
212 .bShortCasePreserve = true,
213 .bHideDotFiles = true,
214 .bHideSpecialFiles = false,
215 .bHideUnReadable = false,
216 .bHideUnWriteableFiles = false,
218 .bAccessBasedShareEnum = false,
222 .bGuest_only = false,
223 .bAdministrative_share = false,
226 .bPrintNotifyBackchannel = true,
227 .bMap_system = false,
228 .bMap_hidden = false,
229 .bMap_archive = true,
230 .bStoreDosAttributes = false,
231 .bDmapiSupport = false,
233 .iStrictLocking = Auto,
234 .bPosixLocking = true,
237 .bKernelOplocks = false,
238 .bLevel2OpLocks = true,
240 .bMangledNames = true,
243 .bSyncAlways = false,
244 .bStrictAllocate = false,
245 .bStrictSync = false,
248 .bDeleteReadonly = false,
249 .bFakeOplocks = false,
250 .bDeleteVetoFiles = false,
251 .bDosFilemode = false,
252 .bDosFiletimes = true,
253 .bDosFiletimeResolution = false,
254 .bFakeDirCreateTimes = false,
255 .bBlockingLocks = true,
256 .bInheritPerms = false,
257 .bInheritACLS = false,
258 .bInheritOwner = false,
260 .bUseClientDriver = false,
261 .bDefaultDevmode = true,
262 .bForcePrintername = false,
263 .bNTAclSupport = true,
264 .bForceUnknownAclUser = false,
265 .bUseSendfile = false,
266 .bProfileAcls = false,
267 .bMap_acl_inherit = false,
270 .bAclCheckPermissions = true,
271 .bAclMapFullControl = true,
272 .bAclGroupControl = false,
273 .bChangeNotify = true,
274 .bKernelChangeNotify = true,
275 .iallocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
278 .iMap_readonly = MAP_READONLY_YES,
279 #ifdef BROKEN_DIRECTORY_HANDLING
280 .iDirectoryNameCacheSize = 0,
282 .iDirectoryNameCacheSize = 100,
284 .ismb_encrypt = SMB_SIGNING_DEFAULT,
289 /* local variables */
290 static struct loadparm_service **ServicePtrs = NULL;
291 static int iNumServices = 0;
292 static int iServiceIndex = 0;
293 static struct db_context *ServiceHash;
294 static int *invalid_services = NULL;
295 static int num_invalid_services = 0;
296 static bool bInGlobalSection = true;
297 static bool bGlobalOnly = false;
299 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
301 /* prototypes for the special type handlers */
302 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
303 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
304 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
305 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
306 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
307 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
308 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
309 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
310 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
311 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
312 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
313 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
315 /* these are parameter handlers which are not needed in the
319 #define handle_logfile NULL
321 static void set_allowed_client_auth(void);
323 static void add_to_file_list(const char *fname, const char *subfname);
324 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
325 static void free_param_opts(struct parmlist_entry **popts);
327 #include "lib/param/param_table.c"
329 /* this is used to prevent lots of mallocs of size 1 */
330 static const char null_string[] = "";
333 Set a string value, allocing the space for the string
336 static bool string_init(char **dest,const char *src)
346 *dest = discard_const_p(char, null_string);
348 (*dest) = SMB_STRDUP(src);
349 if ((*dest) == NULL) {
350 DEBUG(0,("Out of memory in string_init\n"));
361 static void string_free(char **s)
365 if (*s == null_string)
371 Set a string value, deallocating any existing space, and allocing the space
375 static bool string_set(char **dest,const char *src)
378 return(string_init(dest,src));
381 /***************************************************************************
382 Initialise the sDefault parameter structure for the printer values.
383 ***************************************************************************/
385 static void init_printer_values(struct loadparm_service *pService)
387 /* choose defaults depending on the type of printing */
388 switch (pService->iPrinting) {
393 string_set(&pService->szLpqcommand, "lpq -P'%p'");
394 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
395 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
400 string_set(&pService->szLpqcommand, "lpq -P'%p'");
401 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
402 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
403 string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
404 string_set(&pService->szQueueresumecommand, "lpc start '%p'");
405 string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
406 string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
411 /* set the lpq command to contain the destination printer
412 name only. This is used by cups_queue_get() */
413 string_set(&pService->szLpqcommand, "%p");
414 string_set(&pService->szLprmcommand, "");
415 string_set(&pService->szPrintcommand, "");
416 string_set(&pService->szLppausecommand, "");
417 string_set(&pService->szLpresumecommand, "");
418 string_set(&pService->szQueuepausecommand, "");
419 string_set(&pService->szQueueresumecommand, "");
424 string_set(&pService->szLpqcommand, "lpstat -o%p");
425 string_set(&pService->szLprmcommand, "cancel %p-%j");
426 string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
427 string_set(&pService->szQueuepausecommand, "disable %p");
428 string_set(&pService->szQueueresumecommand, "enable %p");
430 string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
431 string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
436 string_set(&pService->szLpqcommand, "lpq -P%p");
437 string_set(&pService->szLprmcommand, "lprm -P%p %j");
438 string_set(&pService->szPrintcommand, "lp -r -P%p %s");
441 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
446 TALLOC_CTX *tmp_ctx = talloc_stackframe();
449 tdbfile = talloc_asprintf(
450 tmp_ctx, "tdbfile=%s",
451 lp_parm_const_string(-1, "vlp", "tdbfile",
453 if (tdbfile == NULL) {
454 tdbfile="tdbfile=/tmp/vlp.tdb";
457 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
459 string_set(&pService->szPrintcommand,
460 tmp ? tmp : "vlp print %p %s");
462 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
464 string_set(&pService->szLpqcommand,
465 tmp ? tmp : "vlp lpq %p");
467 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
469 string_set(&pService->szLprmcommand,
470 tmp ? tmp : "vlp lprm %p %j");
472 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
474 string_set(&pService->szLppausecommand,
475 tmp ? tmp : "vlp lppause %p %j");
477 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
479 string_set(&pService->szLpresumecommand,
480 tmp ? tmp : "vlp lpresume %p %j");
482 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
484 string_set(&pService->szQueuepausecommand,
485 tmp ? tmp : "vlp queuepause %p");
487 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
489 string_set(&pService->szQueueresumecommand,
490 tmp ? tmp : "vlp queueresume %p");
491 TALLOC_FREE(tmp_ctx);
495 #endif /* DEVELOPER */
500 * Function to return the default value for the maximum number of open
501 * file descriptors permitted. This function tries to consult the
502 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
503 * the smaller of those.
505 static int max_open_files(void)
507 int sysctl_max = MAX_OPEN_FILES;
508 int rlimit_max = MAX_OPEN_FILES;
510 #ifdef HAVE_SYSCTLBYNAME
512 size_t size = sizeof(sysctl_max);
513 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
518 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
524 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
525 rlimit_max = rl.rlim_cur;
527 #if defined(RLIM_INFINITY)
528 if(rl.rlim_cur == RLIM_INFINITY)
529 rlimit_max = MAX_OPEN_FILES;
534 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
535 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
536 "minimum Windows limit (%d)\n",
538 MIN_OPEN_FILES_WINDOWS));
539 sysctl_max = MIN_OPEN_FILES_WINDOWS;
542 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
543 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
544 "minimum Windows limit (%d)\n",
546 MIN_OPEN_FILES_WINDOWS));
547 rlimit_max = MIN_OPEN_FILES_WINDOWS;
550 return MIN(sysctl_max, rlimit_max);
554 * Common part of freeing allocated data for one parameter.
556 static void free_one_parameter_common(void *parm_ptr,
557 struct parm_struct parm)
559 if ((parm.type == P_STRING) ||
560 (parm.type == P_USTRING))
562 string_free((char**)parm_ptr);
563 } else if (parm.type == P_LIST) {
564 TALLOC_FREE(*((char***)parm_ptr));
569 * Free the allocated data for one parameter for a share
570 * given as a service struct.
572 static void free_one_parameter(struct loadparm_service *service,
573 struct parm_struct parm)
577 if (parm.p_class != P_LOCAL) {
581 parm_ptr = lp_parm_ptr(service, &parm);
583 free_one_parameter_common(parm_ptr, parm);
587 * Free the allocated parameter data of a share given
588 * as a service struct.
590 static void free_parameters(struct loadparm_service *service)
594 for (i=0; parm_table[i].label; i++) {
595 free_one_parameter(service, parm_table[i]);
600 * Free the allocated data for one parameter for a given share
601 * specified by an snum.
603 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
608 parm_ptr = lp_parm_ptr(NULL, &parm);
609 } else if (parm.p_class != P_LOCAL) {
612 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
615 free_one_parameter_common(parm_ptr, parm);
619 * Free the allocated parameter data for a share specified
622 static void free_parameters_by_snum(int snum)
626 for (i=0; parm_table[i].label; i++) {
627 free_one_parameter_by_snum(snum, parm_table[i]);
632 * Free the allocated global parameters.
634 static void free_global_parameters(void)
636 free_param_opts(&Globals.param_opt);
637 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
638 TALLOC_FREE(Globals.ctx);
641 static int map_parameter(const char *pszParmName);
643 struct lp_stored_option {
644 struct lp_stored_option *prev, *next;
649 static struct lp_stored_option *stored_options;
652 save options set by lp_set_cmdline() into a list. This list is
653 re-applied when we do a globals reset, so that cmdline set options
654 are sticky across reloads of smb.conf
656 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
658 struct lp_stored_option *entry, *entry_next;
659 for (entry = stored_options; entry != NULL; entry = entry_next) {
660 entry_next = entry->next;
661 if (strcmp(pszParmName, entry->label) == 0) {
662 DLIST_REMOVE(stored_options, entry);
668 entry = talloc(NULL, struct lp_stored_option);
673 entry->label = talloc_strdup(entry, pszParmName);
679 entry->value = talloc_strdup(entry, pszParmValue);
685 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
690 static bool apply_lp_set_cmdline(void)
692 struct lp_stored_option *entry = NULL;
693 for (entry = stored_options; entry != NULL; entry = entry->next) {
694 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
695 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
696 entry->label, entry->value));
703 /***************************************************************************
704 Initialise the global parameter structure.
705 ***************************************************************************/
707 static void init_globals(bool reinit_globals)
709 static bool done_init = false;
713 /* If requested to initialize only once and we've already done it... */
714 if (!reinit_globals && done_init) {
715 /* ... then we have nothing more to do */
720 /* The logfile can be set before this is invoked. Free it if so. */
721 if (Globals.logfile != NULL) {
722 string_free(&Globals.logfile);
723 Globals.logfile = NULL;
727 free_global_parameters();
730 /* This memset and the free_global_parameters() above will
731 * wipe out smb.conf options set with lp_set_cmdline(). The
732 * apply_lp_set_cmdline() call puts these values back in the
733 * table once the defaults are set */
734 ZERO_STRUCT(Globals);
736 Globals.ctx = talloc_new(NULL);
738 for (i = 0; parm_table[i].label; i++) {
739 if ((parm_table[i].type == P_STRING ||
740 parm_table[i].type == P_USTRING))
742 string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
747 string_set(&sDefault.fstype, FSTYPE_STRING);
748 string_set(&sDefault.szPrintjobUsername, "%U");
750 init_printer_values(&sDefault);
753 DEBUG(3, ("Initialising global parameters\n"));
755 /* Must manually force to upper case here, as this does not go via the handler */
756 string_set(&Globals.szNetbiosName, myhostname_upper());
758 string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
759 string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
761 /* use the new 'hash2' method by default, with a prefix of 1 */
762 string_set(&Globals.szManglingMethod, "hash2");
763 Globals.mangle_prefix = 1;
765 string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
767 /* using UTF8 by default allows us to support all chars */
768 string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
770 /* Use codepage 850 as a default for the dos character set */
771 string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
774 * Allow the default PASSWD_CHAT to be overridden in local.h.
776 string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
778 string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
780 string_set(&Globals.szPasswdProgram, "");
781 string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
782 string_set(&Globals.szStateDir, get_dyn_STATEDIR());
783 string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
784 string_set(&Globals.szPidDir, get_dyn_PIDDIR());
785 string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
787 * By default support explicit binding to broadcast
790 Globals.bNmbdBindExplicitBroadcast = true;
792 if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
793 smb_panic("init_globals: ENOMEM");
795 string_set(&Globals.szServerString, s);
798 string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
801 string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
803 string_set(&Globals.szLogonDrive, "");
804 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
805 string_set(&Globals.szLogonHome, "\\\\%N\\%U");
806 string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
808 Globals.szNameResolveOrder = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
809 string_set(&Globals.szPasswordServer, "*");
811 Globals.AlgorithmicRidBase = BASE_RID;
813 Globals.bLoadPrinters = true;
814 Globals.PrintcapCacheTime = 750; /* 12.5 minutes */
816 Globals.ConfigBackend = config_backend;
817 Globals.server_role = ROLE_AUTO;
819 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
820 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
821 Globals.max_xmit = 0x4104;
822 Globals.max_mux = 50; /* This is *needed* for profile support. */
823 Globals.lpqcachetime = 30; /* changed to handle large print servers better -- jerry */
824 Globals.bDisableSpoolss = false;
825 Globals.iMaxSmbdProcesses = 0;/* no limit specified */
826 Globals.pwordlevel = 0;
827 Globals.unamelevel = 0;
828 Globals.deadtime = 0;
829 Globals.getwd_cache = true;
830 Globals.bLargeReadwrite = true;
831 Globals.max_log_size = 5000;
832 Globals.max_open_files = max_open_files();
833 Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
834 Globals.srv_maxprotocol = PROTOCOL_SMB3_00;
835 Globals.srv_minprotocol = PROTOCOL_LANMAN1;
836 Globals.security = SEC_USER;
837 Globals.bEncryptPasswords = true;
838 Globals.clientSchannel = Auto;
839 Globals.serverSchannel = Auto;
840 Globals.bReadRaw = true;
841 Globals.bWriteRaw = true;
842 Globals.bNullPasswords = false;
843 Globals.bObeyPamRestrictions = false;
845 Globals.bSyslogOnly = false;
846 Globals.bTimestampLogs = true;
847 string_set(&Globals.loglevel, "0");
848 Globals.bDebugPrefixTimestamp = false;
849 Globals.bDebugHiresTimestamp = true;
850 Globals.bDebugPid = false;
851 Globals.bDebugUid = false;
852 Globals.bDebugClass = false;
853 Globals.bEnableCoreFiles = true;
854 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
855 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
856 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
857 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
858 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
859 Globals.lm_interval = 60;
860 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
861 Globals.bNISHomeMap = false;
862 #ifdef WITH_NISPLUS_HOME
863 string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
865 string_set(&Globals.szNISHomeMapName, "auto.home");
868 Globals.bTimeServer = false;
869 Globals.bBindInterfacesOnly = false;
870 Globals.bUnixPasswdSync = false;
871 Globals.bPamPasswordChange = false;
872 Globals.bPasswdChatDebug = false;
873 Globals.iPasswdChatTimeout = 2; /* 2 second default. */
874 Globals.bNTPipeSupport = true; /* Do NT pipes by default. */
875 Globals.bNTStatusSupport = true; /* Use NT status by default. */
876 Globals.bStatCache = true; /* use stat cache by default */
877 Globals.iMaxStatCacheSize = 256; /* 256k by default */
878 Globals.restrict_anonymous = 0;
879 Globals.bClientLanManAuth = false; /* Do NOT use the LanMan hash if it is available */
880 Globals.bClientPlaintextAuth = false; /* Do NOT use a plaintext password even if is requested by the server */
881 Globals.bLanmanAuth = false; /* Do NOT use the LanMan hash, even if it is supplied */
882 Globals.bNTLMAuth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
883 Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
884 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
886 Globals.map_to_guest = 0; /* By Default, "Never" */
887 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
888 Globals.enhanced_browsing = true;
889 Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
890 #ifdef MMAP_BLACKLIST
891 Globals.bUseMmap = false;
893 Globals.bUseMmap = true;
895 Globals.bUnicode = true;
896 Globals.bUnixExtensions = true;
897 Globals.bResetOnZeroVC = false;
898 Globals.bLogWriteableFilesOnExit = false;
899 Globals.bCreateKrb5Conf = true;
900 Globals.winbindMaxDomainConnections = 1;
902 /* hostname lookups can be very expensive and are broken on
903 a large number of sites (tridge) */
904 Globals.bHostnameLookups = false;
906 string_set(&Globals.passdb_backend, "tdbsam");
907 string_set(&Globals.szLdapSuffix, "");
908 string_set(&Globals.szLdapMachineSuffix, "");
909 string_set(&Globals.szLdapUserSuffix, "");
910 string_set(&Globals.szLdapGroupSuffix, "");
911 string_set(&Globals.szLdapIdmapSuffix, "");
913 string_set(&Globals.szLdapAdminDn, "");
914 Globals.ldap_ssl = LDAP_SSL_START_TLS;
915 Globals.ldap_ssl_ads = false;
916 Globals.ldap_deref = -1;
917 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
918 Globals.ldap_delete_dn = false;
919 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
920 Globals.ldap_follow_referral = Auto;
921 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
922 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
923 Globals.ldap_page_size = LDAP_PAGE_SIZE;
925 Globals.ldap_debug_level = 0;
926 Globals.ldap_debug_threshold = 10;
928 /* This is what we tell the afs client. in reality we set the token
929 * to never expire, though, when this runs out the afs client will
930 * forget the token. Set to 0 to get NEVERDATE.*/
931 Globals.iAfsTokenLifetime = 604800;
932 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
934 /* these parameters are set to defaults that are more appropriate
935 for the increasing samba install base:
937 as a member of the workgroup, that will possibly become a
938 _local_ master browser (lm = true). this is opposed to a forced
939 local master browser startup (pm = true).
941 doesn't provide WINS server service by default (wsupp = false),
942 and doesn't provide domain master browser services by default, either.
946 Globals.bMsAddPrinterWizard = true;
947 Globals.os_level = 20;
948 Globals.bLocalMaster = true;
949 Globals.domain_master = Auto; /* depending on bDomainLogons */
950 Globals.bDomainLogons = false;
951 Globals.bBrowseList = true;
952 Globals.bWINSsupport = false;
953 Globals.bWINSproxy = false;
955 TALLOC_FREE(Globals.szInitLogonDelayedHosts);
956 Globals.InitLogonDelay = 100; /* 100 ms default delay */
958 Globals.bWINSdnsProxy = true;
960 Globals.bAllowTrustedDomains = true;
961 string_set(&Globals.szIdmapBackend, "tdb");
963 string_set(&Globals.szTemplateShell, "/bin/false");
964 string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
965 string_set(&Globals.szWinbindSeparator, "\\");
967 string_set(&Globals.szCupsServer, "");
968 string_set(&Globals.szIPrintServer, "");
970 #ifdef CLUSTER_SUPPORT
971 string_set(&Globals.ctdbdSocket, CTDB_PATH);
973 string_set(&Globals.ctdbdSocket, "");
976 Globals.szClusterAddresses = NULL;
977 Globals.clustering = false;
978 Globals.ctdb_timeout = 0;
979 Globals.ctdb_locktime_warn_threshold = 0;
981 Globals.winbind_cache_time = 300; /* 5 minutes */
982 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
983 Globals.winbind_max_clients = 200;
984 Globals.bWinbindEnumUsers = false;
985 Globals.bWinbindEnumGroups = false;
986 Globals.bWinbindUseDefaultDomain = false;
987 Globals.bWinbindTrustedDomainsOnly = false;
988 Globals.bWinbindNestedGroups = true;
989 Globals.winbind_expand_groups = 1;
990 Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
991 Globals.bWinbindRefreshTickets = false;
992 Globals.bWinbindOfflineLogon = false;
994 Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
995 Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
997 Globals.bPassdbExpandExplicit = false;
999 Globals.name_cache_timeout = 660; /* In seconds */
1001 Globals.bUseSpnego = true;
1002 Globals.bClientUseSpnego = true;
1004 Globals.client_signing = SMB_SIGNING_DEFAULT;
1005 Globals.server_signing = SMB_SIGNING_DEFAULT;
1007 Globals.bDeferSharingViolations = true;
1008 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
1010 Globals.bEnablePrivileges = true;
1011 Globals.bHostMSDfs = true;
1012 Globals.bASUSupport = false;
1014 /* User defined shares. */
1015 if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
1016 smb_panic("init_globals: ENOMEM");
1018 string_set(&Globals.szUsersharePath, s);
1020 string_set(&Globals.szUsershareTemplateShare, "");
1021 Globals.iUsershareMaxShares = 0;
1022 /* By default disallow sharing of directories not owned by the sharer. */
1023 Globals.bUsershareOwnerOnly = true;
1024 /* By default disallow guest access to usershares. */
1025 Globals.bUsershareAllowGuests = false;
1027 Globals.iKeepalive = DEFAULT_KEEPALIVE;
1029 /* By default no shares out of the registry */
1030 Globals.bRegistryShares = false;
1032 Globals.iminreceivefile = 0;
1034 Globals.bMapUntrustedToDomain = false;
1035 Globals.bMulticastDnsRegister = true;
1037 Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
1038 Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
1039 Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
1040 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1042 string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1044 /* Now put back the settings that were set with lp_set_cmdline() */
1045 apply_lp_set_cmdline();
1048 /*******************************************************************
1049 Convenience routine to grab string parameters into talloced memory
1050 and run standard_sub_basic on them. The buffers can be written to by
1051 callers without affecting the source string.
1052 ********************************************************************/
1054 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1058 /* The follow debug is useful for tracking down memory problems
1059 especially if you have an inner loop that is calling a lp_*()
1060 function that returns a string. Perhaps this debug should be
1061 present all the time? */
1064 DEBUG(10, ("lp_string(%s)\n", s));
1070 ret = talloc_sub_basic(ctx,
1071 get_current_username(),
1072 current_user_info.domain,
1074 if (trim_char(ret, '\"', '\"')) {
1075 if (strchr(ret,'\"') != NULL) {
1077 ret = talloc_sub_basic(ctx,
1078 get_current_username(),
1079 current_user_info.domain,
1087 In this section all the functions that are used to access the
1088 parameters from the rest of the program are defined
1091 #define FN_GLOBAL_STRING(fn_name,ptr) \
1092 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1093 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1094 const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1095 #define FN_GLOBAL_LIST(fn_name,ptr) \
1096 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1097 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1098 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1099 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1100 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1101 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1102 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1104 #define FN_LOCAL_STRING(fn_name,val) \
1105 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));}
1106 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1107 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1108 #define FN_LOCAL_LIST(fn_name,val) \
1109 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1110 #define FN_LOCAL_BOOL(fn_name,val) \
1111 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1112 #define FN_LOCAL_INTEGER(fn_name,val) \
1113 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1115 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1116 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1117 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1118 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1119 #define FN_LOCAL_CHAR(fn_name,val) \
1120 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1123 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1124 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1126 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1127 * build process or in smb.conf, we use that value. Otherwise they
1128 * default to the value of lp_lockdir(). */
1129 const char *lp_statedir(void) {
1130 if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1131 (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1132 return(*(char **)(&Globals.szStateDir) ?
1133 *(char **)(&Globals.szStateDir) : "");
1135 return(*(char **)(&Globals.szLockDir) ?
1136 *(char **)(&Globals.szLockDir) : "");
1138 const char *lp_cachedir(void) {
1139 if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1140 (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1141 return(*(char **)(&Globals.szCacheDir) ?
1142 *(char **)(&Globals.szCacheDir) : "");
1144 return(*(char **)(&Globals.szLockDir) ?
1145 *(char **)(&Globals.szLockDir) : "");
1147 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1148 winbindMaxDomainConnections)
1150 int lp_winbind_max_domain_connections(void)
1152 if (lp_winbind_offline_logon() &&
1153 lp_winbind_max_domain_connections_int() > 1) {
1154 DEBUG(1, ("offline logons active, restricting max domain "
1155 "connections to 1\n"));
1158 return MAX(1, lp_winbind_max_domain_connections_int());
1161 int lp_smb2_max_credits(void)
1163 if (Globals.ismb2_max_credits == 0) {
1164 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1166 return Globals.ismb2_max_credits;
1168 int lp_cups_encrypt(void)
1171 #ifdef HAVE_HTTPCONNECTENCRYPT
1172 switch (Globals.CupsEncrypt) {
1174 result = HTTP_ENCRYPT_REQUIRED;
1177 result = HTTP_ENCRYPT_ALWAYS;
1180 result = HTTP_ENCRYPT_NEVER;
1187 /* These functions remain in source3/param for now */
1189 FN_GLOBAL_STRING(configfile, szConfigFile)
1191 #include "lib/param/param_functions.c"
1193 FN_LOCAL_STRING(servicename, szService)
1194 FN_LOCAL_CONST_STRING(const_servicename, szService)
1196 /* local prototypes */
1198 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1199 static const char *get_boolean(bool bool_value);
1200 static int getservicebyname(const char *pszServiceName,
1201 struct loadparm_service *pserviceDest);
1202 static void copy_service(struct loadparm_service *pserviceDest,
1203 struct loadparm_service *pserviceSource,
1204 struct bitmap *pcopymapDest);
1205 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1207 static bool do_section(const char *pszSectionName, void *userdata);
1208 static void init_copymap(struct loadparm_service *pservice);
1209 static bool hash_a_service(const char *name, int number);
1210 static void free_service_byindex(int iService);
1211 static void show_parameter(int parmIndex);
1212 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1215 * This is a helper function for parametrical options support. It returns a
1216 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1217 * parametrical functions are quite simple
1219 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1222 bool global_section = false;
1224 struct parmlist_entry *data;
1226 if (service == NULL) {
1227 data = Globals.param_opt;
1228 global_section = true;
1230 data = service->param_opt;
1233 if (asprintf(¶m_key, "%s:%s", type, option) == -1) {
1234 DEBUG(0,("asprintf failed!\n"));
1239 if (strwicmp(data->key, param_key) == 0) {
1240 string_free(¶m_key);
1246 if (!global_section) {
1247 /* Try to fetch the same option but from globals */
1248 /* but only if we are not already working with Globals */
1249 data = Globals.param_opt;
1251 if (strwicmp(data->key, param_key) == 0) {
1252 string_free(¶m_key);
1259 string_free(¶m_key);
1265 * This is a helper function for parametrical options support. It returns a
1266 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1267 * parametrical functions are quite simple
1269 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1272 if (snum >= iNumServices) return NULL;
1275 return get_parametrics_by_service(NULL, type, option);
1277 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1282 #define MISSING_PARAMETER(name) \
1283 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1285 /*******************************************************************
1286 convenience routine to return int parameters.
1287 ********************************************************************/
1288 static int lp_int(const char *s)
1292 MISSING_PARAMETER(lp_int);
1296 return (int)strtol(s, NULL, 0);
1299 /*******************************************************************
1300 convenience routine to return unsigned long parameters.
1301 ********************************************************************/
1302 static unsigned long lp_ulong(const char *s)
1306 MISSING_PARAMETER(lp_ulong);
1310 return strtoul(s, NULL, 0);
1313 /*******************************************************************
1314 convenience routine to return boolean parameters.
1315 ********************************************************************/
1316 static bool lp_bool(const char *s)
1321 MISSING_PARAMETER(lp_bool);
1325 if (!set_boolean(s, &ret)) {
1326 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1333 /*******************************************************************
1334 convenience routine to return enum parameters.
1335 ********************************************************************/
1336 static int lp_enum(const char *s,const struct enum_list *_enum)
1340 if (!s || !*s || !_enum) {
1341 MISSING_PARAMETER(lp_enum);
1345 for (i=0; _enum[i].name; i++) {
1346 if (strequal(_enum[i].name,s))
1347 return _enum[i].value;
1350 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1354 #undef MISSING_PARAMETER
1356 /* Return parametric option from a given service. Type is a part of option before ':' */
1357 /* Parametric option has following syntax: 'Type: option = value' */
1358 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1360 struct parmlist_entry *data = get_parametrics(snum, type, option);
1362 if (data == NULL||data->value==NULL) {
1364 return lp_string(ctx, def);
1370 return lp_string(ctx, data->value);
1373 /* Return parametric option from a given service. Type is a part of option before ':' */
1374 /* Parametric option has following syntax: 'Type: option = value' */
1375 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1377 struct parmlist_entry *data = get_parametrics(snum, type, option);
1379 if (data == NULL||data->value==NULL)
1385 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1387 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1389 if (data == NULL||data->value==NULL)
1396 /* Return parametric option from a given service. Type is a part of option before ':' */
1397 /* Parametric option has following syntax: 'Type: option = value' */
1399 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1401 struct parmlist_entry *data = get_parametrics(snum, type, option);
1403 if (data == NULL||data->value==NULL)
1404 return (const char **)def;
1406 if (data->list==NULL) {
1407 data->list = str_list_make_v3(NULL, data->value, NULL);
1410 return (const char **)data->list;
1413 /* Return parametric option from a given service. Type is a part of option before ':' */
1414 /* Parametric option has following syntax: 'Type: option = value' */
1416 int lp_parm_int(int snum, const char *type, const char *option, int def)
1418 struct parmlist_entry *data = get_parametrics(snum, type, option);
1420 if (data && data->value && *data->value)
1421 return lp_int(data->value);
1426 /* Return parametric option from a given service. Type is a part of option before ':' */
1427 /* Parametric option has following syntax: 'Type: option = value' */
1429 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1431 struct parmlist_entry *data = get_parametrics(snum, type, option);
1433 if (data && data->value && *data->value)
1434 return lp_ulong(data->value);
1439 /* Return parametric option from a given service. Type is a part of option before ':' */
1440 /* Parametric option has following syntax: 'Type: option = value' */
1442 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1444 struct parmlist_entry *data = get_parametrics(snum, type, option);
1446 if (data && data->value && *data->value)
1447 return lp_bool(data->value);
1452 /* Return parametric option from a given service. Type is a part of option before ':' */
1453 /* Parametric option has following syntax: 'Type: option = value' */
1455 int lp_parm_enum(int snum, const char *type, const char *option,
1456 const struct enum_list *_enum, int def)
1458 struct parmlist_entry *data = get_parametrics(snum, type, option);
1460 if (data && data->value && *data->value && _enum)
1461 return lp_enum(data->value, _enum);
1467 /***************************************************************************
1468 Initialise a service to the defaults.
1469 ***************************************************************************/
1471 static void init_service(struct loadparm_service *pservice)
1473 memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1474 copy_service(pservice, &sDefault, NULL);
1479 * free a param_opts structure.
1480 * param_opts handling should be moved to talloc;
1481 * then this whole functions reduces to a TALLOC_FREE().
1484 static void free_param_opts(struct parmlist_entry **popts)
1486 struct parmlist_entry *opt, *next_opt;
1488 if (*popts != NULL) {
1489 DEBUG(5, ("Freeing parametrics:\n"));
1492 while (opt != NULL) {
1493 string_free(&opt->key);
1494 string_free(&opt->value);
1495 TALLOC_FREE(opt->list);
1496 next_opt = opt->next;
1503 /***************************************************************************
1504 Free the dynamically allocated parts of a service struct.
1505 ***************************************************************************/
1507 static void free_service(struct loadparm_service *pservice)
1512 if (pservice->szService)
1513 DEBUG(5, ("free_service: Freeing service %s\n",
1514 pservice->szService));
1516 free_parameters(pservice);
1518 string_free(&pservice->szService);
1519 TALLOC_FREE(pservice->copymap);
1521 free_param_opts(&pservice->param_opt);
1523 ZERO_STRUCTP(pservice);
1527 /***************************************************************************
1528 remove a service indexed in the ServicePtrs array from the ServiceHash
1529 and free the dynamically allocated parts
1530 ***************************************************************************/
1532 static void free_service_byindex(int idx)
1534 if ( !LP_SNUM_OK(idx) )
1537 ServicePtrs[idx]->valid = false;
1538 invalid_services[num_invalid_services++] = idx;
1540 /* we have to cleanup the hash record */
1542 if (ServicePtrs[idx]->szService) {
1543 char *canon_name = canonicalize_servicename(
1545 ServicePtrs[idx]->szService );
1547 dbwrap_delete_bystring(ServiceHash, canon_name );
1548 TALLOC_FREE(canon_name);
1551 free_service(ServicePtrs[idx]);
1552 talloc_free_children(ServicePtrs[idx]);
1555 /***************************************************************************
1556 Add a new service to the services array initialising it with the given
1558 ***************************************************************************/
1560 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1563 struct loadparm_service tservice;
1564 int num_to_alloc = iNumServices + 1;
1566 tservice = *pservice;
1568 /* it might already exist */
1570 i = getservicebyname(name, NULL);
1576 /* find an invalid one */
1578 if (num_invalid_services > 0) {
1579 i = invalid_services[--num_invalid_services];
1582 /* if not, then create one */
1583 if (i == iNumServices) {
1584 struct loadparm_service **tsp;
1587 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1589 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1593 ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1594 if (!ServicePtrs[iNumServices]) {
1595 DEBUG(0,("add_a_service: out of memory!\n"));
1600 /* enlarge invalid_services here for now... */
1601 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
1603 if (tinvalid == NULL) {
1604 DEBUG(0,("add_a_service: failed to enlarge "
1605 "invalid_services!\n"));
1608 invalid_services = tinvalid;
1610 free_service_byindex(i);
1613 ServicePtrs[i]->valid = true;
1615 init_service(ServicePtrs[i]);
1616 copy_service(ServicePtrs[i], &tservice, NULL);
1618 string_set(&ServicePtrs[i]->szService, name);
1620 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1621 i, ServicePtrs[i]->szService));
1623 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1630 /***************************************************************************
1631 Convert a string to uppercase and remove whitespaces.
1632 ***************************************************************************/
1634 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1639 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1643 result = talloc_strdup(ctx, src);
1644 SMB_ASSERT(result != NULL);
1646 if (!strlower_m(result)) {
1647 TALLOC_FREE(result);
1653 /***************************************************************************
1654 Add a name/index pair for the services array to the hash table.
1655 ***************************************************************************/
1657 static bool hash_a_service(const char *name, int idx)
1661 if ( !ServiceHash ) {
1662 DEBUG(10,("hash_a_service: creating servicehash\n"));
1663 ServiceHash = db_open_rbt(NULL);
1664 if ( !ServiceHash ) {
1665 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1670 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1673 canon_name = canonicalize_servicename(talloc_tos(), name );
1675 dbwrap_store_bystring(ServiceHash, canon_name,
1676 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1679 TALLOC_FREE(canon_name);
1684 /***************************************************************************
1685 Add a new home service, with the specified home directory, defaults coming
1687 ***************************************************************************/
1689 bool lp_add_home(const char *pszHomename, int iDefaultService,
1690 const char *user, const char *pszHomedir)
1694 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1695 pszHomedir[0] == '\0') {
1699 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1704 if (!(*(ServicePtrs[iDefaultService]->szPath))
1705 || strequal(ServicePtrs[iDefaultService]->szPath,
1706 lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1707 string_set(&ServicePtrs[i]->szPath, pszHomedir);
1710 if (!(*(ServicePtrs[i]->comment))) {
1711 char *comment = NULL;
1712 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1715 string_set(&ServicePtrs[i]->comment, comment);
1719 /* set the browseable flag from the global default */
1721 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1722 ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
1724 ServicePtrs[i]->autoloaded = true;
1726 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1727 user, ServicePtrs[i]->szPath ));
1732 /***************************************************************************
1733 Add a new service, based on an old one.
1734 ***************************************************************************/
1736 int lp_add_service(const char *pszService, int iDefaultService)
1738 if (iDefaultService < 0) {
1739 return add_a_service(&sDefault, pszService);
1742 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1745 /***************************************************************************
1746 Add the IPC service.
1747 ***************************************************************************/
1749 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1751 char *comment = NULL;
1752 int i = add_a_service(&sDefault, ipc_name);
1757 if (asprintf(&comment, "IPC Service (%s)",
1758 Globals.szServerString) < 0) {
1762 string_set(&ServicePtrs[i]->szPath, tmpdir());
1763 string_set(&ServicePtrs[i]->szUsername, "");
1764 string_set(&ServicePtrs[i]->comment, comment);
1765 string_set(&ServicePtrs[i]->fstype, "IPC");
1766 ServicePtrs[i]->iMaxConnections = 0;
1767 ServicePtrs[i]->bAvailable = true;
1768 ServicePtrs[i]->bRead_only = true;
1769 ServicePtrs[i]->bGuest_only = false;
1770 ServicePtrs[i]->bAdministrative_share = true;
1771 ServicePtrs[i]->bGuest_ok = guest_ok;
1772 ServicePtrs[i]->bPrint_ok = false;
1773 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1775 DEBUG(3, ("adding IPC service\n"));
1781 /***************************************************************************
1782 Add a new printer service, with defaults coming from service iFrom.
1783 ***************************************************************************/
1785 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1787 const char *comment = "From Printcap";
1788 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1793 /* note that we do NOT default the availability flag to true - */
1794 /* we take it from the default service passed. This allows all */
1795 /* dynamic printers to be disabled by disabling the [printers] */
1796 /* entry (if/when the 'available' keyword is implemented!). */
1798 /* the printer name is set to the service name. */
1799 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1800 string_set(&ServicePtrs[i]->comment, comment);
1802 /* set the browseable flag from the gloabl default */
1803 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1805 /* Printers cannot be read_only. */
1806 ServicePtrs[i]->bRead_only = false;
1807 /* No share modes on printer services. */
1808 ServicePtrs[i]->bShareModes = false;
1809 /* No oplocks on printer services. */
1810 ServicePtrs[i]->bOpLocks = false;
1811 /* Printer services must be printable. */
1812 ServicePtrs[i]->bPrint_ok = true;
1814 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1820 /***************************************************************************
1821 Check whether the given parameter name is valid.
1822 Parametric options (names containing a colon) are considered valid.
1823 ***************************************************************************/
1825 bool lp_parameter_is_valid(const char *pszParmName)
1827 return ((map_parameter(pszParmName) != -1) ||
1828 (strchr(pszParmName, ':') != NULL));
1831 /***************************************************************************
1832 Check whether the given name is the name of a global parameter.
1833 Returns true for strings belonging to parameters of class
1834 P_GLOBAL, false for all other strings, also for parametric options
1835 and strings not belonging to any option.
1836 ***************************************************************************/
1838 bool lp_parameter_is_global(const char *pszParmName)
1840 int num = map_parameter(pszParmName);
1843 return (parm_table[num].p_class == P_GLOBAL);
1849 /**************************************************************************
1850 Check whether the given name is the canonical name of a parameter.
1851 Returns false if it is not a valid parameter Name.
1852 For parametric options, true is returned.
1853 **************************************************************************/
1855 bool lp_parameter_is_canonical(const char *parm_name)
1857 if (!lp_parameter_is_valid(parm_name)) {
1861 return (map_parameter(parm_name) ==
1862 map_parameter_canonical(parm_name, NULL));
1865 /**************************************************************************
1866 Determine the canonical name for a parameter.
1867 Indicate when it is an inverse (boolean) synonym instead of a
1869 **************************************************************************/
1871 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1876 if (!lp_parameter_is_valid(parm_name)) {
1881 num = map_parameter_canonical(parm_name, inverse);
1883 /* parametric option */
1884 *canon_parm = parm_name;
1886 *canon_parm = parm_table[num].label;
1893 /**************************************************************************
1894 Determine the canonical name for a parameter.
1895 Turn the value given into the inverse boolean expression when
1896 the synonym is an invers boolean synonym.
1898 Return true if parm_name is a valid parameter name and
1899 in case it is an invers boolean synonym, if the val string could
1900 successfully be converted to the reverse bool.
1901 Return false in all other cases.
1902 **************************************************************************/
1904 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1906 const char **canon_parm,
1907 const char **canon_val)
1912 if (!lp_parameter_is_valid(parm_name)) {
1918 num = map_parameter_canonical(parm_name, &inverse);
1920 /* parametric option */
1921 *canon_parm = parm_name;
1924 *canon_parm = parm_table[num].label;
1926 if (!lp_invert_boolean(val, canon_val)) {
1938 /***************************************************************************
1939 Map a parameter's string representation to something we can use.
1940 Returns false if the parameter string is not recognised, else TRUE.
1941 ***************************************************************************/
1943 static int map_parameter(const char *pszParmName)
1947 if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
1950 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1951 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1954 /* Warn only if it isn't parametric option */
1955 if (strchr(pszParmName, ':') == NULL)
1956 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1957 /* We do return 'fail' for parametric options as well because they are
1958 stored in different storage
1963 /***************************************************************************
1964 Map a parameter's string representation to the index of the canonical
1965 form of the parameter (it might be a synonym).
1966 Returns -1 if the parameter string is not recognised.
1967 ***************************************************************************/
1969 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1971 int parm_num, canon_num;
1972 bool loc_inverse = false;
1974 parm_num = map_parameter(pszParmName);
1975 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1976 /* invalid, parametric or no canidate for synonyms ... */
1980 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1981 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1982 parm_num = canon_num;
1988 if (inverse != NULL) {
1989 *inverse = loc_inverse;
1994 /***************************************************************************
1995 return true if parameter number parm1 is a synonym of parameter
1996 number parm2 (parm2 being the principal name).
1997 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1999 ***************************************************************************/
2001 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
2003 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
2004 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
2005 (parm_table[parm1].flags & FLAG_HIDE) &&
2006 !(parm_table[parm2].flags & FLAG_HIDE))
2008 if (inverse != NULL) {
2009 if ((parm_table[parm1].type == P_BOOLREV) &&
2010 (parm_table[parm2].type == P_BOOL))
2022 /***************************************************************************
2023 Show one parameter's name, type, [values,] and flags.
2024 (helper functions for show_parameter_list)
2025 ***************************************************************************/
2027 static void show_parameter(int parmIndex)
2029 int enumIndex, flagIndex;
2034 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2035 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2037 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2038 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2040 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2041 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2042 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2044 printf("%s=%s", parm_table[parmIndex].label,
2045 type[parm_table[parmIndex].type]);
2046 if (parm_table[parmIndex].type == P_ENUM) {
2049 parm_table[parmIndex].enum_list[enumIndex].name;
2053 enumIndex ? "|" : "",
2054 parm_table[parmIndex].enum_list[enumIndex].name);
2059 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2060 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2063 flag_names[flagIndex]);
2068 /* output synonyms */
2070 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2071 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2072 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2073 parm_table[parmIndex2].label);
2074 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2076 printf(" (synonyms: ");
2081 printf("%s%s", parm_table[parmIndex2].label,
2082 inverse ? "[i]" : "");
2092 /***************************************************************************
2093 Show all parameter's name, type, [values,] and flags.
2094 ***************************************************************************/
2096 void show_parameter_list(void)
2098 int classIndex, parmIndex;
2099 const char *section_names[] = { "local", "global", NULL};
2101 for (classIndex=0; section_names[classIndex]; classIndex++) {
2102 printf("[%s]\n", section_names[classIndex]);
2103 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2104 if (parm_table[parmIndex].p_class == classIndex) {
2105 show_parameter(parmIndex);
2111 /***************************************************************************
2112 Check if a given string correctly represents a boolean value.
2113 ***************************************************************************/
2115 bool lp_string_is_valid_boolean(const char *parm_value)
2117 return set_boolean(parm_value, NULL);
2120 /***************************************************************************
2121 Get the standard string representation of a boolean value ("yes" or "no")
2122 ***************************************************************************/
2124 static const char *get_boolean(bool bool_value)
2126 static const char *yes_str = "yes";
2127 static const char *no_str = "no";
2129 return (bool_value ? yes_str : no_str);
2132 /***************************************************************************
2133 Provide the string of the negated boolean value associated to the boolean
2134 given as a string. Returns false if the passed string does not correctly
2135 represent a boolean.
2136 ***************************************************************************/
2138 bool lp_invert_boolean(const char *str, const char **inverse_str)
2142 if (!set_boolean(str, &val)) {
2146 *inverse_str = get_boolean(!val);
2150 /***************************************************************************
2151 Provide the canonical string representation of a boolean value given
2152 as a string. Return true on success, false if the string given does
2153 not correctly represent a boolean.
2154 ***************************************************************************/
2156 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2160 if (!set_boolean(str, &val)) {
2164 *canon_str = get_boolean(val);
2168 /***************************************************************************
2169 Find a service by name. Otherwise works like get_service.
2170 ***************************************************************************/
2172 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2179 if (ServiceHash == NULL) {
2183 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2185 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2188 if (NT_STATUS_IS_OK(status) &&
2189 (data.dptr != NULL) &&
2190 (data.dsize == sizeof(iService)))
2192 iService = *(int *)data.dptr;
2195 TALLOC_FREE(canon_name);
2197 if ((iService != -1) && (LP_SNUM_OK(iService))
2198 && (pserviceDest != NULL)) {
2199 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2205 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2206 struct loadparm_service *lp_service(const char *pszServiceName)
2208 int iService = getservicebyname(pszServiceName, NULL);
2209 if (iService == -1 || !LP_SNUM_OK(iService)) {
2212 return ServicePtrs[iService];
2215 struct loadparm_service *lp_servicebynum(int snum)
2217 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2220 return ServicePtrs[snum];
2223 struct loadparm_service *lp_default_loadparm_service()
2229 /***************************************************************************
2230 Copy a service structure to another.
2231 If pcopymapDest is NULL then copy all fields
2232 ***************************************************************************/
2235 * Add a parametric option to a parmlist_entry,
2236 * replacing old value, if already present.
2238 static void set_param_opt(struct parmlist_entry **opt_list,
2239 const char *opt_name,
2240 const char *opt_value,
2243 struct parmlist_entry *new_opt, *opt;
2249 /* Traverse destination */
2251 /* If we already have same option, override it */
2252 if (strwicmp(opt->key, opt_name) == 0) {
2253 if ((opt->priority & FLAG_CMDLINE) &&
2254 !(priority & FLAG_CMDLINE)) {
2255 /* it's been marked as not to be
2259 string_free(&opt->value);
2260 TALLOC_FREE(opt->list);
2261 opt->value = SMB_STRDUP(opt_value);
2262 opt->priority = priority;
2269 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2270 new_opt->key = SMB_STRDUP(opt_name);
2271 new_opt->value = SMB_STRDUP(opt_value);
2272 new_opt->list = NULL;
2273 new_opt->priority = priority;
2274 DLIST_ADD(*opt_list, new_opt);
2278 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2279 struct bitmap *pcopymapDest)
2282 bool bcopyall = (pcopymapDest == NULL);
2283 struct parmlist_entry *data;
2285 for (i = 0; parm_table[i].label; i++)
2286 if (parm_table[i].p_class == P_LOCAL &&
2287 (bcopyall || bitmap_query(pcopymapDest,i))) {
2288 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2289 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2291 switch (parm_table[i].type) {
2294 *(bool *)dest_ptr = *(bool *)src_ptr;
2301 *(int *)dest_ptr = *(int *)src_ptr;
2305 *(char *)dest_ptr = *(char *)src_ptr;
2309 string_set((char **)dest_ptr,
2315 char *upper_string = strupper_talloc(talloc_tos(),
2317 string_set((char **)dest_ptr,
2319 TALLOC_FREE(upper_string);
2323 TALLOC_FREE(*((char ***)dest_ptr));
2324 *((char ***)dest_ptr) = str_list_copy(NULL,
2325 *(const char ***)src_ptr);
2333 init_copymap(pserviceDest);
2334 if (pserviceSource->copymap)
2335 bitmap_copy(pserviceDest->copymap,
2336 pserviceSource->copymap);
2339 data = pserviceSource->param_opt;
2341 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2346 /***************************************************************************
2347 Check a service for consistency. Return false if the service is in any way
2348 incomplete or faulty, else true.
2349 ***************************************************************************/
2351 bool service_ok(int iService)
2356 if (ServicePtrs[iService]->szService[0] == '\0') {
2357 DEBUG(0, ("The following message indicates an internal error:\n"));
2358 DEBUG(0, ("No service name in service entry.\n"));
2362 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2363 /* I can't see why you'd want a non-printable printer service... */
2364 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2365 if (!ServicePtrs[iService]->bPrint_ok) {
2366 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2367 ServicePtrs[iService]->szService));
2368 ServicePtrs[iService]->bPrint_ok = true;
2370 /* [printers] service must also be non-browsable. */
2371 if (ServicePtrs[iService]->bBrowseable)
2372 ServicePtrs[iService]->bBrowseable = false;
2375 if (ServicePtrs[iService]->szPath[0] == '\0' &&
2376 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2377 ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2379 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2380 ServicePtrs[iService]->szService));
2381 ServicePtrs[iService]->bAvailable = false;
2384 /* If a service is flagged unavailable, log the fact at level 1. */
2385 if (!ServicePtrs[iService]->bAvailable)
2386 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2387 ServicePtrs[iService]->szService));
2392 static struct smbconf_ctx *lp_smbconf_ctx(void)
2395 static struct smbconf_ctx *conf_ctx = NULL;
2397 if (conf_ctx == NULL) {
2398 err = smbconf_init(NULL, &conf_ctx, "registry:");
2399 if (!SBC_ERROR_IS_OK(err)) {
2400 DEBUG(1, ("error initializing registry configuration: "
2401 "%s\n", sbcErrorString(err)));
2409 static bool process_smbconf_service(struct smbconf_service *service)
2414 if (service == NULL) {
2418 ret = do_section(service->name, NULL);
2422 for (count = 0; count < service->num_params; count++) {
2423 ret = do_parameter(service->param_names[count],
2424 service->param_values[count],
2430 if (iServiceIndex >= 0) {
2431 return service_ok(iServiceIndex);
2437 * load a service from registry and activate it
2439 bool process_registry_service(const char *service_name)
2442 struct smbconf_service *service = NULL;
2443 TALLOC_CTX *mem_ctx = talloc_stackframe();
2444 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2447 if (conf_ctx == NULL) {
2451 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2453 if (!smbconf_share_exists(conf_ctx, service_name)) {
2455 * Registry does not contain data for this service (yet),
2456 * but make sure lp_load doesn't return false.
2462 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2463 if (!SBC_ERROR_IS_OK(err)) {
2467 ret = process_smbconf_service(service);
2473 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2476 TALLOC_FREE(mem_ctx);
2481 * process_registry_globals
2483 static bool process_registry_globals(void)
2487 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2489 ret = do_parameter("registry shares", "yes", NULL);
2494 return process_registry_service(GLOBAL_NAME);
2497 bool process_registry_shares(void)
2501 struct smbconf_service **service = NULL;
2502 uint32_t num_shares = 0;
2503 TALLOC_CTX *mem_ctx = talloc_stackframe();
2504 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2507 if (conf_ctx == NULL) {
2511 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2512 if (!SBC_ERROR_IS_OK(err)) {
2518 for (count = 0; count < num_shares; count++) {
2519 if (strequal(service[count]->name, GLOBAL_NAME)) {
2522 ret = process_smbconf_service(service[count]);
2529 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2532 TALLOC_FREE(mem_ctx);
2537 * reload those shares from registry that are already
2538 * activated in the services array.
2540 static bool reload_registry_shares(void)
2545 for (i = 0; i < iNumServices; i++) {
2550 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2554 ret = process_registry_service(ServicePtrs[i]->szService);
2565 #define MAX_INCLUDE_DEPTH 100
2567 static uint8_t include_depth;
2569 static struct file_lists {
2570 struct file_lists *next;
2574 } *file_lists = NULL;
2576 /*******************************************************************
2577 Keep a linked list of all config files so we know when one has changed
2578 it's date and needs to be reloaded.
2579 ********************************************************************/
2581 static void add_to_file_list(const char *fname, const char *subfname)
2583 struct file_lists *f = file_lists;
2586 if (f->name && !strcmp(f->name, fname))
2592 f = SMB_MALLOC_P(struct file_lists);
2595 f->next = file_lists;
2596 f->name = SMB_STRDUP(fname);
2601 f->subfname = SMB_STRDUP(subfname);
2608 f->modtime = file_modtime(subfname);
2610 time_t t = file_modtime(subfname);
2618 * Free the file lists
2620 static void free_file_list(void)
2622 struct file_lists *f;
2623 struct file_lists *next;
2628 SAFE_FREE( f->name );
2629 SAFE_FREE( f->subfname );
2638 * Utility function for outsiders to check if we're running on registry.
2640 bool lp_config_backend_is_registry(void)
2642 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2646 * Utility function to check if the config backend is FILE.
2648 bool lp_config_backend_is_file(void)
2650 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2653 /*******************************************************************
2654 Check if a config file has changed date.
2655 ********************************************************************/
2657 bool lp_file_list_changed(void)
2659 struct file_lists *f = file_lists;
2661 DEBUG(6, ("lp_file_list_changed()\n"));
2666 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2667 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2669 if (conf_ctx == NULL) {
2672 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2675 DEBUGADD(6, ("registry config changed\n"));
2680 n2 = talloc_sub_basic(talloc_tos(),
2681 get_current_username(),
2682 current_user_info.domain,
2687 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2688 f->name, n2, ctime(&f->modtime)));
2690 mod_time = file_modtime(n2);
2693 ((f->modtime != mod_time) ||
2694 (f->subfname == NULL) ||
2695 (strcmp(n2, f->subfname) != 0)))
2698 ("file %s modified: %s\n", n2,
2700 f->modtime = mod_time;
2701 SAFE_FREE(f->subfname);
2702 f->subfname = SMB_STRDUP(n2);
2715 * Initialize iconv conversion descriptors.
2717 * This is called the first time it is needed, and also called again
2718 * every time the configuration is reloaded, because the charset or
2719 * codepage might have changed.
2721 static void init_iconv(void)
2723 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2725 true, global_iconv_handle);
2728 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2730 if (strcmp(*ptr, pszParmValue) != 0) {
2731 string_set(ptr, pszParmValue);
2737 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2739 bool is_utf8 = false;
2740 size_t len = strlen(pszParmValue);
2742 if (len == 4 || len == 5) {
2743 /* Don't use StrCaseCmp here as we don't want to
2744 initialize iconv. */
2745 if ((toupper_m(pszParmValue[0]) == 'U') &&
2746 (toupper_m(pszParmValue[1]) == 'T') &&
2747 (toupper_m(pszParmValue[2]) == 'F')) {
2749 if (pszParmValue[3] == '8') {
2753 if (pszParmValue[3] == '-' &&
2754 pszParmValue[4] == '8') {
2761 if (strcmp(*ptr, pszParmValue) != 0) {
2763 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2764 "be UTF8, using (default value) %s instead.\n",
2765 DEFAULT_DOS_CHARSET));
2766 pszParmValue = DEFAULT_DOS_CHARSET;
2768 string_set(ptr, pszParmValue);
2774 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2777 TALLOC_CTX *frame = talloc_stackframe();
2778 char *realm = strupper_talloc(frame, pszParmValue);
2779 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2781 ret &= string_set(&Globals.szRealm, pszParmValue);
2782 ret &= string_set(&Globals.szRealm_upper, realm);
2783 ret &= string_set(&Globals.szRealm_lower, dnsdomain);
2789 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2791 TALLOC_FREE(Globals.szNetbiosAliases);
2792 Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2793 return set_netbios_aliases(Globals.szNetbiosAliases);
2796 /***************************************************************************
2797 Handle the include operation.
2798 ***************************************************************************/
2799 static bool bAllowIncludeRegistry = true;
2801 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2805 if (include_depth >= MAX_INCLUDE_DEPTH) {
2806 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2811 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2812 if (!bAllowIncludeRegistry) {
2815 if (bInGlobalSection) {
2818 ret = process_registry_globals();
2822 DEBUG(1, ("\"include = registry\" only effective "
2823 "in %s section\n", GLOBAL_NAME));
2828 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2829 current_user_info.domain,
2832 add_to_file_list(pszParmValue, fname);
2834 string_set(ptr, fname);
2836 if (file_exist(fname)) {
2839 ret = pm_process(fname, do_section, do_parameter, NULL);
2845 DEBUG(2, ("Can't find include file %s\n", fname));
2850 /***************************************************************************
2851 Handle the interpretation of the copy parameter.
2852 ***************************************************************************/
2854 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2858 struct loadparm_service serviceTemp;
2860 string_set(ptr, pszParmValue);
2862 init_service(&serviceTemp);
2866 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2868 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2869 if (iTemp == iServiceIndex) {
2870 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2872 copy_service(ServicePtrs[iServiceIndex],
2874 ServicePtrs[iServiceIndex]->copymap);
2878 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2882 free_service(&serviceTemp);
2886 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2888 Globals.ldap_debug_level = lp_int(pszParmValue);
2889 init_ldap_debugging();
2893 /***************************************************************************
2894 Handle idmap/non unix account uid and gid allocation parameters. The format of these
2899 idmap uid = 1000-1999
2902 We only do simple parsing checks here. The strings are parsed into useful
2903 structures in the idmap daemon code.
2905 ***************************************************************************/
2907 /* Some lp_ routines to return idmap [ug]id information */
2909 static uid_t idmap_uid_low, idmap_uid_high;
2910 static gid_t idmap_gid_low, idmap_gid_high;
2912 bool lp_idmap_uid(uid_t *low, uid_t *high)
2914 if (idmap_uid_low == 0 || idmap_uid_high == 0)
2918 *low = idmap_uid_low;
2921 *high = idmap_uid_high;
2926 bool lp_idmap_gid(gid_t *low, gid_t *high)
2928 if (idmap_gid_low == 0 || idmap_gid_high == 0)
2932 *low = idmap_gid_low;
2935 *high = idmap_gid_high;
2940 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2942 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2947 /* Do some simple checks on "idmap [ug]id" parameter values */
2949 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2951 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2956 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2958 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2963 /***************************************************************************
2964 Handle the DEBUG level list.
2965 ***************************************************************************/
2967 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2969 string_set(ptr, pszParmValueIn);
2970 return debug_parse_levels(pszParmValueIn);
2973 /***************************************************************************
2974 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2975 ***************************************************************************/
2977 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2979 const char *suffix_string;
2981 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2982 Globals.szLdapSuffix );
2983 if ( !suffix_string ) {
2984 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2988 return suffix_string;
2991 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2993 if (Globals.szLdapMachineSuffix[0])
2994 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
2996 return lp_string(ctx, Globals.szLdapSuffix);
2999 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
3001 if (Globals.szLdapUserSuffix[0])
3002 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3004 return lp_string(ctx, Globals.szLdapSuffix);
3007 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3009 if (Globals.szLdapGroupSuffix[0])
3010 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3012 return lp_string(ctx, Globals.szLdapSuffix);
3015 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3017 if (Globals.szLdapIdmapSuffix[0])
3018 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3020 return lp_string(ctx, Globals.szLdapSuffix);
3023 /****************************************************************************
3024 set the value for a P_ENUM
3025 ***************************************************************************/
3027 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3032 for (i = 0; parm->enum_list[i].name; i++) {
3033 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3034 *ptr = parm->enum_list[i].value;
3038 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3039 pszParmValue, parm->label));
3042 /***************************************************************************
3043 ***************************************************************************/
3045 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3047 static int parm_num = -1;
3048 struct loadparm_service *s;
3050 if ( parm_num == -1 )
3051 parm_num = map_parameter( "printing" );
3053 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3058 s = ServicePtrs[snum];
3060 init_printer_values( s );
3066 /***************************************************************************
3067 Initialise a copymap.
3068 ***************************************************************************/
3070 static void init_copymap(struct loadparm_service *pservice)
3074 TALLOC_FREE(pservice->copymap);
3076 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3077 if (!pservice->copymap)
3079 ("Couldn't allocate copymap!! (size %d)\n",
3080 (int)NUMPARAMETERS));
3082 for (i = 0; i < NUMPARAMETERS; i++)
3083 bitmap_set(pservice->copymap, i);
3087 return the parameter pointer for a parameter
3089 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3091 if (service == NULL) {
3092 if (parm->p_class == P_LOCAL)
3093 return (void *)(((char *)&sDefault)+parm->offset);
3094 else if (parm->p_class == P_GLOBAL)
3095 return (void *)(((char *)&Globals)+parm->offset);
3098 return (void *)(((char *)service) + parm->offset);
3102 /***************************************************************************
3103 Return the local pointer to a parameter given the service number and parameter
3104 ***************************************************************************/
3106 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3108 return lp_parm_ptr(ServicePtrs[snum], parm);
3111 /***************************************************************************
3112 Process a parameter for a particular service number. If snum < 0
3113 then assume we are in the globals.
3114 ***************************************************************************/
3116 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3119 void *parm_ptr = NULL; /* where we are going to store the result */
3120 struct parmlist_entry **opt_list;
3122 parmnum = map_parameter(pszParmName);
3125 if (strchr(pszParmName, ':') == NULL) {
3126 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3132 * We've got a parametric option
3135 opt_list = (snum < 0)
3136 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3137 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3142 /* if it's already been set by the command line, then we don't
3144 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3148 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3149 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3153 /* we might point at a service, the default service or a global */
3155 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3157 if (parm_table[parmnum].p_class == P_GLOBAL) {
3159 ("Global parameter %s found in service section!\n",
3163 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3167 if (!ServicePtrs[snum]->copymap)
3168 init_copymap(ServicePtrs[snum]);
3170 /* this handles the aliases - set the copymap for other entries with
3171 the same data pointer */
3172 for (i = 0; parm_table[i].label; i++) {
3173 if ((parm_table[i].offset == parm_table[parmnum].offset)
3174 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3175 bitmap_clear(ServicePtrs[snum]->copymap, i);
3180 /* if it is a special case then go ahead */
3181 if (parm_table[parmnum].special) {
3182 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3186 /* now switch on the type of variable it is */
3187 switch (parm_table[parmnum].type)
3190 *(bool *)parm_ptr = lp_bool(pszParmValue);
3194 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3198 *(int *)parm_ptr = lp_int(pszParmValue);
3202 *(char *)parm_ptr = *pszParmValue;
3206 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3208 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3215 if (conv_str_size_error(pszParmValue, &val)) {
3216 if (val <= INT_MAX) {
3217 *(int *)parm_ptr = (int)val;
3222 DEBUG(0,("lp_do_parameter(%s): value is not "
3223 "a valid size specifier!\n", pszParmValue));
3229 TALLOC_FREE(*((char ***)parm_ptr));
3230 *(char ***)parm_ptr = str_list_make_v3(
3231 NULL, pszParmValue, NULL);
3235 string_set((char **)parm_ptr, pszParmValue);
3240 char *upper_string = strupper_talloc(talloc_tos(),
3242 string_set((char **)parm_ptr, upper_string);
3243 TALLOC_FREE(upper_string);
3247 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3256 /***************************************************************************
3257 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3258 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3259 ***************************************************************************/
3261 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3264 parmnum = map_parameter(pszParmName);
3266 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3267 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3270 parm_table[parmnum].flags |= FLAG_CMDLINE;
3272 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3273 * be grouped in the table, so we don't have to search the
3276 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3277 && parm_table[i].p_class == parm_table[parmnum].p_class;
3279 parm_table[i].flags |= FLAG_CMDLINE;
3281 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3282 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3283 parm_table[i].flags |= FLAG_CMDLINE;
3287 store_lp_set_cmdline(pszParmName, pszParmValue);
3292 /* it might be parametric */
3293 if (strchr(pszParmName, ':') != NULL) {
3294 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3296 store_lp_set_cmdline(pszParmName, pszParmValue);
3301 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3305 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3307 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3310 /***************************************************************************
3311 Process a parameter.
3312 ***************************************************************************/
3314 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3317 if (!bInGlobalSection && bGlobalOnly)
3320 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3322 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3323 pszParmName, pszParmValue));
3327 set a option from the commandline in 'a=b' format. Use to support --option
3329 bool lp_set_option(const char *option)
3334 s = talloc_strdup(NULL, option);
3347 /* skip white spaces after the = sign */
3350 } while (*p == ' ');
3352 ret = lp_set_cmdline(s, p);
3357 /**************************************************************************
3358 Print a parameter of the specified type.
3359 ***************************************************************************/
3361 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3363 /* For the seperation of lists values that we print below */
3364 const char *list_sep = ", ";
3369 for (i = 0; p->enum_list[i].name; i++) {
3370 if (*(int *)ptr == p->enum_list[i].value) {
3372 p->enum_list[i].name);
3379 fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3383 fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3388 fprintf(f, "%d", *(int *)ptr);
3392 fprintf(f, "%c", *(char *)ptr);
3396 int val = *(int *)ptr;
3400 fprintf(f, "0%o", val);
3409 if ((char ***)ptr && *(char ***)ptr) {
3410 char **list = *(char ***)ptr;
3411 for (; *list; list++) {
3412 /* surround strings with whitespace in double quotes */
3413 if (*(list+1) == NULL) {
3414 /* last item, no extra separator */
3417 if ( strchr_m( *list, ' ' ) ) {
3418 fprintf(f, "\"%s\"%s", *list, list_sep);
3420 fprintf(f, "%s%s", *list, list_sep);
3428 if (*(char **)ptr) {
3429 fprintf(f, "%s", *(char **)ptr);
3437 /***************************************************************************
3438 Check if two parameters are equal.
3439 ***************************************************************************/
3441 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3446 return (*((bool *)ptr1) == *((bool *)ptr2));
3452 return (*((int *)ptr1) == *((int *)ptr2));
3455 return (*((char *)ptr1) == *((char *)ptr2));
3459 return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3464 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3469 return (p1 == p2 || strequal(p1, p2));
3477 /***************************************************************************
3478 Initialize any local varients in the sDefault table.
3479 ***************************************************************************/
3481 void init_locals(void)
3486 /***************************************************************************
3487 Process a new section (service). At this stage all sections are services.
3488 Later we'll have special sections that permit server parameters to be set.
3489 Returns true on success, false on failure.
3490 ***************************************************************************/
3492 static bool do_section(const char *pszSectionName, void *userdata)
3495 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3496 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3499 /* if we were in a global section then do the local inits */
3500 if (bInGlobalSection && !isglobal)
3503 /* if we've just struck a global section, note the fact. */
3504 bInGlobalSection = isglobal;
3506 /* check for multiple global sections */
3507 if (bInGlobalSection) {
3508 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3512 if (!bInGlobalSection && bGlobalOnly)
3515 /* if we have a current service, tidy it up before moving on */
3518 if (iServiceIndex >= 0)
3519 bRetval = service_ok(iServiceIndex);
3521 /* if all is still well, move to the next record in the services array */
3523 /* We put this here to avoid an odd message order if messages are */
3524 /* issued by the post-processing of a previous section. */
3525 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3527 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3528 if (iServiceIndex < 0) {
3529 DEBUG(0, ("Failed to add a new service\n"));
3532 /* Clean all parametric options for service */
3533 /* They will be added during parsing again */
3534 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3541 /***************************************************************************
3542 Determine if a partcular base parameter is currentl set to the default value.
3543 ***************************************************************************/
3545 static bool is_default(int i)
3547 if (!defaults_saved)
3549 switch (parm_table[i].type) {
3552 return str_list_equal((const char **)parm_table[i].def.lvalue,
3553 *(const char ***)lp_parm_ptr(NULL,
3557 return strequal(parm_table[i].def.svalue,
3558 *(char **)lp_parm_ptr(NULL,
3562 return parm_table[i].def.bvalue ==
3563 *(bool *)lp_parm_ptr(NULL,
3566 return parm_table[i].def.cvalue ==
3567 *(char *)lp_parm_ptr(NULL,
3573 return parm_table[i].def.ivalue ==
3574 *(int *)lp_parm_ptr(NULL,
3582 /***************************************************************************
3583 Display the contents of the global structure.
3584 ***************************************************************************/
3586 static void dump_globals(FILE *f)
3589 struct parmlist_entry *data;
3591 fprintf(f, "[global]\n");
3593 for (i = 0; parm_table[i].label; i++)
3594 if (parm_table[i].p_class == P_GLOBAL &&
3595 !(parm_table[i].flags & FLAG_META) &&
3596 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3597 if (defaults_saved && is_default(i))
3599 fprintf(f, "\t%s = ", parm_table[i].label);
3600 print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3605 if (Globals.param_opt != NULL) {
3606 data = Globals.param_opt;
3608 fprintf(f, "\t%s = %s\n", data->key, data->value);
3615 /***************************************************************************
3616 Return true if a local parameter is currently set to the global default.
3617 ***************************************************************************/
3619 bool lp_is_default(int snum, struct parm_struct *parm)
3621 return equal_parameter(parm->type,
3622 lp_parm_ptr(ServicePtrs[snum], parm),
3623 lp_parm_ptr(NULL, parm));
3626 /***************************************************************************
3627 Display the contents of a single services record.
3628 ***************************************************************************/
3630 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3633 struct parmlist_entry *data;
3635 if (pService != &sDefault)
3636 fprintf(f, "[%s]\n", pService->szService);
3638 for (i = 0; parm_table[i].label; i++) {
3640 if (parm_table[i].p_class == P_LOCAL &&
3641 !(parm_table[i].flags & FLAG_META) &&
3642 (*parm_table[i].label != '-') &&
3643 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3645 if (pService == &sDefault) {
3646 if (defaults_saved && is_default(i))
3649 if (equal_parameter(parm_table[i].type,
3650 lp_parm_ptr(pService, &parm_table[i]),
3651 lp_parm_ptr(NULL, &parm_table[i])))
3655 fprintf(f, "\t%s = ", parm_table[i].label);
3656 print_parameter(&parm_table[i],
3657 lp_parm_ptr(pService, &parm_table[i]),
3663 if (pService->param_opt != NULL) {
3664 data = pService->param_opt;
3666 fprintf(f, "\t%s = %s\n", data->key, data->value);
3672 /***************************************************************************
3673 Display the contents of a parameter of a single services record.
3674 ***************************************************************************/
3676 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3679 bool result = false;
3682 fstring local_parm_name;
3684 const char *parm_opt_value;
3686 /* check for parametrical option */
3687 fstrcpy( local_parm_name, parm_name);
3688 parm_opt = strchr( local_parm_name, ':');
3693 if (strlen(parm_opt)) {
3694 parm_opt_value = lp_parm_const_string( snum,
3695 local_parm_name, parm_opt, NULL);
3696 if (parm_opt_value) {
3697 printf( "%s\n", parm_opt_value);
3704 /* check for a key and print the value */
3711 for (i = 0; parm_table[i].label; i++) {
3712 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3713 !(parm_table[i].flags & FLAG_META) &&
3714 (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3715 (*parm_table[i].label != '-') &&
3716 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3721 ptr = lp_parm_ptr(NULL,
3724 ptr = lp_parm_ptr(ServicePtrs[snum],
3728 print_parameter(&parm_table[i],
3739 /***************************************************************************
3740 Return info about the requested parameter (given as a string).
3741 Return NULL when the string is not a valid parameter name.
3742 ***************************************************************************/
3744 struct parm_struct *lp_get_parameter(const char *param_name)
3746 int num = map_parameter(param_name);
3752 return &parm_table[num];
3755 /***************************************************************************
3756 Return info about the next parameter in a service.
3757 snum==GLOBAL_SECTION_SNUM gives the globals.
3758 Return NULL when out of parameters.
3759 ***************************************************************************/
3761 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3764 /* do the globals */
3765 for (; parm_table[*i].label; (*i)++) {
3766 if (parm_table[*i].p_class == P_SEPARATOR)
3767 return &parm_table[(*i)++];
3769 if ((*parm_table[*i].label == '-'))
3773 && (parm_table[*i].offset ==
3774 parm_table[(*i) - 1].offset)
3775 && (parm_table[*i].p_class ==
3776 parm_table[(*i) - 1].p_class))
3779 if (is_default(*i) && !allparameters)
3782 return &parm_table[(*i)++];
3785 struct loadparm_service *pService = ServicePtrs[snum];
3787 for (; parm_table[*i].label; (*i)++) {
3788 if (parm_table[*i].p_class == P_SEPARATOR)
3789 return &parm_table[(*i)++];
3791 if (parm_table[*i].p_class == P_LOCAL &&
3792 (*parm_table[*i].label != '-') &&
3794 (parm_table[*i].offset !=
3795 parm_table[(*i) - 1].offset)))
3797 if (allparameters ||
3798 !equal_parameter(parm_table[*i].type,
3799 lp_parm_ptr(pService,
3804 return &parm_table[(*i)++];
3815 /***************************************************************************
3816 Display the contents of a single copy structure.
3817 ***************************************************************************/
3818 static void dump_copy_map(bool *pcopymap)
3824 printf("\n\tNon-Copied parameters:\n");
3826 for (i = 0; parm_table[i].label; i++)
3827 if (parm_table[i].p_class == P_LOCAL &&
3828 parm_table[i].ptr && !pcopymap[i] &&
3829 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3831 printf("\t\t%s\n", parm_table[i].label);
3836 /***************************************************************************
3837 Return TRUE if the passed service number is within range.
3838 ***************************************************************************/
3840 bool lp_snum_ok(int iService)
3842 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3845 /***************************************************************************
3846 Auto-load some home services.
3847 ***************************************************************************/
3849 static void lp_add_auto_services(char *str)
3859 s = SMB_STRDUP(str);
3863 homes = lp_servicenumber(HOMES_NAME);
3865 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3866 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3869 if (lp_servicenumber(p) >= 0)
3872 home = get_user_home_dir(talloc_tos(), p);
3874 if (home && home[0] && homes >= 0)
3875 lp_add_home(p, homes, p, home);
3882 /***************************************************************************
3883 Auto-load one printer.
3884 ***************************************************************************/
3886 void lp_add_one_printer(const char *name, const char *comment,
3887 const char *location, void *pdata)
3889 int printers = lp_servicenumber(PRINTERS_NAME);
3892 if (lp_servicenumber(name) < 0) {
3893 lp_add_printer(name, printers);
3894 if ((i = lp_servicenumber(name)) >= 0) {
3895 string_set(&ServicePtrs[i]->comment, comment);
3896 ServicePtrs[i]->autoloaded = true;
3901 /***************************************************************************
3902 Have we loaded a services file yet?
3903 ***************************************************************************/
3905 bool lp_loaded(void)
3910 /***************************************************************************
3911 Unload unused services.
3912 ***************************************************************************/
3914 void lp_killunused(struct smbd_server_connection *sconn,
3915 bool (*snumused) (struct smbd_server_connection *, int))
3918 for (i = 0; i < iNumServices; i++) {
3922 /* don't kill autoloaded or usershare services */
3923 if ( ServicePtrs[i]->autoloaded ||
3924 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3928 if (!snumused || !snumused(sconn, i)) {
3929 free_service_byindex(i);
3935 * Kill all except autoloaded and usershare services - convenience wrapper
3937 void lp_kill_all_services(void)
3939 lp_killunused(NULL, NULL);
3942 /***************************************************************************
3944 ***************************************************************************/
3946 void lp_killservice(int iServiceIn)
3948 if (VALID(iServiceIn)) {
3949 free_service_byindex(iServiceIn);
3953 /***************************************************************************
3954 Save the curent values of all global and sDefault parameters into the
3955 defaults union. This allows swat and testparm to show only the
3956 changed (ie. non-default) parameters.
3957 ***************************************************************************/
3959 static void lp_save_defaults(void)
3962 for (i = 0; parm_table[i].label; i++) {
3963 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3964 && parm_table[i].p_class == parm_table[i - 1].p_class)
3966 switch (parm_table[i].type) {
3969 parm_table[i].def.lvalue = str_list_copy(
3970 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3974 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3978 parm_table[i].def.bvalue =
3979 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3982 parm_table[i].def.cvalue =
3983 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3989 parm_table[i].def.ivalue =
3990 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3996 defaults_saved = true;
3999 /***********************************************************
4000 If we should send plaintext/LANMAN passwords in the clinet
4001 ************************************************************/
4003 static void set_allowed_client_auth(void)
4005 if (Globals.bClientNTLMv2Auth) {
4006 Globals.bClientLanManAuth = false;
4008 if (!Globals.bClientLanManAuth) {
4009 Globals.bClientPlaintextAuth = false;
4013 /***************************************************************************
4015 The following code allows smbd to read a user defined share file.
4016 Yes, this is my intent. Yes, I'm comfortable with that...
4018 THE FOLLOWING IS SECURITY CRITICAL CODE.
4020 It washes your clothes, it cleans your house, it guards you while you sleep...
4021 Do not f%^k with it....
4022 ***************************************************************************/
4024 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4026 /***************************************************************************
4027 Check allowed stat state of a usershare file.
4028 Ensure we print out who is dicking with us so the admin can
4029 get their sorry ass fired.
4030 ***************************************************************************/
4032 static bool check_usershare_stat(const char *fname,
4033 const SMB_STRUCT_STAT *psbuf)
4035 if (!S_ISREG(psbuf->st_ex_mode)) {
4036 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4037 "not a regular file\n",
4038 fname, (unsigned int)psbuf->st_ex_uid ));
4042 /* Ensure this doesn't have the other write bit set. */
4043 if (psbuf->st_ex_mode & S_IWOTH) {
4044 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4045 "public write. Refusing to allow as a usershare file.\n",
4046 fname, (unsigned int)psbuf->st_ex_uid ));
4050 /* Should be 10k or less. */
4051 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4052 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4053 "too large (%u) to be a user share file.\n",
4054 fname, (unsigned int)psbuf->st_ex_uid,
4055 (unsigned int)psbuf->st_ex_size ));
4062 /***************************************************************************
4063 Parse the contents of a usershare file.
4064 ***************************************************************************/
4066 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4067 SMB_STRUCT_STAT *psbuf,
4068 const char *servicename,
4072 char **pp_sharepath,
4074 char **pp_cp_servicename,
4075 struct security_descriptor **ppsd,
4078 const char **prefixallowlist = lp_usershare_prefix_allow_list();
4079 const char **prefixdenylist = lp_usershare_prefix_deny_list();
4082 SMB_STRUCT_STAT sbuf;
4083 char *sharepath = NULL;
4084 char *comment = NULL;
4086 *pp_sharepath = NULL;
4089 *pallow_guest = false;
4092 return USERSHARE_MALFORMED_FILE;
4095 if (strcmp(lines[0], "#VERSION 1") == 0) {
4097 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4100 return USERSHARE_MALFORMED_FILE;
4103 return USERSHARE_BAD_VERSION;
4106 if (strncmp(lines[1], "path=", 5) != 0) {
4107 return USERSHARE_MALFORMED_PATH;
4110 sharepath = talloc_strdup(ctx, &lines[1][5]);
4112 return USERSHARE_POSIX_ERR;
4114 trim_string(sharepath, " ", " ");
4116 if (strncmp(lines[2], "comment=", 8) != 0) {
4117 return USERSHARE_MALFORMED_COMMENT_DEF;
4120 comment = talloc_strdup(ctx, &lines[2][8]);
4122 return USERSHARE_POSIX_ERR;
4124 trim_string(comment, " ", " ");
4125 trim_char(comment, '"', '"');
4127 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4128 return USERSHARE_MALFORMED_ACL_DEF;
4131 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4132 return USERSHARE_ACL_ERR;
4136 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4137 return USERSHARE_MALFORMED_ACL_DEF;
4139 if (lines[4][9] == 'y') {
4140 *pallow_guest = true;
4143 /* Backwards compatible extension to file version #2. */
4145 if (strncmp(lines[5], "sharename=", 10) != 0) {
4146 return USERSHARE_MALFORMED_SHARENAME_DEF;
4148 if (!strequal(&lines[5][10], servicename)) {
4149 return USERSHARE_BAD_SHARENAME;
4151 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4152 if (!*pp_cp_servicename) {
4153 return USERSHARE_POSIX_ERR;
4158 if (*pp_cp_servicename == NULL) {
4159 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4160 if (!*pp_cp_servicename) {
4161 return USERSHARE_POSIX_ERR;
4165 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4166 /* Path didn't change, no checks needed. */
4167 *pp_sharepath = sharepath;
4168 *pp_comment = comment;
4169 return USERSHARE_OK;
4172 /* The path *must* be absolute. */
4173 if (sharepath[0] != '/') {
4174 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4175 servicename, sharepath));
4176 return USERSHARE_PATH_NOT_ABSOLUTE;
4179 /* If there is a usershare prefix deny list ensure one of these paths
4180 doesn't match the start of the user given path. */
4181 if (prefixdenylist) {
4183 for ( i=0; prefixdenylist[i]; i++ ) {
4184 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4185 servicename, i, prefixdenylist[i], sharepath ));
4186 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4187 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4188 "usershare prefix deny list entries.\n",
4189 servicename, sharepath));
4190 return USERSHARE_PATH_IS_DENIED;
4195 /* If there is a usershare prefix allow list ensure one of these paths
4196 does match the start of the user given path. */
4198 if (prefixallowlist) {
4200 for ( i=0; prefixallowlist[i]; i++ ) {
4201 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4202 servicename, i, prefixallowlist[i], sharepath ));
4203 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4207 if (prefixallowlist[i] == NULL) {
4208 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4209 "usershare prefix allow list entries.\n",
4210 servicename, sharepath));
4211 return USERSHARE_PATH_NOT_ALLOWED;
4215 /* Ensure this is pointing to a directory. */
4216 dp = opendir(sharepath);
4219 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4220 servicename, sharepath));
4221 return USERSHARE_PATH_NOT_DIRECTORY;
4224 /* Ensure the owner of the usershare file has permission to share
4227 if (sys_stat(sharepath, &sbuf, false) == -1) {
4228 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4229 servicename, sharepath, strerror(errno) ));
4231 return USERSHARE_POSIX_ERR;
4236 if (!S_ISDIR(sbuf.st_ex_mode)) {
4237 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4238 servicename, sharepath ));
4239 return USERSHARE_PATH_NOT_DIRECTORY;
4242 /* Check if sharing is restricted to owner-only. */
4243 /* psbuf is the stat of the usershare definition file,
4244 sbuf is the stat of the target directory to be shared. */
4246 if (lp_usershare_owner_only()) {
4247 /* root can share anything. */
4248 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4249 return USERSHARE_PATH_NOT_ALLOWED;
4253 *pp_sharepath = sharepath;
4254 *pp_comment = comment;
4255 return USERSHARE_OK;
4258 /***************************************************************************
4259 Deal with a usershare file.
4262 -1 - Bad name, invalid contents.
4263 - service name already existed and not a usershare, problem
4264 with permissions to share directory etc.
4265 ***************************************************************************/
4267 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4269 SMB_STRUCT_STAT sbuf;
4270 SMB_STRUCT_STAT lsbuf;
4272 char *sharepath = NULL;
4273 char *comment = NULL;
4274 char *cp_service_name = NULL;
4275 char **lines = NULL;
4279 TALLOC_CTX *ctx = talloc_stackframe();
4280 struct security_descriptor *psd = NULL;
4281 bool guest_ok = false;
4282 char *canon_name = NULL;
4283 bool added_service = false;
4286 /* Ensure share name doesn't contain invalid characters. */
4287 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4288 DEBUG(0,("process_usershare_file: share name %s contains "
4289 "invalid characters (any of %s)\n",
4290 file_name, INVALID_SHARENAME_CHARS ));
4294 canon_name = canonicalize_servicename(ctx, file_name);
4299 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4304 /* Minimize the race condition by doing an lstat before we
4305 open and fstat. Ensure this isn't a symlink link. */
4307 if (sys_lstat(fname, &lsbuf, false) != 0) {
4308 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4309 fname, strerror(errno) ));
4313 /* This must be a regular file, not a symlink, directory or
4314 other strange filetype. */
4315 if (!check_usershare_stat(fname, &lsbuf)) {
4323 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4328 if (NT_STATUS_IS_OK(status) &&
4329 (data.dptr != NULL) &&
4330 (data.dsize == sizeof(iService))) {
4331 memcpy(&iService, data.dptr, sizeof(iService));
4335 if (iService != -1 &&
4336 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4337 &lsbuf.st_ex_mtime) == 0) {
4338 /* Nothing changed - Mark valid and return. */
4339 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4341 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4346 /* Try and open the file read only - no symlinks allowed. */
4348 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4350 fd = open(fname, O_RDONLY, 0);
4354 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4355 fname, strerror(errno) ));
4359 /* Now fstat to be *SURE* it's a regular file. */
4360 if (sys_fstat(fd, &sbuf, false) != 0) {
4362 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4363 fname, strerror(errno) ));
4367 /* Is it the same dev/inode as was lstated ? */
4368 if (!check_same_stat(&lsbuf, &sbuf)) {
4370 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4371 "Symlink spoofing going on ?\n", fname ));
4375 /* This must be a regular file, not a symlink, directory or
4376 other strange filetype. */
4377 if (!check_usershare_stat(fname, &sbuf)) {
4381 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4384 if (lines == NULL) {
4385 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4386 fname, (unsigned int)sbuf.st_ex_uid ));
4390 if (parse_usershare_file(ctx, &sbuf, file_name,
4391 iService, lines, numlines, &sharepath,
4392 &comment, &cp_service_name,
4393 &psd, &guest_ok) != USERSHARE_OK) {
4397 /* Everything ok - add the service possibly using a template. */
4399 const struct loadparm_service *sp = &sDefault;
4400 if (snum_template != -1) {
4401 sp = ServicePtrs[snum_template];
4404 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4405 DEBUG(0, ("process_usershare_file: Failed to add "
4406 "new service %s\n", cp_service_name));
4410 added_service = true;
4412 /* Read only is controlled by usershare ACL below. */
4413 ServicePtrs[iService]->bRead_only = false;
4416 /* Write the ACL of the new/modified share. */
4417 if (!set_share_security(canon_name, psd)) {
4418 DEBUG(0, ("process_usershare_file: Failed to set share "
4419 "security for user share %s\n",
4424 /* If from a template it may be marked invalid. */
4425 ServicePtrs[iService]->valid = true;
4427 /* Set the service as a valid usershare. */
4428 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4430 /* Set guest access. */
4431 if (lp_usershare_allow_guests()) {
4432 ServicePtrs[iService]->bGuest_ok = guest_ok;
4435 /* And note when it was loaded. */
4436 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4437 string_set(&ServicePtrs[iService]->szPath, sharepath);
4438 string_set(&ServicePtrs[iService]->comment, comment);
4444 if (ret == -1 && iService != -1 && added_service) {
4445 lp_remove_service(iService);
4453 /***************************************************************************
4454 Checks if a usershare entry has been modified since last load.
4455 ***************************************************************************/
4457 static bool usershare_exists(int iService, struct timespec *last_mod)
4459 SMB_STRUCT_STAT lsbuf;
4460 const char *usersharepath = Globals.szUsersharePath;
4463 if (asprintf(&fname, "%s/%s",
4465 ServicePtrs[iService]->szService) < 0) {
4469 if (sys_lstat(fname, &lsbuf, false) != 0) {
4474 if (!S_ISREG(lsbuf.st_ex_mode)) {
4480 *last_mod = lsbuf.st_ex_mtime;
4484 /***************************************************************************
4485 Load a usershare service by name. Returns a valid servicenumber or -1.
4486 ***************************************************************************/
4488 int load_usershare_service(const char *servicename)
4490 SMB_STRUCT_STAT sbuf;
4491 const char *usersharepath = Globals.szUsersharePath;
4492 int max_user_shares = Globals.iUsershareMaxShares;
4493 int snum_template = -1;
4495 if (*usersharepath == 0 || max_user_shares == 0) {
4499 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4500 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4501 usersharepath, strerror(errno) ));
4505 if (!S_ISDIR(sbuf.st_ex_mode)) {
4506 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4512 * This directory must be owned by root, and have the 't' bit set.
4513 * It also must not be writable by "other".
4517 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4519 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4521 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4522 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4527 /* Ensure the template share exists if it's set. */
4528 if (Globals.szUsershareTemplateShare[0]) {
4529 /* We can't use lp_servicenumber here as we are recommending that
4530 template shares have -valid=false set. */
4531 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4532 if (ServicePtrs[snum_template]->szService &&
4533 strequal(ServicePtrs[snum_template]->szService,
4534 Globals.szUsershareTemplateShare)) {
4539 if (snum_template == -1) {
4540 DEBUG(0,("load_usershare_service: usershare template share %s "
4541 "does not exist.\n",
4542 Globals.szUsershareTemplateShare ));
4547 return process_usershare_file(usersharepath, servicename, snum_template);
4550 /***************************************************************************
4551 Load all user defined shares from the user share directory.
4552 We only do this if we're enumerating the share list.
4553 This is the function that can delete usershares that have
4555 ***************************************************************************/
4557 int load_usershare_shares(struct smbd_server_connection *sconn,
4558 bool (*snumused) (struct smbd_server_connection *, int))
4561 SMB_STRUCT_STAT sbuf;
4563 int num_usershares = 0;
4564 int max_user_shares = Globals.iUsershareMaxShares;
4565 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4566 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4567 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4569 int snum_template = -1;
4570 const char *usersharepath = Globals.szUsersharePath;
4571 int ret = lp_numservices();
4572 TALLOC_CTX *tmp_ctx;
4574 if (max_user_shares == 0 || *usersharepath == '\0') {
4575 return lp_numservices();
4578 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4579 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4580 usersharepath, strerror(errno) ));
4585 * This directory must be owned by root, and have the 't' bit set.
4586 * It also must not be writable by "other".
4590 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4592 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4594 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4595 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4600 /* Ensure the template share exists if it's set. */
4601 if (Globals.szUsershareTemplateShare[0]) {
4602 /* We can't use lp_servicenumber here as we are recommending that
4603 template shares have -valid=false set. */
4604 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4605 if (ServicePtrs[snum_template]->szService &&
4606 strequal(ServicePtrs[snum_template]->szService,
4607 Globals.szUsershareTemplateShare)) {
4612 if (snum_template == -1) {
4613 DEBUG(0,("load_usershare_shares: usershare template share %s "
4614 "does not exist.\n",
4615 Globals.szUsershareTemplateShare ));
4620 /* Mark all existing usershares as pending delete. */
4621 for (iService = iNumServices - 1; iService >= 0; iService--) {
4622 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4623 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4627 dp = opendir(usersharepath);
4629 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4630 usersharepath, strerror(errno) ));
4634 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4636 num_dir_entries++ ) {
4638 const char *n = de->d_name;
4640 /* Ignore . and .. */
4642 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4648 /* Temporary file used when creating a share. */
4649 num_tmp_dir_entries++;
4652 /* Allow 20% tmp entries. */
4653 if (num_tmp_dir_entries > allowed_tmp_entries) {
4654 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4655 "in directory %s\n",
4656 num_tmp_dir_entries, usersharepath));
4660 r = process_usershare_file(usersharepath, n, snum_template);
4662 /* Update the services count. */
4664 if (num_usershares >= max_user_shares) {
4665 DEBUG(0,("load_usershare_shares: max user shares reached "
4666 "on file %s in directory %s\n",
4667 n, usersharepath ));
4670 } else if (r == -1) {
4671 num_bad_dir_entries++;
4674 /* Allow 20% bad entries. */
4675 if (num_bad_dir_entries > allowed_bad_entries) {
4676 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4677 "in directory %s\n",
4678 num_bad_dir_entries, usersharepath));
4682 /* Allow 20% bad entries. */
4683 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4684 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4685 "in directory %s\n",
4686 num_dir_entries, usersharepath));
4693 /* Sweep through and delete any non-refreshed usershares that are
4694 not currently in use. */
4695 tmp_ctx = talloc_stackframe();
4696 for (iService = iNumServices - 1; iService >= 0; iService--) {
4697 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4700 if (snumused && snumused(sconn, iService)) {
4704 servname = lp_servicename(tmp_ctx, iService);
4706 /* Remove from the share ACL db. */
4707 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4709 delete_share_security(servname);
4710 free_service_byindex(iService);
4713 talloc_free(tmp_ctx);
4715 return lp_numservices();
4718 /********************************************************
4719 Destroy global resources allocated in this file
4720 ********************************************************/
4722 void gfree_loadparm(void)
4728 /* Free resources allocated to services */
4730 for ( i = 0; i < iNumServices; i++ ) {
4732 free_service_byindex(i);
4736 SAFE_FREE( ServicePtrs );
4739 /* Now release all resources allocated to global
4740 parameters and the default service */
4742 free_global_parameters();
4746 /***************************************************************************
4747 Allow client apps to specify that they are a client
4748 ***************************************************************************/
4749 static void lp_set_in_client(bool b)
4755 /***************************************************************************
4756 Determine if we're running in a client app
4757 ***************************************************************************/
4758 static bool lp_is_in_client(void)
4763 /***************************************************************************
4764 Load the services array from the services file. Return true on success,
4766 ***************************************************************************/
4768 static bool lp_load_ex(const char *pszFname,
4772 bool initialize_globals,
4773 bool allow_include_registry,
4774 bool load_all_shares)
4781 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4783 bInGlobalSection = true;
4784 bGlobalOnly = global_only;
4785 bAllowIncludeRegistry = allow_include_registry;
4787 init_globals(initialize_globals);
4791 if (save_defaults) {
4796 if (!initialize_globals) {
4797 free_param_opts(&Globals.param_opt);
4798 apply_lp_set_cmdline();
4801 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4803 /* We get sections first, so have to start 'behind' to make up */
4806 if (lp_config_backend_is_file()) {
4807 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4808 current_user_info.domain,
4811 smb_panic("lp_load_ex: out of memory");
4814 add_to_file_list(pszFname, n2);
4816 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4819 /* finish up the last section */
4820 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4822 if (iServiceIndex >= 0) {
4823 bRetval = service_ok(iServiceIndex);
4827 if (lp_config_backend_is_registry()) {
4828 /* config backend changed to registry in config file */
4830 * We need to use this extra global variable here to
4831 * survive restart: init_globals uses this as a default
4832 * for ConfigBackend. Otherwise, init_globals would
4833 * send us into an endless loop here.
4835 config_backend = CONFIG_BACKEND_REGISTRY;
4837 DEBUG(1, ("lp_load_ex: changing to config backend "
4840 lp_kill_all_services();
4841 return lp_load_ex(pszFname, global_only, save_defaults,
4842 add_ipc, initialize_globals,
4843 allow_include_registry,
4846 } else if (lp_config_backend_is_registry()) {
4847 bRetval = process_registry_globals();
4849 DEBUG(0, ("Illegal config backend given: %d\n",
4850 lp_config_backend()));
4854 if (bRetval && lp_registry_shares()) {
4855 if (load_all_shares) {
4856 bRetval = process_registry_shares();
4858 bRetval = reload_registry_shares();
4863 char *serv = lp_auto_services(talloc_tos());
4864 lp_add_auto_services(serv);
4869 /* When 'restrict anonymous = 2' guest connections to ipc$
4871 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4872 if ( lp_enable_asu_support() ) {
4873 lp_add_ipc("ADMIN$", false);
4877 set_allowed_client_auth();
4879 if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4880 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4881 lp_passwordserver()));
4886 /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4887 /* if bWINSsupport is true and we are in the client */
4888 if (lp_is_in_client() && Globals.bWINSsupport) {
4889 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4894 fault_configure(smb_panic_s3);
4896 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4897 const char **vfs_objects = lp_vfs_objects(-1);
4898 if (!vfs_objects || !vfs_objects[0]) {
4899 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
4900 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
4901 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
4902 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
4904 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
4907 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4910 bAllowIncludeRegistry = true;
4915 bool lp_load(const char *pszFname,
4919 bool initialize_globals)
4921 return lp_load_ex(pszFname,
4926 true, /* allow_include_registry */
4927 false); /* load_all_shares*/
4930 bool lp_load_initial_only(const char *pszFname)
4932 return lp_load_ex(pszFname,
4933 true, /* global only */
4934 false, /* save_defaults */
4935 false, /* add_ipc */
4936 true, /* initialize_globals */
4937 false, /* allow_include_registry */
4938 false); /* load_all_shares*/
4942 * most common lp_load wrapper, loading only the globals
4944 bool lp_load_global(const char *file_name)
4946 return lp_load_ex(file_name,
4947 true, /* global_only */
4948 false, /* save_defaults */
4949 false, /* add_ipc */
4950 true, /* initialize_globals */
4951 true, /* allow_include_registry */
4952 false); /* load_all_shares*/
4956 * lp_load wrapper, especially for clients
4958 bool lp_load_client(const char *file_name)
4960 lp_set_in_client(true);
4962 return lp_load_global(file_name);
4966 * lp_load wrapper, loading only globals, but intended
4967 * for subsequent calls, not reinitializing the globals
4970 bool lp_load_global_no_reinit(const char *file_name)
4972 return lp_load_ex(file_name,
4973 true, /* global_only */
4974 false, /* save_defaults */
4975 false, /* add_ipc */
4976 false, /* initialize_globals */
4977 true, /* allow_include_registry */
4978 false); /* load_all_shares*/
4982 * lp_load wrapper, especially for clients, no reinitialization
4984 bool lp_load_client_no_reinit(const char *file_name)
4986 lp_set_in_client(true);
4988 return lp_load_global_no_reinit(file_name);
4991 bool lp_load_with_registry_shares(const char *pszFname,
4995 bool initialize_globals)
4997 return lp_load_ex(pszFname,
5002 true, /* allow_include_registry */
5003 true); /* load_all_shares*/
5006 /***************************************************************************
5007 Return the max number of services.
5008 ***************************************************************************/
5010 int lp_numservices(void)
5012 return (iNumServices);
5015 /***************************************************************************
5016 Display the contents of the services array in human-readable form.
5017 ***************************************************************************/
5019 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5024 defaults_saved = false;
5028 dump_a_service(&sDefault, f);
5030 for (iService = 0; iService < maxtoprint; iService++) {
5032 lp_dump_one(f, show_defaults, iService);
5036 /***************************************************************************
5037 Display the contents of one service in human-readable form.
5038 ***************************************************************************/
5040 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5043 if (ServicePtrs[snum]->szService[0] == '\0')
5045 dump_a_service(ServicePtrs[snum], f);
5049 /***************************************************************************
5050 Return the number of the service with the given name, or -1 if it doesn't
5051 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5052 getservicebyname()! This works ONLY if all services have been loaded, and
5053 does not copy the found service.
5054 ***************************************************************************/
5056 int lp_servicenumber(const char *pszServiceName)
5059 fstring serviceName;
5061 if (!pszServiceName) {
5062 return GLOBAL_SECTION_SNUM;
5065 for (iService = iNumServices - 1; iService >= 0; iService--) {
5066 if (VALID(iService) && ServicePtrs[iService]->szService) {
5068 * The substitution here is used to support %U is
5071 fstrcpy(serviceName, ServicePtrs[iService]->szService);
5072 standard_sub_basic(get_current_username(),
5073 current_user_info.domain,
5074 serviceName,sizeof(serviceName));
5075 if (strequal(serviceName, pszServiceName)) {
5081 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5082 struct timespec last_mod;
5084 if (!usershare_exists(iService, &last_mod)) {
5085 /* Remove the share security tdb entry for it. */
5086 delete_share_security(lp_servicename(talloc_tos(), iService));
5087 /* Remove it from the array. */
5088 free_service_byindex(iService);
5089 /* Doesn't exist anymore. */
5090 return GLOBAL_SECTION_SNUM;
5093 /* Has it been modified ? If so delete and reload. */
5094 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5096 /* Remove it from the array. */
5097 free_service_byindex(iService);
5098 /* and now reload it. */
5099 iService = load_usershare_service(pszServiceName);
5104 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5105 return GLOBAL_SECTION_SNUM;
5111 /*******************************************************************
5112 A useful volume label function.
5113 ********************************************************************/
5115 const char *volume_label(TALLOC_CTX *ctx, int snum)
5118 const char *label = lp_volume(ctx, snum);
5120 label = lp_servicename(ctx, snum);
5123 /* This returns a 33 byte guarenteed null terminated string. */
5124 ret = talloc_strndup(ctx, label, 32);
5131 /*******************************************************************
5132 Get the default server type we will announce as via nmbd.
5133 ********************************************************************/
5135 int lp_default_server_announce(void)
5137 int default_server_announce = 0;
5138 default_server_announce |= SV_TYPE_WORKSTATION;
5139 default_server_announce |= SV_TYPE_SERVER;
5140 default_server_announce |= SV_TYPE_SERVER_UNIX;
5142 /* note that the flag should be set only if we have a
5143 printer service but nmbd doesn't actually load the
5144 services so we can't tell --jerry */
5146 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5148 default_server_announce |= SV_TYPE_SERVER_NT;
5149 default_server_announce |= SV_TYPE_NT;
5151 switch (lp_server_role()) {
5152 case ROLE_DOMAIN_MEMBER:
5153 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5155 case ROLE_DOMAIN_PDC:
5156 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5158 case ROLE_DOMAIN_BDC:
5159 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5161 case ROLE_STANDALONE:
5165 if (lp_time_server())
5166 default_server_announce |= SV_TYPE_TIME_SOURCE;
5168 if (lp_host_msdfs())
5169 default_server_announce |= SV_TYPE_DFS_SERVER;
5171 return default_server_announce;
5174 /***********************************************************
5175 If we are PDC then prefer us as DMB
5176 ************************************************************/
5178 bool lp_domain_master(void)
5180 if (Globals.domain_master == Auto)
5181 return (lp_server_role() == ROLE_DOMAIN_PDC);
5183 return (bool)Globals.domain_master;
5186 /***********************************************************
5187 If we are PDC then prefer us as DMB
5188 ************************************************************/
5190 static bool lp_domain_master_true_or_auto(void)
5192 if (Globals.domain_master) /* auto or yes */
5198 /***********************************************************
5199 If we are DMB then prefer us as LMB
5200 ************************************************************/
5202 bool lp_preferred_master(void)
5204 if (Globals.iPreferredMaster == Auto)
5205 return (lp_local_master() && lp_domain_master());
5207 return (bool)Globals.iPreferredMaster;
5210 /*******************************************************************
5212 ********************************************************************/
5214 void lp_remove_service(int snum)
5216 ServicePtrs[snum]->valid = false;
5217 invalid_services[num_invalid_services++] = snum;
5220 /*******************************************************************
5222 ********************************************************************/
5224 void lp_copy_service(int snum, const char *new_name)
5226 do_section(new_name, NULL);
5228 snum = lp_servicenumber(new_name);
5230 char *name = lp_servicename(talloc_tos(), snum);
5231 lp_do_parameter(snum, "copy", name);
5236 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5238 const char *ret = lp__printername(talloc_tos(), snum);
5239 if (ret == NULL || *ret == '\0') {
5240 ret = lp_const_servicename(snum);
5247 /***********************************************************
5248 Allow daemons such as winbindd to fix their logfile name.
5249 ************************************************************/
5251 void lp_set_logfile(const char *name)
5253 string_set(&Globals.logfile, name);
5254 debug_set_logfile(name);
5257 /*******************************************************************
5258 Return the max print jobs per queue.
5259 ********************************************************************/
5261 int lp_maxprintjobs(int snum)
5263 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5264 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5265 maxjobs = PRINT_MAX_JOBID - 1;
5270 const char *lp_printcapname(void)
5272 if ((Globals.szPrintcapname != NULL) &&
5273 (Globals.szPrintcapname[0] != '\0'))
5274 return Globals.szPrintcapname;
5276 if (sDefault.iPrinting == PRINT_CUPS) {
5280 if (sDefault.iPrinting == PRINT_BSD)
5281 return "/etc/printcap";
5283 return PRINTCAP_NAME;
5286 static uint32 spoolss_state;
5288 bool lp_disable_spoolss( void )
5290 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5291 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5293 return spoolss_state == SVCCTL_STOPPED ? true : false;
5296 void lp_set_spoolss_state( uint32 state )
5298 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5300 spoolss_state = state;
5303 uint32 lp_get_spoolss_state( void )
5305 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5308 /*******************************************************************
5309 Ensure we don't use sendfile if server smb signing is active.
5310 ********************************************************************/
5312 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5314 bool sign_active = false;
5316 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5317 if (get_Protocol() < PROTOCOL_NT1) {
5320 if (signing_state) {
5321 sign_active = smb_signing_is_active(signing_state);
5323 return (lp__use_sendfile(snum) &&
5324 (get_remote_arch() != RA_WIN95) &&
5328 /*******************************************************************
5329 Turn off sendfile if we find the underlying OS doesn't support it.
5330 ********************************************************************/
5332 void set_use_sendfile(int snum, bool val)
5334 if (LP_SNUM_OK(snum))
5335 ServicePtrs[snum]->bUseSendfile = val;
5337 sDefault.bUseSendfile = val;
5340 /*******************************************************************
5341 Turn off storing DOS attributes if this share doesn't support it.
5342 ********************************************************************/
5344 void set_store_dos_attributes(int snum, bool val)
5346 if (!LP_SNUM_OK(snum))
5348 ServicePtrs[(snum)]->bStoreDosAttributes = val;
5351 void lp_set_mangling_method(const char *new_method)
5353 string_set(&Globals.szManglingMethod, new_method);
5356 /*******************************************************************
5357 Global state for POSIX pathname processing.
5358 ********************************************************************/
5360 static bool posix_pathnames;
5362 bool lp_posix_pathnames(void)
5364 return posix_pathnames;
5367 /*******************************************************************
5368 Change everything needed to ensure POSIX pathname processing (currently
5370 ********************************************************************/
5372 void lp_set_posix_pathnames(void)
5374 posix_pathnames = true;
5377 /*******************************************************************
5378 Global state for POSIX lock processing - CIFS unix extensions.
5379 ********************************************************************/
5381 bool posix_default_lock_was_set;
5382 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5384 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5386 if (posix_default_lock_was_set) {
5387 return posix_cifsx_locktype;
5389 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5393 /*******************************************************************
5394 ********************************************************************/
5396 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5398 posix_default_lock_was_set = true;
5399 posix_cifsx_locktype = val;
5402 int lp_min_receive_file_size(void)
5404 if (Globals.iminreceivefile < 0) {
5407 return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5410 /*******************************************************************
5411 Safe wide links checks.
5412 This helper function always verify the validity of wide links,
5413 even after a configuration file reload.
5414 ********************************************************************/
5416 static bool lp_widelinks_internal(int snum)
5418 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5419 sDefault.bWidelinks);
5422 void widelinks_warning(int snum)
5424 if (lp_allow_insecure_widelinks()) {
5428 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5429 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5430 "These parameters are incompatible. "
5431 "Wide links will be disabled for this share.\n",
5432 lp_servicename(talloc_tos(), snum) ));
5436 bool lp_widelinks(int snum)
5438 /* wide links is always incompatible with unix extensions */
5439 if (lp_unix_extensions()) {
5441 * Unless we have "allow insecure widelinks"
5444 if (!lp_allow_insecure_widelinks()) {
5449 return lp_widelinks_internal(snum);
5452 bool lp_writeraw(void)
5454 if (lp_async_smb_echo_handler()) {
5457 return lp__writeraw();
5460 bool lp_readraw(void)
5462 if (lp_async_smb_echo_handler()) {
5465 return lp__readraw();
5468 int lp_server_role(void)
5470 return lp_find_server_role(lp__server_role(),
5472 lp__domain_logons(),
5473 lp_domain_master_true_or_auto());
5476 int lp_security(void)
5478 return lp_find_security(lp__server_role(),