auth: Make sure that creds_out is initialized with NULL.
[Samba.git] / source3 / param / loadparm.c
blobd3d18f4c86ae550f10347b85b58e7b71f7e3a2d4
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 .iDir_mask = 0755,
195 .iDir_force_mode = 0,
196 .iMaxConnections = 0,
197 .iDefaultCase = CASE_LOWER,
198 .iPrinting = DEFAULT_PRINTING,
199 .iOplockContentionLimit = 2,
200 .iCSCPolicy = 0,
201 .iBlock_size = 1024,
202 .iDfreeCacheTime = 0,
203 .bPreexecClose = false,
204 .bRootpreexecClose = false,
205 .iCaseSensitive = Auto,
206 .bCasePreserve = true,
207 .bShortCasePreserve = true,
208 .bHideDotFiles = true,
209 .bHideSpecialFiles = false,
210 .bHideUnReadable = false,
211 .bHideUnWriteableFiles = false,
212 .bBrowseable = true,
213 .bAccessBasedShareEnum = false,
214 .bAvailable = true,
215 .bRead_only = true,
216 .bNo_set_dir = true,
217 .bGuest_only = false,
218 .bAdministrative_share = false,
219 .bGuest_ok = false,
220 .bPrint_ok = false,
221 .bPrintNotifyBackchannel = true,
222 .bMap_system = false,
223 .bMap_hidden = false,
224 .bMap_archive = true,
225 .bStoreDosAttributes = false,
226 .bDmapiSupport = false,
227 .bLocking = true,
228 .iStrictLocking = Auto,
229 .bPosixLocking = true,
230 .bOpLocks = true,
231 .bKernelOplocks = false,
232 .bLevel2OpLocks = true,
233 .bOnlyUser = false,
234 .bMangledNames = true,
235 .bWidelinks = false,
236 .bSymlinks = true,
237 .bSyncAlways = false,
238 .bStrictAllocate = false,
239 .bStrictSync = false,
240 .magic_char = '~',
241 .copymap = NULL,
242 .bDeleteReadonly = false,
243 .bFakeOplocks = false,
244 .bDeleteVetoFiles = false,
245 .bDosFilemode = false,
246 .bDosFiletimes = true,
247 .bDosFiletimeResolution = false,
248 .bFakeDirCreateTimes = false,
249 .bBlockingLocks = true,
250 .bInheritPerms = false,
251 .bInheritACLS = false,
252 .bInheritOwner = false,
253 .bMSDfsRoot = false,
254 .bUseClientDriver = false,
255 .bDefaultDevmode = true,
256 .bForcePrintername = false,
257 .bNTAclSupport = true,
258 .bForceUnknownAclUser = false,
259 .bUseSendfile = false,
260 .bProfileAcls = false,
261 .bMap_acl_inherit = false,
262 .bAfs_Share = false,
263 .bEASupport = false,
264 .bAclCheckPermissions = true,
265 .bAclMapFullControl = true,
266 .bAclGroupControl = false,
267 .bAclAllowExecuteAlways = false,
268 .bChangeNotify = true,
269 .bKernelChangeNotify = true,
270 .iallocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
271 .iAioReadSize = 0,
272 .iAioWriteSize = 0,
273 .iMap_readonly = MAP_READONLY_YES,
274 #ifdef BROKEN_DIRECTORY_HANDLING
275 .iDirectoryNameCacheSize = 0,
276 #else
277 .iDirectoryNameCacheSize = 100,
278 #endif
279 .ismb_encrypt = SMB_SIGNING_DEFAULT,
280 .bKernelShareModes = true,
281 .bDurableHandles = true,
282 .param_opt = NULL,
283 .dummy = ""
286 /* local variables */
287 static struct loadparm_service **ServicePtrs = NULL;
288 static int iNumServices = 0;
289 static int iServiceIndex = 0;
290 static struct db_context *ServiceHash;
291 static int *invalid_services = NULL;
292 static int num_invalid_services = 0;
293 static bool bInGlobalSection = true;
294 static bool bGlobalOnly = false;
296 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
298 /* prototypes for the special type handlers */
299 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
300 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
301 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
302 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
303 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
304 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
305 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
306 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
307 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
308 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
309 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
310 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
312 /* these are parameter handlers which are not needed in the
313 * source3 code
316 #define handle_logfile NULL
318 static void set_allowed_client_auth(void);
320 static void add_to_file_list(const char *fname, const char *subfname);
321 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
322 static void free_param_opts(struct parmlist_entry **popts);
324 #include "lib/param/param_table.c"
326 /* this is used to prevent lots of mallocs of size 1 */
327 static const char null_string[] = "";
330 Set a string value, allocing the space for the string
333 static bool string_init(char **dest,const char *src)
335 size_t l;
337 if (!src)
338 src = "";
340 l = strlen(src);
342 if (l == 0) {
343 *dest = discard_const_p(char, null_string);
344 } else {
345 (*dest) = SMB_STRDUP(src);
346 if ((*dest) == NULL) {
347 DEBUG(0,("Out of memory in string_init\n"));
348 return false;
351 return(true);
355 Free a string value.
358 static void string_free(char **s)
360 if (!s || !(*s))
361 return;
362 if (*s == null_string)
363 *s = NULL;
364 SAFE_FREE(*s);
368 Set a string value, deallocating any existing space, and allocing the space
369 for the string
372 static bool string_set(char **dest,const char *src)
374 string_free(dest);
375 return(string_init(dest,src));
378 /***************************************************************************
379 Initialise the sDefault parameter structure for the printer values.
380 ***************************************************************************/
382 static void init_printer_values(struct loadparm_service *pService)
384 /* choose defaults depending on the type of printing */
385 switch (pService->iPrinting) {
386 case PRINT_BSD:
387 case PRINT_AIX:
388 case PRINT_LPRNT:
389 case PRINT_LPROS2:
390 string_set(&pService->szLpqcommand, "lpq -P'%p'");
391 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
392 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
393 break;
395 case PRINT_LPRNG:
396 case PRINT_PLP:
397 string_set(&pService->szLpqcommand, "lpq -P'%p'");
398 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
399 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
400 string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
401 string_set(&pService->szQueueresumecommand, "lpc start '%p'");
402 string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
403 string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
404 break;
406 case PRINT_CUPS:
407 case PRINT_IPRINT:
408 /* set the lpq command to contain the destination printer
409 name only. This is used by cups_queue_get() */
410 string_set(&pService->szLpqcommand, "%p");
411 string_set(&pService->szLprmcommand, "");
412 string_set(&pService->szPrintcommand, "");
413 string_set(&pService->szLppausecommand, "");
414 string_set(&pService->szLpresumecommand, "");
415 string_set(&pService->szQueuepausecommand, "");
416 string_set(&pService->szQueueresumecommand, "");
417 break;
419 case PRINT_SYSV:
420 case PRINT_HPUX:
421 string_set(&pService->szLpqcommand, "lpstat -o%p");
422 string_set(&pService->szLprmcommand, "cancel %p-%j");
423 string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
424 string_set(&pService->szQueuepausecommand, "disable %p");
425 string_set(&pService->szQueueresumecommand, "enable %p");
426 #ifndef HPUX
427 string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
428 string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
429 #endif /* HPUX */
430 break;
432 case PRINT_QNX:
433 string_set(&pService->szLpqcommand, "lpq -P%p");
434 string_set(&pService->szLprmcommand, "lprm -P%p %j");
435 string_set(&pService->szPrintcommand, "lp -r -P%p %s");
436 break;
438 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
440 case PRINT_TEST:
441 case PRINT_VLP: {
442 const char *tdbfile;
443 TALLOC_CTX *tmp_ctx = talloc_stackframe();
444 char *tmp;
446 tdbfile = talloc_asprintf(
447 tmp_ctx, "tdbfile=%s",
448 lp_parm_const_string(-1, "vlp", "tdbfile",
449 "/tmp/vlp.tdb"));
450 if (tdbfile == NULL) {
451 tdbfile="tdbfile=/tmp/vlp.tdb";
454 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
455 tdbfile);
456 string_set(&pService->szPrintcommand,
457 tmp ? tmp : "vlp print %p %s");
459 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
460 tdbfile);
461 string_set(&pService->szLpqcommand,
462 tmp ? tmp : "vlp lpq %p");
464 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
465 tdbfile);
466 string_set(&pService->szLprmcommand,
467 tmp ? tmp : "vlp lprm %p %j");
469 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
470 tdbfile);
471 string_set(&pService->szLppausecommand,
472 tmp ? tmp : "vlp lppause %p %j");
474 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
475 tdbfile);
476 string_set(&pService->szLpresumecommand,
477 tmp ? tmp : "vlp lpresume %p %j");
479 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
480 tdbfile);
481 string_set(&pService->szQueuepausecommand,
482 tmp ? tmp : "vlp queuepause %p");
484 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
485 tdbfile);
486 string_set(&pService->szQueueresumecommand,
487 tmp ? tmp : "vlp queueresume %p");
488 TALLOC_FREE(tmp_ctx);
490 break;
492 #endif /* DEVELOPER */
497 * Function to return the default value for the maximum number of open
498 * file descriptors permitted. This function tries to consult the
499 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
500 * the smaller of those.
502 static int max_open_files(void)
504 int sysctl_max = MAX_OPEN_FILES;
505 int rlimit_max = MAX_OPEN_FILES;
507 #ifdef HAVE_SYSCTLBYNAME
509 size_t size = sizeof(sysctl_max);
510 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
513 #endif
515 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
517 struct rlimit rl;
519 ZERO_STRUCT(rl);
521 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
522 rlimit_max = rl.rlim_cur;
524 #if defined(RLIM_INFINITY)
525 if(rl.rlim_cur == RLIM_INFINITY)
526 rlimit_max = MAX_OPEN_FILES;
527 #endif
529 #endif
531 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
532 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
533 "minimum Windows limit (%d)\n",
534 sysctl_max,
535 MIN_OPEN_FILES_WINDOWS));
536 sysctl_max = MIN_OPEN_FILES_WINDOWS;
539 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
540 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
541 "minimum Windows limit (%d)\n",
542 rlimit_max,
543 MIN_OPEN_FILES_WINDOWS));
544 rlimit_max = MIN_OPEN_FILES_WINDOWS;
547 return MIN(sysctl_max, rlimit_max);
551 * Common part of freeing allocated data for one parameter.
553 static void free_one_parameter_common(void *parm_ptr,
554 struct parm_struct parm)
556 if ((parm.type == P_STRING) ||
557 (parm.type == P_USTRING))
559 string_free((char**)parm_ptr);
560 } else if (parm.type == P_LIST) {
561 TALLOC_FREE(*((char***)parm_ptr));
566 * Free the allocated data for one parameter for a share
567 * given as a service struct.
569 static void free_one_parameter(struct loadparm_service *service,
570 struct parm_struct parm)
572 void *parm_ptr;
574 if (parm.p_class != P_LOCAL) {
575 return;
578 parm_ptr = lp_parm_ptr(service, &parm);
580 free_one_parameter_common(parm_ptr, parm);
584 * Free the allocated parameter data of a share given
585 * as a service struct.
587 static void free_parameters(struct loadparm_service *service)
589 uint32_t i;
591 for (i=0; parm_table[i].label; i++) {
592 free_one_parameter(service, parm_table[i]);
597 * Free the allocated data for one parameter for a given share
598 * specified by an snum.
600 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
602 void *parm_ptr;
604 if (snum < 0) {
605 parm_ptr = lp_parm_ptr(NULL, &parm);
606 } else if (parm.p_class != P_LOCAL) {
607 return;
608 } else {
609 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
612 free_one_parameter_common(parm_ptr, parm);
616 * Free the allocated parameter data for a share specified
617 * by an snum.
619 static void free_parameters_by_snum(int snum)
621 uint32_t i;
623 for (i=0; parm_table[i].label; i++) {
624 free_one_parameter_by_snum(snum, parm_table[i]);
629 * Free the allocated global parameters.
631 static void free_global_parameters(void)
633 free_param_opts(&Globals.param_opt);
634 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
635 TALLOC_FREE(Globals.ctx);
638 static int map_parameter(const char *pszParmName);
640 struct lp_stored_option {
641 struct lp_stored_option *prev, *next;
642 const char *label;
643 const char *value;
646 static struct lp_stored_option *stored_options;
649 save options set by lp_set_cmdline() into a list. This list is
650 re-applied when we do a globals reset, so that cmdline set options
651 are sticky across reloads of smb.conf
653 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
655 struct lp_stored_option *entry, *entry_next;
656 for (entry = stored_options; entry != NULL; entry = entry_next) {
657 entry_next = entry->next;
658 if (strcmp(pszParmName, entry->label) == 0) {
659 DLIST_REMOVE(stored_options, entry);
660 talloc_free(entry);
661 break;
665 entry = talloc(NULL, struct lp_stored_option);
666 if (!entry) {
667 return false;
670 entry->label = talloc_strdup(entry, pszParmName);
671 if (!entry->label) {
672 talloc_free(entry);
673 return false;
676 entry->value = talloc_strdup(entry, pszParmValue);
677 if (!entry->value) {
678 talloc_free(entry);
679 return false;
682 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
684 return true;
687 static bool apply_lp_set_cmdline(void)
689 struct lp_stored_option *entry = NULL;
690 for (entry = stored_options; entry != NULL; entry = entry->next) {
691 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
692 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
693 entry->label, entry->value));
694 return false;
697 return true;
700 /***************************************************************************
701 Initialise the global parameter structure.
702 ***************************************************************************/
704 static void init_globals(bool reinit_globals)
706 static bool done_init = false;
707 char *s = NULL;
708 int i;
710 /* If requested to initialize only once and we've already done it... */
711 if (!reinit_globals && done_init) {
712 /* ... then we have nothing more to do */
713 return;
716 if (!done_init) {
717 /* The logfile can be set before this is invoked. Free it if so. */
718 if (Globals.logfile != NULL) {
719 string_free(&Globals.logfile);
720 Globals.logfile = NULL;
722 done_init = true;
723 } else {
724 free_global_parameters();
727 /* This memset and the free_global_parameters() above will
728 * wipe out smb.conf options set with lp_set_cmdline(). The
729 * apply_lp_set_cmdline() call puts these values back in the
730 * table once the defaults are set */
731 ZERO_STRUCT(Globals);
733 Globals.ctx = talloc_new(NULL);
735 for (i = 0; parm_table[i].label; i++) {
736 if ((parm_table[i].type == P_STRING ||
737 parm_table[i].type == P_USTRING))
739 string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
744 string_set(&sDefault.fstype, FSTYPE_STRING);
745 string_set(&sDefault.szPrintjobUsername, "%U");
747 init_printer_values(&sDefault);
750 DEBUG(3, ("Initialising global parameters\n"));
752 /* Must manually force to upper case here, as this does not go via the handler */
753 string_set(&Globals.szNetbiosName, myhostname_upper());
755 string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
756 string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
758 /* use the new 'hash2' method by default, with a prefix of 1 */
759 string_set(&Globals.szManglingMethod, "hash2");
760 Globals.mangle_prefix = 1;
762 string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
764 /* using UTF8 by default allows us to support all chars */
765 string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
767 /* Use codepage 850 as a default for the dos character set */
768 string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
771 * Allow the default PASSWD_CHAT to be overridden in local.h.
773 string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
775 string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
777 string_set(&Globals.szPasswdProgram, "");
778 string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
779 string_set(&Globals.szStateDir, get_dyn_STATEDIR());
780 string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
781 string_set(&Globals.szPidDir, get_dyn_PIDDIR());
782 string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
784 * By default support explicit binding to broadcast
785 * addresses.
787 Globals.bNmbdBindExplicitBroadcast = true;
789 if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
790 smb_panic("init_globals: ENOMEM");
792 string_set(&Globals.szServerString, s);
793 SAFE_FREE(s);
794 #ifdef DEVELOPER
795 string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
796 #endif
798 string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
800 string_set(&Globals.szLogonDrive, "");
801 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
802 string_set(&Globals.szLogonHome, "\\\\%N\\%U");
803 string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
805 Globals.szNameResolveOrder = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
806 string_set(&Globals.szPasswordServer, "*");
808 Globals.AlgorithmicRidBase = BASE_RID;
810 Globals.bLoadPrinters = true;
811 Globals.PrintcapCacheTime = 750; /* 12.5 minutes */
813 Globals.ConfigBackend = config_backend;
814 Globals.server_role = ROLE_AUTO;
816 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
817 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
818 Globals.max_xmit = 0x4104;
819 Globals.max_mux = 50; /* This is *needed* for profile support. */
820 Globals.lpqcachetime = 30; /* changed to handle large print servers better -- jerry */
821 Globals.bDisableSpoolss = false;
822 Globals.iMaxSmbdProcesses = 0;/* no limit specified */
823 Globals.pwordlevel = 0;
824 Globals.unamelevel = 0;
825 Globals.deadtime = 0;
826 Globals.getwd_cache = true;
827 Globals.bLargeReadwrite = true;
828 Globals.max_log_size = 5000;
829 Globals.max_open_files = max_open_files();
830 Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
831 Globals.srv_maxprotocol = PROTOCOL_SMB3_00;
832 Globals.srv_minprotocol = PROTOCOL_LANMAN1;
833 Globals.security = SEC_USER;
834 Globals.bEncryptPasswords = true;
835 Globals.clientSchannel = Auto;
836 Globals.serverSchannel = Auto;
837 Globals.bReadRaw = true;
838 Globals.bWriteRaw = true;
839 Globals.bNullPasswords = false;
840 Globals.bObeyPamRestrictions = false;
841 Globals.syslog = 1;
842 Globals.bSyslogOnly = false;
843 Globals.bTimestampLogs = true;
844 string_set(&Globals.loglevel, "0");
845 Globals.bDebugPrefixTimestamp = false;
846 Globals.bDebugHiresTimestamp = true;
847 Globals.bDebugPid = false;
848 Globals.bDebugUid = false;
849 Globals.bDebugClass = false;
850 Globals.bEnableCoreFiles = true;
851 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
852 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
853 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
854 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
855 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
856 Globals.lm_interval = 60;
857 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
858 Globals.bNISHomeMap = false;
859 #ifdef WITH_NISPLUS_HOME
860 string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
861 #else
862 string_set(&Globals.szNISHomeMapName, "auto.home");
863 #endif
864 #endif
865 Globals.bTimeServer = false;
866 Globals.bBindInterfacesOnly = false;
867 Globals.bUnixPasswdSync = false;
868 Globals.bPamPasswordChange = false;
869 Globals.bPasswdChatDebug = false;
870 Globals.iPasswdChatTimeout = 2; /* 2 second default. */
871 Globals.bNTPipeSupport = true; /* Do NT pipes by default. */
872 Globals.bNTStatusSupport = true; /* Use NT status by default. */
873 Globals.bStatCache = true; /* use stat cache by default */
874 Globals.iMaxStatCacheSize = 256; /* 256k by default */
875 Globals.restrict_anonymous = 0;
876 Globals.bClientLanManAuth = false; /* Do NOT use the LanMan hash if it is available */
877 Globals.bClientPlaintextAuth = false; /* Do NOT use a plaintext password even if is requested by the server */
878 Globals.bLanmanAuth = false; /* Do NOT use the LanMan hash, even if it is supplied */
879 Globals.bNTLMAuth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
880 Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
881 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
883 Globals.map_to_guest = 0; /* By Default, "Never" */
884 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
885 Globals.enhanced_browsing = true;
886 Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
887 #ifdef MMAP_BLACKLIST
888 Globals.bUseMmap = false;
889 #else
890 Globals.bUseMmap = true;
891 #endif
892 Globals.bUnicode = true;
893 Globals.bUnixExtensions = true;
894 Globals.bResetOnZeroVC = false;
895 Globals.bLogWriteableFilesOnExit = false;
896 Globals.bCreateKrb5Conf = true;
897 Globals.winbindMaxDomainConnections = 1;
899 /* hostname lookups can be very expensive and are broken on
900 a large number of sites (tridge) */
901 Globals.bHostnameLookups = false;
903 string_set(&Globals.passdb_backend, "tdbsam");
904 string_set(&Globals.szLdapSuffix, "");
905 string_set(&Globals.szLdapMachineSuffix, "");
906 string_set(&Globals.szLdapUserSuffix, "");
907 string_set(&Globals.szLdapGroupSuffix, "");
908 string_set(&Globals.szLdapIdmapSuffix, "");
910 string_set(&Globals.szLdapAdminDn, "");
911 Globals.ldap_ssl = LDAP_SSL_START_TLS;
912 Globals.ldap_ssl_ads = false;
913 Globals.ldap_deref = -1;
914 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
915 Globals.ldap_delete_dn = false;
916 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
917 Globals.ldap_follow_referral = Auto;
918 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
919 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
920 Globals.ldap_page_size = LDAP_PAGE_SIZE;
922 Globals.ldap_debug_level = 0;
923 Globals.ldap_debug_threshold = 10;
925 /* This is what we tell the afs client. in reality we set the token
926 * to never expire, though, when this runs out the afs client will
927 * forget the token. Set to 0 to get NEVERDATE.*/
928 Globals.iAfsTokenLifetime = 604800;
929 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
931 /* these parameters are set to defaults that are more appropriate
932 for the increasing samba install base:
934 as a member of the workgroup, that will possibly become a
935 _local_ master browser (lm = true). this is opposed to a forced
936 local master browser startup (pm = true).
938 doesn't provide WINS server service by default (wsupp = false),
939 and doesn't provide domain master browser services by default, either.
943 Globals.bMsAddPrinterWizard = true;
944 Globals.os_level = 20;
945 Globals.bLocalMaster = true;
946 Globals.domain_master = Auto; /* depending on bDomainLogons */
947 Globals.bDomainLogons = false;
948 Globals.bBrowseList = true;
949 Globals.bWINSsupport = false;
950 Globals.bWINSproxy = false;
952 TALLOC_FREE(Globals.szInitLogonDelayedHosts);
953 Globals.InitLogonDelay = 100; /* 100 ms default delay */
955 Globals.bWINSdnsProxy = true;
957 Globals.bAllowTrustedDomains = true;
958 string_set(&Globals.szIdmapBackend, "tdb");
960 string_set(&Globals.szTemplateShell, "/bin/false");
961 string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
962 string_set(&Globals.szWinbindSeparator, "\\");
964 string_set(&Globals.szCupsServer, "");
965 string_set(&Globals.szIPrintServer, "");
967 #ifdef CLUSTER_SUPPORT
968 string_set(&Globals.ctdbdSocket, CTDB_PATH);
969 #else
970 string_set(&Globals.ctdbdSocket, "");
971 #endif
973 Globals.szClusterAddresses = NULL;
974 Globals.clustering = false;
975 Globals.ctdb_timeout = 0;
976 Globals.ctdb_locktime_warn_threshold = 0;
978 Globals.winbind_cache_time = 300; /* 5 minutes */
979 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
980 Globals.winbind_request_timeout = 60; /* 60 seconds */
981 Globals.winbind_max_clients = 200;
982 Globals.bWinbindEnumUsers = false;
983 Globals.bWinbindEnumGroups = false;
984 Globals.bWinbindUseDefaultDomain = false;
985 Globals.bWinbindTrustedDomainsOnly = false;
986 Globals.bWinbindNestedGroups = true;
987 Globals.winbind_expand_groups = 1;
988 Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
989 Globals.bWinbindRefreshTickets = false;
990 Globals.bWinbindOfflineLogon = false;
992 Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
993 Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
995 Globals.bPassdbExpandExplicit = false;
997 Globals.name_cache_timeout = 660; /* In seconds */
999 Globals.bUseSpnego = true;
1000 Globals.bClientUseSpnego = true;
1002 Globals.client_signing = SMB_SIGNING_DEFAULT;
1003 Globals.server_signing = SMB_SIGNING_DEFAULT;
1005 Globals.bDeferSharingViolations = true;
1006 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
1008 Globals.bEnablePrivileges = true;
1009 Globals.bHostMSDfs = true;
1010 Globals.bASUSupport = false;
1012 /* User defined shares. */
1013 if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
1014 smb_panic("init_globals: ENOMEM");
1016 string_set(&Globals.szUsersharePath, s);
1017 SAFE_FREE(s);
1018 string_set(&Globals.szUsershareTemplateShare, "");
1019 Globals.iUsershareMaxShares = 0;
1020 /* By default disallow sharing of directories not owned by the sharer. */
1021 Globals.bUsershareOwnerOnly = true;
1022 /* By default disallow guest access to usershares. */
1023 Globals.bUsershareAllowGuests = false;
1025 Globals.iKeepalive = DEFAULT_KEEPALIVE;
1027 /* By default no shares out of the registry */
1028 Globals.bRegistryShares = false;
1030 Globals.iminreceivefile = 0;
1032 Globals.bMapUntrustedToDomain = false;
1033 Globals.bMulticastDnsRegister = true;
1035 Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
1036 Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
1037 Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
1038 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1040 string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1042 /* Now put back the settings that were set with lp_set_cmdline() */
1043 apply_lp_set_cmdline();
1046 /*******************************************************************
1047 Convenience routine to grab string parameters into talloced memory
1048 and run standard_sub_basic on them. The buffers can be written to by
1049 callers without affecting the source string.
1050 ********************************************************************/
1052 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1054 char *ret;
1056 /* The follow debug is useful for tracking down memory problems
1057 especially if you have an inner loop that is calling a lp_*()
1058 function that returns a string. Perhaps this debug should be
1059 present all the time? */
1061 #if 0
1062 DEBUG(10, ("lp_string(%s)\n", s));
1063 #endif
1064 if (!s) {
1065 return NULL;
1068 ret = talloc_sub_basic(ctx,
1069 get_current_username(),
1070 current_user_info.domain,
1072 if (trim_char(ret, '\"', '\"')) {
1073 if (strchr(ret,'\"') != NULL) {
1074 TALLOC_FREE(ret);
1075 ret = talloc_sub_basic(ctx,
1076 get_current_username(),
1077 current_user_info.domain,
1081 return ret;
1085 In this section all the functions that are used to access the
1086 parameters from the rest of the program are defined
1089 #define FN_GLOBAL_STRING(fn_name,ptr) \
1090 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1091 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1092 const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1093 #define FN_GLOBAL_LIST(fn_name,ptr) \
1094 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1095 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1096 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1097 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1098 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1099 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1100 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1102 #define FN_LOCAL_STRING(fn_name,val) \
1103 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));}
1104 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1105 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1106 #define FN_LOCAL_LIST(fn_name,val) \
1107 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1108 #define FN_LOCAL_BOOL(fn_name,val) \
1109 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1110 #define FN_LOCAL_INTEGER(fn_name,val) \
1111 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1113 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1114 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1115 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1116 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1117 #define FN_LOCAL_CHAR(fn_name,val) \
1118 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1121 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1122 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1124 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1125 * build process or in smb.conf, we use that value. Otherwise they
1126 * default to the value of lp_lockdir(). */
1127 const char *lp_statedir(void) {
1128 if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1129 (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1130 return(*(char **)(&Globals.szStateDir) ?
1131 *(char **)(&Globals.szStateDir) : "");
1132 else
1133 return(*(char **)(&Globals.szLockDir) ?
1134 *(char **)(&Globals.szLockDir) : "");
1136 const char *lp_cachedir(void) {
1137 if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1138 (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1139 return(*(char **)(&Globals.szCacheDir) ?
1140 *(char **)(&Globals.szCacheDir) : "");
1141 else
1142 return(*(char **)(&Globals.szLockDir) ?
1143 *(char **)(&Globals.szLockDir) : "");
1145 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1146 winbindMaxDomainConnections)
1148 int lp_winbind_max_domain_connections(void)
1150 if (lp_winbind_offline_logon() &&
1151 lp_winbind_max_domain_connections_int() > 1) {
1152 DEBUG(1, ("offline logons active, restricting max domain "
1153 "connections to 1\n"));
1154 return 1;
1156 return MAX(1, lp_winbind_max_domain_connections_int());
1159 int lp_smb2_max_credits(void)
1161 if (Globals.ismb2_max_credits == 0) {
1162 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1164 return Globals.ismb2_max_credits;
1166 int lp_cups_encrypt(void)
1168 int result = 0;
1169 #ifdef HAVE_HTTPCONNECTENCRYPT
1170 switch (Globals.CupsEncrypt) {
1171 case Auto:
1172 result = HTTP_ENCRYPT_REQUIRED;
1173 break;
1174 case true:
1175 result = HTTP_ENCRYPT_ALWAYS;
1176 break;
1177 case false:
1178 result = HTTP_ENCRYPT_NEVER;
1179 break;
1181 #endif
1182 return result;
1185 /* These functions remain in source3/param for now */
1187 FN_GLOBAL_STRING(configfile, szConfigFile)
1189 #include "lib/param/param_functions.c"
1191 FN_LOCAL_STRING(servicename, szService)
1192 FN_LOCAL_CONST_STRING(const_servicename, szService)
1194 /* local prototypes */
1196 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1197 static const char *get_boolean(bool bool_value);
1198 static int getservicebyname(const char *pszServiceName,
1199 struct loadparm_service *pserviceDest);
1200 static void copy_service(struct loadparm_service *pserviceDest,
1201 struct loadparm_service *pserviceSource,
1202 struct bitmap *pcopymapDest);
1203 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1204 void *userdata);
1205 static bool do_section(const char *pszSectionName, void *userdata);
1206 static void init_copymap(struct loadparm_service *pservice);
1207 static bool hash_a_service(const char *name, int number);
1208 static void free_service_byindex(int iService);
1209 static void show_parameter(int parmIndex);
1210 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1213 * This is a helper function for parametrical options support. It returns a
1214 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1215 * parametrical functions are quite simple
1217 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1218 const char *option)
1220 bool global_section = false;
1221 char* param_key;
1222 struct parmlist_entry *data;
1224 if (service == NULL) {
1225 data = Globals.param_opt;
1226 global_section = true;
1227 } else {
1228 data = service->param_opt;
1231 if (asprintf(&param_key, "%s:%s", type, option) == -1) {
1232 DEBUG(0,("asprintf failed!\n"));
1233 return NULL;
1236 while (data) {
1237 if (strwicmp(data->key, param_key) == 0) {
1238 string_free(&param_key);
1239 return data;
1241 data = data->next;
1244 if (!global_section) {
1245 /* Try to fetch the same option but from globals */
1246 /* but only if we are not already working with Globals */
1247 data = Globals.param_opt;
1248 while (data) {
1249 if (strwicmp(data->key, param_key) == 0) {
1250 string_free(&param_key);
1251 return data;
1253 data = data->next;
1257 string_free(&param_key);
1259 return NULL;
1263 * This is a helper function for parametrical options support. It returns a
1264 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1265 * parametrical functions are quite simple
1267 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1268 const char *option)
1270 if (snum >= iNumServices) return NULL;
1272 if (snum < 0) {
1273 return get_parametrics_by_service(NULL, type, option);
1274 } else {
1275 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1280 #define MISSING_PARAMETER(name) \
1281 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1283 /*******************************************************************
1284 convenience routine to return int parameters.
1285 ********************************************************************/
1286 static int lp_int(const char *s)
1289 if (!s || !*s) {
1290 MISSING_PARAMETER(lp_int);
1291 return (-1);
1294 return (int)strtol(s, NULL, 0);
1297 /*******************************************************************
1298 convenience routine to return unsigned long parameters.
1299 ********************************************************************/
1300 static unsigned long lp_ulong(const char *s)
1303 if (!s || !*s) {
1304 MISSING_PARAMETER(lp_ulong);
1305 return (0);
1308 return strtoul(s, NULL, 0);
1311 /*******************************************************************
1312 convenience routine to return boolean parameters.
1313 ********************************************************************/
1314 static bool lp_bool(const char *s)
1316 bool ret = false;
1318 if (!s || !*s) {
1319 MISSING_PARAMETER(lp_bool);
1320 return false;
1323 if (!set_boolean(s, &ret)) {
1324 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1325 return false;
1328 return ret;
1331 /*******************************************************************
1332 convenience routine to return enum parameters.
1333 ********************************************************************/
1334 static int lp_enum(const char *s,const struct enum_list *_enum)
1336 int i;
1338 if (!s || !*s || !_enum) {
1339 MISSING_PARAMETER(lp_enum);
1340 return (-1);
1343 for (i=0; _enum[i].name; i++) {
1344 if (strequal(_enum[i].name,s))
1345 return _enum[i].value;
1348 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1349 return (-1);
1352 #undef MISSING_PARAMETER
1354 /* Return parametric option from a given service. Type is a part of option before ':' */
1355 /* Parametric option has following syntax: 'Type: option = value' */
1356 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1358 struct parmlist_entry *data = get_parametrics(snum, type, option);
1360 if (data == NULL||data->value==NULL) {
1361 if (def) {
1362 return lp_string(ctx, def);
1363 } else {
1364 return NULL;
1368 return lp_string(ctx, data->value);
1371 /* Return parametric option from a given service. Type is a part of option before ':' */
1372 /* Parametric option has following syntax: 'Type: option = value' */
1373 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1375 struct parmlist_entry *data = get_parametrics(snum, type, option);
1377 if (data == NULL||data->value==NULL)
1378 return def;
1380 return data->value;
1383 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1385 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1387 if (data == NULL||data->value==NULL)
1388 return NULL;
1390 return data->value;
1394 /* Return parametric option from a given service. Type is a part of option before ':' */
1395 /* Parametric option has following syntax: 'Type: option = value' */
1397 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1399 struct parmlist_entry *data = get_parametrics(snum, type, option);
1401 if (data == NULL||data->value==NULL)
1402 return (const char **)def;
1404 if (data->list==NULL) {
1405 data->list = str_list_make_v3(NULL, data->value, NULL);
1408 return (const char **)data->list;
1411 /* Return parametric option from a given service. Type is a part of option before ':' */
1412 /* Parametric option has following syntax: 'Type: option = value' */
1414 int lp_parm_int(int snum, const char *type, const char *option, int def)
1416 struct parmlist_entry *data = get_parametrics(snum, type, option);
1418 if (data && data->value && *data->value)
1419 return lp_int(data->value);
1421 return def;
1424 /* Return parametric option from a given service. Type is a part of option before ':' */
1425 /* Parametric option has following syntax: 'Type: option = value' */
1427 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1429 struct parmlist_entry *data = get_parametrics(snum, type, option);
1431 if (data && data->value && *data->value)
1432 return lp_ulong(data->value);
1434 return def;
1437 /* Return parametric option from a given service. Type is a part of option before ':' */
1438 /* Parametric option has following syntax: 'Type: option = value' */
1440 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1442 struct parmlist_entry *data = get_parametrics(snum, type, option);
1444 if (data && data->value && *data->value)
1445 return lp_bool(data->value);
1447 return def;
1450 /* Return parametric option from a given service. Type is a part of option before ':' */
1451 /* Parametric option has following syntax: 'Type: option = value' */
1453 int lp_parm_enum(int snum, const char *type, const char *option,
1454 const struct enum_list *_enum, int def)
1456 struct parmlist_entry *data = get_parametrics(snum, type, option);
1458 if (data && data->value && *data->value && _enum)
1459 return lp_enum(data->value, _enum);
1461 return def;
1465 /***************************************************************************
1466 Initialise a service to the defaults.
1467 ***************************************************************************/
1469 static void init_service(struct loadparm_service *pservice)
1471 memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1472 copy_service(pservice, &sDefault, NULL);
1477 * free a param_opts structure.
1478 * param_opts handling should be moved to talloc;
1479 * then this whole functions reduces to a TALLOC_FREE().
1482 static void free_param_opts(struct parmlist_entry **popts)
1484 struct parmlist_entry *opt, *next_opt;
1486 if (*popts != NULL) {
1487 DEBUG(5, ("Freeing parametrics:\n"));
1489 opt = *popts;
1490 while (opt != NULL) {
1491 string_free(&opt->key);
1492 string_free(&opt->value);
1493 TALLOC_FREE(opt->list);
1494 next_opt = opt->next;
1495 SAFE_FREE(opt);
1496 opt = next_opt;
1498 *popts = NULL;
1501 /***************************************************************************
1502 Free the dynamically allocated parts of a service struct.
1503 ***************************************************************************/
1505 static void free_service(struct loadparm_service *pservice)
1507 if (!pservice)
1508 return;
1510 if (pservice->szService)
1511 DEBUG(5, ("free_service: Freeing service %s\n",
1512 pservice->szService));
1514 free_parameters(pservice);
1516 string_free(&pservice->szService);
1517 TALLOC_FREE(pservice->copymap);
1519 free_param_opts(&pservice->param_opt);
1521 ZERO_STRUCTP(pservice);
1525 /***************************************************************************
1526 remove a service indexed in the ServicePtrs array from the ServiceHash
1527 and free the dynamically allocated parts
1528 ***************************************************************************/
1530 static void free_service_byindex(int idx)
1532 if ( !LP_SNUM_OK(idx) )
1533 return;
1535 ServicePtrs[idx]->valid = false;
1536 invalid_services[num_invalid_services++] = idx;
1538 /* we have to cleanup the hash record */
1540 if (ServicePtrs[idx]->szService) {
1541 char *canon_name = canonicalize_servicename(
1542 talloc_tos(),
1543 ServicePtrs[idx]->szService );
1545 dbwrap_delete_bystring(ServiceHash, canon_name );
1546 TALLOC_FREE(canon_name);
1549 free_service(ServicePtrs[idx]);
1550 talloc_free_children(ServicePtrs[idx]);
1553 /***************************************************************************
1554 Add a new service to the services array initialising it with the given
1555 service.
1556 ***************************************************************************/
1558 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1560 int i;
1561 struct loadparm_service tservice;
1562 int num_to_alloc = iNumServices + 1;
1564 tservice = *pservice;
1566 /* it might already exist */
1567 if (name) {
1568 i = getservicebyname(name, NULL);
1569 if (i >= 0) {
1570 return (i);
1574 /* find an invalid one */
1575 i = iNumServices;
1576 if (num_invalid_services > 0) {
1577 i = invalid_services[--num_invalid_services];
1580 /* if not, then create one */
1581 if (i == iNumServices) {
1582 struct loadparm_service **tsp;
1583 int *tinvalid;
1585 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1586 if (tsp == NULL) {
1587 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1588 return (-1);
1590 ServicePtrs = tsp;
1591 ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1592 if (!ServicePtrs[iNumServices]) {
1593 DEBUG(0,("add_a_service: out of memory!\n"));
1594 return (-1);
1596 iNumServices++;
1598 /* enlarge invalid_services here for now... */
1599 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
1600 num_to_alloc);
1601 if (tinvalid == NULL) {
1602 DEBUG(0,("add_a_service: failed to enlarge "
1603 "invalid_services!\n"));
1604 return (-1);
1606 invalid_services = tinvalid;
1607 } else {
1608 free_service_byindex(i);
1611 ServicePtrs[i]->valid = true;
1613 init_service(ServicePtrs[i]);
1614 copy_service(ServicePtrs[i], &tservice, NULL);
1615 if (name)
1616 string_set(&ServicePtrs[i]->szService, name);
1618 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1619 i, ServicePtrs[i]->szService));
1621 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1622 return (-1);
1625 return (i);
1628 /***************************************************************************
1629 Convert a string to uppercase and remove whitespaces.
1630 ***************************************************************************/
1632 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1634 char *result;
1636 if ( !src ) {
1637 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1638 return NULL;
1641 result = talloc_strdup(ctx, src);
1642 SMB_ASSERT(result != NULL);
1644 if (!strlower_m(result)) {
1645 TALLOC_FREE(result);
1646 return NULL;
1648 return result;
1651 /***************************************************************************
1652 Add a name/index pair for the services array to the hash table.
1653 ***************************************************************************/
1655 static bool hash_a_service(const char *name, int idx)
1657 char *canon_name;
1659 if ( !ServiceHash ) {
1660 DEBUG(10,("hash_a_service: creating servicehash\n"));
1661 ServiceHash = db_open_rbt(NULL);
1662 if ( !ServiceHash ) {
1663 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1664 return false;
1668 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1669 idx, name));
1671 canon_name = canonicalize_servicename(talloc_tos(), name );
1673 dbwrap_store_bystring(ServiceHash, canon_name,
1674 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1675 TDB_REPLACE);
1677 TALLOC_FREE(canon_name);
1679 return true;
1682 /***************************************************************************
1683 Add a new home service, with the specified home directory, defaults coming
1684 from service ifrom.
1685 ***************************************************************************/
1687 bool lp_add_home(const char *pszHomename, int iDefaultService,
1688 const char *user, const char *pszHomedir)
1690 int i;
1692 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1693 pszHomedir[0] == '\0') {
1694 return false;
1697 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1699 if (i < 0)
1700 return false;
1702 if (!(*(ServicePtrs[iDefaultService]->szPath))
1703 || strequal(ServicePtrs[iDefaultService]->szPath,
1704 lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1705 string_set(&ServicePtrs[i]->szPath, pszHomedir);
1708 if (!(*(ServicePtrs[i]->comment))) {
1709 char *comment = NULL;
1710 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1711 return false;
1713 string_set(&ServicePtrs[i]->comment, comment);
1714 SAFE_FREE(comment);
1717 /* set the browseable flag from the global default */
1719 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1720 ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
1722 ServicePtrs[i]->autoloaded = true;
1724 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1725 user, ServicePtrs[i]->szPath ));
1727 return true;
1730 /***************************************************************************
1731 Add a new service, based on an old one.
1732 ***************************************************************************/
1734 int lp_add_service(const char *pszService, int iDefaultService)
1736 if (iDefaultService < 0) {
1737 return add_a_service(&sDefault, pszService);
1740 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1743 /***************************************************************************
1744 Add the IPC service.
1745 ***************************************************************************/
1747 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1749 char *comment = NULL;
1750 int i = add_a_service(&sDefault, ipc_name);
1752 if (i < 0)
1753 return false;
1755 if (asprintf(&comment, "IPC Service (%s)",
1756 Globals.szServerString) < 0) {
1757 return false;
1760 string_set(&ServicePtrs[i]->szPath, tmpdir());
1761 string_set(&ServicePtrs[i]->szUsername, "");
1762 string_set(&ServicePtrs[i]->comment, comment);
1763 string_set(&ServicePtrs[i]->fstype, "IPC");
1764 ServicePtrs[i]->iMaxConnections = 0;
1765 ServicePtrs[i]->bAvailable = true;
1766 ServicePtrs[i]->bRead_only = true;
1767 ServicePtrs[i]->bGuest_only = false;
1768 ServicePtrs[i]->bAdministrative_share = true;
1769 ServicePtrs[i]->bGuest_ok = guest_ok;
1770 ServicePtrs[i]->bPrint_ok = false;
1771 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1773 DEBUG(3, ("adding IPC service\n"));
1775 SAFE_FREE(comment);
1776 return true;
1779 /***************************************************************************
1780 Add a new printer service, with defaults coming from service iFrom.
1781 ***************************************************************************/
1783 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1785 const char *comment = "From Printcap";
1786 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1788 if (i < 0)
1789 return false;
1791 /* note that we do NOT default the availability flag to true - */
1792 /* we take it from the default service passed. This allows all */
1793 /* dynamic printers to be disabled by disabling the [printers] */
1794 /* entry (if/when the 'available' keyword is implemented!). */
1796 /* the printer name is set to the service name. */
1797 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1798 string_set(&ServicePtrs[i]->comment, comment);
1800 /* set the browseable flag from the gloabl default */
1801 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1803 /* Printers cannot be read_only. */
1804 ServicePtrs[i]->bRead_only = false;
1805 /* No oplocks on printer services. */
1806 ServicePtrs[i]->bOpLocks = false;
1807 /* Printer services must be printable. */
1808 ServicePtrs[i]->bPrint_ok = true;
1810 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1812 return true;
1816 /***************************************************************************
1817 Check whether the given parameter name is valid.
1818 Parametric options (names containing a colon) are considered valid.
1819 ***************************************************************************/
1821 bool lp_parameter_is_valid(const char *pszParmName)
1823 return ((map_parameter(pszParmName) != -1) ||
1824 (strchr(pszParmName, ':') != NULL));
1827 /***************************************************************************
1828 Check whether the given name is the name of a global parameter.
1829 Returns true for strings belonging to parameters of class
1830 P_GLOBAL, false for all other strings, also for parametric options
1831 and strings not belonging to any option.
1832 ***************************************************************************/
1834 bool lp_parameter_is_global(const char *pszParmName)
1836 int num = map_parameter(pszParmName);
1838 if (num >= 0) {
1839 return (parm_table[num].p_class == P_GLOBAL);
1842 return false;
1845 /**************************************************************************
1846 Check whether the given name is the canonical name of a parameter.
1847 Returns false if it is not a valid parameter Name.
1848 For parametric options, true is returned.
1849 **************************************************************************/
1851 bool lp_parameter_is_canonical(const char *parm_name)
1853 if (!lp_parameter_is_valid(parm_name)) {
1854 return false;
1857 return (map_parameter(parm_name) ==
1858 map_parameter_canonical(parm_name, NULL));
1861 /**************************************************************************
1862 Determine the canonical name for a parameter.
1863 Indicate when it is an inverse (boolean) synonym instead of a
1864 "usual" synonym.
1865 **************************************************************************/
1867 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1868 bool *inverse)
1870 int num;
1872 if (!lp_parameter_is_valid(parm_name)) {
1873 *canon_parm = NULL;
1874 return false;
1877 num = map_parameter_canonical(parm_name, inverse);
1878 if (num < 0) {
1879 /* parametric option */
1880 *canon_parm = parm_name;
1881 } else {
1882 *canon_parm = parm_table[num].label;
1885 return true;
1889 /**************************************************************************
1890 Determine the canonical name for a parameter.
1891 Turn the value given into the inverse boolean expression when
1892 the synonym is an invers boolean synonym.
1894 Return true if parm_name is a valid parameter name and
1895 in case it is an invers boolean synonym, if the val string could
1896 successfully be converted to the reverse bool.
1897 Return false in all other cases.
1898 **************************************************************************/
1900 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1901 const char *val,
1902 const char **canon_parm,
1903 const char **canon_val)
1905 int num;
1906 bool inverse;
1908 if (!lp_parameter_is_valid(parm_name)) {
1909 *canon_parm = NULL;
1910 *canon_val = NULL;
1911 return false;
1914 num = map_parameter_canonical(parm_name, &inverse);
1915 if (num < 0) {
1916 /* parametric option */
1917 *canon_parm = parm_name;
1918 *canon_val = val;
1919 } else {
1920 *canon_parm = parm_table[num].label;
1921 if (inverse) {
1922 if (!lp_invert_boolean(val, canon_val)) {
1923 *canon_val = NULL;
1924 return false;
1926 } else {
1927 *canon_val = val;
1931 return true;
1934 /***************************************************************************
1935 Map a parameter's string representation to something we can use.
1936 Returns false if the parameter string is not recognised, else TRUE.
1937 ***************************************************************************/
1939 static int map_parameter(const char *pszParmName)
1941 int iIndex;
1943 if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
1944 return (-1);
1946 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1947 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1948 return (iIndex);
1950 /* Warn only if it isn't parametric option */
1951 if (strchr(pszParmName, ':') == NULL)
1952 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1953 /* We do return 'fail' for parametric options as well because they are
1954 stored in different storage
1956 return (-1);
1959 /***************************************************************************
1960 Map a parameter's string representation to the index of the canonical
1961 form of the parameter (it might be a synonym).
1962 Returns -1 if the parameter string is not recognised.
1963 ***************************************************************************/
1965 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1967 int parm_num, canon_num;
1968 bool loc_inverse = false;
1970 parm_num = map_parameter(pszParmName);
1971 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1972 /* invalid, parametric or no canidate for synonyms ... */
1973 goto done;
1976 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1977 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1978 parm_num = canon_num;
1979 goto done;
1983 done:
1984 if (inverse != NULL) {
1985 *inverse = loc_inverse;
1987 return parm_num;
1990 /***************************************************************************
1991 return true if parameter number parm1 is a synonym of parameter
1992 number parm2 (parm2 being the principal name).
1993 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1994 false otherwise.
1995 ***************************************************************************/
1997 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
1999 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
2000 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
2001 (parm_table[parm1].flags & FLAG_HIDE) &&
2002 !(parm_table[parm2].flags & FLAG_HIDE))
2004 if (inverse != NULL) {
2005 if ((parm_table[parm1].type == P_BOOLREV) &&
2006 (parm_table[parm2].type == P_BOOL))
2008 *inverse = true;
2009 } else {
2010 *inverse = false;
2013 return true;
2015 return false;
2018 /***************************************************************************
2019 Show one parameter's name, type, [values,] and flags.
2020 (helper functions for show_parameter_list)
2021 ***************************************************************************/
2023 static void show_parameter(int parmIndex)
2025 int enumIndex, flagIndex;
2026 int parmIndex2;
2027 bool hadFlag;
2028 bool hadSyn;
2029 bool inverse;
2030 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2031 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2032 "P_ENUM", "P_SEP"};
2033 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2034 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2035 FLAG_HIDE};
2036 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2037 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2038 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2040 printf("%s=%s", parm_table[parmIndex].label,
2041 type[parm_table[parmIndex].type]);
2042 if (parm_table[parmIndex].type == P_ENUM) {
2043 printf(",");
2044 for (enumIndex=0;
2045 parm_table[parmIndex].enum_list[enumIndex].name;
2046 enumIndex++)
2048 printf("%s%s",
2049 enumIndex ? "|" : "",
2050 parm_table[parmIndex].enum_list[enumIndex].name);
2053 printf(",");
2054 hadFlag = false;
2055 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2056 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2057 printf("%s%s",
2058 hadFlag ? "|" : "",
2059 flag_names[flagIndex]);
2060 hadFlag = true;
2064 /* output synonyms */
2065 hadSyn = false;
2066 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2067 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2068 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2069 parm_table[parmIndex2].label);
2070 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2071 if (!hadSyn) {
2072 printf(" (synonyms: ");
2073 hadSyn = true;
2074 } else {
2075 printf(", ");
2077 printf("%s%s", parm_table[parmIndex2].label,
2078 inverse ? "[i]" : "");
2081 if (hadSyn) {
2082 printf(")");
2085 printf("\n");
2088 /***************************************************************************
2089 Show all parameter's name, type, [values,] and flags.
2090 ***************************************************************************/
2092 void show_parameter_list(void)
2094 int classIndex, parmIndex;
2095 const char *section_names[] = { "local", "global", NULL};
2097 for (classIndex=0; section_names[classIndex]; classIndex++) {
2098 printf("[%s]\n", section_names[classIndex]);
2099 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2100 if (parm_table[parmIndex].p_class == classIndex) {
2101 show_parameter(parmIndex);
2107 /***************************************************************************
2108 Check if a given string correctly represents a boolean value.
2109 ***************************************************************************/
2111 bool lp_string_is_valid_boolean(const char *parm_value)
2113 return set_boolean(parm_value, NULL);
2116 /***************************************************************************
2117 Get the standard string representation of a boolean value ("yes" or "no")
2118 ***************************************************************************/
2120 static const char *get_boolean(bool bool_value)
2122 static const char *yes_str = "yes";
2123 static const char *no_str = "no";
2125 return (bool_value ? yes_str : no_str);
2128 /***************************************************************************
2129 Provide the string of the negated boolean value associated to the boolean
2130 given as a string. Returns false if the passed string does not correctly
2131 represent a boolean.
2132 ***************************************************************************/
2134 bool lp_invert_boolean(const char *str, const char **inverse_str)
2136 bool val;
2138 if (!set_boolean(str, &val)) {
2139 return false;
2142 *inverse_str = get_boolean(!val);
2143 return true;
2146 /***************************************************************************
2147 Provide the canonical string representation of a boolean value given
2148 as a string. Return true on success, false if the string given does
2149 not correctly represent a boolean.
2150 ***************************************************************************/
2152 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2154 bool val;
2156 if (!set_boolean(str, &val)) {
2157 return false;
2160 *canon_str = get_boolean(val);
2161 return true;
2164 /***************************************************************************
2165 Find a service by name. Otherwise works like get_service.
2166 ***************************************************************************/
2168 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2170 int iService = -1;
2171 char *canon_name;
2172 TDB_DATA data;
2173 NTSTATUS status;
2175 if (ServiceHash == NULL) {
2176 return -1;
2179 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2181 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2182 &data);
2184 if (NT_STATUS_IS_OK(status) &&
2185 (data.dptr != NULL) &&
2186 (data.dsize == sizeof(iService)))
2188 iService = *(int *)data.dptr;
2191 TALLOC_FREE(canon_name);
2193 if ((iService != -1) && (LP_SNUM_OK(iService))
2194 && (pserviceDest != NULL)) {
2195 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2198 return (iService);
2201 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2202 struct loadparm_service *lp_service(const char *pszServiceName)
2204 int iService = getservicebyname(pszServiceName, NULL);
2205 if (iService == -1 || !LP_SNUM_OK(iService)) {
2206 return NULL;
2208 return ServicePtrs[iService];
2211 struct loadparm_service *lp_servicebynum(int snum)
2213 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2214 return NULL;
2216 return ServicePtrs[snum];
2219 struct loadparm_service *lp_default_loadparm_service()
2221 return &sDefault;
2225 /***************************************************************************
2226 Copy a service structure to another.
2227 If pcopymapDest is NULL then copy all fields
2228 ***************************************************************************/
2231 * Add a parametric option to a parmlist_entry,
2232 * replacing old value, if already present.
2234 static void set_param_opt(struct parmlist_entry **opt_list,
2235 const char *opt_name,
2236 const char *opt_value,
2237 unsigned priority)
2239 struct parmlist_entry *new_opt, *opt;
2240 bool not_added;
2242 opt = *opt_list;
2243 not_added = true;
2245 /* Traverse destination */
2246 while (opt) {
2247 /* If we already have same option, override it */
2248 if (strwicmp(opt->key, opt_name) == 0) {
2249 if ((opt->priority & FLAG_CMDLINE) &&
2250 !(priority & FLAG_CMDLINE)) {
2251 /* it's been marked as not to be
2252 overridden */
2253 return;
2255 string_free(&opt->value);
2256 TALLOC_FREE(opt->list);
2257 opt->value = SMB_STRDUP(opt_value);
2258 opt->priority = priority;
2259 not_added = false;
2260 break;
2262 opt = opt->next;
2264 if (not_added) {
2265 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2266 new_opt->key = SMB_STRDUP(opt_name);
2267 new_opt->value = SMB_STRDUP(opt_value);
2268 new_opt->list = NULL;
2269 new_opt->priority = priority;
2270 DLIST_ADD(*opt_list, new_opt);
2274 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2275 struct bitmap *pcopymapDest)
2277 int i;
2278 bool bcopyall = (pcopymapDest == NULL);
2279 struct parmlist_entry *data;
2281 for (i = 0; parm_table[i].label; i++)
2282 if (parm_table[i].p_class == P_LOCAL &&
2283 (bcopyall || bitmap_query(pcopymapDest,i))) {
2284 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2285 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2287 switch (parm_table[i].type) {
2288 case P_BOOL:
2289 case P_BOOLREV:
2290 *(bool *)dest_ptr = *(bool *)src_ptr;
2291 break;
2293 case P_INTEGER:
2294 case P_ENUM:
2295 case P_OCTAL:
2296 case P_BYTES:
2297 *(int *)dest_ptr = *(int *)src_ptr;
2298 break;
2300 case P_CHAR:
2301 *(char *)dest_ptr = *(char *)src_ptr;
2302 break;
2304 case P_STRING:
2305 string_set((char **)dest_ptr,
2306 *(char **)src_ptr);
2307 break;
2309 case P_USTRING:
2311 char *upper_string = strupper_talloc(talloc_tos(),
2312 *(char **)src_ptr);
2313 string_set((char **)dest_ptr,
2314 upper_string);
2315 TALLOC_FREE(upper_string);
2316 break;
2318 case P_LIST:
2319 TALLOC_FREE(*((char ***)dest_ptr));
2320 *((char ***)dest_ptr) = str_list_copy(NULL,
2321 *(const char ***)src_ptr);
2322 break;
2323 default:
2324 break;
2328 if (bcopyall) {
2329 init_copymap(pserviceDest);
2330 if (pserviceSource->copymap)
2331 bitmap_copy(pserviceDest->copymap,
2332 pserviceSource->copymap);
2335 data = pserviceSource->param_opt;
2336 while (data) {
2337 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2338 data = data->next;
2342 /***************************************************************************
2343 Check a service for consistency. Return false if the service is in any way
2344 incomplete or faulty, else true.
2345 ***************************************************************************/
2347 bool service_ok(int iService)
2349 bool bRetval;
2351 bRetval = true;
2352 if (ServicePtrs[iService]->szService[0] == '\0') {
2353 DEBUG(0, ("The following message indicates an internal error:\n"));
2354 DEBUG(0, ("No service name in service entry.\n"));
2355 bRetval = false;
2358 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2359 /* I can't see why you'd want a non-printable printer service... */
2360 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2361 if (!ServicePtrs[iService]->bPrint_ok) {
2362 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2363 ServicePtrs[iService]->szService));
2364 ServicePtrs[iService]->bPrint_ok = true;
2366 /* [printers] service must also be non-browsable. */
2367 if (ServicePtrs[iService]->bBrowseable)
2368 ServicePtrs[iService]->bBrowseable = false;
2371 if (ServicePtrs[iService]->szPath[0] == '\0' &&
2372 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2373 ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2375 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2376 ServicePtrs[iService]->szService));
2377 ServicePtrs[iService]->bAvailable = false;
2380 /* If a service is flagged unavailable, log the fact at level 1. */
2381 if (!ServicePtrs[iService]->bAvailable)
2382 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2383 ServicePtrs[iService]->szService));
2385 return (bRetval);
2388 static struct smbconf_ctx *lp_smbconf_ctx(void)
2390 sbcErr err;
2391 static struct smbconf_ctx *conf_ctx = NULL;
2393 if (conf_ctx == NULL) {
2394 err = smbconf_init(NULL, &conf_ctx, "registry:");
2395 if (!SBC_ERROR_IS_OK(err)) {
2396 DEBUG(1, ("error initializing registry configuration: "
2397 "%s\n", sbcErrorString(err)));
2398 conf_ctx = NULL;
2402 return conf_ctx;
2405 static bool process_smbconf_service(struct smbconf_service *service)
2407 uint32_t count;
2408 bool ret;
2410 if (service == NULL) {
2411 return false;
2414 ret = do_section(service->name, NULL);
2415 if (ret != true) {
2416 return false;
2418 for (count = 0; count < service->num_params; count++) {
2419 ret = do_parameter(service->param_names[count],
2420 service->param_values[count],
2421 NULL);
2422 if (ret != true) {
2423 return false;
2426 if (iServiceIndex >= 0) {
2427 return service_ok(iServiceIndex);
2429 return true;
2433 * load a service from registry and activate it
2435 bool process_registry_service(const char *service_name)
2437 sbcErr err;
2438 struct smbconf_service *service = NULL;
2439 TALLOC_CTX *mem_ctx = talloc_stackframe();
2440 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2441 bool ret = false;
2443 if (conf_ctx == NULL) {
2444 goto done;
2447 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2449 if (!smbconf_share_exists(conf_ctx, service_name)) {
2451 * Registry does not contain data for this service (yet),
2452 * but make sure lp_load doesn't return false.
2454 ret = true;
2455 goto done;
2458 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2459 if (!SBC_ERROR_IS_OK(err)) {
2460 goto done;
2463 ret = process_smbconf_service(service);
2464 if (!ret) {
2465 goto done;
2468 /* store the csn */
2469 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2471 done:
2472 TALLOC_FREE(mem_ctx);
2473 return ret;
2477 * process_registry_globals
2479 static bool process_registry_globals(void)
2481 bool ret;
2483 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2485 ret = do_parameter("registry shares", "yes", NULL);
2486 if (!ret) {
2487 return ret;
2490 return process_registry_service(GLOBAL_NAME);
2493 bool process_registry_shares(void)
2495 sbcErr err;
2496 uint32_t count;
2497 struct smbconf_service **service = NULL;
2498 uint32_t num_shares = 0;
2499 TALLOC_CTX *mem_ctx = talloc_stackframe();
2500 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2501 bool ret = false;
2503 if (conf_ctx == NULL) {
2504 goto done;
2507 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2508 if (!SBC_ERROR_IS_OK(err)) {
2509 goto done;
2512 ret = true;
2514 for (count = 0; count < num_shares; count++) {
2515 if (strequal(service[count]->name, GLOBAL_NAME)) {
2516 continue;
2518 ret = process_smbconf_service(service[count]);
2519 if (!ret) {
2520 goto done;
2524 /* store the csn */
2525 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2527 done:
2528 TALLOC_FREE(mem_ctx);
2529 return ret;
2533 * reload those shares from registry that are already
2534 * activated in the services array.
2536 static bool reload_registry_shares(void)
2538 int i;
2539 bool ret = true;
2541 for (i = 0; i < iNumServices; i++) {
2542 if (!VALID(i)) {
2543 continue;
2546 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2547 continue;
2550 ret = process_registry_service(ServicePtrs[i]->szService);
2551 if (!ret) {
2552 goto done;
2556 done:
2557 return ret;
2561 #define MAX_INCLUDE_DEPTH 100
2563 static uint8_t include_depth;
2565 static struct file_lists {
2566 struct file_lists *next;
2567 char *name;
2568 char *subfname;
2569 time_t modtime;
2570 } *file_lists = NULL;
2572 /*******************************************************************
2573 Keep a linked list of all config files so we know when one has changed
2574 it's date and needs to be reloaded.
2575 ********************************************************************/
2577 static void add_to_file_list(const char *fname, const char *subfname)
2579 struct file_lists *f = file_lists;
2581 while (f) {
2582 if (f->name && !strcmp(f->name, fname))
2583 break;
2584 f = f->next;
2587 if (!f) {
2588 f = SMB_MALLOC_P(struct file_lists);
2589 if (!f)
2590 return;
2591 f->next = file_lists;
2592 f->name = SMB_STRDUP(fname);
2593 if (!f->name) {
2594 SAFE_FREE(f);
2595 return;
2597 f->subfname = SMB_STRDUP(subfname);
2598 if (!f->subfname) {
2599 SAFE_FREE(f->name);
2600 SAFE_FREE(f);
2601 return;
2603 file_lists = f;
2604 f->modtime = file_modtime(subfname);
2605 } else {
2606 time_t t = file_modtime(subfname);
2607 if (t)
2608 f->modtime = t;
2610 return;
2614 * Free the file lists
2616 static void free_file_list(void)
2618 struct file_lists *f;
2619 struct file_lists *next;
2621 f = file_lists;
2622 while( f ) {
2623 next = f->next;
2624 SAFE_FREE( f->name );
2625 SAFE_FREE( f->subfname );
2626 SAFE_FREE( f );
2627 f = next;
2629 file_lists = NULL;
2634 * Utility function for outsiders to check if we're running on registry.
2636 bool lp_config_backend_is_registry(void)
2638 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2642 * Utility function to check if the config backend is FILE.
2644 bool lp_config_backend_is_file(void)
2646 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2649 /*******************************************************************
2650 Check if a config file has changed date.
2651 ********************************************************************/
2653 bool lp_file_list_changed(void)
2655 struct file_lists *f = file_lists;
2657 DEBUG(6, ("lp_file_list_changed()\n"));
2659 while (f) {
2660 time_t mod_time;
2662 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2663 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2665 if (conf_ctx == NULL) {
2666 return false;
2668 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2669 NULL))
2671 DEBUGADD(6, ("registry config changed\n"));
2672 return true;
2674 } else {
2675 char *n2 = NULL;
2676 n2 = talloc_sub_basic(talloc_tos(),
2677 get_current_username(),
2678 current_user_info.domain,
2679 f->name);
2680 if (!n2) {
2681 return false;
2683 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2684 f->name, n2, ctime(&f->modtime)));
2686 mod_time = file_modtime(n2);
2688 if (mod_time &&
2689 ((f->modtime != mod_time) ||
2690 (f->subfname == NULL) ||
2691 (strcmp(n2, f->subfname) != 0)))
2693 DEBUGADD(6,
2694 ("file %s modified: %s\n", n2,
2695 ctime(&mod_time)));
2696 f->modtime = mod_time;
2697 SAFE_FREE(f->subfname);
2698 f->subfname = SMB_STRDUP(n2);
2699 TALLOC_FREE(n2);
2700 return true;
2702 TALLOC_FREE(n2);
2704 f = f->next;
2706 return false;
2711 * Initialize iconv conversion descriptors.
2713 * This is called the first time it is needed, and also called again
2714 * every time the configuration is reloaded, because the charset or
2715 * codepage might have changed.
2717 static void init_iconv(void)
2719 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2720 lp_unix_charset(),
2721 true, global_iconv_handle);
2724 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2726 if (strcmp(*ptr, pszParmValue) != 0) {
2727 string_set(ptr, pszParmValue);
2728 init_iconv();
2730 return true;
2733 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2735 bool is_utf8 = false;
2736 size_t len = strlen(pszParmValue);
2738 if (len == 4 || len == 5) {
2739 /* Don't use StrCaseCmp here as we don't want to
2740 initialize iconv. */
2741 if ((toupper_m(pszParmValue[0]) == 'U') &&
2742 (toupper_m(pszParmValue[1]) == 'T') &&
2743 (toupper_m(pszParmValue[2]) == 'F')) {
2744 if (len == 4) {
2745 if (pszParmValue[3] == '8') {
2746 is_utf8 = true;
2748 } else {
2749 if (pszParmValue[3] == '-' &&
2750 pszParmValue[4] == '8') {
2751 is_utf8 = true;
2757 if (strcmp(*ptr, pszParmValue) != 0) {
2758 if (is_utf8) {
2759 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2760 "be UTF8, using (default value) %s instead.\n",
2761 DEFAULT_DOS_CHARSET));
2762 pszParmValue = DEFAULT_DOS_CHARSET;
2764 string_set(ptr, pszParmValue);
2765 init_iconv();
2767 return true;
2770 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2772 bool ret = true;
2773 TALLOC_CTX *frame = talloc_stackframe();
2774 char *realm = strupper_talloc(frame, pszParmValue);
2775 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2777 ret &= string_set(&Globals.szRealm, pszParmValue);
2778 ret &= string_set(&Globals.szRealm_upper, realm);
2779 ret &= string_set(&Globals.szRealm_lower, dnsdomain);
2780 TALLOC_FREE(frame);
2782 return ret;
2785 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2787 TALLOC_FREE(Globals.szNetbiosAliases);
2788 Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2789 return set_netbios_aliases(Globals.szNetbiosAliases);
2792 /***************************************************************************
2793 Handle the include operation.
2794 ***************************************************************************/
2795 static bool bAllowIncludeRegistry = true;
2797 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2799 char *fname;
2801 if (include_depth >= MAX_INCLUDE_DEPTH) {
2802 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2803 include_depth));
2804 return false;
2807 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2808 if (!bAllowIncludeRegistry) {
2809 return true;
2811 if (bInGlobalSection) {
2812 bool ret;
2813 include_depth++;
2814 ret = process_registry_globals();
2815 include_depth--;
2816 return ret;
2817 } else {
2818 DEBUG(1, ("\"include = registry\" only effective "
2819 "in %s section\n", GLOBAL_NAME));
2820 return false;
2824 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2825 current_user_info.domain,
2826 pszParmValue);
2828 add_to_file_list(pszParmValue, fname);
2830 string_set(ptr, fname);
2832 if (file_exist(fname)) {
2833 bool ret;
2834 include_depth++;
2835 ret = pm_process(fname, do_section, do_parameter, NULL);
2836 include_depth--;
2837 TALLOC_FREE(fname);
2838 return ret;
2841 DEBUG(2, ("Can't find include file %s\n", fname));
2842 TALLOC_FREE(fname);
2843 return true;
2846 /***************************************************************************
2847 Handle the interpretation of the copy parameter.
2848 ***************************************************************************/
2850 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2852 bool bRetval;
2853 int iTemp;
2854 struct loadparm_service serviceTemp;
2856 string_set(ptr, pszParmValue);
2858 init_service(&serviceTemp);
2860 bRetval = false;
2862 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2864 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2865 if (iTemp == iServiceIndex) {
2866 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2867 } else {
2868 copy_service(ServicePtrs[iServiceIndex],
2869 &serviceTemp,
2870 ServicePtrs[iServiceIndex]->copymap);
2871 bRetval = true;
2873 } else {
2874 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2875 bRetval = false;
2878 free_service(&serviceTemp);
2879 return (bRetval);
2882 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2884 Globals.ldap_debug_level = lp_int(pszParmValue);
2885 init_ldap_debugging();
2886 return true;
2889 /***************************************************************************
2890 Handle idmap/non unix account uid and gid allocation parameters. The format of these
2891 parameters is:
2893 [global]
2895 idmap uid = 1000-1999
2896 idmap gid = 700-899
2898 We only do simple parsing checks here. The strings are parsed into useful
2899 structures in the idmap daemon code.
2901 ***************************************************************************/
2903 /* Some lp_ routines to return idmap [ug]id information */
2905 static uid_t idmap_uid_low, idmap_uid_high;
2906 static gid_t idmap_gid_low, idmap_gid_high;
2908 bool lp_idmap_uid(uid_t *low, uid_t *high)
2910 if (idmap_uid_low == 0 || idmap_uid_high == 0)
2911 return false;
2913 if (low)
2914 *low = idmap_uid_low;
2916 if (high)
2917 *high = idmap_uid_high;
2919 return true;
2922 bool lp_idmap_gid(gid_t *low, gid_t *high)
2924 if (idmap_gid_low == 0 || idmap_gid_high == 0)
2925 return false;
2927 if (low)
2928 *low = idmap_gid_low;
2930 if (high)
2931 *high = idmap_gid_high;
2933 return true;
2936 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2938 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2940 return true;
2943 /* Do some simple checks on "idmap [ug]id" parameter values */
2945 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2947 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2949 return true;
2952 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2954 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2956 return true;
2959 /***************************************************************************
2960 Handle the DEBUG level list.
2961 ***************************************************************************/
2963 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2965 string_set(ptr, pszParmValueIn);
2966 return debug_parse_levels(pszParmValueIn);
2969 /***************************************************************************
2970 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2971 ***************************************************************************/
2973 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2975 const char *suffix_string;
2977 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2978 Globals.szLdapSuffix );
2979 if ( !suffix_string ) {
2980 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2981 return "";
2984 return suffix_string;
2987 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2989 if (Globals.szLdapMachineSuffix[0])
2990 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
2992 return lp_string(ctx, Globals.szLdapSuffix);
2995 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
2997 if (Globals.szLdapUserSuffix[0])
2998 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3000 return lp_string(ctx, Globals.szLdapSuffix);
3003 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3005 if (Globals.szLdapGroupSuffix[0])
3006 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3008 return lp_string(ctx, Globals.szLdapSuffix);
3011 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3013 if (Globals.szLdapIdmapSuffix[0])
3014 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3016 return lp_string(ctx, Globals.szLdapSuffix);
3019 /****************************************************************************
3020 set the value for a P_ENUM
3021 ***************************************************************************/
3023 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3024 int *ptr )
3026 int i;
3028 for (i = 0; parm->enum_list[i].name; i++) {
3029 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3030 *ptr = parm->enum_list[i].value;
3031 return;
3034 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3035 pszParmValue, parm->label));
3038 /***************************************************************************
3039 ***************************************************************************/
3041 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3043 static int parm_num = -1;
3044 struct loadparm_service *s;
3046 if ( parm_num == -1 )
3047 parm_num = map_parameter( "printing" );
3049 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3051 if ( snum < 0 )
3052 s = &sDefault;
3053 else
3054 s = ServicePtrs[snum];
3056 init_printer_values( s );
3058 return true;
3062 /***************************************************************************
3063 Initialise a copymap.
3064 ***************************************************************************/
3066 static void init_copymap(struct loadparm_service *pservice)
3068 int i;
3070 TALLOC_FREE(pservice->copymap);
3072 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3073 if (!pservice->copymap)
3074 DEBUG(0,
3075 ("Couldn't allocate copymap!! (size %d)\n",
3076 (int)NUMPARAMETERS));
3077 else
3078 for (i = 0; i < NUMPARAMETERS; i++)
3079 bitmap_set(pservice->copymap, i);
3083 return the parameter pointer for a parameter
3085 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3087 if (service == NULL) {
3088 if (parm->p_class == P_LOCAL)
3089 return (void *)(((char *)&sDefault)+parm->offset);
3090 else if (parm->p_class == P_GLOBAL)
3091 return (void *)(((char *)&Globals)+parm->offset);
3092 else return NULL;
3093 } else {
3094 return (void *)(((char *)service) + parm->offset);
3098 /***************************************************************************
3099 Return the local pointer to a parameter given the service number and parameter
3100 ***************************************************************************/
3102 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3104 return lp_parm_ptr(ServicePtrs[snum], parm);
3107 /***************************************************************************
3108 Process a parameter for a particular service number. If snum < 0
3109 then assume we are in the globals.
3110 ***************************************************************************/
3112 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3114 int parmnum, i;
3115 void *parm_ptr = NULL; /* where we are going to store the result */
3116 struct parmlist_entry **opt_list;
3118 parmnum = map_parameter(pszParmName);
3120 if (parmnum < 0) {
3121 if (strchr(pszParmName, ':') == NULL) {
3122 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3123 pszParmName));
3124 return true;
3128 * We've got a parametric option
3131 opt_list = (snum < 0)
3132 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3133 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3135 return true;
3138 /* if it's already been set by the command line, then we don't
3139 override here */
3140 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3141 return true;
3144 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3145 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3146 pszParmName));
3149 /* we might point at a service, the default service or a global */
3150 if (snum < 0) {
3151 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3152 } else {
3153 if (parm_table[parmnum].p_class == P_GLOBAL) {
3154 DEBUG(0,
3155 ("Global parameter %s found in service section!\n",
3156 pszParmName));
3157 return true;
3159 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3162 if (snum >= 0) {
3163 if (!ServicePtrs[snum]->copymap)
3164 init_copymap(ServicePtrs[snum]);
3166 /* this handles the aliases - set the copymap for other entries with
3167 the same data pointer */
3168 for (i = 0; parm_table[i].label; i++) {
3169 if ((parm_table[i].offset == parm_table[parmnum].offset)
3170 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3171 bitmap_clear(ServicePtrs[snum]->copymap, i);
3176 /* if it is a special case then go ahead */
3177 if (parm_table[parmnum].special) {
3178 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3179 (char **)parm_ptr);
3182 /* now switch on the type of variable it is */
3183 switch (parm_table[parmnum].type)
3185 case P_BOOL:
3186 *(bool *)parm_ptr = lp_bool(pszParmValue);
3187 break;
3189 case P_BOOLREV:
3190 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3191 break;
3193 case P_INTEGER:
3194 *(int *)parm_ptr = lp_int(pszParmValue);
3195 break;
3197 case P_CHAR:
3198 *(char *)parm_ptr = *pszParmValue;
3199 break;
3201 case P_OCTAL:
3202 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3203 if ( i != 1 ) {
3204 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3206 break;
3208 case P_BYTES:
3210 uint64_t val;
3211 if (conv_str_size_error(pszParmValue, &val)) {
3212 if (val <= INT_MAX) {
3213 *(int *)parm_ptr = (int)val;
3214 break;
3218 DEBUG(0,("lp_do_parameter(%s): value is not "
3219 "a valid size specifier!\n", pszParmValue));
3220 return false;
3223 case P_LIST:
3224 case P_CMDLIST:
3225 TALLOC_FREE(*((char ***)parm_ptr));
3226 *(char ***)parm_ptr = str_list_make_v3(
3227 NULL, pszParmValue, NULL);
3228 break;
3230 case P_STRING:
3231 string_set((char **)parm_ptr, pszParmValue);
3232 break;
3234 case P_USTRING:
3236 char *upper_string = strupper_talloc(talloc_tos(),
3237 pszParmValue);
3238 string_set((char **)parm_ptr, upper_string);
3239 TALLOC_FREE(upper_string);
3240 break;
3242 case P_ENUM:
3243 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3244 break;
3245 case P_SEP:
3246 break;
3249 return true;
3252 /***************************************************************************
3253 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3254 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3255 ***************************************************************************/
3257 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3259 int parmnum, i;
3260 parmnum = map_parameter(pszParmName);
3261 if (parmnum >= 0) {
3262 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3263 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3264 return false;
3266 parm_table[parmnum].flags |= FLAG_CMDLINE;
3268 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3269 * be grouped in the table, so we don't have to search the
3270 * whole table */
3271 for (i=parmnum-1;
3272 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3273 && parm_table[i].p_class == parm_table[parmnum].p_class;
3274 i--) {
3275 parm_table[i].flags |= FLAG_CMDLINE;
3277 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3278 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3279 parm_table[i].flags |= FLAG_CMDLINE;
3282 if (store_values) {
3283 store_lp_set_cmdline(pszParmName, pszParmValue);
3285 return true;
3288 /* it might be parametric */
3289 if (strchr(pszParmName, ':') != NULL) {
3290 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3291 if (store_values) {
3292 store_lp_set_cmdline(pszParmName, pszParmValue);
3294 return true;
3297 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3298 return true;
3301 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3303 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3306 /***************************************************************************
3307 Process a parameter.
3308 ***************************************************************************/
3310 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3311 void *userdata)
3313 if (!bInGlobalSection && bGlobalOnly)
3314 return true;
3316 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3318 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3319 pszParmName, pszParmValue));
3323 set a option from the commandline in 'a=b' format. Use to support --option
3325 bool lp_set_option(const char *option)
3327 char *p, *s;
3328 bool ret;
3330 s = talloc_strdup(NULL, option);
3331 if (!s) {
3332 return false;
3335 p = strchr(s, '=');
3336 if (!p) {
3337 talloc_free(s);
3338 return false;
3341 *p = 0;
3343 /* skip white spaces after the = sign */
3344 do {
3345 p++;
3346 } while (*p == ' ');
3348 ret = lp_set_cmdline(s, p);
3349 talloc_free(s);
3350 return ret;
3353 /**************************************************************************
3354 Print a parameter of the specified type.
3355 ***************************************************************************/
3357 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3359 /* For the seperation of lists values that we print below */
3360 const char *list_sep = ", ";
3361 int i;
3362 switch (p->type)
3364 case P_ENUM:
3365 for (i = 0; p->enum_list[i].name; i++) {
3366 if (*(int *)ptr == p->enum_list[i].value) {
3367 fprintf(f, "%s",
3368 p->enum_list[i].name);
3369 break;
3372 break;
3374 case P_BOOL:
3375 fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3376 break;
3378 case P_BOOLREV:
3379 fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3380 break;
3382 case P_INTEGER:
3383 case P_BYTES:
3384 fprintf(f, "%d", *(int *)ptr);
3385 break;
3387 case P_CHAR:
3388 fprintf(f, "%c", *(char *)ptr);
3389 break;
3391 case P_OCTAL: {
3392 int val = *(int *)ptr;
3393 if (val == -1) {
3394 fprintf(f, "-1");
3395 } else {
3396 fprintf(f, "0%o", val);
3398 break;
3401 case P_CMDLIST:
3402 list_sep = " ";
3403 /* fall through */
3404 case P_LIST:
3405 if ((char ***)ptr && *(char ***)ptr) {
3406 char **list = *(char ***)ptr;
3407 for (; *list; list++) {
3408 /* surround strings with whitespace in double quotes */
3409 if (*(list+1) == NULL) {
3410 /* last item, no extra separator */
3411 list_sep = "";
3413 if ( strchr_m( *list, ' ' ) ) {
3414 fprintf(f, "\"%s\"%s", *list, list_sep);
3415 } else {
3416 fprintf(f, "%s%s", *list, list_sep);
3420 break;
3422 case P_STRING:
3423 case P_USTRING:
3424 if (*(char **)ptr) {
3425 fprintf(f, "%s", *(char **)ptr);
3427 break;
3428 case P_SEP:
3429 break;
3433 /***************************************************************************
3434 Check if two parameters are equal.
3435 ***************************************************************************/
3437 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3439 switch (type) {
3440 case P_BOOL:
3441 case P_BOOLREV:
3442 return (*((bool *)ptr1) == *((bool *)ptr2));
3444 case P_INTEGER:
3445 case P_ENUM:
3446 case P_OCTAL:
3447 case P_BYTES:
3448 return (*((int *)ptr1) == *((int *)ptr2));
3450 case P_CHAR:
3451 return (*((char *)ptr1) == *((char *)ptr2));
3453 case P_LIST:
3454 case P_CMDLIST:
3455 return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3457 case P_STRING:
3458 case P_USTRING:
3460 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3461 if (p1 && !*p1)
3462 p1 = NULL;
3463 if (p2 && !*p2)
3464 p2 = NULL;
3465 return (p1 == p2 || strequal(p1, p2));
3467 case P_SEP:
3468 break;
3470 return false;
3473 /***************************************************************************
3474 Initialize any local variables in the sDefault table, after parsing a
3475 [globals] section.
3476 ***************************************************************************/
3478 static void init_locals(void)
3481 * We run this check once the [globals] is parsed, to force
3482 * the VFS objects and other per-share settings we need for
3483 * the standard way a AD DC is operated. We may change these
3484 * as our code evolves, which is why we force these settings.
3486 * We can't do this at the end of lp_load_ex(), as by that
3487 * point the services have been loaded and they will already
3488 * have "" as their vfs objects.
3490 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
3491 const char **vfs_objects = lp_vfs_objects(-1);
3492 if (!vfs_objects || !vfs_objects[0]) {
3493 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
3494 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
3495 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
3496 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
3497 } else {
3498 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
3502 lp_do_parameter(-1, "map hidden", "no");
3503 lp_do_parameter(-1, "map system", "no");
3504 lp_do_parameter(-1, "map readonly", "no");
3505 lp_do_parameter(-1, "map archive", "no");
3506 lp_do_parameter(-1, "store dos attributes", "yes");
3510 /***************************************************************************
3511 Process a new section (service). At this stage all sections are services.
3512 Later we'll have special sections that permit server parameters to be set.
3513 Returns true on success, false on failure.
3514 ***************************************************************************/
3516 static bool do_section(const char *pszSectionName, void *userdata)
3518 bool bRetval;
3519 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3520 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3521 bRetval = false;
3523 /* if we were in a global section then do the local inits */
3524 if (bInGlobalSection && !isglobal)
3525 init_locals();
3527 /* if we've just struck a global section, note the fact. */
3528 bInGlobalSection = isglobal;
3530 /* check for multiple global sections */
3531 if (bInGlobalSection) {
3532 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3533 return true;
3536 if (!bInGlobalSection && bGlobalOnly)
3537 return true;
3539 /* if we have a current service, tidy it up before moving on */
3540 bRetval = true;
3542 if (iServiceIndex >= 0)
3543 bRetval = service_ok(iServiceIndex);
3545 /* if all is still well, move to the next record in the services array */
3546 if (bRetval) {
3547 /* We put this here to avoid an odd message order if messages are */
3548 /* issued by the post-processing of a previous section. */
3549 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3551 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3552 if (iServiceIndex < 0) {
3553 DEBUG(0, ("Failed to add a new service\n"));
3554 return false;
3556 /* Clean all parametric options for service */
3557 /* They will be added during parsing again */
3558 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3561 return bRetval;
3565 /***************************************************************************
3566 Determine if a partcular base parameter is currentl set to the default value.
3567 ***************************************************************************/
3569 static bool is_default(int i)
3571 if (!defaults_saved)
3572 return false;
3573 switch (parm_table[i].type) {
3574 case P_LIST:
3575 case P_CMDLIST:
3576 return str_list_equal((const char **)parm_table[i].def.lvalue,
3577 *(const char ***)lp_parm_ptr(NULL,
3578 &parm_table[i]));
3579 case P_STRING:
3580 case P_USTRING:
3581 return strequal(parm_table[i].def.svalue,
3582 *(char **)lp_parm_ptr(NULL,
3583 &parm_table[i]));
3584 case P_BOOL:
3585 case P_BOOLREV:
3586 return parm_table[i].def.bvalue ==
3587 *(bool *)lp_parm_ptr(NULL,
3588 &parm_table[i]);
3589 case P_CHAR:
3590 return parm_table[i].def.cvalue ==
3591 *(char *)lp_parm_ptr(NULL,
3592 &parm_table[i]);
3593 case P_INTEGER:
3594 case P_OCTAL:
3595 case P_ENUM:
3596 case P_BYTES:
3597 return parm_table[i].def.ivalue ==
3598 *(int *)lp_parm_ptr(NULL,
3599 &parm_table[i]);
3600 case P_SEP:
3601 break;
3603 return false;
3606 /***************************************************************************
3607 Display the contents of the global structure.
3608 ***************************************************************************/
3610 static void dump_globals(FILE *f)
3612 int i;
3613 struct parmlist_entry *data;
3615 fprintf(f, "[global]\n");
3617 for (i = 0; parm_table[i].label; i++)
3618 if (parm_table[i].p_class == P_GLOBAL &&
3619 !(parm_table[i].flags & FLAG_META) &&
3620 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3621 if (defaults_saved && is_default(i))
3622 continue;
3623 fprintf(f, "\t%s = ", parm_table[i].label);
3624 print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3625 &parm_table[i]),
3627 fprintf(f, "\n");
3629 if (Globals.param_opt != NULL) {
3630 data = Globals.param_opt;
3631 while(data) {
3632 fprintf(f, "\t%s = %s\n", data->key, data->value);
3633 data = data->next;
3639 /***************************************************************************
3640 Return true if a local parameter is currently set to the global default.
3641 ***************************************************************************/
3643 bool lp_is_default(int snum, struct parm_struct *parm)
3645 return equal_parameter(parm->type,
3646 lp_parm_ptr(ServicePtrs[snum], parm),
3647 lp_parm_ptr(NULL, parm));
3650 /***************************************************************************
3651 Display the contents of a single services record.
3652 ***************************************************************************/
3654 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3656 int i;
3657 struct parmlist_entry *data;
3659 if (pService != &sDefault)
3660 fprintf(f, "[%s]\n", pService->szService);
3662 for (i = 0; parm_table[i].label; i++) {
3664 if (parm_table[i].p_class == P_LOCAL &&
3665 !(parm_table[i].flags & FLAG_META) &&
3666 (*parm_table[i].label != '-') &&
3667 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3669 if (pService == &sDefault) {
3670 if (defaults_saved && is_default(i))
3671 continue;
3672 } else {
3673 if (equal_parameter(parm_table[i].type,
3674 lp_parm_ptr(pService, &parm_table[i]),
3675 lp_parm_ptr(NULL, &parm_table[i])))
3676 continue;
3679 fprintf(f, "\t%s = ", parm_table[i].label);
3680 print_parameter(&parm_table[i],
3681 lp_parm_ptr(pService, &parm_table[i]),
3683 fprintf(f, "\n");
3687 if (pService->param_opt != NULL) {
3688 data = pService->param_opt;
3689 while(data) {
3690 fprintf(f, "\t%s = %s\n", data->key, data->value);
3691 data = data->next;
3696 /***************************************************************************
3697 Display the contents of a parameter of a single services record.
3698 ***************************************************************************/
3700 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3702 int i;
3703 bool result = false;
3704 parm_class p_class;
3705 unsigned flag = 0;
3706 fstring local_parm_name;
3707 char *parm_opt;
3708 const char *parm_opt_value;
3710 /* check for parametrical option */
3711 fstrcpy( local_parm_name, parm_name);
3712 parm_opt = strchr( local_parm_name, ':');
3714 if (parm_opt) {
3715 *parm_opt = '\0';
3716 parm_opt++;
3717 if (strlen(parm_opt)) {
3718 parm_opt_value = lp_parm_const_string( snum,
3719 local_parm_name, parm_opt, NULL);
3720 if (parm_opt_value) {
3721 printf( "%s\n", parm_opt_value);
3722 result = true;
3725 return result;
3728 /* check for a key and print the value */
3729 if (isGlobal) {
3730 p_class = P_GLOBAL;
3731 flag = FLAG_GLOBAL;
3732 } else
3733 p_class = P_LOCAL;
3735 for (i = 0; parm_table[i].label; i++) {
3736 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3737 !(parm_table[i].flags & FLAG_META) &&
3738 (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3739 (*parm_table[i].label != '-') &&
3740 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3742 void *ptr;
3744 if (isGlobal) {
3745 ptr = lp_parm_ptr(NULL,
3746 &parm_table[i]);
3747 } else {
3748 ptr = lp_parm_ptr(ServicePtrs[snum],
3749 &parm_table[i]);
3752 print_parameter(&parm_table[i],
3753 ptr, f);
3754 fprintf(f, "\n");
3755 result = true;
3756 break;
3760 return result;
3763 /***************************************************************************
3764 Return info about the requested parameter (given as a string).
3765 Return NULL when the string is not a valid parameter name.
3766 ***************************************************************************/
3768 struct parm_struct *lp_get_parameter(const char *param_name)
3770 int num = map_parameter(param_name);
3772 if (num < 0) {
3773 return NULL;
3776 return &parm_table[num];
3779 /***************************************************************************
3780 Return info about the next parameter in a service.
3781 snum==GLOBAL_SECTION_SNUM gives the globals.
3782 Return NULL when out of parameters.
3783 ***************************************************************************/
3785 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3787 if (snum < 0) {
3788 /* do the globals */
3789 for (; parm_table[*i].label; (*i)++) {
3790 if (parm_table[*i].p_class == P_SEPARATOR)
3791 return &parm_table[(*i)++];
3793 if ((*parm_table[*i].label == '-'))
3794 continue;
3796 if ((*i) > 0
3797 && (parm_table[*i].offset ==
3798 parm_table[(*i) - 1].offset)
3799 && (parm_table[*i].p_class ==
3800 parm_table[(*i) - 1].p_class))
3801 continue;
3803 if (is_default(*i) && !allparameters)
3804 continue;
3806 return &parm_table[(*i)++];
3808 } else {
3809 struct loadparm_service *pService = ServicePtrs[snum];
3811 for (; parm_table[*i].label; (*i)++) {
3812 if (parm_table[*i].p_class == P_SEPARATOR)
3813 return &parm_table[(*i)++];
3815 if (parm_table[*i].p_class == P_LOCAL &&
3816 (*parm_table[*i].label != '-') &&
3817 ((*i) == 0 ||
3818 (parm_table[*i].offset !=
3819 parm_table[(*i) - 1].offset)))
3821 if (allparameters ||
3822 !equal_parameter(parm_table[*i].type,
3823 lp_parm_ptr(pService,
3824 &parm_table[*i]),
3825 lp_parm_ptr(NULL,
3826 &parm_table[*i])))
3828 return &parm_table[(*i)++];
3834 return NULL;
3838 #if 0
3839 /***************************************************************************
3840 Display the contents of a single copy structure.
3841 ***************************************************************************/
3842 static void dump_copy_map(bool *pcopymap)
3844 int i;
3845 if (!pcopymap)
3846 return;
3848 printf("\n\tNon-Copied parameters:\n");
3850 for (i = 0; parm_table[i].label; i++)
3851 if (parm_table[i].p_class == P_LOCAL &&
3852 parm_table[i].ptr && !pcopymap[i] &&
3853 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3855 printf("\t\t%s\n", parm_table[i].label);
3858 #endif
3860 /***************************************************************************
3861 Return TRUE if the passed service number is within range.
3862 ***************************************************************************/
3864 bool lp_snum_ok(int iService)
3866 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3869 /***************************************************************************
3870 Auto-load some home services.
3871 ***************************************************************************/
3873 static void lp_add_auto_services(char *str)
3875 char *s;
3876 char *p;
3877 int homes;
3878 char *saveptr;
3880 if (!str)
3881 return;
3883 s = SMB_STRDUP(str);
3884 if (!s)
3885 return;
3887 homes = lp_servicenumber(HOMES_NAME);
3889 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3890 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3891 char *home;
3893 if (lp_servicenumber(p) >= 0)
3894 continue;
3896 home = get_user_home_dir(talloc_tos(), p);
3898 if (home && home[0] && homes >= 0)
3899 lp_add_home(p, homes, p, home);
3901 TALLOC_FREE(home);
3903 SAFE_FREE(s);
3906 /***************************************************************************
3907 Auto-load one printer.
3908 ***************************************************************************/
3910 void lp_add_one_printer(const char *name, const char *comment,
3911 const char *location, void *pdata)
3913 int printers = lp_servicenumber(PRINTERS_NAME);
3914 int i;
3916 if (lp_servicenumber(name) < 0) {
3917 lp_add_printer(name, printers);
3918 if ((i = lp_servicenumber(name)) >= 0) {
3919 string_set(&ServicePtrs[i]->comment, comment);
3920 ServicePtrs[i]->autoloaded = true;
3925 /***************************************************************************
3926 Have we loaded a services file yet?
3927 ***************************************************************************/
3929 bool lp_loaded(void)
3931 return (bLoaded);
3934 /***************************************************************************
3935 Unload unused services.
3936 ***************************************************************************/
3938 void lp_killunused(struct smbd_server_connection *sconn,
3939 bool (*snumused) (struct smbd_server_connection *, int))
3941 int i;
3942 for (i = 0; i < iNumServices; i++) {
3943 if (!VALID(i))
3944 continue;
3946 /* don't kill autoloaded or usershare services */
3947 if ( ServicePtrs[i]->autoloaded ||
3948 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3949 continue;
3952 if (!snumused || !snumused(sconn, i)) {
3953 free_service_byindex(i);
3959 * Kill all except autoloaded and usershare services - convenience wrapper
3961 void lp_kill_all_services(void)
3963 lp_killunused(NULL, NULL);
3966 /***************************************************************************
3967 Unload a service.
3968 ***************************************************************************/
3970 void lp_killservice(int iServiceIn)
3972 if (VALID(iServiceIn)) {
3973 free_service_byindex(iServiceIn);
3977 /***************************************************************************
3978 Save the curent values of all global and sDefault parameters into the
3979 defaults union. This allows swat and testparm to show only the
3980 changed (ie. non-default) parameters.
3981 ***************************************************************************/
3983 static void lp_save_defaults(void)
3985 int i;
3986 for (i = 0; parm_table[i].label; i++) {
3987 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3988 && parm_table[i].p_class == parm_table[i - 1].p_class)
3989 continue;
3990 switch (parm_table[i].type) {
3991 case P_LIST:
3992 case P_CMDLIST:
3993 parm_table[i].def.lvalue = str_list_copy(
3994 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3995 break;
3996 case P_STRING:
3997 case P_USTRING:
3998 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3999 break;
4000 case P_BOOL:
4001 case P_BOOLREV:
4002 parm_table[i].def.bvalue =
4003 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
4004 break;
4005 case P_CHAR:
4006 parm_table[i].def.cvalue =
4007 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
4008 break;
4009 case P_INTEGER:
4010 case P_OCTAL:
4011 case P_ENUM:
4012 case P_BYTES:
4013 parm_table[i].def.ivalue =
4014 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
4015 break;
4016 case P_SEP:
4017 break;
4020 defaults_saved = true;
4023 /***********************************************************
4024 If we should send plaintext/LANMAN passwords in the clinet
4025 ************************************************************/
4027 static void set_allowed_client_auth(void)
4029 if (Globals.bClientNTLMv2Auth) {
4030 Globals.bClientLanManAuth = false;
4032 if (!Globals.bClientLanManAuth) {
4033 Globals.bClientPlaintextAuth = false;
4037 /***************************************************************************
4038 JRA.
4039 The following code allows smbd to read a user defined share file.
4040 Yes, this is my intent. Yes, I'm comfortable with that...
4042 THE FOLLOWING IS SECURITY CRITICAL CODE.
4044 It washes your clothes, it cleans your house, it guards you while you sleep...
4045 Do not f%^k with it....
4046 ***************************************************************************/
4048 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4050 /***************************************************************************
4051 Check allowed stat state of a usershare file.
4052 Ensure we print out who is dicking with us so the admin can
4053 get their sorry ass fired.
4054 ***************************************************************************/
4056 static bool check_usershare_stat(const char *fname,
4057 const SMB_STRUCT_STAT *psbuf)
4059 if (!S_ISREG(psbuf->st_ex_mode)) {
4060 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4061 "not a regular file\n",
4062 fname, (unsigned int)psbuf->st_ex_uid ));
4063 return false;
4066 /* Ensure this doesn't have the other write bit set. */
4067 if (psbuf->st_ex_mode & S_IWOTH) {
4068 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4069 "public write. Refusing to allow as a usershare file.\n",
4070 fname, (unsigned int)psbuf->st_ex_uid ));
4071 return false;
4074 /* Should be 10k or less. */
4075 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4076 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4077 "too large (%u) to be a user share file.\n",
4078 fname, (unsigned int)psbuf->st_ex_uid,
4079 (unsigned int)psbuf->st_ex_size ));
4080 return false;
4083 return true;
4086 /***************************************************************************
4087 Parse the contents of a usershare file.
4088 ***************************************************************************/
4090 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4091 SMB_STRUCT_STAT *psbuf,
4092 const char *servicename,
4093 int snum,
4094 char **lines,
4095 int numlines,
4096 char **pp_sharepath,
4097 char **pp_comment,
4098 char **pp_cp_servicename,
4099 struct security_descriptor **ppsd,
4100 bool *pallow_guest)
4102 const char **prefixallowlist = lp_usershare_prefix_allow_list();
4103 const char **prefixdenylist = lp_usershare_prefix_deny_list();
4104 int us_vers;
4105 DIR *dp;
4106 SMB_STRUCT_STAT sbuf;
4107 char *sharepath = NULL;
4108 char *comment = NULL;
4110 *pp_sharepath = NULL;
4111 *pp_comment = NULL;
4113 *pallow_guest = false;
4115 if (numlines < 4) {
4116 return USERSHARE_MALFORMED_FILE;
4119 if (strcmp(lines[0], "#VERSION 1") == 0) {
4120 us_vers = 1;
4121 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4122 us_vers = 2;
4123 if (numlines < 5) {
4124 return USERSHARE_MALFORMED_FILE;
4126 } else {
4127 return USERSHARE_BAD_VERSION;
4130 if (strncmp(lines[1], "path=", 5) != 0) {
4131 return USERSHARE_MALFORMED_PATH;
4134 sharepath = talloc_strdup(ctx, &lines[1][5]);
4135 if (!sharepath) {
4136 return USERSHARE_POSIX_ERR;
4138 trim_string(sharepath, " ", " ");
4140 if (strncmp(lines[2], "comment=", 8) != 0) {
4141 return USERSHARE_MALFORMED_COMMENT_DEF;
4144 comment = talloc_strdup(ctx, &lines[2][8]);
4145 if (!comment) {
4146 return USERSHARE_POSIX_ERR;
4148 trim_string(comment, " ", " ");
4149 trim_char(comment, '"', '"');
4151 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4152 return USERSHARE_MALFORMED_ACL_DEF;
4155 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4156 return USERSHARE_ACL_ERR;
4159 if (us_vers == 2) {
4160 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4161 return USERSHARE_MALFORMED_ACL_DEF;
4163 if (lines[4][9] == 'y') {
4164 *pallow_guest = true;
4167 /* Backwards compatible extension to file version #2. */
4168 if (numlines > 5) {
4169 if (strncmp(lines[5], "sharename=", 10) != 0) {
4170 return USERSHARE_MALFORMED_SHARENAME_DEF;
4172 if (!strequal(&lines[5][10], servicename)) {
4173 return USERSHARE_BAD_SHARENAME;
4175 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4176 if (!*pp_cp_servicename) {
4177 return USERSHARE_POSIX_ERR;
4182 if (*pp_cp_servicename == NULL) {
4183 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4184 if (!*pp_cp_servicename) {
4185 return USERSHARE_POSIX_ERR;
4189 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4190 /* Path didn't change, no checks needed. */
4191 *pp_sharepath = sharepath;
4192 *pp_comment = comment;
4193 return USERSHARE_OK;
4196 /* The path *must* be absolute. */
4197 if (sharepath[0] != '/') {
4198 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4199 servicename, sharepath));
4200 return USERSHARE_PATH_NOT_ABSOLUTE;
4203 /* If there is a usershare prefix deny list ensure one of these paths
4204 doesn't match the start of the user given path. */
4205 if (prefixdenylist) {
4206 int i;
4207 for ( i=0; prefixdenylist[i]; i++ ) {
4208 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4209 servicename, i, prefixdenylist[i], sharepath ));
4210 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4211 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4212 "usershare prefix deny list entries.\n",
4213 servicename, sharepath));
4214 return USERSHARE_PATH_IS_DENIED;
4219 /* If there is a usershare prefix allow list ensure one of these paths
4220 does match the start of the user given path. */
4222 if (prefixallowlist) {
4223 int i;
4224 for ( i=0; prefixallowlist[i]; i++ ) {
4225 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4226 servicename, i, prefixallowlist[i], sharepath ));
4227 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4228 break;
4231 if (prefixallowlist[i] == NULL) {
4232 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4233 "usershare prefix allow list entries.\n",
4234 servicename, sharepath));
4235 return USERSHARE_PATH_NOT_ALLOWED;
4239 /* Ensure this is pointing to a directory. */
4240 dp = opendir(sharepath);
4242 if (!dp) {
4243 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4244 servicename, sharepath));
4245 return USERSHARE_PATH_NOT_DIRECTORY;
4248 /* Ensure the owner of the usershare file has permission to share
4249 this directory. */
4251 if (sys_stat(sharepath, &sbuf, false) == -1) {
4252 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4253 servicename, sharepath, strerror(errno) ));
4254 closedir(dp);
4255 return USERSHARE_POSIX_ERR;
4258 closedir(dp);
4260 if (!S_ISDIR(sbuf.st_ex_mode)) {
4261 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4262 servicename, sharepath ));
4263 return USERSHARE_PATH_NOT_DIRECTORY;
4266 /* Check if sharing is restricted to owner-only. */
4267 /* psbuf is the stat of the usershare definition file,
4268 sbuf is the stat of the target directory to be shared. */
4270 if (lp_usershare_owner_only()) {
4271 /* root can share anything. */
4272 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4273 return USERSHARE_PATH_NOT_ALLOWED;
4277 *pp_sharepath = sharepath;
4278 *pp_comment = comment;
4279 return USERSHARE_OK;
4282 /***************************************************************************
4283 Deal with a usershare file.
4284 Returns:
4285 >= 0 - snum
4286 -1 - Bad name, invalid contents.
4287 - service name already existed and not a usershare, problem
4288 with permissions to share directory etc.
4289 ***************************************************************************/
4291 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4293 SMB_STRUCT_STAT sbuf;
4294 SMB_STRUCT_STAT lsbuf;
4295 char *fname = NULL;
4296 char *sharepath = NULL;
4297 char *comment = NULL;
4298 char *cp_service_name = NULL;
4299 char **lines = NULL;
4300 int numlines = 0;
4301 int fd = -1;
4302 int iService = -1;
4303 TALLOC_CTX *ctx = talloc_stackframe();
4304 struct security_descriptor *psd = NULL;
4305 bool guest_ok = false;
4306 char *canon_name = NULL;
4307 bool added_service = false;
4308 int ret = -1;
4310 /* Ensure share name doesn't contain invalid characters. */
4311 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4312 DEBUG(0,("process_usershare_file: share name %s contains "
4313 "invalid characters (any of %s)\n",
4314 file_name, INVALID_SHARENAME_CHARS ));
4315 goto out;
4318 canon_name = canonicalize_servicename(ctx, file_name);
4319 if (!canon_name) {
4320 goto out;
4323 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4324 if (!fname) {
4325 goto out;
4328 /* Minimize the race condition by doing an lstat before we
4329 open and fstat. Ensure this isn't a symlink link. */
4331 if (sys_lstat(fname, &lsbuf, false) != 0) {
4332 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4333 fname, strerror(errno) ));
4334 goto out;
4337 /* This must be a regular file, not a symlink, directory or
4338 other strange filetype. */
4339 if (!check_usershare_stat(fname, &lsbuf)) {
4340 goto out;
4344 TDB_DATA data;
4345 NTSTATUS status;
4347 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4348 canon_name, &data);
4350 iService = -1;
4352 if (NT_STATUS_IS_OK(status) &&
4353 (data.dptr != NULL) &&
4354 (data.dsize == sizeof(iService))) {
4355 memcpy(&iService, data.dptr, sizeof(iService));
4359 if (iService != -1 &&
4360 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4361 &lsbuf.st_ex_mtime) == 0) {
4362 /* Nothing changed - Mark valid and return. */
4363 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4364 canon_name ));
4365 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4366 ret = iService;
4367 goto out;
4370 /* Try and open the file read only - no symlinks allowed. */
4371 #ifdef O_NOFOLLOW
4372 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4373 #else
4374 fd = open(fname, O_RDONLY, 0);
4375 #endif
4377 if (fd == -1) {
4378 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4379 fname, strerror(errno) ));
4380 goto out;
4383 /* Now fstat to be *SURE* it's a regular file. */
4384 if (sys_fstat(fd, &sbuf, false) != 0) {
4385 close(fd);
4386 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4387 fname, strerror(errno) ));
4388 goto out;
4391 /* Is it the same dev/inode as was lstated ? */
4392 if (!check_same_stat(&lsbuf, &sbuf)) {
4393 close(fd);
4394 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4395 "Symlink spoofing going on ?\n", fname ));
4396 goto out;
4399 /* This must be a regular file, not a symlink, directory or
4400 other strange filetype. */
4401 if (!check_usershare_stat(fname, &sbuf)) {
4402 close(fd);
4403 goto out;
4406 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4408 close(fd);
4409 if (lines == NULL) {
4410 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4411 fname, (unsigned int)sbuf.st_ex_uid ));
4412 goto out;
4415 if (parse_usershare_file(ctx, &sbuf, file_name,
4416 iService, lines, numlines, &sharepath,
4417 &comment, &cp_service_name,
4418 &psd, &guest_ok) != USERSHARE_OK) {
4419 goto out;
4422 /* Everything ok - add the service possibly using a template. */
4423 if (iService < 0) {
4424 const struct loadparm_service *sp = &sDefault;
4425 if (snum_template != -1) {
4426 sp = ServicePtrs[snum_template];
4429 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4430 DEBUG(0, ("process_usershare_file: Failed to add "
4431 "new service %s\n", cp_service_name));
4432 goto out;
4435 added_service = true;
4437 /* Read only is controlled by usershare ACL below. */
4438 ServicePtrs[iService]->bRead_only = false;
4441 /* Write the ACL of the new/modified share. */
4442 if (!set_share_security(canon_name, psd)) {
4443 DEBUG(0, ("process_usershare_file: Failed to set share "
4444 "security for user share %s\n",
4445 canon_name ));
4446 goto out;
4449 /* If from a template it may be marked invalid. */
4450 ServicePtrs[iService]->valid = true;
4452 /* Set the service as a valid usershare. */
4453 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4455 /* Set guest access. */
4456 if (lp_usershare_allow_guests()) {
4457 ServicePtrs[iService]->bGuest_ok = guest_ok;
4460 /* And note when it was loaded. */
4461 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4462 string_set(&ServicePtrs[iService]->szPath, sharepath);
4463 string_set(&ServicePtrs[iService]->comment, comment);
4465 ret = iService;
4467 out:
4469 if (ret == -1 && iService != -1 && added_service) {
4470 lp_remove_service(iService);
4473 TALLOC_FREE(lines);
4474 TALLOC_FREE(ctx);
4475 return ret;
4478 /***************************************************************************
4479 Checks if a usershare entry has been modified since last load.
4480 ***************************************************************************/
4482 static bool usershare_exists(int iService, struct timespec *last_mod)
4484 SMB_STRUCT_STAT lsbuf;
4485 const char *usersharepath = Globals.szUsersharePath;
4486 char *fname;
4488 if (asprintf(&fname, "%s/%s",
4489 usersharepath,
4490 ServicePtrs[iService]->szService) < 0) {
4491 return false;
4494 if (sys_lstat(fname, &lsbuf, false) != 0) {
4495 SAFE_FREE(fname);
4496 return false;
4499 if (!S_ISREG(lsbuf.st_ex_mode)) {
4500 SAFE_FREE(fname);
4501 return false;
4504 SAFE_FREE(fname);
4505 *last_mod = lsbuf.st_ex_mtime;
4506 return true;
4509 /***************************************************************************
4510 Load a usershare service by name. Returns a valid servicenumber or -1.
4511 ***************************************************************************/
4513 int load_usershare_service(const char *servicename)
4515 SMB_STRUCT_STAT sbuf;
4516 const char *usersharepath = Globals.szUsersharePath;
4517 int max_user_shares = Globals.iUsershareMaxShares;
4518 int snum_template = -1;
4520 if (*usersharepath == 0 || max_user_shares == 0) {
4521 return -1;
4524 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4525 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4526 usersharepath, strerror(errno) ));
4527 return -1;
4530 if (!S_ISDIR(sbuf.st_ex_mode)) {
4531 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4532 usersharepath ));
4533 return -1;
4537 * This directory must be owned by root, and have the 't' bit set.
4538 * It also must not be writable by "other".
4541 #ifdef S_ISVTX
4542 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4543 #else
4544 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4545 #endif
4546 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4547 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4548 usersharepath ));
4549 return -1;
4552 /* Ensure the template share exists if it's set. */
4553 if (Globals.szUsershareTemplateShare[0]) {
4554 /* We can't use lp_servicenumber here as we are recommending that
4555 template shares have -valid=false set. */
4556 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4557 if (ServicePtrs[snum_template]->szService &&
4558 strequal(ServicePtrs[snum_template]->szService,
4559 Globals.szUsershareTemplateShare)) {
4560 break;
4564 if (snum_template == -1) {
4565 DEBUG(0,("load_usershare_service: usershare template share %s "
4566 "does not exist.\n",
4567 Globals.szUsershareTemplateShare ));
4568 return -1;
4572 return process_usershare_file(usersharepath, servicename, snum_template);
4575 /***************************************************************************
4576 Load all user defined shares from the user share directory.
4577 We only do this if we're enumerating the share list.
4578 This is the function that can delete usershares that have
4579 been removed.
4580 ***************************************************************************/
4582 int load_usershare_shares(struct smbd_server_connection *sconn,
4583 bool (*snumused) (struct smbd_server_connection *, int))
4585 DIR *dp;
4586 SMB_STRUCT_STAT sbuf;
4587 struct dirent *de;
4588 int num_usershares = 0;
4589 int max_user_shares = Globals.iUsershareMaxShares;
4590 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4591 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4592 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4593 int iService;
4594 int snum_template = -1;
4595 const char *usersharepath = Globals.szUsersharePath;
4596 int ret = lp_numservices();
4597 TALLOC_CTX *tmp_ctx;
4599 if (max_user_shares == 0 || *usersharepath == '\0') {
4600 return lp_numservices();
4603 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4604 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4605 usersharepath, strerror(errno) ));
4606 return ret;
4610 * This directory must be owned by root, and have the 't' bit set.
4611 * It also must not be writable by "other".
4614 #ifdef S_ISVTX
4615 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4616 #else
4617 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4618 #endif
4619 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4620 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4621 usersharepath ));
4622 return ret;
4625 /* Ensure the template share exists if it's set. */
4626 if (Globals.szUsershareTemplateShare[0]) {
4627 /* We can't use lp_servicenumber here as we are recommending that
4628 template shares have -valid=false set. */
4629 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4630 if (ServicePtrs[snum_template]->szService &&
4631 strequal(ServicePtrs[snum_template]->szService,
4632 Globals.szUsershareTemplateShare)) {
4633 break;
4637 if (snum_template == -1) {
4638 DEBUG(0,("load_usershare_shares: usershare template share %s "
4639 "does not exist.\n",
4640 Globals.szUsershareTemplateShare ));
4641 return ret;
4645 /* Mark all existing usershares as pending delete. */
4646 for (iService = iNumServices - 1; iService >= 0; iService--) {
4647 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4648 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4652 dp = opendir(usersharepath);
4653 if (!dp) {
4654 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4655 usersharepath, strerror(errno) ));
4656 return ret;
4659 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4660 (de = readdir(dp));
4661 num_dir_entries++ ) {
4662 int r;
4663 const char *n = de->d_name;
4665 /* Ignore . and .. */
4666 if (*n == '.') {
4667 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4668 continue;
4672 if (n[0] == ':') {
4673 /* Temporary file used when creating a share. */
4674 num_tmp_dir_entries++;
4677 /* Allow 20% tmp entries. */
4678 if (num_tmp_dir_entries > allowed_tmp_entries) {
4679 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4680 "in directory %s\n",
4681 num_tmp_dir_entries, usersharepath));
4682 break;
4685 r = process_usershare_file(usersharepath, n, snum_template);
4686 if (r == 0) {
4687 /* Update the services count. */
4688 num_usershares++;
4689 if (num_usershares >= max_user_shares) {
4690 DEBUG(0,("load_usershare_shares: max user shares reached "
4691 "on file %s in directory %s\n",
4692 n, usersharepath ));
4693 break;
4695 } else if (r == -1) {
4696 num_bad_dir_entries++;
4699 /* Allow 20% bad entries. */
4700 if (num_bad_dir_entries > allowed_bad_entries) {
4701 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4702 "in directory %s\n",
4703 num_bad_dir_entries, usersharepath));
4704 break;
4707 /* Allow 20% bad entries. */
4708 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4709 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4710 "in directory %s\n",
4711 num_dir_entries, usersharepath));
4712 break;
4716 closedir(dp);
4718 /* Sweep through and delete any non-refreshed usershares that are
4719 not currently in use. */
4720 tmp_ctx = talloc_stackframe();
4721 for (iService = iNumServices - 1; iService >= 0; iService--) {
4722 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4723 char *servname;
4725 if (snumused && snumused(sconn, iService)) {
4726 continue;
4729 servname = lp_servicename(tmp_ctx, iService);
4731 /* Remove from the share ACL db. */
4732 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4733 servname ));
4734 delete_share_security(servname);
4735 free_service_byindex(iService);
4738 talloc_free(tmp_ctx);
4740 return lp_numservices();
4743 /********************************************************
4744 Destroy global resources allocated in this file
4745 ********************************************************/
4747 void gfree_loadparm(void)
4749 int i;
4751 free_file_list();
4753 /* Free resources allocated to services */
4755 for ( i = 0; i < iNumServices; i++ ) {
4756 if ( VALID(i) ) {
4757 free_service_byindex(i);
4761 SAFE_FREE( ServicePtrs );
4762 iNumServices = 0;
4764 /* Now release all resources allocated to global
4765 parameters and the default service */
4767 free_global_parameters();
4771 /***************************************************************************
4772 Allow client apps to specify that they are a client
4773 ***************************************************************************/
4774 static void lp_set_in_client(bool b)
4776 in_client = b;
4780 /***************************************************************************
4781 Determine if we're running in a client app
4782 ***************************************************************************/
4783 static bool lp_is_in_client(void)
4785 return in_client;
4788 /***************************************************************************
4789 Load the services array from the services file. Return true on success,
4790 false on failure.
4791 ***************************************************************************/
4793 static bool lp_load_ex(const char *pszFname,
4794 bool global_only,
4795 bool save_defaults,
4796 bool add_ipc,
4797 bool initialize_globals,
4798 bool allow_include_registry,
4799 bool load_all_shares)
4801 char *n2 = NULL;
4802 bool bRetval;
4804 bRetval = false;
4806 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4808 bInGlobalSection = true;
4809 bGlobalOnly = global_only;
4810 bAllowIncludeRegistry = allow_include_registry;
4812 init_globals(initialize_globals);
4814 free_file_list();
4816 if (save_defaults) {
4817 init_locals();
4818 lp_save_defaults();
4821 if (!initialize_globals) {
4822 free_param_opts(&Globals.param_opt);
4823 apply_lp_set_cmdline();
4826 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4828 /* We get sections first, so have to start 'behind' to make up */
4829 iServiceIndex = -1;
4831 if (lp_config_backend_is_file()) {
4832 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4833 current_user_info.domain,
4834 pszFname);
4835 if (!n2) {
4836 smb_panic("lp_load_ex: out of memory");
4839 add_to_file_list(pszFname, n2);
4841 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4842 TALLOC_FREE(n2);
4844 /* finish up the last section */
4845 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4846 if (bRetval) {
4847 if (iServiceIndex >= 0) {
4848 bRetval = service_ok(iServiceIndex);
4852 if (lp_config_backend_is_registry()) {
4853 /* config backend changed to registry in config file */
4855 * We need to use this extra global variable here to
4856 * survive restart: init_globals uses this as a default
4857 * for ConfigBackend. Otherwise, init_globals would
4858 * send us into an endless loop here.
4860 config_backend = CONFIG_BACKEND_REGISTRY;
4861 /* start over */
4862 DEBUG(1, ("lp_load_ex: changing to config backend "
4863 "registry\n"));
4864 init_globals(true);
4865 lp_kill_all_services();
4866 return lp_load_ex(pszFname, global_only, save_defaults,
4867 add_ipc, initialize_globals,
4868 allow_include_registry,
4869 load_all_shares);
4871 } else if (lp_config_backend_is_registry()) {
4872 bRetval = process_registry_globals();
4873 } else {
4874 DEBUG(0, ("Illegal config backend given: %d\n",
4875 lp_config_backend()));
4876 bRetval = false;
4879 if (bRetval && lp_registry_shares()) {
4880 if (load_all_shares) {
4881 bRetval = process_registry_shares();
4882 } else {
4883 bRetval = reload_registry_shares();
4888 char *serv = lp_auto_services(talloc_tos());
4889 lp_add_auto_services(serv);
4890 TALLOC_FREE(serv);
4893 if (add_ipc) {
4894 /* When 'restrict anonymous = 2' guest connections to ipc$
4895 are denied */
4896 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4897 if ( lp_enable_asu_support() ) {
4898 lp_add_ipc("ADMIN$", false);
4902 set_allowed_client_auth();
4904 if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4905 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4906 lp_passwordserver()));
4909 bLoaded = true;
4911 /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4912 /* if bWINSsupport is true and we are in the client */
4913 if (lp_is_in_client() && Globals.bWINSsupport) {
4914 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4917 init_iconv();
4919 fault_configure(smb_panic_s3);
4922 * We run this check once the whole smb.conf is parsed, to
4923 * force some settings for the standard way a AD DC is
4924 * operated. We may changed these as our code evolves, which
4925 * is why we force these settings.
4927 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4928 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4930 lp_do_parameter(-1, "rpc_server:default", "external");
4931 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4932 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4933 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4934 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4935 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4936 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4937 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4938 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4941 bAllowIncludeRegistry = true;
4943 return (bRetval);
4946 bool lp_load(const char *pszFname,
4947 bool global_only,
4948 bool save_defaults,
4949 bool add_ipc,
4950 bool initialize_globals)
4952 return lp_load_ex(pszFname,
4953 global_only,
4954 save_defaults,
4955 add_ipc,
4956 initialize_globals,
4957 true, /* allow_include_registry */
4958 false); /* load_all_shares*/
4961 bool lp_load_initial_only(const char *pszFname)
4963 return lp_load_ex(pszFname,
4964 true, /* global only */
4965 false, /* save_defaults */
4966 false, /* add_ipc */
4967 true, /* initialize_globals */
4968 false, /* allow_include_registry */
4969 false); /* load_all_shares*/
4973 * most common lp_load wrapper, loading only the globals
4975 bool lp_load_global(const char *file_name)
4977 return lp_load_ex(file_name,
4978 true, /* global_only */
4979 false, /* save_defaults */
4980 false, /* add_ipc */
4981 true, /* initialize_globals */
4982 true, /* allow_include_registry */
4983 false); /* load_all_shares*/
4987 * lp_load wrapper, especially for clients
4989 bool lp_load_client(const char *file_name)
4991 lp_set_in_client(true);
4993 return lp_load_global(file_name);
4997 * lp_load wrapper, loading only globals, but intended
4998 * for subsequent calls, not reinitializing the globals
4999 * to default values
5001 bool lp_load_global_no_reinit(const char *file_name)
5003 return lp_load_ex(file_name,
5004 true, /* global_only */
5005 false, /* save_defaults */
5006 false, /* add_ipc */
5007 false, /* initialize_globals */
5008 true, /* allow_include_registry */
5009 false); /* load_all_shares*/
5013 * lp_load wrapper, especially for clients, no reinitialization
5015 bool lp_load_client_no_reinit(const char *file_name)
5017 lp_set_in_client(true);
5019 return lp_load_global_no_reinit(file_name);
5022 bool lp_load_with_registry_shares(const char *pszFname,
5023 bool global_only,
5024 bool save_defaults,
5025 bool add_ipc,
5026 bool initialize_globals)
5028 return lp_load_ex(pszFname,
5029 global_only,
5030 save_defaults,
5031 add_ipc,
5032 initialize_globals,
5033 true, /* allow_include_registry */
5034 true); /* load_all_shares*/
5037 /***************************************************************************
5038 Return the max number of services.
5039 ***************************************************************************/
5041 int lp_numservices(void)
5043 return (iNumServices);
5046 /***************************************************************************
5047 Display the contents of the services array in human-readable form.
5048 ***************************************************************************/
5050 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5052 int iService;
5054 if (show_defaults)
5055 defaults_saved = false;
5057 dump_globals(f);
5059 dump_a_service(&sDefault, f);
5061 for (iService = 0; iService < maxtoprint; iService++) {
5062 fprintf(f,"\n");
5063 lp_dump_one(f, show_defaults, iService);
5067 /***************************************************************************
5068 Display the contents of one service in human-readable form.
5069 ***************************************************************************/
5071 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5073 if (VALID(snum)) {
5074 if (ServicePtrs[snum]->szService[0] == '\0')
5075 return;
5076 dump_a_service(ServicePtrs[snum], f);
5080 /***************************************************************************
5081 Return the number of the service with the given name, or -1 if it doesn't
5082 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5083 getservicebyname()! This works ONLY if all services have been loaded, and
5084 does not copy the found service.
5085 ***************************************************************************/
5087 int lp_servicenumber(const char *pszServiceName)
5089 int iService;
5090 fstring serviceName;
5092 if (!pszServiceName) {
5093 return GLOBAL_SECTION_SNUM;
5096 for (iService = iNumServices - 1; iService >= 0; iService--) {
5097 if (VALID(iService) && ServicePtrs[iService]->szService) {
5099 * The substitution here is used to support %U is
5100 * service names
5102 fstrcpy(serviceName, ServicePtrs[iService]->szService);
5103 standard_sub_basic(get_current_username(),
5104 current_user_info.domain,
5105 serviceName,sizeof(serviceName));
5106 if (strequal(serviceName, pszServiceName)) {
5107 break;
5112 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5113 struct timespec last_mod;
5115 if (!usershare_exists(iService, &last_mod)) {
5116 /* Remove the share security tdb entry for it. */
5117 delete_share_security(lp_servicename(talloc_tos(), iService));
5118 /* Remove it from the array. */
5119 free_service_byindex(iService);
5120 /* Doesn't exist anymore. */
5121 return GLOBAL_SECTION_SNUM;
5124 /* Has it been modified ? If so delete and reload. */
5125 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5126 &last_mod) < 0) {
5127 /* Remove it from the array. */
5128 free_service_byindex(iService);
5129 /* and now reload it. */
5130 iService = load_usershare_service(pszServiceName);
5134 if (iService < 0) {
5135 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5136 return GLOBAL_SECTION_SNUM;
5139 return (iService);
5142 /*******************************************************************
5143 A useful volume label function.
5144 ********************************************************************/
5146 const char *volume_label(TALLOC_CTX *ctx, int snum)
5148 char *ret;
5149 const char *label = lp_volume(ctx, snum);
5150 if (!*label) {
5151 label = lp_servicename(ctx, snum);
5154 /* This returns a 33 byte guarenteed null terminated string. */
5155 ret = talloc_strndup(ctx, label, 32);
5156 if (!ret) {
5157 return "";
5159 return ret;
5162 /*******************************************************************
5163 Get the default server type we will announce as via nmbd.
5164 ********************************************************************/
5166 int lp_default_server_announce(void)
5168 int default_server_announce = 0;
5169 default_server_announce |= SV_TYPE_WORKSTATION;
5170 default_server_announce |= SV_TYPE_SERVER;
5171 default_server_announce |= SV_TYPE_SERVER_UNIX;
5173 /* note that the flag should be set only if we have a
5174 printer service but nmbd doesn't actually load the
5175 services so we can't tell --jerry */
5177 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5179 default_server_announce |= SV_TYPE_SERVER_NT;
5180 default_server_announce |= SV_TYPE_NT;
5182 switch (lp_server_role()) {
5183 case ROLE_DOMAIN_MEMBER:
5184 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5185 break;
5186 case ROLE_DOMAIN_PDC:
5187 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5188 break;
5189 case ROLE_DOMAIN_BDC:
5190 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5191 break;
5192 case ROLE_STANDALONE:
5193 default:
5194 break;
5196 if (lp_time_server())
5197 default_server_announce |= SV_TYPE_TIME_SOURCE;
5199 if (lp_host_msdfs())
5200 default_server_announce |= SV_TYPE_DFS_SERVER;
5202 return default_server_announce;
5205 /***********************************************************
5206 If we are PDC then prefer us as DMB
5207 ************************************************************/
5209 bool lp_domain_master(void)
5211 if (Globals.domain_master == Auto)
5212 return (lp_server_role() == ROLE_DOMAIN_PDC);
5214 return (bool)Globals.domain_master;
5217 /***********************************************************
5218 If we are PDC then prefer us as DMB
5219 ************************************************************/
5221 static bool lp_domain_master_true_or_auto(void)
5223 if (Globals.domain_master) /* auto or yes */
5224 return true;
5226 return false;
5229 /***********************************************************
5230 If we are DMB then prefer us as LMB
5231 ************************************************************/
5233 bool lp_preferred_master(void)
5235 if (Globals.iPreferredMaster == Auto)
5236 return (lp_local_master() && lp_domain_master());
5238 return (bool)Globals.iPreferredMaster;
5241 /*******************************************************************
5242 Remove a service.
5243 ********************************************************************/
5245 void lp_remove_service(int snum)
5247 ServicePtrs[snum]->valid = false;
5248 invalid_services[num_invalid_services++] = snum;
5251 /*******************************************************************
5252 Copy a service.
5253 ********************************************************************/
5255 void lp_copy_service(int snum, const char *new_name)
5257 do_section(new_name, NULL);
5258 if (snum >= 0) {
5259 snum = lp_servicenumber(new_name);
5260 if (snum >= 0) {
5261 char *name = lp_servicename(talloc_tos(), snum);
5262 lp_do_parameter(snum, "copy", name);
5267 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5269 const char *ret = lp__printername(talloc_tos(), snum);
5270 if (ret == NULL || *ret == '\0') {
5271 ret = lp_const_servicename(snum);
5274 return ret;
5278 /***********************************************************
5279 Allow daemons such as winbindd to fix their logfile name.
5280 ************************************************************/
5282 void lp_set_logfile(const char *name)
5284 string_set(&Globals.logfile, name);
5285 debug_set_logfile(name);
5288 /*******************************************************************
5289 Return the max print jobs per queue.
5290 ********************************************************************/
5292 int lp_maxprintjobs(int snum)
5294 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5295 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5296 maxjobs = PRINT_MAX_JOBID - 1;
5298 return maxjobs;
5301 const char *lp_printcapname(void)
5303 if ((Globals.szPrintcapname != NULL) &&
5304 (Globals.szPrintcapname[0] != '\0'))
5305 return Globals.szPrintcapname;
5307 if (sDefault.iPrinting == PRINT_CUPS) {
5308 return "cups";
5311 if (sDefault.iPrinting == PRINT_BSD)
5312 return "/etc/printcap";
5314 return PRINTCAP_NAME;
5317 static uint32 spoolss_state;
5319 bool lp_disable_spoolss( void )
5321 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5322 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5324 return spoolss_state == SVCCTL_STOPPED ? true : false;
5327 void lp_set_spoolss_state( uint32 state )
5329 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5331 spoolss_state = state;
5334 uint32 lp_get_spoolss_state( void )
5336 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5339 /*******************************************************************
5340 Ensure we don't use sendfile if server smb signing is active.
5341 ********************************************************************/
5343 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5345 bool sign_active = false;
5347 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5348 if (get_Protocol() < PROTOCOL_NT1) {
5349 return false;
5351 if (signing_state) {
5352 sign_active = smb_signing_is_active(signing_state);
5354 return (lp__use_sendfile(snum) &&
5355 (get_remote_arch() != RA_WIN95) &&
5356 !sign_active);
5359 /*******************************************************************
5360 Turn off sendfile if we find the underlying OS doesn't support it.
5361 ********************************************************************/
5363 void set_use_sendfile(int snum, bool val)
5365 if (LP_SNUM_OK(snum))
5366 ServicePtrs[snum]->bUseSendfile = val;
5367 else
5368 sDefault.bUseSendfile = val;
5371 /*******************************************************************
5372 Turn off storing DOS attributes if this share doesn't support it.
5373 ********************************************************************/
5375 void set_store_dos_attributes(int snum, bool val)
5377 if (!LP_SNUM_OK(snum))
5378 return;
5379 ServicePtrs[(snum)]->bStoreDosAttributes = val;
5382 void lp_set_mangling_method(const char *new_method)
5384 string_set(&Globals.szManglingMethod, new_method);
5387 /*******************************************************************
5388 Global state for POSIX pathname processing.
5389 ********************************************************************/
5391 static bool posix_pathnames;
5393 bool lp_posix_pathnames(void)
5395 return posix_pathnames;
5398 /*******************************************************************
5399 Change everything needed to ensure POSIX pathname processing (currently
5400 not much).
5401 ********************************************************************/
5403 void lp_set_posix_pathnames(void)
5405 posix_pathnames = true;
5408 /*******************************************************************
5409 Global state for POSIX lock processing - CIFS unix extensions.
5410 ********************************************************************/
5412 bool posix_default_lock_was_set;
5413 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5415 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5417 if (posix_default_lock_was_set) {
5418 return posix_cifsx_locktype;
5419 } else {
5420 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5424 /*******************************************************************
5425 ********************************************************************/
5427 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5429 posix_default_lock_was_set = true;
5430 posix_cifsx_locktype = val;
5433 int lp_min_receive_file_size(void)
5435 if (Globals.iminreceivefile < 0) {
5436 return 0;
5438 return Globals.iminreceivefile;
5441 /*******************************************************************
5442 Safe wide links checks.
5443 This helper function always verify the validity of wide links,
5444 even after a configuration file reload.
5445 ********************************************************************/
5447 static bool lp_widelinks_internal(int snum)
5449 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5450 sDefault.bWidelinks);
5453 void widelinks_warning(int snum)
5455 if (lp_allow_insecure_widelinks()) {
5456 return;
5459 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5460 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5461 "These parameters are incompatible. "
5462 "Wide links will be disabled for this share.\n",
5463 lp_servicename(talloc_tos(), snum) ));
5467 bool lp_widelinks(int snum)
5469 /* wide links is always incompatible with unix extensions */
5470 if (lp_unix_extensions()) {
5472 * Unless we have "allow insecure widelinks"
5473 * turned on.
5475 if (!lp_allow_insecure_widelinks()) {
5476 return false;
5480 return lp_widelinks_internal(snum);
5483 bool lp_writeraw(void)
5485 if (lp_async_smb_echo_handler()) {
5486 return false;
5488 return lp__writeraw();
5491 bool lp_readraw(void)
5493 if (lp_async_smb_echo_handler()) {
5494 return false;
5496 return lp__readraw();
5499 int lp_server_role(void)
5501 return lp_find_server_role(lp__server_role(),
5502 lp__security(),
5503 lp__domain_logons(),
5504 lp_domain_master_true_or_auto());
5507 int lp_security(void)
5509 return lp_find_security(lp__server_role(),
5510 lp__security());