script/autobuild.py: remove --rebase-master and --push-master options
[Samba/gebeck_regimport.git] / source3 / param / loadparm.c
blob61606ce9d20577b00df9c9a061c6a75020660f59
1 /*
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/>.
31 * Load parameters.
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.
37 * To add a parameter:
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
46 * Notes:
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
52 * careful!
56 #include "includes.h"
57 #include "system/filesys.h"
58 #include "util_tdb.h"
59 #include "lib/param/loadparm.h"
60 #include "printing.h"
61 #include "lib/smbconf/smbconf.h"
62 #include "lib/smbconf/smbconf_init.h"
64 #include "ads.h"
65 #include "../librpc/gen_ndr/svcctl.h"
66 #include "intl.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>
74 #endif
76 #ifdef HAVE_HTTPCONNECTENCRYPT
77 #include <cups/http.h>
78 #endif
80 #ifdef CLUSTER_SUPPORT
81 #include "ctdb_private.h"
82 #endif
84 bool bLoaded = false;
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
91 * from registry. */
92 #ifndef INCLUDE_REGISTRY_NAME
93 #define INCLUDE_REGISTRY_NAME "registry"
94 #endif
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; \
112 char *szRealm; \
113 char *loglevel; \
114 int iminreceivefile; \
115 char *szPrintcapname; \
116 int CupsEncrypt; \
117 int iPreferredMaster; \
118 char *szLdapMachineSuffix; \
119 char *szLdapUserSuffix; \
120 char *szLdapIdmapSuffix; \
121 char *szLdapGroupSuffix; \
122 char *szStateDir; \
123 char *szCacheDir; \
124 char *szUsershareTemplateShare; \
125 char *szIdmapUID; \
126 char *szIdmapGID; \
127 int winbindMaxDomainConnections; \
128 int ismb2_max_credits; \
129 char *tls_keyfile; \
130 char *tls_certfile; \
131 char *tls_cafile; \
132 char *tls_crlfile; \
133 char *tls_dhpfile; \
134 int bPreferredMaster;
136 #include "param/param_global.h"
138 static struct loadparm_global Globals;
140 /* This is a default service used to prime a services structure */
141 static struct loadparm_service sDefault =
143 .valid = true,
144 .autoloaded = false,
145 .usershare = 0,
146 .usershare_last_mod = {0, 0},
147 .szService = NULL,
148 .szPath = NULL,
149 .szUsername = NULL,
150 .szInvalidUsers = NULL,
151 .szValidUsers = NULL,
152 .szAdminUsers = NULL,
153 .szCopy = NULL,
154 .szInclude = NULL,
155 .szPreExec = NULL,
156 .szPostExec = NULL,
157 .szRootPreExec = NULL,
158 .szRootPostExec = NULL,
159 .szCupsOptions = NULL,
160 .szPrintcommand = NULL,
161 .szLpqcommand = NULL,
162 .szLprmcommand = NULL,
163 .szLppausecommand = NULL,
164 .szLpresumecommand = NULL,
165 .szQueuepausecommand = NULL,
166 .szQueueresumecommand = NULL,
167 .szPrintername = NULL,
168 .szPrintjobUsername = NULL,
169 .szDontdescend = NULL,
170 .szHostsallow = NULL,
171 .szHostsdeny = NULL,
172 .szMagicScript = NULL,
173 .szMagicOutput = NULL,
174 .szVetoFiles = NULL,
175 .szHideFiles = NULL,
176 .szVetoOplockFiles = NULL,
177 .comment = NULL,
178 .force_user = NULL,
179 .force_group = NULL,
180 .readlist = NULL,
181 .writelist = NULL,
182 .volume = NULL,
183 .fstype = NULL,
184 .szVfsObjects = NULL,
185 .szMSDfsProxy = NULL,
186 .szAioWriteBehind = NULL,
187 .szDfree = NULL,
188 .iMinPrintSpace = 0,
189 .iMaxPrintJobs = 1000,
190 .iMaxReportedPrintJobs = 0,
191 .iWriteCacheSize = 0,
192 .iCreate_mask = 0744,
193 .iCreate_force_mode = 0,
194 .iSecurity_mask = 0777,
195 .iSecurity_force_mode = 0,
196 .iDir_mask = 0755,
197 .iDir_force_mode = 0,
198 .iDir_Security_mask = 0777,
199 .iDir_Security_force_mode = 0,
200 .iMaxConnections = 0,
201 .iDefaultCase = CASE_LOWER,
202 .iPrinting = DEFAULT_PRINTING,
203 .iOplockContentionLimit = 2,
204 .iCSCPolicy = 0,
205 .iBlock_size = 1024,
206 .iDfreeCacheTime = 0,
207 .bPreexecClose = false,
208 .bRootpreexecClose = false,
209 .iCaseSensitive = Auto,
210 .bCasePreserve = true,
211 .bShortCasePreserve = true,
212 .bHideDotFiles = true,
213 .bHideSpecialFiles = false,
214 .bHideUnReadable = false,
215 .bHideUnWriteableFiles = false,
216 .bBrowseable = true,
217 .bAccessBasedShareEnum = false,
218 .bAvailable = true,
219 .bRead_only = true,
220 .bNo_set_dir = true,
221 .bGuest_only = false,
222 .bAdministrative_share = false,
223 .bGuest_ok = false,
224 .bPrint_ok = false,
225 .bPrintNotifyBackchannel = true,
226 .bMap_system = false,
227 .bMap_hidden = false,
228 .bMap_archive = true,
229 .bStoreDosAttributes = false,
230 .bDmapiSupport = false,
231 .bLocking = true,
232 .iStrictLocking = Auto,
233 .bPosixLocking = true,
234 .bOpLocks = true,
235 .bKernelOplocks = false,
236 .bLevel2OpLocks = true,
237 .bOnlyUser = false,
238 .bMangledNames = true,
239 .bWidelinks = false,
240 .bSymlinks = true,
241 .bSyncAlways = false,
242 .bStrictAllocate = false,
243 .bStrictSync = false,
244 .magic_char = '~',
245 .copymap = NULL,
246 .bDeleteReadonly = false,
247 .bFakeOplocks = false,
248 .bDeleteVetoFiles = false,
249 .bDosFilemode = false,
250 .bDosFiletimes = true,
251 .bDosFiletimeResolution = false,
252 .bFakeDirCreateTimes = false,
253 .bBlockingLocks = true,
254 .bInheritPerms = false,
255 .bInheritACLS = false,
256 .bInheritOwner = false,
257 .bMSDfsRoot = false,
258 .bUseClientDriver = false,
259 .bDefaultDevmode = true,
260 .bForcePrintername = false,
261 .bNTAclSupport = true,
262 .bForceUnknownAclUser = false,
263 .bUseSendfile = false,
264 .bProfileAcls = false,
265 .bMap_acl_inherit = false,
266 .bAfs_Share = false,
267 .bEASupport = false,
268 .bAclCheckPermissions = true,
269 .bAclMapFullControl = true,
270 .bAclGroupControl = false,
271 .bChangeNotify = true,
272 .bKernelChangeNotify = true,
273 .iallocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
274 .iAioReadSize = 0,
275 .iAioWriteSize = 0,
276 .iMap_readonly = MAP_READONLY_YES,
277 #ifdef BROKEN_DIRECTORY_HANDLING
278 .iDirectoryNameCacheSize = 0,
279 #else
280 .iDirectoryNameCacheSize = 100,
281 #endif
282 .ismb_encrypt = SMB_SIGNING_DEFAULT,
283 .bKernelShareModes = true,
284 .bDurableHandles = true,
285 .param_opt = NULL,
286 .dummy = ""
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
316 * source3 code
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)
338 size_t l;
340 if (!src)
341 src = "";
343 l = strlen(src);
345 if (l == 0) {
346 *dest = discard_const_p(char, null_string);
347 } else {
348 (*dest) = SMB_STRDUP(src);
349 if ((*dest) == NULL) {
350 DEBUG(0,("Out of memory in string_init\n"));
351 return false;
354 return(true);
358 Free a string value.
361 static void string_free(char **s)
363 if (!s || !(*s))
364 return;
365 if (*s == null_string)
366 *s = NULL;
367 SAFE_FREE(*s);
371 Set a string value, deallocating any existing space, and allocing the space
372 for the string
375 static bool string_set(char **dest,const char *src)
377 string_free(dest);
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) {
389 case PRINT_BSD:
390 case PRINT_AIX:
391 case PRINT_LPRNT:
392 case PRINT_LPROS2:
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");
396 break;
398 case PRINT_LPRNG:
399 case PRINT_PLP:
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");
407 break;
409 case PRINT_CUPS:
410 case PRINT_IPRINT:
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, "");
420 break;
422 case PRINT_SYSV:
423 case PRINT_HPUX:
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");
429 #ifndef HPUX
430 string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
431 string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
432 #endif /* HPUX */
433 break;
435 case PRINT_QNX:
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");
439 break;
441 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
443 case PRINT_TEST:
444 case PRINT_VLP: {
445 const char *tdbfile;
446 TALLOC_CTX *tmp_ctx = talloc_stackframe();
447 char *tmp;
449 tdbfile = talloc_asprintf(
450 tmp_ctx, "tdbfile=%s",
451 lp_parm_const_string(-1, "vlp", "tdbfile",
452 "/tmp/vlp.tdb"));
453 if (tdbfile == NULL) {
454 tdbfile="tdbfile=/tmp/vlp.tdb";
457 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
458 tdbfile);
459 string_set(&pService->szPrintcommand,
460 tmp ? tmp : "vlp print %p %s");
462 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
463 tdbfile);
464 string_set(&pService->szLpqcommand,
465 tmp ? tmp : "vlp lpq %p");
467 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
468 tdbfile);
469 string_set(&pService->szLprmcommand,
470 tmp ? tmp : "vlp lprm %p %j");
472 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
473 tdbfile);
474 string_set(&pService->szLppausecommand,
475 tmp ? tmp : "vlp lppause %p %j");
477 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
478 tdbfile);
479 string_set(&pService->szLpresumecommand,
480 tmp ? tmp : "vlp lpresume %p %j");
482 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
483 tdbfile);
484 string_set(&pService->szQueuepausecommand,
485 tmp ? tmp : "vlp queuepause %p");
487 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
488 tdbfile);
489 string_set(&pService->szQueueresumecommand,
490 tmp ? tmp : "vlp queueresume %p");
491 TALLOC_FREE(tmp_ctx);
493 break;
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,
516 #endif
518 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
520 struct rlimit rl;
522 ZERO_STRUCT(rl);
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;
530 #endif
532 #endif
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",
537 sysctl_max,
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",
545 rlimit_max,
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)
575 void *parm_ptr;
577 if (parm.p_class != P_LOCAL) {
578 return;
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)
592 uint32_t i;
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)
605 void *parm_ptr;
607 if (snum < 0) {
608 parm_ptr = lp_parm_ptr(NULL, &parm);
609 } else if (parm.p_class != P_LOCAL) {
610 return;
611 } else {
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
620 * by an snum.
622 static void free_parameters_by_snum(int snum)
624 uint32_t i;
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;
645 const char *label;
646 const char *value;
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);
663 talloc_free(entry);
664 break;
668 entry = talloc(NULL, struct lp_stored_option);
669 if (!entry) {
670 return false;
673 entry->label = talloc_strdup(entry, pszParmName);
674 if (!entry->label) {
675 talloc_free(entry);
676 return false;
679 entry->value = talloc_strdup(entry, pszParmValue);
680 if (!entry->value) {
681 talloc_free(entry);
682 return false;
685 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
687 return true;
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));
697 return false;
700 return true;
703 /***************************************************************************
704 Initialise the global parameter structure.
705 ***************************************************************************/
707 static void init_globals(bool reinit_globals)
709 static bool done_init = false;
710 char *s = NULL;
711 int i;
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 */
716 return;
719 if (!done_init) {
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;
725 done_init = true;
726 } else {
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
788 * addresses.
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);
796 SAFE_FREE(s);
797 #ifdef DEVELOPER
798 string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
799 #endif
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;
844 Globals.syslog = 1;
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");
864 #else
865 string_set(&Globals.szNISHomeMapName, "auto.home");
866 #endif
867 #endif
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;
892 #else
893 Globals.bUseMmap = true;
894 #endif
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);
972 #else
973 string_set(&Globals.ctdbdSocket, "");
974 #endif
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);
1019 SAFE_FREE(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)
1056 char *ret;
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? */
1063 #if 0
1064 DEBUG(10, ("lp_string(%s)\n", s));
1065 #endif
1066 if (!s) {
1067 return NULL;
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) {
1076 TALLOC_FREE(ret);
1077 ret = talloc_sub_basic(ctx,
1078 get_current_username(),
1079 current_user_info.domain,
1083 return ret;
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) : "");
1134 else
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) : "");
1143 else
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"));
1156 return 1;
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)
1170 int result = 0;
1171 #ifdef HAVE_HTTPCONNECTENCRYPT
1172 switch (Globals.CupsEncrypt) {
1173 case Auto:
1174 result = HTTP_ENCRYPT_REQUIRED;
1175 break;
1176 case true:
1177 result = HTTP_ENCRYPT_ALWAYS;
1178 break;
1179 case false:
1180 result = HTTP_ENCRYPT_NEVER;
1181 break;
1183 #endif
1184 return result;
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,
1206 void *userdata);
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,
1220 const char *option)
1222 bool global_section = false;
1223 char* param_key;
1224 struct parmlist_entry *data;
1226 if (service == NULL) {
1227 data = Globals.param_opt;
1228 global_section = true;
1229 } else {
1230 data = service->param_opt;
1233 if (asprintf(&param_key, "%s:%s", type, option) == -1) {
1234 DEBUG(0,("asprintf failed!\n"));
1235 return NULL;
1238 while (data) {
1239 if (strwicmp(data->key, param_key) == 0) {
1240 string_free(&param_key);
1241 return data;
1243 data = data->next;
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;
1250 while (data) {
1251 if (strwicmp(data->key, param_key) == 0) {
1252 string_free(&param_key);
1253 return data;
1255 data = data->next;
1259 string_free(&param_key);
1261 return NULL;
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,
1270 const char *option)
1272 if (snum >= iNumServices) return NULL;
1274 if (snum < 0) {
1275 return get_parametrics_by_service(NULL, type, option);
1276 } else {
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)
1291 if (!s || !*s) {
1292 MISSING_PARAMETER(lp_int);
1293 return (-1);
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)
1305 if (!s || !*s) {
1306 MISSING_PARAMETER(lp_ulong);
1307 return (0);
1310 return strtoul(s, NULL, 0);
1313 /*******************************************************************
1314 convenience routine to return boolean parameters.
1315 ********************************************************************/
1316 static bool lp_bool(const char *s)
1318 bool ret = false;
1320 if (!s || !*s) {
1321 MISSING_PARAMETER(lp_bool);
1322 return false;
1325 if (!set_boolean(s, &ret)) {
1326 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1327 return false;
1330 return ret;
1333 /*******************************************************************
1334 convenience routine to return enum parameters.
1335 ********************************************************************/
1336 static int lp_enum(const char *s,const struct enum_list *_enum)
1338 int i;
1340 if (!s || !*s || !_enum) {
1341 MISSING_PARAMETER(lp_enum);
1342 return (-1);
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));
1351 return (-1);
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) {
1363 if (def) {
1364 return lp_string(ctx, def);
1365 } else {
1366 return NULL;
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)
1380 return def;
1382 return data->value;
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)
1390 return NULL;
1392 return data->value;
1396 /* Return parametric option from a given service. Type is a part of option before ':' */
1397 /* Parametric option has following syntax: 'Type: option = value' */
1399 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);
1423 return def;
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);
1436 return def;
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);
1449 return def;
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);
1463 return def;
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"));
1491 opt = *popts;
1492 while (opt != NULL) {
1493 string_free(&opt->key);
1494 string_free(&opt->value);
1495 TALLOC_FREE(opt->list);
1496 next_opt = opt->next;
1497 SAFE_FREE(opt);
1498 opt = next_opt;
1500 *popts = NULL;
1503 /***************************************************************************
1504 Free the dynamically allocated parts of a service struct.
1505 ***************************************************************************/
1507 static void free_service(struct loadparm_service *pservice)
1509 if (!pservice)
1510 return;
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) )
1535 return;
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(
1544 talloc_tos(),
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
1557 service.
1558 ***************************************************************************/
1560 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1562 int i;
1563 struct loadparm_service tservice;
1564 int num_to_alloc = iNumServices + 1;
1566 tservice = *pservice;
1568 /* it might already exist */
1569 if (name) {
1570 i = getservicebyname(name, NULL);
1571 if (i >= 0) {
1572 return (i);
1576 /* find an invalid one */
1577 i = iNumServices;
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;
1585 int *tinvalid;
1587 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1588 if (tsp == NULL) {
1589 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1590 return (-1);
1592 ServicePtrs = tsp;
1593 ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1594 if (!ServicePtrs[iNumServices]) {
1595 DEBUG(0,("add_a_service: out of memory!\n"));
1596 return (-1);
1598 iNumServices++;
1600 /* enlarge invalid_services here for now... */
1601 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
1602 num_to_alloc);
1603 if (tinvalid == NULL) {
1604 DEBUG(0,("add_a_service: failed to enlarge "
1605 "invalid_services!\n"));
1606 return (-1);
1608 invalid_services = tinvalid;
1609 } else {
1610 free_service_byindex(i);
1613 ServicePtrs[i]->valid = true;
1615 init_service(ServicePtrs[i]);
1616 copy_service(ServicePtrs[i], &tservice, NULL);
1617 if (name)
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)) {
1624 return (-1);
1627 return (i);
1630 /***************************************************************************
1631 Convert a string to uppercase and remove whitespaces.
1632 ***************************************************************************/
1634 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1636 char *result;
1638 if ( !src ) {
1639 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1640 return NULL;
1643 result = talloc_strdup(ctx, src);
1644 SMB_ASSERT(result != NULL);
1646 if (!strlower_m(result)) {
1647 TALLOC_FREE(result);
1648 return NULL;
1650 return 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)
1659 char *canon_name;
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"));
1666 return false;
1670 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1671 idx, name));
1673 canon_name = canonicalize_servicename(talloc_tos(), name );
1675 dbwrap_store_bystring(ServiceHash, canon_name,
1676 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1677 TDB_REPLACE);
1679 TALLOC_FREE(canon_name);
1681 return true;
1684 /***************************************************************************
1685 Add a new home service, with the specified home directory, defaults coming
1686 from service ifrom.
1687 ***************************************************************************/
1689 bool lp_add_home(const char *pszHomename, int iDefaultService,
1690 const char *user, const char *pszHomedir)
1692 int i;
1694 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1695 pszHomedir[0] == '\0') {
1696 return false;
1699 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1701 if (i < 0)
1702 return false;
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) {
1713 return false;
1715 string_set(&ServicePtrs[i]->comment, comment);
1716 SAFE_FREE(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 ));
1729 return true;
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);
1754 if (i < 0)
1755 return false;
1757 if (asprintf(&comment, "IPC Service (%s)",
1758 Globals.szServerString) < 0) {
1759 return false;
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"));
1777 SAFE_FREE(comment);
1778 return true;
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);
1790 if (i < 0)
1791 return false;
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 oplocks on printer services. */
1808 ServicePtrs[i]->bOpLocks = false;
1809 /* Printer services must be printable. */
1810 ServicePtrs[i]->bPrint_ok = true;
1812 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1814 return true;
1818 /***************************************************************************
1819 Check whether the given parameter name is valid.
1820 Parametric options (names containing a colon) are considered valid.
1821 ***************************************************************************/
1823 bool lp_parameter_is_valid(const char *pszParmName)
1825 return ((map_parameter(pszParmName) != -1) ||
1826 (strchr(pszParmName, ':') != NULL));
1829 /***************************************************************************
1830 Check whether the given name is the name of a global parameter.
1831 Returns true for strings belonging to parameters of class
1832 P_GLOBAL, false for all other strings, also for parametric options
1833 and strings not belonging to any option.
1834 ***************************************************************************/
1836 bool lp_parameter_is_global(const char *pszParmName)
1838 int num = map_parameter(pszParmName);
1840 if (num >= 0) {
1841 return (parm_table[num].p_class == P_GLOBAL);
1844 return false;
1847 /**************************************************************************
1848 Check whether the given name is the canonical name of a parameter.
1849 Returns false if it is not a valid parameter Name.
1850 For parametric options, true is returned.
1851 **************************************************************************/
1853 bool lp_parameter_is_canonical(const char *parm_name)
1855 if (!lp_parameter_is_valid(parm_name)) {
1856 return false;
1859 return (map_parameter(parm_name) ==
1860 map_parameter_canonical(parm_name, NULL));
1863 /**************************************************************************
1864 Determine the canonical name for a parameter.
1865 Indicate when it is an inverse (boolean) synonym instead of a
1866 "usual" synonym.
1867 **************************************************************************/
1869 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1870 bool *inverse)
1872 int num;
1874 if (!lp_parameter_is_valid(parm_name)) {
1875 *canon_parm = NULL;
1876 return false;
1879 num = map_parameter_canonical(parm_name, inverse);
1880 if (num < 0) {
1881 /* parametric option */
1882 *canon_parm = parm_name;
1883 } else {
1884 *canon_parm = parm_table[num].label;
1887 return true;
1891 /**************************************************************************
1892 Determine the canonical name for a parameter.
1893 Turn the value given into the inverse boolean expression when
1894 the synonym is an invers boolean synonym.
1896 Return true if parm_name is a valid parameter name and
1897 in case it is an invers boolean synonym, if the val string could
1898 successfully be converted to the reverse bool.
1899 Return false in all other cases.
1900 **************************************************************************/
1902 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1903 const char *val,
1904 const char **canon_parm,
1905 const char **canon_val)
1907 int num;
1908 bool inverse;
1910 if (!lp_parameter_is_valid(parm_name)) {
1911 *canon_parm = NULL;
1912 *canon_val = NULL;
1913 return false;
1916 num = map_parameter_canonical(parm_name, &inverse);
1917 if (num < 0) {
1918 /* parametric option */
1919 *canon_parm = parm_name;
1920 *canon_val = val;
1921 } else {
1922 *canon_parm = parm_table[num].label;
1923 if (inverse) {
1924 if (!lp_invert_boolean(val, canon_val)) {
1925 *canon_val = NULL;
1926 return false;
1928 } else {
1929 *canon_val = val;
1933 return true;
1936 /***************************************************************************
1937 Map a parameter's string representation to something we can use.
1938 Returns false if the parameter string is not recognised, else TRUE.
1939 ***************************************************************************/
1941 static int map_parameter(const char *pszParmName)
1943 int iIndex;
1945 if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
1946 return (-1);
1948 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1949 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1950 return (iIndex);
1952 /* Warn only if it isn't parametric option */
1953 if (strchr(pszParmName, ':') == NULL)
1954 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1955 /* We do return 'fail' for parametric options as well because they are
1956 stored in different storage
1958 return (-1);
1961 /***************************************************************************
1962 Map a parameter's string representation to the index of the canonical
1963 form of the parameter (it might be a synonym).
1964 Returns -1 if the parameter string is not recognised.
1965 ***************************************************************************/
1967 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1969 int parm_num, canon_num;
1970 bool loc_inverse = false;
1972 parm_num = map_parameter(pszParmName);
1973 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1974 /* invalid, parametric or no canidate for synonyms ... */
1975 goto done;
1978 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1979 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1980 parm_num = canon_num;
1981 goto done;
1985 done:
1986 if (inverse != NULL) {
1987 *inverse = loc_inverse;
1989 return parm_num;
1992 /***************************************************************************
1993 return true if parameter number parm1 is a synonym of parameter
1994 number parm2 (parm2 being the principal name).
1995 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1996 false otherwise.
1997 ***************************************************************************/
1999 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
2001 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
2002 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
2003 (parm_table[parm1].flags & FLAG_HIDE) &&
2004 !(parm_table[parm2].flags & FLAG_HIDE))
2006 if (inverse != NULL) {
2007 if ((parm_table[parm1].type == P_BOOLREV) &&
2008 (parm_table[parm2].type == P_BOOL))
2010 *inverse = true;
2011 } else {
2012 *inverse = false;
2015 return true;
2017 return false;
2020 /***************************************************************************
2021 Show one parameter's name, type, [values,] and flags.
2022 (helper functions for show_parameter_list)
2023 ***************************************************************************/
2025 static void show_parameter(int parmIndex)
2027 int enumIndex, flagIndex;
2028 int parmIndex2;
2029 bool hadFlag;
2030 bool hadSyn;
2031 bool inverse;
2032 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2033 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2034 "P_ENUM", "P_SEP"};
2035 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2036 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2037 FLAG_HIDE};
2038 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2039 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2040 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2042 printf("%s=%s", parm_table[parmIndex].label,
2043 type[parm_table[parmIndex].type]);
2044 if (parm_table[parmIndex].type == P_ENUM) {
2045 printf(",");
2046 for (enumIndex=0;
2047 parm_table[parmIndex].enum_list[enumIndex].name;
2048 enumIndex++)
2050 printf("%s%s",
2051 enumIndex ? "|" : "",
2052 parm_table[parmIndex].enum_list[enumIndex].name);
2055 printf(",");
2056 hadFlag = false;
2057 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2058 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2059 printf("%s%s",
2060 hadFlag ? "|" : "",
2061 flag_names[flagIndex]);
2062 hadFlag = true;
2066 /* output synonyms */
2067 hadSyn = false;
2068 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2069 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2070 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2071 parm_table[parmIndex2].label);
2072 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2073 if (!hadSyn) {
2074 printf(" (synonyms: ");
2075 hadSyn = true;
2076 } else {
2077 printf(", ");
2079 printf("%s%s", parm_table[parmIndex2].label,
2080 inverse ? "[i]" : "");
2083 if (hadSyn) {
2084 printf(")");
2087 printf("\n");
2090 /***************************************************************************
2091 Show all parameter's name, type, [values,] and flags.
2092 ***************************************************************************/
2094 void show_parameter_list(void)
2096 int classIndex, parmIndex;
2097 const char *section_names[] = { "local", "global", NULL};
2099 for (classIndex=0; section_names[classIndex]; classIndex++) {
2100 printf("[%s]\n", section_names[classIndex]);
2101 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2102 if (parm_table[parmIndex].p_class == classIndex) {
2103 show_parameter(parmIndex);
2109 /***************************************************************************
2110 Check if a given string correctly represents a boolean value.
2111 ***************************************************************************/
2113 bool lp_string_is_valid_boolean(const char *parm_value)
2115 return set_boolean(parm_value, NULL);
2118 /***************************************************************************
2119 Get the standard string representation of a boolean value ("yes" or "no")
2120 ***************************************************************************/
2122 static const char *get_boolean(bool bool_value)
2124 static const char *yes_str = "yes";
2125 static const char *no_str = "no";
2127 return (bool_value ? yes_str : no_str);
2130 /***************************************************************************
2131 Provide the string of the negated boolean value associated to the boolean
2132 given as a string. Returns false if the passed string does not correctly
2133 represent a boolean.
2134 ***************************************************************************/
2136 bool lp_invert_boolean(const char *str, const char **inverse_str)
2138 bool val;
2140 if (!set_boolean(str, &val)) {
2141 return false;
2144 *inverse_str = get_boolean(!val);
2145 return true;
2148 /***************************************************************************
2149 Provide the canonical string representation of a boolean value given
2150 as a string. Return true on success, false if the string given does
2151 not correctly represent a boolean.
2152 ***************************************************************************/
2154 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2156 bool val;
2158 if (!set_boolean(str, &val)) {
2159 return false;
2162 *canon_str = get_boolean(val);
2163 return true;
2166 /***************************************************************************
2167 Find a service by name. Otherwise works like get_service.
2168 ***************************************************************************/
2170 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2172 int iService = -1;
2173 char *canon_name;
2174 TDB_DATA data;
2175 NTSTATUS status;
2177 if (ServiceHash == NULL) {
2178 return -1;
2181 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2183 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2184 &data);
2186 if (NT_STATUS_IS_OK(status) &&
2187 (data.dptr != NULL) &&
2188 (data.dsize == sizeof(iService)))
2190 iService = *(int *)data.dptr;
2193 TALLOC_FREE(canon_name);
2195 if ((iService != -1) && (LP_SNUM_OK(iService))
2196 && (pserviceDest != NULL)) {
2197 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2200 return (iService);
2203 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2204 struct loadparm_service *lp_service(const char *pszServiceName)
2206 int iService = getservicebyname(pszServiceName, NULL);
2207 if (iService == -1 || !LP_SNUM_OK(iService)) {
2208 return NULL;
2210 return ServicePtrs[iService];
2213 struct loadparm_service *lp_servicebynum(int snum)
2215 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2216 return NULL;
2218 return ServicePtrs[snum];
2221 struct loadparm_service *lp_default_loadparm_service()
2223 return &sDefault;
2227 /***************************************************************************
2228 Copy a service structure to another.
2229 If pcopymapDest is NULL then copy all fields
2230 ***************************************************************************/
2233 * Add a parametric option to a parmlist_entry,
2234 * replacing old value, if already present.
2236 static void set_param_opt(struct parmlist_entry **opt_list,
2237 const char *opt_name,
2238 const char *opt_value,
2239 unsigned priority)
2241 struct parmlist_entry *new_opt, *opt;
2242 bool not_added;
2244 opt = *opt_list;
2245 not_added = true;
2247 /* Traverse destination */
2248 while (opt) {
2249 /* If we already have same option, override it */
2250 if (strwicmp(opt->key, opt_name) == 0) {
2251 if ((opt->priority & FLAG_CMDLINE) &&
2252 !(priority & FLAG_CMDLINE)) {
2253 /* it's been marked as not to be
2254 overridden */
2255 return;
2257 string_free(&opt->value);
2258 TALLOC_FREE(opt->list);
2259 opt->value = SMB_STRDUP(opt_value);
2260 opt->priority = priority;
2261 not_added = false;
2262 break;
2264 opt = opt->next;
2266 if (not_added) {
2267 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2268 new_opt->key = SMB_STRDUP(opt_name);
2269 new_opt->value = SMB_STRDUP(opt_value);
2270 new_opt->list = NULL;
2271 new_opt->priority = priority;
2272 DLIST_ADD(*opt_list, new_opt);
2276 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2277 struct bitmap *pcopymapDest)
2279 int i;
2280 bool bcopyall = (pcopymapDest == NULL);
2281 struct parmlist_entry *data;
2283 for (i = 0; parm_table[i].label; i++)
2284 if (parm_table[i].p_class == P_LOCAL &&
2285 (bcopyall || bitmap_query(pcopymapDest,i))) {
2286 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2287 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2289 switch (parm_table[i].type) {
2290 case P_BOOL:
2291 case P_BOOLREV:
2292 *(bool *)dest_ptr = *(bool *)src_ptr;
2293 break;
2295 case P_INTEGER:
2296 case P_ENUM:
2297 case P_OCTAL:
2298 case P_BYTES:
2299 *(int *)dest_ptr = *(int *)src_ptr;
2300 break;
2302 case P_CHAR:
2303 *(char *)dest_ptr = *(char *)src_ptr;
2304 break;
2306 case P_STRING:
2307 string_set((char **)dest_ptr,
2308 *(char **)src_ptr);
2309 break;
2311 case P_USTRING:
2313 char *upper_string = strupper_talloc(talloc_tos(),
2314 *(char **)src_ptr);
2315 string_set((char **)dest_ptr,
2316 upper_string);
2317 TALLOC_FREE(upper_string);
2318 break;
2320 case P_LIST:
2321 TALLOC_FREE(*((char ***)dest_ptr));
2322 *((char ***)dest_ptr) = str_list_copy(NULL,
2323 *(const char ***)src_ptr);
2324 break;
2325 default:
2326 break;
2330 if (bcopyall) {
2331 init_copymap(pserviceDest);
2332 if (pserviceSource->copymap)
2333 bitmap_copy(pserviceDest->copymap,
2334 pserviceSource->copymap);
2337 data = pserviceSource->param_opt;
2338 while (data) {
2339 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2340 data = data->next;
2344 /***************************************************************************
2345 Check a service for consistency. Return false if the service is in any way
2346 incomplete or faulty, else true.
2347 ***************************************************************************/
2349 bool service_ok(int iService)
2351 bool bRetval;
2353 bRetval = true;
2354 if (ServicePtrs[iService]->szService[0] == '\0') {
2355 DEBUG(0, ("The following message indicates an internal error:\n"));
2356 DEBUG(0, ("No service name in service entry.\n"));
2357 bRetval = false;
2360 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2361 /* I can't see why you'd want a non-printable printer service... */
2362 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2363 if (!ServicePtrs[iService]->bPrint_ok) {
2364 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2365 ServicePtrs[iService]->szService));
2366 ServicePtrs[iService]->bPrint_ok = true;
2368 /* [printers] service must also be non-browsable. */
2369 if (ServicePtrs[iService]->bBrowseable)
2370 ServicePtrs[iService]->bBrowseable = false;
2373 if (ServicePtrs[iService]->szPath[0] == '\0' &&
2374 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2375 ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2377 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2378 ServicePtrs[iService]->szService));
2379 ServicePtrs[iService]->bAvailable = false;
2382 /* If a service is flagged unavailable, log the fact at level 1. */
2383 if (!ServicePtrs[iService]->bAvailable)
2384 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2385 ServicePtrs[iService]->szService));
2387 return (bRetval);
2390 static struct smbconf_ctx *lp_smbconf_ctx(void)
2392 sbcErr err;
2393 static struct smbconf_ctx *conf_ctx = NULL;
2395 if (conf_ctx == NULL) {
2396 err = smbconf_init(NULL, &conf_ctx, "registry:");
2397 if (!SBC_ERROR_IS_OK(err)) {
2398 DEBUG(1, ("error initializing registry configuration: "
2399 "%s\n", sbcErrorString(err)));
2400 conf_ctx = NULL;
2404 return conf_ctx;
2407 static bool process_smbconf_service(struct smbconf_service *service)
2409 uint32_t count;
2410 bool ret;
2412 if (service == NULL) {
2413 return false;
2416 ret = do_section(service->name, NULL);
2417 if (ret != true) {
2418 return false;
2420 for (count = 0; count < service->num_params; count++) {
2421 ret = do_parameter(service->param_names[count],
2422 service->param_values[count],
2423 NULL);
2424 if (ret != true) {
2425 return false;
2428 if (iServiceIndex >= 0) {
2429 return service_ok(iServiceIndex);
2431 return true;
2435 * load a service from registry and activate it
2437 bool process_registry_service(const char *service_name)
2439 sbcErr err;
2440 struct smbconf_service *service = NULL;
2441 TALLOC_CTX *mem_ctx = talloc_stackframe();
2442 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2443 bool ret = false;
2445 if (conf_ctx == NULL) {
2446 goto done;
2449 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2451 if (!smbconf_share_exists(conf_ctx, service_name)) {
2453 * Registry does not contain data for this service (yet),
2454 * but make sure lp_load doesn't return false.
2456 ret = true;
2457 goto done;
2460 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2461 if (!SBC_ERROR_IS_OK(err)) {
2462 goto done;
2465 ret = process_smbconf_service(service);
2466 if (!ret) {
2467 goto done;
2470 /* store the csn */
2471 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2473 done:
2474 TALLOC_FREE(mem_ctx);
2475 return ret;
2479 * process_registry_globals
2481 static bool process_registry_globals(void)
2483 bool ret;
2485 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2487 ret = do_parameter("registry shares", "yes", NULL);
2488 if (!ret) {
2489 return ret;
2492 return process_registry_service(GLOBAL_NAME);
2495 bool process_registry_shares(void)
2497 sbcErr err;
2498 uint32_t count;
2499 struct smbconf_service **service = NULL;
2500 uint32_t num_shares = 0;
2501 TALLOC_CTX *mem_ctx = talloc_stackframe();
2502 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2503 bool ret = false;
2505 if (conf_ctx == NULL) {
2506 goto done;
2509 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2510 if (!SBC_ERROR_IS_OK(err)) {
2511 goto done;
2514 ret = true;
2516 for (count = 0; count < num_shares; count++) {
2517 if (strequal(service[count]->name, GLOBAL_NAME)) {
2518 continue;
2520 ret = process_smbconf_service(service[count]);
2521 if (!ret) {
2522 goto done;
2526 /* store the csn */
2527 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2529 done:
2530 TALLOC_FREE(mem_ctx);
2531 return ret;
2535 * reload those shares from registry that are already
2536 * activated in the services array.
2538 static bool reload_registry_shares(void)
2540 int i;
2541 bool ret = true;
2543 for (i = 0; i < iNumServices; i++) {
2544 if (!VALID(i)) {
2545 continue;
2548 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2549 continue;
2552 ret = process_registry_service(ServicePtrs[i]->szService);
2553 if (!ret) {
2554 goto done;
2558 done:
2559 return ret;
2563 #define MAX_INCLUDE_DEPTH 100
2565 static uint8_t include_depth;
2567 static struct file_lists {
2568 struct file_lists *next;
2569 char *name;
2570 char *subfname;
2571 time_t modtime;
2572 } *file_lists = NULL;
2574 /*******************************************************************
2575 Keep a linked list of all config files so we know when one has changed
2576 it's date and needs to be reloaded.
2577 ********************************************************************/
2579 static void add_to_file_list(const char *fname, const char *subfname)
2581 struct file_lists *f = file_lists;
2583 while (f) {
2584 if (f->name && !strcmp(f->name, fname))
2585 break;
2586 f = f->next;
2589 if (!f) {
2590 f = SMB_MALLOC_P(struct file_lists);
2591 if (!f)
2592 return;
2593 f->next = file_lists;
2594 f->name = SMB_STRDUP(fname);
2595 if (!f->name) {
2596 SAFE_FREE(f);
2597 return;
2599 f->subfname = SMB_STRDUP(subfname);
2600 if (!f->subfname) {
2601 SAFE_FREE(f->name);
2602 SAFE_FREE(f);
2603 return;
2605 file_lists = f;
2606 f->modtime = file_modtime(subfname);
2607 } else {
2608 time_t t = file_modtime(subfname);
2609 if (t)
2610 f->modtime = t;
2612 return;
2616 * Free the file lists
2618 static void free_file_list(void)
2620 struct file_lists *f;
2621 struct file_lists *next;
2623 f = file_lists;
2624 while( f ) {
2625 next = f->next;
2626 SAFE_FREE( f->name );
2627 SAFE_FREE( f->subfname );
2628 SAFE_FREE( f );
2629 f = next;
2631 file_lists = NULL;
2636 * Utility function for outsiders to check if we're running on registry.
2638 bool lp_config_backend_is_registry(void)
2640 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2644 * Utility function to check if the config backend is FILE.
2646 bool lp_config_backend_is_file(void)
2648 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2651 /*******************************************************************
2652 Check if a config file has changed date.
2653 ********************************************************************/
2655 bool lp_file_list_changed(void)
2657 struct file_lists *f = file_lists;
2659 DEBUG(6, ("lp_file_list_changed()\n"));
2661 while (f) {
2662 time_t mod_time;
2664 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2665 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2667 if (conf_ctx == NULL) {
2668 return false;
2670 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2671 NULL))
2673 DEBUGADD(6, ("registry config changed\n"));
2674 return true;
2676 } else {
2677 char *n2 = NULL;
2678 n2 = talloc_sub_basic(talloc_tos(),
2679 get_current_username(),
2680 current_user_info.domain,
2681 f->name);
2682 if (!n2) {
2683 return false;
2685 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2686 f->name, n2, ctime(&f->modtime)));
2688 mod_time = file_modtime(n2);
2690 if (mod_time &&
2691 ((f->modtime != mod_time) ||
2692 (f->subfname == NULL) ||
2693 (strcmp(n2, f->subfname) != 0)))
2695 DEBUGADD(6,
2696 ("file %s modified: %s\n", n2,
2697 ctime(&mod_time)));
2698 f->modtime = mod_time;
2699 SAFE_FREE(f->subfname);
2700 f->subfname = SMB_STRDUP(n2);
2701 TALLOC_FREE(n2);
2702 return true;
2704 TALLOC_FREE(n2);
2706 f = f->next;
2708 return false;
2713 * Initialize iconv conversion descriptors.
2715 * This is called the first time it is needed, and also called again
2716 * every time the configuration is reloaded, because the charset or
2717 * codepage might have changed.
2719 static void init_iconv(void)
2721 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2722 lp_unix_charset(),
2723 true, global_iconv_handle);
2726 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2728 if (strcmp(*ptr, pszParmValue) != 0) {
2729 string_set(ptr, pszParmValue);
2730 init_iconv();
2732 return true;
2735 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2737 bool is_utf8 = false;
2738 size_t len = strlen(pszParmValue);
2740 if (len == 4 || len == 5) {
2741 /* Don't use StrCaseCmp here as we don't want to
2742 initialize iconv. */
2743 if ((toupper_m(pszParmValue[0]) == 'U') &&
2744 (toupper_m(pszParmValue[1]) == 'T') &&
2745 (toupper_m(pszParmValue[2]) == 'F')) {
2746 if (len == 4) {
2747 if (pszParmValue[3] == '8') {
2748 is_utf8 = true;
2750 } else {
2751 if (pszParmValue[3] == '-' &&
2752 pszParmValue[4] == '8') {
2753 is_utf8 = true;
2759 if (strcmp(*ptr, pszParmValue) != 0) {
2760 if (is_utf8) {
2761 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2762 "be UTF8, using (default value) %s instead.\n",
2763 DEFAULT_DOS_CHARSET));
2764 pszParmValue = DEFAULT_DOS_CHARSET;
2766 string_set(ptr, pszParmValue);
2767 init_iconv();
2769 return true;
2772 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2774 bool ret = true;
2775 TALLOC_CTX *frame = talloc_stackframe();
2776 char *realm = strupper_talloc(frame, pszParmValue);
2777 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2779 ret &= string_set(&Globals.szRealm, pszParmValue);
2780 ret &= string_set(&Globals.szRealm_upper, realm);
2781 ret &= string_set(&Globals.szRealm_lower, dnsdomain);
2782 TALLOC_FREE(frame);
2784 return ret;
2787 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2789 TALLOC_FREE(Globals.szNetbiosAliases);
2790 Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2791 return set_netbios_aliases(Globals.szNetbiosAliases);
2794 /***************************************************************************
2795 Handle the include operation.
2796 ***************************************************************************/
2797 static bool bAllowIncludeRegistry = true;
2799 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2801 char *fname;
2803 if (include_depth >= MAX_INCLUDE_DEPTH) {
2804 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2805 include_depth));
2806 return false;
2809 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2810 if (!bAllowIncludeRegistry) {
2811 return true;
2813 if (bInGlobalSection) {
2814 bool ret;
2815 include_depth++;
2816 ret = process_registry_globals();
2817 include_depth--;
2818 return ret;
2819 } else {
2820 DEBUG(1, ("\"include = registry\" only effective "
2821 "in %s section\n", GLOBAL_NAME));
2822 return false;
2826 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2827 current_user_info.domain,
2828 pszParmValue);
2830 add_to_file_list(pszParmValue, fname);
2832 string_set(ptr, fname);
2834 if (file_exist(fname)) {
2835 bool ret;
2836 include_depth++;
2837 ret = pm_process(fname, do_section, do_parameter, NULL);
2838 include_depth--;
2839 TALLOC_FREE(fname);
2840 return ret;
2843 DEBUG(2, ("Can't find include file %s\n", fname));
2844 TALLOC_FREE(fname);
2845 return true;
2848 /***************************************************************************
2849 Handle the interpretation of the copy parameter.
2850 ***************************************************************************/
2852 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2854 bool bRetval;
2855 int iTemp;
2856 struct loadparm_service serviceTemp;
2858 string_set(ptr, pszParmValue);
2860 init_service(&serviceTemp);
2862 bRetval = false;
2864 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2866 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2867 if (iTemp == iServiceIndex) {
2868 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2869 } else {
2870 copy_service(ServicePtrs[iServiceIndex],
2871 &serviceTemp,
2872 ServicePtrs[iServiceIndex]->copymap);
2873 bRetval = true;
2875 } else {
2876 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2877 bRetval = false;
2880 free_service(&serviceTemp);
2881 return (bRetval);
2884 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2886 Globals.ldap_debug_level = lp_int(pszParmValue);
2887 init_ldap_debugging();
2888 return true;
2891 /***************************************************************************
2892 Handle idmap/non unix account uid and gid allocation parameters. The format of these
2893 parameters is:
2895 [global]
2897 idmap uid = 1000-1999
2898 idmap gid = 700-899
2900 We only do simple parsing checks here. The strings are parsed into useful
2901 structures in the idmap daemon code.
2903 ***************************************************************************/
2905 /* Some lp_ routines to return idmap [ug]id information */
2907 static uid_t idmap_uid_low, idmap_uid_high;
2908 static gid_t idmap_gid_low, idmap_gid_high;
2910 bool lp_idmap_uid(uid_t *low, uid_t *high)
2912 if (idmap_uid_low == 0 || idmap_uid_high == 0)
2913 return false;
2915 if (low)
2916 *low = idmap_uid_low;
2918 if (high)
2919 *high = idmap_uid_high;
2921 return true;
2924 bool lp_idmap_gid(gid_t *low, gid_t *high)
2926 if (idmap_gid_low == 0 || idmap_gid_high == 0)
2927 return false;
2929 if (low)
2930 *low = idmap_gid_low;
2932 if (high)
2933 *high = idmap_gid_high;
2935 return true;
2938 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2940 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2942 return true;
2945 /* Do some simple checks on "idmap [ug]id" parameter values */
2947 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2949 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2951 return true;
2954 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2956 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2958 return true;
2961 /***************************************************************************
2962 Handle the DEBUG level list.
2963 ***************************************************************************/
2965 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2967 string_set(ptr, pszParmValueIn);
2968 return debug_parse_levels(pszParmValueIn);
2971 /***************************************************************************
2972 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2973 ***************************************************************************/
2975 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2977 const char *suffix_string;
2979 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2980 Globals.szLdapSuffix );
2981 if ( !suffix_string ) {
2982 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2983 return "";
2986 return suffix_string;
2989 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2991 if (Globals.szLdapMachineSuffix[0])
2992 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
2994 return lp_string(ctx, Globals.szLdapSuffix);
2997 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
2999 if (Globals.szLdapUserSuffix[0])
3000 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3002 return lp_string(ctx, Globals.szLdapSuffix);
3005 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3007 if (Globals.szLdapGroupSuffix[0])
3008 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3010 return lp_string(ctx, Globals.szLdapSuffix);
3013 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3015 if (Globals.szLdapIdmapSuffix[0])
3016 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3018 return lp_string(ctx, Globals.szLdapSuffix);
3021 /****************************************************************************
3022 set the value for a P_ENUM
3023 ***************************************************************************/
3025 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3026 int *ptr )
3028 int i;
3030 for (i = 0; parm->enum_list[i].name; i++) {
3031 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3032 *ptr = parm->enum_list[i].value;
3033 return;
3036 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3037 pszParmValue, parm->label));
3040 /***************************************************************************
3041 ***************************************************************************/
3043 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3045 static int parm_num = -1;
3046 struct loadparm_service *s;
3048 if ( parm_num == -1 )
3049 parm_num = map_parameter( "printing" );
3051 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3053 if ( snum < 0 )
3054 s = &sDefault;
3055 else
3056 s = ServicePtrs[snum];
3058 init_printer_values( s );
3060 return true;
3064 /***************************************************************************
3065 Initialise a copymap.
3066 ***************************************************************************/
3068 static void init_copymap(struct loadparm_service *pservice)
3070 int i;
3072 TALLOC_FREE(pservice->copymap);
3074 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3075 if (!pservice->copymap)
3076 DEBUG(0,
3077 ("Couldn't allocate copymap!! (size %d)\n",
3078 (int)NUMPARAMETERS));
3079 else
3080 for (i = 0; i < NUMPARAMETERS; i++)
3081 bitmap_set(pservice->copymap, i);
3085 return the parameter pointer for a parameter
3087 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3089 if (service == NULL) {
3090 if (parm->p_class == P_LOCAL)
3091 return (void *)(((char *)&sDefault)+parm->offset);
3092 else if (parm->p_class == P_GLOBAL)
3093 return (void *)(((char *)&Globals)+parm->offset);
3094 else return NULL;
3095 } else {
3096 return (void *)(((char *)service) + parm->offset);
3100 /***************************************************************************
3101 Return the local pointer to a parameter given the service number and parameter
3102 ***************************************************************************/
3104 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3106 return lp_parm_ptr(ServicePtrs[snum], parm);
3109 /***************************************************************************
3110 Process a parameter for a particular service number. If snum < 0
3111 then assume we are in the globals.
3112 ***************************************************************************/
3114 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3116 int parmnum, i;
3117 void *parm_ptr = NULL; /* where we are going to store the result */
3118 struct parmlist_entry **opt_list;
3120 parmnum = map_parameter(pszParmName);
3122 if (parmnum < 0) {
3123 if (strchr(pszParmName, ':') == NULL) {
3124 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3125 pszParmName));
3126 return true;
3130 * We've got a parametric option
3133 opt_list = (snum < 0)
3134 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3135 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3137 return true;
3140 /* if it's already been set by the command line, then we don't
3141 override here */
3142 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3143 return true;
3146 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3147 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3148 pszParmName));
3151 /* we might point at a service, the default service or a global */
3152 if (snum < 0) {
3153 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3154 } else {
3155 if (parm_table[parmnum].p_class == P_GLOBAL) {
3156 DEBUG(0,
3157 ("Global parameter %s found in service section!\n",
3158 pszParmName));
3159 return true;
3161 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3164 if (snum >= 0) {
3165 if (!ServicePtrs[snum]->copymap)
3166 init_copymap(ServicePtrs[snum]);
3168 /* this handles the aliases - set the copymap for other entries with
3169 the same data pointer */
3170 for (i = 0; parm_table[i].label; i++) {
3171 if ((parm_table[i].offset == parm_table[parmnum].offset)
3172 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3173 bitmap_clear(ServicePtrs[snum]->copymap, i);
3178 /* if it is a special case then go ahead */
3179 if (parm_table[parmnum].special) {
3180 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3181 (char **)parm_ptr);
3184 /* now switch on the type of variable it is */
3185 switch (parm_table[parmnum].type)
3187 case P_BOOL:
3188 *(bool *)parm_ptr = lp_bool(pszParmValue);
3189 break;
3191 case P_BOOLREV:
3192 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3193 break;
3195 case P_INTEGER:
3196 *(int *)parm_ptr = lp_int(pszParmValue);
3197 break;
3199 case P_CHAR:
3200 *(char *)parm_ptr = *pszParmValue;
3201 break;
3203 case P_OCTAL:
3204 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3205 if ( i != 1 ) {
3206 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3208 break;
3210 case P_BYTES:
3212 uint64_t val;
3213 if (conv_str_size_error(pszParmValue, &val)) {
3214 if (val <= INT_MAX) {
3215 *(int *)parm_ptr = (int)val;
3216 break;
3220 DEBUG(0,("lp_do_parameter(%s): value is not "
3221 "a valid size specifier!\n", pszParmValue));
3222 return false;
3225 case P_LIST:
3226 case P_CMDLIST:
3227 TALLOC_FREE(*((char ***)parm_ptr));
3228 *(char ***)parm_ptr = str_list_make_v3(
3229 NULL, pszParmValue, NULL);
3230 break;
3232 case P_STRING:
3233 string_set((char **)parm_ptr, pszParmValue);
3234 break;
3236 case P_USTRING:
3238 char *upper_string = strupper_talloc(talloc_tos(),
3239 pszParmValue);
3240 string_set((char **)parm_ptr, upper_string);
3241 TALLOC_FREE(upper_string);
3242 break;
3244 case P_ENUM:
3245 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3246 break;
3247 case P_SEP:
3248 break;
3251 return true;
3254 /***************************************************************************
3255 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3256 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3257 ***************************************************************************/
3259 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3261 int parmnum, i;
3262 parmnum = map_parameter(pszParmName);
3263 if (parmnum >= 0) {
3264 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3265 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3266 return false;
3268 parm_table[parmnum].flags |= FLAG_CMDLINE;
3270 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3271 * be grouped in the table, so we don't have to search the
3272 * whole table */
3273 for (i=parmnum-1;
3274 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3275 && parm_table[i].p_class == parm_table[parmnum].p_class;
3276 i--) {
3277 parm_table[i].flags |= FLAG_CMDLINE;
3279 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3280 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3281 parm_table[i].flags |= FLAG_CMDLINE;
3284 if (store_values) {
3285 store_lp_set_cmdline(pszParmName, pszParmValue);
3287 return true;
3290 /* it might be parametric */
3291 if (strchr(pszParmName, ':') != NULL) {
3292 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3293 if (store_values) {
3294 store_lp_set_cmdline(pszParmName, pszParmValue);
3296 return true;
3299 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3300 return true;
3303 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3305 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3308 /***************************************************************************
3309 Process a parameter.
3310 ***************************************************************************/
3312 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3313 void *userdata)
3315 if (!bInGlobalSection && bGlobalOnly)
3316 return true;
3318 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3320 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3321 pszParmName, pszParmValue));
3325 set a option from the commandline in 'a=b' format. Use to support --option
3327 bool lp_set_option(const char *option)
3329 char *p, *s;
3330 bool ret;
3332 s = talloc_strdup(NULL, option);
3333 if (!s) {
3334 return false;
3337 p = strchr(s, '=');
3338 if (!p) {
3339 talloc_free(s);
3340 return false;
3343 *p = 0;
3345 /* skip white spaces after the = sign */
3346 do {
3347 p++;
3348 } while (*p == ' ');
3350 ret = lp_set_cmdline(s, p);
3351 talloc_free(s);
3352 return ret;
3355 /**************************************************************************
3356 Print a parameter of the specified type.
3357 ***************************************************************************/
3359 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3361 /* For the seperation of lists values that we print below */
3362 const char *list_sep = ", ";
3363 int i;
3364 switch (p->type)
3366 case P_ENUM:
3367 for (i = 0; p->enum_list[i].name; i++) {
3368 if (*(int *)ptr == p->enum_list[i].value) {
3369 fprintf(f, "%s",
3370 p->enum_list[i].name);
3371 break;
3374 break;
3376 case P_BOOL:
3377 fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3378 break;
3380 case P_BOOLREV:
3381 fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3382 break;
3384 case P_INTEGER:
3385 case P_BYTES:
3386 fprintf(f, "%d", *(int *)ptr);
3387 break;
3389 case P_CHAR:
3390 fprintf(f, "%c", *(char *)ptr);
3391 break;
3393 case P_OCTAL: {
3394 int val = *(int *)ptr;
3395 if (val == -1) {
3396 fprintf(f, "-1");
3397 } else {
3398 fprintf(f, "0%o", val);
3400 break;
3403 case P_CMDLIST:
3404 list_sep = " ";
3405 /* fall through */
3406 case P_LIST:
3407 if ((char ***)ptr && *(char ***)ptr) {
3408 char **list = *(char ***)ptr;
3409 for (; *list; list++) {
3410 /* surround strings with whitespace in double quotes */
3411 if (*(list+1) == NULL) {
3412 /* last item, no extra separator */
3413 list_sep = "";
3415 if ( strchr_m( *list, ' ' ) ) {
3416 fprintf(f, "\"%s\"%s", *list, list_sep);
3417 } else {
3418 fprintf(f, "%s%s", *list, list_sep);
3422 break;
3424 case P_STRING:
3425 case P_USTRING:
3426 if (*(char **)ptr) {
3427 fprintf(f, "%s", *(char **)ptr);
3429 break;
3430 case P_SEP:
3431 break;
3435 /***************************************************************************
3436 Check if two parameters are equal.
3437 ***************************************************************************/
3439 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3441 switch (type) {
3442 case P_BOOL:
3443 case P_BOOLREV:
3444 return (*((bool *)ptr1) == *((bool *)ptr2));
3446 case P_INTEGER:
3447 case P_ENUM:
3448 case P_OCTAL:
3449 case P_BYTES:
3450 return (*((int *)ptr1) == *((int *)ptr2));
3452 case P_CHAR:
3453 return (*((char *)ptr1) == *((char *)ptr2));
3455 case P_LIST:
3456 case P_CMDLIST:
3457 return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3459 case P_STRING:
3460 case P_USTRING:
3462 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3463 if (p1 && !*p1)
3464 p1 = NULL;
3465 if (p2 && !*p2)
3466 p2 = NULL;
3467 return (p1 == p2 || strequal(p1, p2));
3469 case P_SEP:
3470 break;
3472 return false;
3475 /***************************************************************************
3476 Initialize any local varients in the sDefault table.
3477 ***************************************************************************/
3479 void init_locals(void)
3481 /* None as yet. */
3484 /***************************************************************************
3485 Process a new section (service). At this stage all sections are services.
3486 Later we'll have special sections that permit server parameters to be set.
3487 Returns true on success, false on failure.
3488 ***************************************************************************/
3490 static bool do_section(const char *pszSectionName, void *userdata)
3492 bool bRetval;
3493 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3494 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3495 bRetval = false;
3497 /* if we were in a global section then do the local inits */
3498 if (bInGlobalSection && !isglobal)
3499 init_locals();
3501 /* if we've just struck a global section, note the fact. */
3502 bInGlobalSection = isglobal;
3504 /* check for multiple global sections */
3505 if (bInGlobalSection) {
3506 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3507 return true;
3510 if (!bInGlobalSection && bGlobalOnly)
3511 return true;
3513 /* if we have a current service, tidy it up before moving on */
3514 bRetval = true;
3516 if (iServiceIndex >= 0)
3517 bRetval = service_ok(iServiceIndex);
3519 /* if all is still well, move to the next record in the services array */
3520 if (bRetval) {
3521 /* We put this here to avoid an odd message order if messages are */
3522 /* issued by the post-processing of a previous section. */
3523 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3525 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3526 if (iServiceIndex < 0) {
3527 DEBUG(0, ("Failed to add a new service\n"));
3528 return false;
3530 /* Clean all parametric options for service */
3531 /* They will be added during parsing again */
3532 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3535 return bRetval;
3539 /***************************************************************************
3540 Determine if a partcular base parameter is currentl set to the default value.
3541 ***************************************************************************/
3543 static bool is_default(int i)
3545 if (!defaults_saved)
3546 return false;
3547 switch (parm_table[i].type) {
3548 case P_LIST:
3549 case P_CMDLIST:
3550 return str_list_equal((const char **)parm_table[i].def.lvalue,
3551 *(const char ***)lp_parm_ptr(NULL,
3552 &parm_table[i]));
3553 case P_STRING:
3554 case P_USTRING:
3555 return strequal(parm_table[i].def.svalue,
3556 *(char **)lp_parm_ptr(NULL,
3557 &parm_table[i]));
3558 case P_BOOL:
3559 case P_BOOLREV:
3560 return parm_table[i].def.bvalue ==
3561 *(bool *)lp_parm_ptr(NULL,
3562 &parm_table[i]);
3563 case P_CHAR:
3564 return parm_table[i].def.cvalue ==
3565 *(char *)lp_parm_ptr(NULL,
3566 &parm_table[i]);
3567 case P_INTEGER:
3568 case P_OCTAL:
3569 case P_ENUM:
3570 case P_BYTES:
3571 return parm_table[i].def.ivalue ==
3572 *(int *)lp_parm_ptr(NULL,
3573 &parm_table[i]);
3574 case P_SEP:
3575 break;
3577 return false;
3580 /***************************************************************************
3581 Display the contents of the global structure.
3582 ***************************************************************************/
3584 static void dump_globals(FILE *f)
3586 int i;
3587 struct parmlist_entry *data;
3589 fprintf(f, "[global]\n");
3591 for (i = 0; parm_table[i].label; i++)
3592 if (parm_table[i].p_class == P_GLOBAL &&
3593 !(parm_table[i].flags & FLAG_META) &&
3594 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3595 if (defaults_saved && is_default(i))
3596 continue;
3597 fprintf(f, "\t%s = ", parm_table[i].label);
3598 print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3599 &parm_table[i]),
3601 fprintf(f, "\n");
3603 if (Globals.param_opt != NULL) {
3604 data = Globals.param_opt;
3605 while(data) {
3606 fprintf(f, "\t%s = %s\n", data->key, data->value);
3607 data = data->next;
3613 /***************************************************************************
3614 Return true if a local parameter is currently set to the global default.
3615 ***************************************************************************/
3617 bool lp_is_default(int snum, struct parm_struct *parm)
3619 return equal_parameter(parm->type,
3620 lp_parm_ptr(ServicePtrs[snum], parm),
3621 lp_parm_ptr(NULL, parm));
3624 /***************************************************************************
3625 Display the contents of a single services record.
3626 ***************************************************************************/
3628 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3630 int i;
3631 struct parmlist_entry *data;
3633 if (pService != &sDefault)
3634 fprintf(f, "[%s]\n", pService->szService);
3636 for (i = 0; parm_table[i].label; i++) {
3638 if (parm_table[i].p_class == P_LOCAL &&
3639 !(parm_table[i].flags & FLAG_META) &&
3640 (*parm_table[i].label != '-') &&
3641 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3643 if (pService == &sDefault) {
3644 if (defaults_saved && is_default(i))
3645 continue;
3646 } else {
3647 if (equal_parameter(parm_table[i].type,
3648 lp_parm_ptr(pService, &parm_table[i]),
3649 lp_parm_ptr(NULL, &parm_table[i])))
3650 continue;
3653 fprintf(f, "\t%s = ", parm_table[i].label);
3654 print_parameter(&parm_table[i],
3655 lp_parm_ptr(pService, &parm_table[i]),
3657 fprintf(f, "\n");
3661 if (pService->param_opt != NULL) {
3662 data = pService->param_opt;
3663 while(data) {
3664 fprintf(f, "\t%s = %s\n", data->key, data->value);
3665 data = data->next;
3670 /***************************************************************************
3671 Display the contents of a parameter of a single services record.
3672 ***************************************************************************/
3674 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3676 int i;
3677 bool result = false;
3678 parm_class p_class;
3679 unsigned flag = 0;
3680 fstring local_parm_name;
3681 char *parm_opt;
3682 const char *parm_opt_value;
3684 /* check for parametrical option */
3685 fstrcpy( local_parm_name, parm_name);
3686 parm_opt = strchr( local_parm_name, ':');
3688 if (parm_opt) {
3689 *parm_opt = '\0';
3690 parm_opt++;
3691 if (strlen(parm_opt)) {
3692 parm_opt_value = lp_parm_const_string( snum,
3693 local_parm_name, parm_opt, NULL);
3694 if (parm_opt_value) {
3695 printf( "%s\n", parm_opt_value);
3696 result = true;
3699 return result;
3702 /* check for a key and print the value */
3703 if (isGlobal) {
3704 p_class = P_GLOBAL;
3705 flag = FLAG_GLOBAL;
3706 } else
3707 p_class = P_LOCAL;
3709 for (i = 0; parm_table[i].label; i++) {
3710 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3711 !(parm_table[i].flags & FLAG_META) &&
3712 (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3713 (*parm_table[i].label != '-') &&
3714 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3716 void *ptr;
3718 if (isGlobal) {
3719 ptr = lp_parm_ptr(NULL,
3720 &parm_table[i]);
3721 } else {
3722 ptr = lp_parm_ptr(ServicePtrs[snum],
3723 &parm_table[i]);
3726 print_parameter(&parm_table[i],
3727 ptr, f);
3728 fprintf(f, "\n");
3729 result = true;
3730 break;
3734 return result;
3737 /***************************************************************************
3738 Return info about the requested parameter (given as a string).
3739 Return NULL when the string is not a valid parameter name.
3740 ***************************************************************************/
3742 struct parm_struct *lp_get_parameter(const char *param_name)
3744 int num = map_parameter(param_name);
3746 if (num < 0) {
3747 return NULL;
3750 return &parm_table[num];
3753 /***************************************************************************
3754 Return info about the next parameter in a service.
3755 snum==GLOBAL_SECTION_SNUM gives the globals.
3756 Return NULL when out of parameters.
3757 ***************************************************************************/
3759 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3761 if (snum < 0) {
3762 /* do the globals */
3763 for (; parm_table[*i].label; (*i)++) {
3764 if (parm_table[*i].p_class == P_SEPARATOR)
3765 return &parm_table[(*i)++];
3767 if ((*parm_table[*i].label == '-'))
3768 continue;
3770 if ((*i) > 0
3771 && (parm_table[*i].offset ==
3772 parm_table[(*i) - 1].offset)
3773 && (parm_table[*i].p_class ==
3774 parm_table[(*i) - 1].p_class))
3775 continue;
3777 if (is_default(*i) && !allparameters)
3778 continue;
3780 return &parm_table[(*i)++];
3782 } else {
3783 struct loadparm_service *pService = ServicePtrs[snum];
3785 for (; parm_table[*i].label; (*i)++) {
3786 if (parm_table[*i].p_class == P_SEPARATOR)
3787 return &parm_table[(*i)++];
3789 if (parm_table[*i].p_class == P_LOCAL &&
3790 (*parm_table[*i].label != '-') &&
3791 ((*i) == 0 ||
3792 (parm_table[*i].offset !=
3793 parm_table[(*i) - 1].offset)))
3795 if (allparameters ||
3796 !equal_parameter(parm_table[*i].type,
3797 lp_parm_ptr(pService,
3798 &parm_table[*i]),
3799 lp_parm_ptr(NULL,
3800 &parm_table[*i])))
3802 return &parm_table[(*i)++];
3808 return NULL;
3812 #if 0
3813 /***************************************************************************
3814 Display the contents of a single copy structure.
3815 ***************************************************************************/
3816 static void dump_copy_map(bool *pcopymap)
3818 int i;
3819 if (!pcopymap)
3820 return;
3822 printf("\n\tNon-Copied parameters:\n");
3824 for (i = 0; parm_table[i].label; i++)
3825 if (parm_table[i].p_class == P_LOCAL &&
3826 parm_table[i].ptr && !pcopymap[i] &&
3827 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3829 printf("\t\t%s\n", parm_table[i].label);
3832 #endif
3834 /***************************************************************************
3835 Return TRUE if the passed service number is within range.
3836 ***************************************************************************/
3838 bool lp_snum_ok(int iService)
3840 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3843 /***************************************************************************
3844 Auto-load some home services.
3845 ***************************************************************************/
3847 static void lp_add_auto_services(char *str)
3849 char *s;
3850 char *p;
3851 int homes;
3852 char *saveptr;
3854 if (!str)
3855 return;
3857 s = SMB_STRDUP(str);
3858 if (!s)
3859 return;
3861 homes = lp_servicenumber(HOMES_NAME);
3863 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3864 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3865 char *home;
3867 if (lp_servicenumber(p) >= 0)
3868 continue;
3870 home = get_user_home_dir(talloc_tos(), p);
3872 if (home && home[0] && homes >= 0)
3873 lp_add_home(p, homes, p, home);
3875 TALLOC_FREE(home);
3877 SAFE_FREE(s);
3880 /***************************************************************************
3881 Auto-load one printer.
3882 ***************************************************************************/
3884 void lp_add_one_printer(const char *name, const char *comment,
3885 const char *location, void *pdata)
3887 int printers = lp_servicenumber(PRINTERS_NAME);
3888 int i;
3890 if (lp_servicenumber(name) < 0) {
3891 lp_add_printer(name, printers);
3892 if ((i = lp_servicenumber(name)) >= 0) {
3893 string_set(&ServicePtrs[i]->comment, comment);
3894 ServicePtrs[i]->autoloaded = true;
3899 /***************************************************************************
3900 Have we loaded a services file yet?
3901 ***************************************************************************/
3903 bool lp_loaded(void)
3905 return (bLoaded);
3908 /***************************************************************************
3909 Unload unused services.
3910 ***************************************************************************/
3912 void lp_killunused(struct smbd_server_connection *sconn,
3913 bool (*snumused) (struct smbd_server_connection *, int))
3915 int i;
3916 for (i = 0; i < iNumServices; i++) {
3917 if (!VALID(i))
3918 continue;
3920 /* don't kill autoloaded or usershare services */
3921 if ( ServicePtrs[i]->autoloaded ||
3922 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3923 continue;
3926 if (!snumused || !snumused(sconn, i)) {
3927 free_service_byindex(i);
3933 * Kill all except autoloaded and usershare services - convenience wrapper
3935 void lp_kill_all_services(void)
3937 lp_killunused(NULL, NULL);
3940 /***************************************************************************
3941 Unload a service.
3942 ***************************************************************************/
3944 void lp_killservice(int iServiceIn)
3946 if (VALID(iServiceIn)) {
3947 free_service_byindex(iServiceIn);
3951 /***************************************************************************
3952 Save the curent values of all global and sDefault parameters into the
3953 defaults union. This allows swat and testparm to show only the
3954 changed (ie. non-default) parameters.
3955 ***************************************************************************/
3957 static void lp_save_defaults(void)
3959 int i;
3960 for (i = 0; parm_table[i].label; i++) {
3961 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3962 && parm_table[i].p_class == parm_table[i - 1].p_class)
3963 continue;
3964 switch (parm_table[i].type) {
3965 case P_LIST:
3966 case P_CMDLIST:
3967 parm_table[i].def.lvalue = str_list_copy(
3968 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3969 break;
3970 case P_STRING:
3971 case P_USTRING:
3972 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3973 break;
3974 case P_BOOL:
3975 case P_BOOLREV:
3976 parm_table[i].def.bvalue =
3977 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3978 break;
3979 case P_CHAR:
3980 parm_table[i].def.cvalue =
3981 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3982 break;
3983 case P_INTEGER:
3984 case P_OCTAL:
3985 case P_ENUM:
3986 case P_BYTES:
3987 parm_table[i].def.ivalue =
3988 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3989 break;
3990 case P_SEP:
3991 break;
3994 defaults_saved = true;
3997 /***********************************************************
3998 If we should send plaintext/LANMAN passwords in the clinet
3999 ************************************************************/
4001 static void set_allowed_client_auth(void)
4003 if (Globals.bClientNTLMv2Auth) {
4004 Globals.bClientLanManAuth = false;
4006 if (!Globals.bClientLanManAuth) {
4007 Globals.bClientPlaintextAuth = false;
4011 /***************************************************************************
4012 JRA.
4013 The following code allows smbd to read a user defined share file.
4014 Yes, this is my intent. Yes, I'm comfortable with that...
4016 THE FOLLOWING IS SECURITY CRITICAL CODE.
4018 It washes your clothes, it cleans your house, it guards you while you sleep...
4019 Do not f%^k with it....
4020 ***************************************************************************/
4022 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4024 /***************************************************************************
4025 Check allowed stat state of a usershare file.
4026 Ensure we print out who is dicking with us so the admin can
4027 get their sorry ass fired.
4028 ***************************************************************************/
4030 static bool check_usershare_stat(const char *fname,
4031 const SMB_STRUCT_STAT *psbuf)
4033 if (!S_ISREG(psbuf->st_ex_mode)) {
4034 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4035 "not a regular file\n",
4036 fname, (unsigned int)psbuf->st_ex_uid ));
4037 return false;
4040 /* Ensure this doesn't have the other write bit set. */
4041 if (psbuf->st_ex_mode & S_IWOTH) {
4042 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4043 "public write. Refusing to allow as a usershare file.\n",
4044 fname, (unsigned int)psbuf->st_ex_uid ));
4045 return false;
4048 /* Should be 10k or less. */
4049 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4050 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4051 "too large (%u) to be a user share file.\n",
4052 fname, (unsigned int)psbuf->st_ex_uid,
4053 (unsigned int)psbuf->st_ex_size ));
4054 return false;
4057 return true;
4060 /***************************************************************************
4061 Parse the contents of a usershare file.
4062 ***************************************************************************/
4064 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4065 SMB_STRUCT_STAT *psbuf,
4066 const char *servicename,
4067 int snum,
4068 char **lines,
4069 int numlines,
4070 char **pp_sharepath,
4071 char **pp_comment,
4072 char **pp_cp_servicename,
4073 struct security_descriptor **ppsd,
4074 bool *pallow_guest)
4076 const char **prefixallowlist = lp_usershare_prefix_allow_list();
4077 const char **prefixdenylist = lp_usershare_prefix_deny_list();
4078 int us_vers;
4079 DIR *dp;
4080 SMB_STRUCT_STAT sbuf;
4081 char *sharepath = NULL;
4082 char *comment = NULL;
4084 *pp_sharepath = NULL;
4085 *pp_comment = NULL;
4087 *pallow_guest = false;
4089 if (numlines < 4) {
4090 return USERSHARE_MALFORMED_FILE;
4093 if (strcmp(lines[0], "#VERSION 1") == 0) {
4094 us_vers = 1;
4095 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4096 us_vers = 2;
4097 if (numlines < 5) {
4098 return USERSHARE_MALFORMED_FILE;
4100 } else {
4101 return USERSHARE_BAD_VERSION;
4104 if (strncmp(lines[1], "path=", 5) != 0) {
4105 return USERSHARE_MALFORMED_PATH;
4108 sharepath = talloc_strdup(ctx, &lines[1][5]);
4109 if (!sharepath) {
4110 return USERSHARE_POSIX_ERR;
4112 trim_string(sharepath, " ", " ");
4114 if (strncmp(lines[2], "comment=", 8) != 0) {
4115 return USERSHARE_MALFORMED_COMMENT_DEF;
4118 comment = talloc_strdup(ctx, &lines[2][8]);
4119 if (!comment) {
4120 return USERSHARE_POSIX_ERR;
4122 trim_string(comment, " ", " ");
4123 trim_char(comment, '"', '"');
4125 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4126 return USERSHARE_MALFORMED_ACL_DEF;
4129 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4130 return USERSHARE_ACL_ERR;
4133 if (us_vers == 2) {
4134 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4135 return USERSHARE_MALFORMED_ACL_DEF;
4137 if (lines[4][9] == 'y') {
4138 *pallow_guest = true;
4141 /* Backwards compatible extension to file version #2. */
4142 if (numlines > 5) {
4143 if (strncmp(lines[5], "sharename=", 10) != 0) {
4144 return USERSHARE_MALFORMED_SHARENAME_DEF;
4146 if (!strequal(&lines[5][10], servicename)) {
4147 return USERSHARE_BAD_SHARENAME;
4149 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4150 if (!*pp_cp_servicename) {
4151 return USERSHARE_POSIX_ERR;
4156 if (*pp_cp_servicename == NULL) {
4157 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4158 if (!*pp_cp_servicename) {
4159 return USERSHARE_POSIX_ERR;
4163 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4164 /* Path didn't change, no checks needed. */
4165 *pp_sharepath = sharepath;
4166 *pp_comment = comment;
4167 return USERSHARE_OK;
4170 /* The path *must* be absolute. */
4171 if (sharepath[0] != '/') {
4172 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4173 servicename, sharepath));
4174 return USERSHARE_PATH_NOT_ABSOLUTE;
4177 /* If there is a usershare prefix deny list ensure one of these paths
4178 doesn't match the start of the user given path. */
4179 if (prefixdenylist) {
4180 int i;
4181 for ( i=0; prefixdenylist[i]; i++ ) {
4182 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4183 servicename, i, prefixdenylist[i], sharepath ));
4184 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4185 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4186 "usershare prefix deny list entries.\n",
4187 servicename, sharepath));
4188 return USERSHARE_PATH_IS_DENIED;
4193 /* If there is a usershare prefix allow list ensure one of these paths
4194 does match the start of the user given path. */
4196 if (prefixallowlist) {
4197 int i;
4198 for ( i=0; prefixallowlist[i]; i++ ) {
4199 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4200 servicename, i, prefixallowlist[i], sharepath ));
4201 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4202 break;
4205 if (prefixallowlist[i] == NULL) {
4206 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4207 "usershare prefix allow list entries.\n",
4208 servicename, sharepath));
4209 return USERSHARE_PATH_NOT_ALLOWED;
4213 /* Ensure this is pointing to a directory. */
4214 dp = opendir(sharepath);
4216 if (!dp) {
4217 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4218 servicename, sharepath));
4219 return USERSHARE_PATH_NOT_DIRECTORY;
4222 /* Ensure the owner of the usershare file has permission to share
4223 this directory. */
4225 if (sys_stat(sharepath, &sbuf, false) == -1) {
4226 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4227 servicename, sharepath, strerror(errno) ));
4228 closedir(dp);
4229 return USERSHARE_POSIX_ERR;
4232 closedir(dp);
4234 if (!S_ISDIR(sbuf.st_ex_mode)) {
4235 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4236 servicename, sharepath ));
4237 return USERSHARE_PATH_NOT_DIRECTORY;
4240 /* Check if sharing is restricted to owner-only. */
4241 /* psbuf is the stat of the usershare definition file,
4242 sbuf is the stat of the target directory to be shared. */
4244 if (lp_usershare_owner_only()) {
4245 /* root can share anything. */
4246 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4247 return USERSHARE_PATH_NOT_ALLOWED;
4251 *pp_sharepath = sharepath;
4252 *pp_comment = comment;
4253 return USERSHARE_OK;
4256 /***************************************************************************
4257 Deal with a usershare file.
4258 Returns:
4259 >= 0 - snum
4260 -1 - Bad name, invalid contents.
4261 - service name already existed and not a usershare, problem
4262 with permissions to share directory etc.
4263 ***************************************************************************/
4265 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4267 SMB_STRUCT_STAT sbuf;
4268 SMB_STRUCT_STAT lsbuf;
4269 char *fname = NULL;
4270 char *sharepath = NULL;
4271 char *comment = NULL;
4272 char *cp_service_name = NULL;
4273 char **lines = NULL;
4274 int numlines = 0;
4275 int fd = -1;
4276 int iService = -1;
4277 TALLOC_CTX *ctx = talloc_stackframe();
4278 struct security_descriptor *psd = NULL;
4279 bool guest_ok = false;
4280 char *canon_name = NULL;
4281 bool added_service = false;
4282 int ret = -1;
4284 /* Ensure share name doesn't contain invalid characters. */
4285 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4286 DEBUG(0,("process_usershare_file: share name %s contains "
4287 "invalid characters (any of %s)\n",
4288 file_name, INVALID_SHARENAME_CHARS ));
4289 goto out;
4292 canon_name = canonicalize_servicename(ctx, file_name);
4293 if (!canon_name) {
4294 goto out;
4297 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4298 if (!fname) {
4299 goto out;
4302 /* Minimize the race condition by doing an lstat before we
4303 open and fstat. Ensure this isn't a symlink link. */
4305 if (sys_lstat(fname, &lsbuf, false) != 0) {
4306 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4307 fname, strerror(errno) ));
4308 goto out;
4311 /* This must be a regular file, not a symlink, directory or
4312 other strange filetype. */
4313 if (!check_usershare_stat(fname, &lsbuf)) {
4314 goto out;
4318 TDB_DATA data;
4319 NTSTATUS status;
4321 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4322 canon_name, &data);
4324 iService = -1;
4326 if (NT_STATUS_IS_OK(status) &&
4327 (data.dptr != NULL) &&
4328 (data.dsize == sizeof(iService))) {
4329 memcpy(&iService, data.dptr, sizeof(iService));
4333 if (iService != -1 &&
4334 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4335 &lsbuf.st_ex_mtime) == 0) {
4336 /* Nothing changed - Mark valid and return. */
4337 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4338 canon_name ));
4339 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4340 ret = iService;
4341 goto out;
4344 /* Try and open the file read only - no symlinks allowed. */
4345 #ifdef O_NOFOLLOW
4346 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4347 #else
4348 fd = open(fname, O_RDONLY, 0);
4349 #endif
4351 if (fd == -1) {
4352 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4353 fname, strerror(errno) ));
4354 goto out;
4357 /* Now fstat to be *SURE* it's a regular file. */
4358 if (sys_fstat(fd, &sbuf, false) != 0) {
4359 close(fd);
4360 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4361 fname, strerror(errno) ));
4362 goto out;
4365 /* Is it the same dev/inode as was lstated ? */
4366 if (!check_same_stat(&lsbuf, &sbuf)) {
4367 close(fd);
4368 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4369 "Symlink spoofing going on ?\n", fname ));
4370 goto out;
4373 /* This must be a regular file, not a symlink, directory or
4374 other strange filetype. */
4375 if (!check_usershare_stat(fname, &sbuf)) {
4376 goto out;
4379 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4381 close(fd);
4382 if (lines == NULL) {
4383 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4384 fname, (unsigned int)sbuf.st_ex_uid ));
4385 goto out;
4388 if (parse_usershare_file(ctx, &sbuf, file_name,
4389 iService, lines, numlines, &sharepath,
4390 &comment, &cp_service_name,
4391 &psd, &guest_ok) != USERSHARE_OK) {
4392 goto out;
4395 /* Everything ok - add the service possibly using a template. */
4396 if (iService < 0) {
4397 const struct loadparm_service *sp = &sDefault;
4398 if (snum_template != -1) {
4399 sp = ServicePtrs[snum_template];
4402 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4403 DEBUG(0, ("process_usershare_file: Failed to add "
4404 "new service %s\n", cp_service_name));
4405 goto out;
4408 added_service = true;
4410 /* Read only is controlled by usershare ACL below. */
4411 ServicePtrs[iService]->bRead_only = false;
4414 /* Write the ACL of the new/modified share. */
4415 if (!set_share_security(canon_name, psd)) {
4416 DEBUG(0, ("process_usershare_file: Failed to set share "
4417 "security for user share %s\n",
4418 canon_name ));
4419 goto out;
4422 /* If from a template it may be marked invalid. */
4423 ServicePtrs[iService]->valid = true;
4425 /* Set the service as a valid usershare. */
4426 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4428 /* Set guest access. */
4429 if (lp_usershare_allow_guests()) {
4430 ServicePtrs[iService]->bGuest_ok = guest_ok;
4433 /* And note when it was loaded. */
4434 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4435 string_set(&ServicePtrs[iService]->szPath, sharepath);
4436 string_set(&ServicePtrs[iService]->comment, comment);
4438 ret = iService;
4440 out:
4442 if (ret == -1 && iService != -1 && added_service) {
4443 lp_remove_service(iService);
4446 TALLOC_FREE(lines);
4447 TALLOC_FREE(ctx);
4448 return ret;
4451 /***************************************************************************
4452 Checks if a usershare entry has been modified since last load.
4453 ***************************************************************************/
4455 static bool usershare_exists(int iService, struct timespec *last_mod)
4457 SMB_STRUCT_STAT lsbuf;
4458 const char *usersharepath = Globals.szUsersharePath;
4459 char *fname;
4461 if (asprintf(&fname, "%s/%s",
4462 usersharepath,
4463 ServicePtrs[iService]->szService) < 0) {
4464 return false;
4467 if (sys_lstat(fname, &lsbuf, false) != 0) {
4468 SAFE_FREE(fname);
4469 return false;
4472 if (!S_ISREG(lsbuf.st_ex_mode)) {
4473 SAFE_FREE(fname);
4474 return false;
4477 SAFE_FREE(fname);
4478 *last_mod = lsbuf.st_ex_mtime;
4479 return true;
4482 /***************************************************************************
4483 Load a usershare service by name. Returns a valid servicenumber or -1.
4484 ***************************************************************************/
4486 int load_usershare_service(const char *servicename)
4488 SMB_STRUCT_STAT sbuf;
4489 const char *usersharepath = Globals.szUsersharePath;
4490 int max_user_shares = Globals.iUsershareMaxShares;
4491 int snum_template = -1;
4493 if (*usersharepath == 0 || max_user_shares == 0) {
4494 return -1;
4497 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4498 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4499 usersharepath, strerror(errno) ));
4500 return -1;
4503 if (!S_ISDIR(sbuf.st_ex_mode)) {
4504 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4505 usersharepath ));
4506 return -1;
4510 * This directory must be owned by root, and have the 't' bit set.
4511 * It also must not be writable by "other".
4514 #ifdef S_ISVTX
4515 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4516 #else
4517 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4518 #endif
4519 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4520 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4521 usersharepath ));
4522 return -1;
4525 /* Ensure the template share exists if it's set. */
4526 if (Globals.szUsershareTemplateShare[0]) {
4527 /* We can't use lp_servicenumber here as we are recommending that
4528 template shares have -valid=false set. */
4529 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4530 if (ServicePtrs[snum_template]->szService &&
4531 strequal(ServicePtrs[snum_template]->szService,
4532 Globals.szUsershareTemplateShare)) {
4533 break;
4537 if (snum_template == -1) {
4538 DEBUG(0,("load_usershare_service: usershare template share %s "
4539 "does not exist.\n",
4540 Globals.szUsershareTemplateShare ));
4541 return -1;
4545 return process_usershare_file(usersharepath, servicename, snum_template);
4548 /***************************************************************************
4549 Load all user defined shares from the user share directory.
4550 We only do this if we're enumerating the share list.
4551 This is the function that can delete usershares that have
4552 been removed.
4553 ***************************************************************************/
4555 int load_usershare_shares(struct smbd_server_connection *sconn,
4556 bool (*snumused) (struct smbd_server_connection *, int))
4558 DIR *dp;
4559 SMB_STRUCT_STAT sbuf;
4560 struct dirent *de;
4561 int num_usershares = 0;
4562 int max_user_shares = Globals.iUsershareMaxShares;
4563 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4564 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4565 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4566 int iService;
4567 int snum_template = -1;
4568 const char *usersharepath = Globals.szUsersharePath;
4569 int ret = lp_numservices();
4570 TALLOC_CTX *tmp_ctx;
4572 if (max_user_shares == 0 || *usersharepath == '\0') {
4573 return lp_numservices();
4576 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4577 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4578 usersharepath, strerror(errno) ));
4579 return ret;
4583 * This directory must be owned by root, and have the 't' bit set.
4584 * It also must not be writable by "other".
4587 #ifdef S_ISVTX
4588 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4589 #else
4590 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4591 #endif
4592 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4593 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4594 usersharepath ));
4595 return ret;
4598 /* Ensure the template share exists if it's set. */
4599 if (Globals.szUsershareTemplateShare[0]) {
4600 /* We can't use lp_servicenumber here as we are recommending that
4601 template shares have -valid=false set. */
4602 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4603 if (ServicePtrs[snum_template]->szService &&
4604 strequal(ServicePtrs[snum_template]->szService,
4605 Globals.szUsershareTemplateShare)) {
4606 break;
4610 if (snum_template == -1) {
4611 DEBUG(0,("load_usershare_shares: usershare template share %s "
4612 "does not exist.\n",
4613 Globals.szUsershareTemplateShare ));
4614 return ret;
4618 /* Mark all existing usershares as pending delete. */
4619 for (iService = iNumServices - 1; iService >= 0; iService--) {
4620 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4621 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4625 dp = opendir(usersharepath);
4626 if (!dp) {
4627 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4628 usersharepath, strerror(errno) ));
4629 return ret;
4632 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4633 (de = readdir(dp));
4634 num_dir_entries++ ) {
4635 int r;
4636 const char *n = de->d_name;
4638 /* Ignore . and .. */
4639 if (*n == '.') {
4640 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4641 continue;
4645 if (n[0] == ':') {
4646 /* Temporary file used when creating a share. */
4647 num_tmp_dir_entries++;
4650 /* Allow 20% tmp entries. */
4651 if (num_tmp_dir_entries > allowed_tmp_entries) {
4652 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4653 "in directory %s\n",
4654 num_tmp_dir_entries, usersharepath));
4655 break;
4658 r = process_usershare_file(usersharepath, n, snum_template);
4659 if (r == 0) {
4660 /* Update the services count. */
4661 num_usershares++;
4662 if (num_usershares >= max_user_shares) {
4663 DEBUG(0,("load_usershare_shares: max user shares reached "
4664 "on file %s in directory %s\n",
4665 n, usersharepath ));
4666 break;
4668 } else if (r == -1) {
4669 num_bad_dir_entries++;
4672 /* Allow 20% bad entries. */
4673 if (num_bad_dir_entries > allowed_bad_entries) {
4674 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4675 "in directory %s\n",
4676 num_bad_dir_entries, usersharepath));
4677 break;
4680 /* Allow 20% bad entries. */
4681 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4682 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4683 "in directory %s\n",
4684 num_dir_entries, usersharepath));
4685 break;
4689 closedir(dp);
4691 /* Sweep through and delete any non-refreshed usershares that are
4692 not currently in use. */
4693 tmp_ctx = talloc_stackframe();
4694 for (iService = iNumServices - 1; iService >= 0; iService--) {
4695 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4696 char *servname;
4698 if (snumused && snumused(sconn, iService)) {
4699 continue;
4702 servname = lp_servicename(tmp_ctx, iService);
4704 /* Remove from the share ACL db. */
4705 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4706 servname ));
4707 delete_share_security(servname);
4708 free_service_byindex(iService);
4711 talloc_free(tmp_ctx);
4713 return lp_numservices();
4716 /********************************************************
4717 Destroy global resources allocated in this file
4718 ********************************************************/
4720 void gfree_loadparm(void)
4722 int i;
4724 free_file_list();
4726 /* Free resources allocated to services */
4728 for ( i = 0; i < iNumServices; i++ ) {
4729 if ( VALID(i) ) {
4730 free_service_byindex(i);
4734 SAFE_FREE( ServicePtrs );
4735 iNumServices = 0;
4737 /* Now release all resources allocated to global
4738 parameters and the default service */
4740 free_global_parameters();
4744 /***************************************************************************
4745 Allow client apps to specify that they are a client
4746 ***************************************************************************/
4747 static void lp_set_in_client(bool b)
4749 in_client = b;
4753 /***************************************************************************
4754 Determine if we're running in a client app
4755 ***************************************************************************/
4756 static bool lp_is_in_client(void)
4758 return in_client;
4761 /***************************************************************************
4762 Load the services array from the services file. Return true on success,
4763 false on failure.
4764 ***************************************************************************/
4766 static bool lp_load_ex(const char *pszFname,
4767 bool global_only,
4768 bool save_defaults,
4769 bool add_ipc,
4770 bool initialize_globals,
4771 bool allow_include_registry,
4772 bool load_all_shares)
4774 char *n2 = NULL;
4775 bool bRetval;
4777 bRetval = false;
4779 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4781 bInGlobalSection = true;
4782 bGlobalOnly = global_only;
4783 bAllowIncludeRegistry = allow_include_registry;
4785 init_globals(initialize_globals);
4787 free_file_list();
4789 if (save_defaults) {
4790 init_locals();
4791 lp_save_defaults();
4794 if (!initialize_globals) {
4795 free_param_opts(&Globals.param_opt);
4796 apply_lp_set_cmdline();
4799 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4801 /* We get sections first, so have to start 'behind' to make up */
4802 iServiceIndex = -1;
4804 if (lp_config_backend_is_file()) {
4805 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4806 current_user_info.domain,
4807 pszFname);
4808 if (!n2) {
4809 smb_panic("lp_load_ex: out of memory");
4812 add_to_file_list(pszFname, n2);
4814 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4815 TALLOC_FREE(n2);
4817 /* finish up the last section */
4818 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4819 if (bRetval) {
4820 if (iServiceIndex >= 0) {
4821 bRetval = service_ok(iServiceIndex);
4825 if (lp_config_backend_is_registry()) {
4826 /* config backend changed to registry in config file */
4828 * We need to use this extra global variable here to
4829 * survive restart: init_globals uses this as a default
4830 * for ConfigBackend. Otherwise, init_globals would
4831 * send us into an endless loop here.
4833 config_backend = CONFIG_BACKEND_REGISTRY;
4834 /* start over */
4835 DEBUG(1, ("lp_load_ex: changing to config backend "
4836 "registry\n"));
4837 init_globals(true);
4838 lp_kill_all_services();
4839 return lp_load_ex(pszFname, global_only, save_defaults,
4840 add_ipc, initialize_globals,
4841 allow_include_registry,
4842 load_all_shares);
4844 } else if (lp_config_backend_is_registry()) {
4845 bRetval = process_registry_globals();
4846 } else {
4847 DEBUG(0, ("Illegal config backend given: %d\n",
4848 lp_config_backend()));
4849 bRetval = false;
4852 if (bRetval && lp_registry_shares()) {
4853 if (load_all_shares) {
4854 bRetval = process_registry_shares();
4855 } else {
4856 bRetval = reload_registry_shares();
4861 char *serv = lp_auto_services(talloc_tos());
4862 lp_add_auto_services(serv);
4863 TALLOC_FREE(serv);
4866 if (add_ipc) {
4867 /* When 'restrict anonymous = 2' guest connections to ipc$
4868 are denied */
4869 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4870 if ( lp_enable_asu_support() ) {
4871 lp_add_ipc("ADMIN$", false);
4875 set_allowed_client_auth();
4877 if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4878 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4879 lp_passwordserver()));
4882 bLoaded = true;
4884 /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4885 /* if bWINSsupport is true and we are in the client */
4886 if (lp_is_in_client() && Globals.bWINSsupport) {
4887 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4890 init_iconv();
4892 fault_configure(smb_panic_s3);
4894 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4895 const char **vfs_objects = lp_vfs_objects(-1);
4896 if (!vfs_objects || !vfs_objects[0]) {
4897 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
4898 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
4899 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
4900 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
4901 } else {
4902 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
4905 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4908 bAllowIncludeRegistry = true;
4910 return (bRetval);
4913 bool lp_load(const char *pszFname,
4914 bool global_only,
4915 bool save_defaults,
4916 bool add_ipc,
4917 bool initialize_globals)
4919 return lp_load_ex(pszFname,
4920 global_only,
4921 save_defaults,
4922 add_ipc,
4923 initialize_globals,
4924 true, /* allow_include_registry */
4925 false); /* load_all_shares*/
4928 bool lp_load_initial_only(const char *pszFname)
4930 return lp_load_ex(pszFname,
4931 true, /* global only */
4932 false, /* save_defaults */
4933 false, /* add_ipc */
4934 true, /* initialize_globals */
4935 false, /* allow_include_registry */
4936 false); /* load_all_shares*/
4940 * most common lp_load wrapper, loading only the globals
4942 bool lp_load_global(const char *file_name)
4944 return lp_load_ex(file_name,
4945 true, /* global_only */
4946 false, /* save_defaults */
4947 false, /* add_ipc */
4948 true, /* initialize_globals */
4949 true, /* allow_include_registry */
4950 false); /* load_all_shares*/
4954 * lp_load wrapper, especially for clients
4956 bool lp_load_client(const char *file_name)
4958 lp_set_in_client(true);
4960 return lp_load_global(file_name);
4964 * lp_load wrapper, loading only globals, but intended
4965 * for subsequent calls, not reinitializing the globals
4966 * to default values
4968 bool lp_load_global_no_reinit(const char *file_name)
4970 return lp_load_ex(file_name,
4971 true, /* global_only */
4972 false, /* save_defaults */
4973 false, /* add_ipc */
4974 false, /* initialize_globals */
4975 true, /* allow_include_registry */
4976 false); /* load_all_shares*/
4980 * lp_load wrapper, especially for clients, no reinitialization
4982 bool lp_load_client_no_reinit(const char *file_name)
4984 lp_set_in_client(true);
4986 return lp_load_global_no_reinit(file_name);
4989 bool lp_load_with_registry_shares(const char *pszFname,
4990 bool global_only,
4991 bool save_defaults,
4992 bool add_ipc,
4993 bool initialize_globals)
4995 return lp_load_ex(pszFname,
4996 global_only,
4997 save_defaults,
4998 add_ipc,
4999 initialize_globals,
5000 true, /* allow_include_registry */
5001 true); /* load_all_shares*/
5004 /***************************************************************************
5005 Return the max number of services.
5006 ***************************************************************************/
5008 int lp_numservices(void)
5010 return (iNumServices);
5013 /***************************************************************************
5014 Display the contents of the services array in human-readable form.
5015 ***************************************************************************/
5017 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5019 int iService;
5021 if (show_defaults)
5022 defaults_saved = false;
5024 dump_globals(f);
5026 dump_a_service(&sDefault, f);
5028 for (iService = 0; iService < maxtoprint; iService++) {
5029 fprintf(f,"\n");
5030 lp_dump_one(f, show_defaults, iService);
5034 /***************************************************************************
5035 Display the contents of one service in human-readable form.
5036 ***************************************************************************/
5038 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5040 if (VALID(snum)) {
5041 if (ServicePtrs[snum]->szService[0] == '\0')
5042 return;
5043 dump_a_service(ServicePtrs[snum], f);
5047 /***************************************************************************
5048 Return the number of the service with the given name, or -1 if it doesn't
5049 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5050 getservicebyname()! This works ONLY if all services have been loaded, and
5051 does not copy the found service.
5052 ***************************************************************************/
5054 int lp_servicenumber(const char *pszServiceName)
5056 int iService;
5057 fstring serviceName;
5059 if (!pszServiceName) {
5060 return GLOBAL_SECTION_SNUM;
5063 for (iService = iNumServices - 1; iService >= 0; iService--) {
5064 if (VALID(iService) && ServicePtrs[iService]->szService) {
5066 * The substitution here is used to support %U is
5067 * service names
5069 fstrcpy(serviceName, ServicePtrs[iService]->szService);
5070 standard_sub_basic(get_current_username(),
5071 current_user_info.domain,
5072 serviceName,sizeof(serviceName));
5073 if (strequal(serviceName, pszServiceName)) {
5074 break;
5079 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5080 struct timespec last_mod;
5082 if (!usershare_exists(iService, &last_mod)) {
5083 /* Remove the share security tdb entry for it. */
5084 delete_share_security(lp_servicename(talloc_tos(), iService));
5085 /* Remove it from the array. */
5086 free_service_byindex(iService);
5087 /* Doesn't exist anymore. */
5088 return GLOBAL_SECTION_SNUM;
5091 /* Has it been modified ? If so delete and reload. */
5092 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5093 &last_mod) < 0) {
5094 /* Remove it from the array. */
5095 free_service_byindex(iService);
5096 /* and now reload it. */
5097 iService = load_usershare_service(pszServiceName);
5101 if (iService < 0) {
5102 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5103 return GLOBAL_SECTION_SNUM;
5106 return (iService);
5109 /*******************************************************************
5110 A useful volume label function.
5111 ********************************************************************/
5113 const char *volume_label(TALLOC_CTX *ctx, int snum)
5115 char *ret;
5116 const char *label = lp_volume(ctx, snum);
5117 if (!*label) {
5118 label = lp_servicename(ctx, snum);
5121 /* This returns a 33 byte guarenteed null terminated string. */
5122 ret = talloc_strndup(ctx, label, 32);
5123 if (!ret) {
5124 return "";
5126 return ret;
5129 /*******************************************************************
5130 Get the default server type we will announce as via nmbd.
5131 ********************************************************************/
5133 int lp_default_server_announce(void)
5135 int default_server_announce = 0;
5136 default_server_announce |= SV_TYPE_WORKSTATION;
5137 default_server_announce |= SV_TYPE_SERVER;
5138 default_server_announce |= SV_TYPE_SERVER_UNIX;
5140 /* note that the flag should be set only if we have a
5141 printer service but nmbd doesn't actually load the
5142 services so we can't tell --jerry */
5144 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5146 default_server_announce |= SV_TYPE_SERVER_NT;
5147 default_server_announce |= SV_TYPE_NT;
5149 switch (lp_server_role()) {
5150 case ROLE_DOMAIN_MEMBER:
5151 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5152 break;
5153 case ROLE_DOMAIN_PDC:
5154 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5155 break;
5156 case ROLE_DOMAIN_BDC:
5157 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5158 break;
5159 case ROLE_STANDALONE:
5160 default:
5161 break;
5163 if (lp_time_server())
5164 default_server_announce |= SV_TYPE_TIME_SOURCE;
5166 if (lp_host_msdfs())
5167 default_server_announce |= SV_TYPE_DFS_SERVER;
5169 return default_server_announce;
5172 /***********************************************************
5173 If we are PDC then prefer us as DMB
5174 ************************************************************/
5176 bool lp_domain_master(void)
5178 if (Globals.domain_master == Auto)
5179 return (lp_server_role() == ROLE_DOMAIN_PDC);
5181 return (bool)Globals.domain_master;
5184 /***********************************************************
5185 If we are PDC then prefer us as DMB
5186 ************************************************************/
5188 static bool lp_domain_master_true_or_auto(void)
5190 if (Globals.domain_master) /* auto or yes */
5191 return true;
5193 return false;
5196 /***********************************************************
5197 If we are DMB then prefer us as LMB
5198 ************************************************************/
5200 bool lp_preferred_master(void)
5202 if (Globals.iPreferredMaster == Auto)
5203 return (lp_local_master() && lp_domain_master());
5205 return (bool)Globals.iPreferredMaster;
5208 /*******************************************************************
5209 Remove a service.
5210 ********************************************************************/
5212 void lp_remove_service(int snum)
5214 ServicePtrs[snum]->valid = false;
5215 invalid_services[num_invalid_services++] = snum;
5218 /*******************************************************************
5219 Copy a service.
5220 ********************************************************************/
5222 void lp_copy_service(int snum, const char *new_name)
5224 do_section(new_name, NULL);
5225 if (snum >= 0) {
5226 snum = lp_servicenumber(new_name);
5227 if (snum >= 0) {
5228 char *name = lp_servicename(talloc_tos(), snum);
5229 lp_do_parameter(snum, "copy", name);
5234 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5236 const char *ret = lp__printername(talloc_tos(), snum);
5237 if (ret == NULL || *ret == '\0') {
5238 ret = lp_const_servicename(snum);
5241 return ret;
5245 /***********************************************************
5246 Allow daemons such as winbindd to fix their logfile name.
5247 ************************************************************/
5249 void lp_set_logfile(const char *name)
5251 string_set(&Globals.logfile, name);
5252 debug_set_logfile(name);
5255 /*******************************************************************
5256 Return the max print jobs per queue.
5257 ********************************************************************/
5259 int lp_maxprintjobs(int snum)
5261 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5262 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5263 maxjobs = PRINT_MAX_JOBID - 1;
5265 return maxjobs;
5268 const char *lp_printcapname(void)
5270 if ((Globals.szPrintcapname != NULL) &&
5271 (Globals.szPrintcapname[0] != '\0'))
5272 return Globals.szPrintcapname;
5274 if (sDefault.iPrinting == PRINT_CUPS) {
5275 return "cups";
5278 if (sDefault.iPrinting == PRINT_BSD)
5279 return "/etc/printcap";
5281 return PRINTCAP_NAME;
5284 static uint32 spoolss_state;
5286 bool lp_disable_spoolss( void )
5288 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5289 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5291 return spoolss_state == SVCCTL_STOPPED ? true : false;
5294 void lp_set_spoolss_state( uint32 state )
5296 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5298 spoolss_state = state;
5301 uint32 lp_get_spoolss_state( void )
5303 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5306 /*******************************************************************
5307 Ensure we don't use sendfile if server smb signing is active.
5308 ********************************************************************/
5310 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5312 bool sign_active = false;
5314 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5315 if (get_Protocol() < PROTOCOL_NT1) {
5316 return false;
5318 if (signing_state) {
5319 sign_active = smb_signing_is_active(signing_state);
5321 return (lp__use_sendfile(snum) &&
5322 (get_remote_arch() != RA_WIN95) &&
5323 !sign_active);
5326 /*******************************************************************
5327 Turn off sendfile if we find the underlying OS doesn't support it.
5328 ********************************************************************/
5330 void set_use_sendfile(int snum, bool val)
5332 if (LP_SNUM_OK(snum))
5333 ServicePtrs[snum]->bUseSendfile = val;
5334 else
5335 sDefault.bUseSendfile = val;
5338 /*******************************************************************
5339 Turn off storing DOS attributes if this share doesn't support it.
5340 ********************************************************************/
5342 void set_store_dos_attributes(int snum, bool val)
5344 if (!LP_SNUM_OK(snum))
5345 return;
5346 ServicePtrs[(snum)]->bStoreDosAttributes = val;
5349 void lp_set_mangling_method(const char *new_method)
5351 string_set(&Globals.szManglingMethod, new_method);
5354 /*******************************************************************
5355 Global state for POSIX pathname processing.
5356 ********************************************************************/
5358 static bool posix_pathnames;
5360 bool lp_posix_pathnames(void)
5362 return posix_pathnames;
5365 /*******************************************************************
5366 Change everything needed to ensure POSIX pathname processing (currently
5367 not much).
5368 ********************************************************************/
5370 void lp_set_posix_pathnames(void)
5372 posix_pathnames = true;
5375 /*******************************************************************
5376 Global state for POSIX lock processing - CIFS unix extensions.
5377 ********************************************************************/
5379 bool posix_default_lock_was_set;
5380 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5382 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5384 if (posix_default_lock_was_set) {
5385 return posix_cifsx_locktype;
5386 } else {
5387 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5391 /*******************************************************************
5392 ********************************************************************/
5394 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5396 posix_default_lock_was_set = true;
5397 posix_cifsx_locktype = val;
5400 int lp_min_receive_file_size(void)
5402 if (Globals.iminreceivefile < 0) {
5403 return 0;
5405 return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5408 /*******************************************************************
5409 Safe wide links checks.
5410 This helper function always verify the validity of wide links,
5411 even after a configuration file reload.
5412 ********************************************************************/
5414 static bool lp_widelinks_internal(int snum)
5416 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5417 sDefault.bWidelinks);
5420 void widelinks_warning(int snum)
5422 if (lp_allow_insecure_widelinks()) {
5423 return;
5426 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5427 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5428 "These parameters are incompatible. "
5429 "Wide links will be disabled for this share.\n",
5430 lp_servicename(talloc_tos(), snum) ));
5434 bool lp_widelinks(int snum)
5436 /* wide links is always incompatible with unix extensions */
5437 if (lp_unix_extensions()) {
5439 * Unless we have "allow insecure widelinks"
5440 * turned on.
5442 if (!lp_allow_insecure_widelinks()) {
5443 return false;
5447 return lp_widelinks_internal(snum);
5450 bool lp_writeraw(void)
5452 if (lp_async_smb_echo_handler()) {
5453 return false;
5455 return lp__writeraw();
5458 bool lp_readraw(void)
5460 if (lp_async_smb_echo_handler()) {
5461 return false;
5463 return lp__readraw();
5466 int lp_server_role(void)
5468 return lp_find_server_role(lp__server_role(),
5469 lp__security(),
5470 lp__domain_logons(),
5471 lp_domain_master_true_or_auto());
5474 int lp_security(void)
5476 return lp_find_security(lp__server_role(),
5477 lp__security());