lib/param: Merge parameter tables into a common file
[Samba/gebeck_regimport.git] / source3 / param / loadparm.c
blob768fa419246b07d333536dccba9da7fb2aa9e8a5
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"
71 #include "../source4/dns_server/dns_update.h"
73 #ifdef HAVE_SYS_SYSCTL_H
74 #include <sys/sysctl.h>
75 #endif
77 #ifdef HAVE_HTTPCONNECTENCRYPT
78 #include <cups/http.h>
79 #endif
81 #ifdef CLUSTER_SUPPORT
82 #include "ctdb_private.h"
83 #endif
85 bool bLoaded = false;
87 extern userdom_struct current_user_info;
89 /* the special value for the include parameter
90 * to be interpreted not as a file name but to
91 * trigger loading of the global smb.conf options
92 * from registry. */
93 #ifndef INCLUDE_REGISTRY_NAME
94 #define INCLUDE_REGISTRY_NAME "registry"
95 #endif
97 static bool in_client = false; /* Not in the client by default */
98 static struct smbconf_csn conf_last_csn;
100 static int config_backend = CONFIG_BACKEND_FILE;
102 /* some helpful bits */
103 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
104 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
106 #define USERSHARE_VALID 1
107 #define USERSHARE_PENDING_DELETE 2
109 static bool defaults_saved = false;
111 #define LOADPARM_EXTRA_GLOBALS \
112 struct parmlist_entry *param_opt; \
113 char *szRealm; \
114 char *loglevel; \
115 int iminreceivefile; \
116 char *szPrintcapname; \
117 int CupsEncrypt; \
118 int iPreferredMaster; \
119 char *szLdapMachineSuffix; \
120 char *szLdapUserSuffix; \
121 char *szLdapIdmapSuffix; \
122 char *szLdapGroupSuffix; \
123 char *szStateDir; \
124 char *szCacheDir; \
125 char *szSocketAddress; \
126 char *szUsershareTemplateShare; \
127 char *szIdmapUID; \
128 char *szIdmapGID; \
129 int winbindMaxDomainConnections; \
130 int ismb2_max_credits; \
131 char *tls_keyfile; \
132 char *tls_certfile; \
133 char *tls_cafile; \
134 char *tls_crlfile; \
135 char *tls_dhpfile; \
136 char *panic_action; \
137 int bPreferredMaster;
139 #include "param/param_global.h"
141 static struct loadparm_global Globals;
143 /* This is a default service used to prime a services structure */
144 static struct loadparm_service sDefault =
146 .valid = true,
147 .autoloaded = false,
148 .usershare = 0,
149 .usershare_last_mod = {0, 0},
150 .szService = NULL,
151 .szPath = NULL,
152 .szUsername = NULL,
153 .szInvalidUsers = NULL,
154 .szValidUsers = NULL,
155 .szAdminUsers = NULL,
156 .szCopy = NULL,
157 .szInclude = NULL,
158 .szPreExec = NULL,
159 .szPostExec = NULL,
160 .szRootPreExec = NULL,
161 .szRootPostExec = NULL,
162 .szCupsOptions = NULL,
163 .szPrintcommand = NULL,
164 .szLpqcommand = NULL,
165 .szLprmcommand = NULL,
166 .szLppausecommand = NULL,
167 .szLpresumecommand = NULL,
168 .szQueuepausecommand = NULL,
169 .szQueueresumecommand = NULL,
170 .szPrintername = NULL,
171 .szPrintjobUsername = NULL,
172 .szDontdescend = NULL,
173 .szHostsallow = NULL,
174 .szHostsdeny = NULL,
175 .szMagicScript = NULL,
176 .szMagicOutput = NULL,
177 .szVetoFiles = NULL,
178 .szHideFiles = NULL,
179 .szVetoOplockFiles = NULL,
180 .comment = NULL,
181 .force_user = NULL,
182 .force_group = NULL,
183 .readlist = NULL,
184 .writelist = NULL,
185 .volume = NULL,
186 .fstype = NULL,
187 .szVfsObjects = NULL,
188 .szMSDfsProxy = NULL,
189 .szAioWriteBehind = NULL,
190 .szDfree = NULL,
191 .iMinPrintSpace = 0,
192 .iMaxPrintJobs = 1000,
193 .iMaxReportedPrintJobs = 0,
194 .iWriteCacheSize = 0,
195 .iCreate_mask = 0744,
196 .iCreate_force_mode = 0,
197 .iSecurity_mask = 0777,
198 .iSecurity_force_mode = 0,
199 .iDir_mask = 0755,
200 .iDir_force_mode = 0,
201 .iDir_Security_mask = 0777,
202 .iDir_Security_force_mode = 0,
203 .iMaxConnections = 0,
204 .iDefaultCase = CASE_LOWER,
205 .iPrinting = DEFAULT_PRINTING,
206 .iOplockContentionLimit = 2,
207 .iCSCPolicy = 0,
208 .iBlock_size = 1024,
209 .iDfreeCacheTime = 0,
210 .bPreexecClose = false,
211 .bRootpreexecClose = false,
212 .iCaseSensitive = Auto,
213 .bCasePreserve = true,
214 .bShortCasePreserve = true,
215 .bHideDotFiles = true,
216 .bHideSpecialFiles = false,
217 .bHideUnReadable = false,
218 .bHideUnWriteableFiles = false,
219 .bBrowseable = true,
220 .bAccessBasedShareEnum = false,
221 .bAvailable = true,
222 .bRead_only = true,
223 .bNo_set_dir = true,
224 .bGuest_only = false,
225 .bAdministrative_share = false,
226 .bGuest_ok = false,
227 .bPrint_ok = false,
228 .bPrintNotifyBackchannel = true,
229 .bMap_system = false,
230 .bMap_hidden = false,
231 .bMap_archive = true,
232 .bStoreDosAttributes = false,
233 .bDmapiSupport = false,
234 .bLocking = true,
235 .iStrictLocking = Auto,
236 .bPosixLocking = true,
237 .bShareModes = true,
238 .bOpLocks = true,
239 .bKernelOplocks = false,
240 .bLevel2OpLocks = true,
241 .bOnlyUser = false,
242 .bMangledNames = true,
243 .bWidelinks = false,
244 .bSymlinks = true,
245 .bSyncAlways = false,
246 .bStrictAllocate = false,
247 .bStrictSync = false,
248 .magic_char = '~',
249 .copymap = NULL,
250 .bDeleteReadonly = false,
251 .bFakeOplocks = false,
252 .bDeleteVetoFiles = false,
253 .bDosFilemode = false,
254 .bDosFiletimes = true,
255 .bDosFiletimeResolution = false,
256 .bFakeDirCreateTimes = false,
257 .bBlockingLocks = true,
258 .bInheritPerms = false,
259 .bInheritACLS = false,
260 .bInheritOwner = false,
261 .bMSDfsRoot = false,
262 .bUseClientDriver = false,
263 .bDefaultDevmode = true,
264 .bForcePrintername = false,
265 .bNTAclSupport = true,
266 .bForceUnknownAclUser = false,
267 .bUseSendfile = false,
268 .bProfileAcls = false,
269 .bMap_acl_inherit = false,
270 .bAfs_Share = false,
271 .bEASupport = false,
272 .bAclCheckPermissions = true,
273 .bAclMapFullControl = true,
274 .bAclGroupControl = false,
275 .bChangeNotify = true,
276 .bKernelChangeNotify = true,
277 .iallocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
278 .iAioReadSize = 0,
279 .iAioWriteSize = 0,
280 .iMap_readonly = MAP_READONLY_YES,
281 #ifdef BROKEN_DIRECTORY_HANDLING
282 .iDirectoryNameCacheSize = 0,
283 #else
284 .iDirectoryNameCacheSize = 100,
285 #endif
286 .ismb_encrypt = Auto,
287 .param_opt = NULL,
288 .dummy = ""
291 /* local variables */
292 static struct loadparm_service **ServicePtrs = NULL;
293 static int iNumServices = 0;
294 static int iServiceIndex = 0;
295 static struct db_context *ServiceHash;
296 static int *invalid_services = NULL;
297 static int num_invalid_services = 0;
298 static bool bInGlobalSection = true;
299 static bool bGlobalOnly = false;
301 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
303 /* prototypes for the special type handlers */
304 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
305 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
306 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
307 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
308 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
309 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
310 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
311 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
312 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
313 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
314 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
315 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
317 /* these are parameter handlers which are not needed in the
318 * source3 code
321 #define handle_logfile NULL
323 static void set_allowed_client_auth(void);
325 static void add_to_file_list(const char *fname, const char *subfname);
326 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
327 static void free_param_opts(struct parmlist_entry **popts);
329 #include "lib/param/param_table.c"
331 /***************************************************************************
332 Initialise the sDefault parameter structure for the printer values.
333 ***************************************************************************/
335 static void init_printer_values(struct loadparm_service *pService)
337 /* choose defaults depending on the type of printing */
338 switch (pService->iPrinting) {
339 case PRINT_BSD:
340 case PRINT_AIX:
341 case PRINT_LPRNT:
342 case PRINT_LPROS2:
343 string_set(&pService->szLpqcommand, "lpq -P'%p'");
344 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
345 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
346 break;
348 case PRINT_LPRNG:
349 case PRINT_PLP:
350 string_set(&pService->szLpqcommand, "lpq -P'%p'");
351 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
352 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
353 string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
354 string_set(&pService->szQueueresumecommand, "lpc start '%p'");
355 string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
356 string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
357 break;
359 case PRINT_CUPS:
360 case PRINT_IPRINT:
361 #ifdef HAVE_CUPS
362 /* set the lpq command to contain the destination printer
363 name only. This is used by cups_queue_get() */
364 string_set(&pService->szLpqcommand, "%p");
365 string_set(&pService->szLprmcommand, "");
366 string_set(&pService->szPrintcommand, "");
367 string_set(&pService->szLppausecommand, "");
368 string_set(&pService->szLpresumecommand, "");
369 string_set(&pService->szQueuepausecommand, "");
370 string_set(&pService->szQueueresumecommand, "");
371 #else
372 string_set(&pService->szLpqcommand, "lpq -P'%p'");
373 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
374 string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
375 string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
376 string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
377 string_set(&pService->szQueuepausecommand, "disable '%p'");
378 string_set(&pService->szQueueresumecommand, "enable '%p'");
379 #endif /* HAVE_CUPS */
380 break;
382 case PRINT_SYSV:
383 case PRINT_HPUX:
384 string_set(&pService->szLpqcommand, "lpstat -o%p");
385 string_set(&pService->szLprmcommand, "cancel %p-%j");
386 string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
387 string_set(&pService->szQueuepausecommand, "disable %p");
388 string_set(&pService->szQueueresumecommand, "enable %p");
389 #ifndef HPUX
390 string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
391 string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
392 #endif /* HPUX */
393 break;
395 case PRINT_QNX:
396 string_set(&pService->szLpqcommand, "lpq -P%p");
397 string_set(&pService->szLprmcommand, "lprm -P%p %j");
398 string_set(&pService->szPrintcommand, "lp -r -P%p %s");
399 break;
401 #if defined(DEVELOPER) || defined(ENABLE_BUILD_FARM_HACKS)
403 case PRINT_TEST:
404 case PRINT_VLP: {
405 const char *tdbfile;
406 TALLOC_CTX *tmp_ctx = talloc_stackframe();
407 char *tmp;
409 tdbfile = talloc_asprintf(
410 tmp_ctx, "tdbfile=%s",
411 lp_parm_const_string(-1, "vlp", "tdbfile",
412 "/tmp/vlp.tdb"));
413 if (tdbfile == NULL) {
414 tdbfile="tdbfile=/tmp/vlp.tdb";
417 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
418 tdbfile);
419 string_set(&pService->szPrintcommand,
420 tmp ? tmp : "vlp print %p %s");
422 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
423 tdbfile);
424 string_set(&pService->szLpqcommand,
425 tmp ? tmp : "vlp lpq %p");
427 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
428 tdbfile);
429 string_set(&pService->szLprmcommand,
430 tmp ? tmp : "vlp lprm %p %j");
432 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
433 tdbfile);
434 string_set(&pService->szLppausecommand,
435 tmp ? tmp : "vlp lppause %p %j");
437 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
438 tdbfile);
439 string_set(&pService->szLpresumecommand,
440 tmp ? tmp : "vlp lpresume %p %j");
442 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
443 tdbfile);
444 string_set(&pService->szQueuepausecommand,
445 tmp ? tmp : "vlp queuepause %p");
447 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
448 tdbfile);
449 string_set(&pService->szQueueresumecommand,
450 tmp ? tmp : "vlp queueresume %p");
451 TALLOC_FREE(tmp_ctx);
453 break;
455 #endif /* DEVELOPER */
460 * Function to return the default value for the maximum number of open
461 * file descriptors permitted. This function tries to consult the
462 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
463 * the smaller of those.
465 static int max_open_files(void)
467 int sysctl_max = MAX_OPEN_FILES;
468 int rlimit_max = MAX_OPEN_FILES;
470 #ifdef HAVE_SYSCTLBYNAME
472 size_t size = sizeof(sysctl_max);
473 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
476 #endif
478 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
480 struct rlimit rl;
482 ZERO_STRUCT(rl);
484 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
485 rlimit_max = rl.rlim_cur;
487 #if defined(RLIM_INFINITY)
488 if(rl.rlim_cur == RLIM_INFINITY)
489 rlimit_max = MAX_OPEN_FILES;
490 #endif
492 #endif
494 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
495 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
496 "minimum Windows limit (%d)\n",
497 sysctl_max,
498 MIN_OPEN_FILES_WINDOWS));
499 sysctl_max = MIN_OPEN_FILES_WINDOWS;
502 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
503 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
504 "minimum Windows limit (%d)\n",
505 rlimit_max,
506 MIN_OPEN_FILES_WINDOWS));
507 rlimit_max = MIN_OPEN_FILES_WINDOWS;
510 return MIN(sysctl_max, rlimit_max);
514 * Common part of freeing allocated data for one parameter.
516 static void free_one_parameter_common(void *parm_ptr,
517 struct parm_struct parm)
519 if ((parm.type == P_STRING) ||
520 (parm.type == P_USTRING))
522 string_free((char**)parm_ptr);
523 } else if (parm.type == P_LIST) {
524 TALLOC_FREE(*((char***)parm_ptr));
529 * Free the allocated data for one parameter for a share
530 * given as a service struct.
532 static void free_one_parameter(struct loadparm_service *service,
533 struct parm_struct parm)
535 void *parm_ptr;
537 if (parm.p_class != P_LOCAL) {
538 return;
541 parm_ptr = lp_parm_ptr(service, &parm);
543 free_one_parameter_common(parm_ptr, parm);
547 * Free the allocated parameter data of a share given
548 * as a service struct.
550 static void free_parameters(struct loadparm_service *service)
552 uint32_t i;
554 for (i=0; parm_table[i].label; i++) {
555 free_one_parameter(service, parm_table[i]);
560 * Free the allocated data for one parameter for a given share
561 * specified by an snum.
563 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
565 void *parm_ptr;
567 if (snum < 0) {
568 parm_ptr = lp_parm_ptr(NULL, &parm);
569 } else if (parm.p_class != P_LOCAL) {
570 return;
571 } else {
572 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
575 free_one_parameter_common(parm_ptr, parm);
579 * Free the allocated parameter data for a share specified
580 * by an snum.
582 static void free_parameters_by_snum(int snum)
584 uint32_t i;
586 for (i=0; parm_table[i].label; i++) {
587 free_one_parameter_by_snum(snum, parm_table[i]);
592 * Free the allocated global parameters.
594 static void free_global_parameters(void)
596 free_param_opts(&Globals.param_opt);
597 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
600 static int map_parameter(const char *pszParmName);
602 struct lp_stored_option {
603 struct lp_stored_option *prev, *next;
604 const char *label;
605 const char *value;
608 static struct lp_stored_option *stored_options;
611 save options set by lp_set_cmdline() into a list. This list is
612 re-applied when we do a globals reset, so that cmdline set options
613 are sticky across reloads of smb.conf
615 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
617 struct lp_stored_option *entry, *entry_next;
618 for (entry = stored_options; entry != NULL; entry = entry_next) {
619 entry_next = entry->next;
620 if (strcmp(pszParmName, entry->label) == 0) {
621 DLIST_REMOVE(stored_options, entry);
622 talloc_free(entry);
623 break;
627 entry = talloc(NULL, struct lp_stored_option);
628 if (!entry) {
629 return false;
632 entry->label = talloc_strdup(entry, pszParmName);
633 if (!entry->label) {
634 talloc_free(entry);
635 return false;
638 entry->value = talloc_strdup(entry, pszParmValue);
639 if (!entry->value) {
640 talloc_free(entry);
641 return false;
644 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
646 return true;
649 static bool apply_lp_set_cmdline(void)
651 struct lp_stored_option *entry = NULL;
652 for (entry = stored_options; entry != NULL; entry = entry->next) {
653 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
654 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
655 entry->label, entry->value));
656 return false;
659 return true;
662 /***************************************************************************
663 Initialise the global parameter structure.
664 ***************************************************************************/
666 static void init_globals(bool reinit_globals)
668 static bool done_init = false;
669 char *s = NULL;
670 int i;
672 /* If requested to initialize only once and we've already done it... */
673 if (!reinit_globals && done_init) {
674 /* ... then we have nothing more to do */
675 return;
678 if (!done_init) {
679 /* The logfile can be set before this is invoked. Free it if so. */
680 if (Globals.logfile != NULL) {
681 string_free(&Globals.logfile);
682 Globals.logfile = NULL;
684 done_init = true;
685 } else {
686 free_global_parameters();
689 /* This memset and the free_global_parameters() above will
690 * wipe out smb.conf options set with lp_set_cmdline(). The
691 * apply_lp_set_cmdline() call puts these values back in the
692 * table once the defaults are set */
693 ZERO_STRUCT(Globals);
695 for (i = 0; parm_table[i].label; i++) {
696 if ((parm_table[i].type == P_STRING ||
697 parm_table[i].type == P_USTRING))
699 string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
704 string_set(&sDefault.fstype, FSTYPE_STRING);
705 string_set(&sDefault.szPrintjobUsername, "%U");
707 init_printer_values(&sDefault);
710 DEBUG(3, ("Initialising global parameters\n"));
712 /* Must manually force to upper case here, as this does not go via the handler */
713 string_set(&Globals.szNetbiosName, myhostname_upper());
715 string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
716 string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
718 /* use the new 'hash2' method by default, with a prefix of 1 */
719 string_set(&Globals.szManglingMethod, "hash2");
720 Globals.mangle_prefix = 1;
722 string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
724 /* using UTF8 by default allows us to support all chars */
725 string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
727 /* Use codepage 850 as a default for the dos character set */
728 string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
731 * Allow the default PASSWD_CHAT to be overridden in local.h.
733 string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
735 string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
737 string_set(&Globals.szPasswdProgram, "");
738 string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
739 string_set(&Globals.szStateDir, get_dyn_STATEDIR());
740 string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
741 string_set(&Globals.szPidDir, get_dyn_PIDDIR());
742 string_set(&Globals.szSocketAddress, "0.0.0.0");
744 * By default support explicit binding to broadcast
745 * addresses.
747 Globals.bNmbdBindExplicitBroadcast = true;
749 if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
750 smb_panic("init_globals: ENOMEM");
752 string_set(&Globals.szServerString, s);
753 SAFE_FREE(s);
754 #ifdef DEVELOPER
755 string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
756 #endif
758 string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
760 string_set(&Globals.szLogonDrive, "");
761 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
762 string_set(&Globals.szLogonHome, "\\\\%N\\%U");
763 string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
765 Globals.szNameResolveOrder = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
766 string_set(&Globals.szPasswordServer, "*");
768 Globals.AlgorithmicRidBase = BASE_RID;
770 Globals.bLoadPrinters = true;
771 Globals.PrintcapCacheTime = 750; /* 12.5 minutes */
773 Globals.ConfigBackend = config_backend;
774 Globals.server_role = ROLE_AUTO;
776 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
777 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
778 Globals.max_xmit = 0x4104;
779 Globals.max_mux = 50; /* This is *needed* for profile support. */
780 Globals.lpqcachetime = 30; /* changed to handle large print servers better -- jerry */
781 Globals.bDisableSpoolss = false;
782 Globals.iMaxSmbdProcesses = 0;/* no limit specified */
783 Globals.pwordlevel = 0;
784 Globals.unamelevel = 0;
785 Globals.deadtime = 0;
786 Globals.getwd_cache = true;
787 Globals.bLargeReadwrite = true;
788 Globals.max_log_size = 5000;
789 Globals.max_open_files = max_open_files();
790 Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
791 Globals.srv_maxprotocol = PROTOCOL_SMB2_10;
792 Globals.srv_minprotocol = PROTOCOL_LANMAN1;
793 Globals.security = SEC_USER;
794 Globals.paranoid_server_security = true;
795 Globals.bEncryptPasswords = true;
796 Globals.clientSchannel = Auto;
797 Globals.serverSchannel = Auto;
798 Globals.bReadRaw = true;
799 Globals.bWriteRaw = true;
800 Globals.bNullPasswords = false;
801 Globals.bObeyPamRestrictions = false;
802 Globals.syslog = 1;
803 Globals.bSyslogOnly = false;
804 Globals.bTimestampLogs = true;
805 string_set(&Globals.loglevel, "0");
806 Globals.bDebugPrefixTimestamp = false;
807 Globals.bDebugHiresTimestamp = true;
808 Globals.bDebugPid = false;
809 Globals.bDebugUid = false;
810 Globals.bDebugClass = false;
811 Globals.bEnableCoreFiles = true;
812 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
813 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
814 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
815 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
816 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
817 Globals.lm_interval = 60;
818 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
819 Globals.bNISHomeMap = false;
820 #ifdef WITH_NISPLUS_HOME
821 string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
822 #else
823 string_set(&Globals.szNISHomeMapName, "auto.home");
824 #endif
825 #endif
826 Globals.bTimeServer = false;
827 Globals.bBindInterfacesOnly = false;
828 Globals.bUnixPasswdSync = false;
829 Globals.bPamPasswordChange = false;
830 Globals.bPasswdChatDebug = false;
831 Globals.iPasswdChatTimeout = 2; /* 2 second default. */
832 Globals.bNTPipeSupport = true; /* Do NT pipes by default. */
833 Globals.bNTStatusSupport = true; /* Use NT status by default. */
834 Globals.bStatCache = true; /* use stat cache by default */
835 Globals.iMaxStatCacheSize = 256; /* 256k by default */
836 Globals.restrict_anonymous = 0;
837 Globals.bClientLanManAuth = false; /* Do NOT use the LanMan hash if it is available */
838 Globals.bClientPlaintextAuth = false; /* Do NOT use a plaintext password even if is requested by the server */
839 Globals.bLanmanAuth = false; /* Do NOT use the LanMan hash, even if it is supplied */
840 Globals.bNTLMAuth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
841 Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
842 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
844 Globals.map_to_guest = 0; /* By Default, "Never" */
845 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
846 Globals.enhanced_browsing = true;
847 Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
848 #ifdef MMAP_BLACKLIST
849 Globals.bUseMmap = false;
850 #else
851 Globals.bUseMmap = true;
852 #endif
853 Globals.bUnicode = true;
854 Globals.bUnixExtensions = true;
855 Globals.bResetOnZeroVC = false;
856 Globals.bLogWriteableFilesOnExit = false;
857 Globals.bCreateKrb5Conf = true;
858 Globals.winbindMaxDomainConnections = 1;
860 /* hostname lookups can be very expensive and are broken on
861 a large number of sites (tridge) */
862 Globals.bHostnameLookups = false;
864 string_set(&Globals.passdb_backend, "tdbsam");
865 string_set(&Globals.szLdapSuffix, "");
866 string_set(&Globals.szLdapMachineSuffix, "");
867 string_set(&Globals.szLdapUserSuffix, "");
868 string_set(&Globals.szLdapGroupSuffix, "");
869 string_set(&Globals.szLdapIdmapSuffix, "");
871 string_set(&Globals.szLdapAdminDn, "");
872 Globals.ldap_ssl = LDAP_SSL_START_TLS;
873 Globals.ldap_ssl_ads = false;
874 Globals.ldap_deref = -1;
875 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
876 Globals.ldap_delete_dn = false;
877 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
878 Globals.ldap_follow_referral = Auto;
879 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
880 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
881 Globals.ldap_page_size = LDAP_PAGE_SIZE;
883 Globals.ldap_debug_level = 0;
884 Globals.ldap_debug_threshold = 10;
886 /* This is what we tell the afs client. in reality we set the token
887 * to never expire, though, when this runs out the afs client will
888 * forget the token. Set to 0 to get NEVERDATE.*/
889 Globals.iAfsTokenLifetime = 604800;
890 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
892 /* these parameters are set to defaults that are more appropriate
893 for the increasing samba install base:
895 as a member of the workgroup, that will possibly become a
896 _local_ master browser (lm = true). this is opposed to a forced
897 local master browser startup (pm = true).
899 doesn't provide WINS server service by default (wsupp = false),
900 and doesn't provide domain master browser services by default, either.
904 Globals.bMsAddPrinterWizard = true;
905 Globals.os_level = 20;
906 Globals.bLocalMaster = true;
907 Globals.domain_master = Auto; /* depending on bDomainLogons */
908 Globals.bDomainLogons = false;
909 Globals.bBrowseList = true;
910 Globals.bWINSsupport = false;
911 Globals.bWINSproxy = false;
913 TALLOC_FREE(Globals.szInitLogonDelayedHosts);
914 Globals.InitLogonDelay = 100; /* 100 ms default delay */
916 Globals.bWINSdnsProxy = true;
918 Globals.bAllowTrustedDomains = true;
919 string_set(&Globals.szIdmapBackend, "tdb");
921 string_set(&Globals.szTemplateShell, "/bin/false");
922 string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
923 string_set(&Globals.szWinbindSeparator, "\\");
925 string_set(&Globals.szCupsServer, "");
926 string_set(&Globals.szIPrintServer, "");
928 #ifdef CLUSTER_SUPPORT
929 string_set(&Globals.ctdbdSocket, CTDB_PATH);
930 #else
931 string_set(&Globals.ctdbdSocket, "");
932 #endif
934 Globals.szClusterAddresses = NULL;
935 Globals.clustering = false;
936 Globals.ctdb_timeout = 0;
937 Globals.ctdb_locktime_warn_threshold = 0;
939 Globals.winbind_cache_time = 300; /* 5 minutes */
940 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
941 Globals.winbind_max_clients = 200;
942 Globals.bWinbindEnumUsers = false;
943 Globals.bWinbindEnumGroups = false;
944 Globals.bWinbindUseDefaultDomain = false;
945 Globals.bWinbindTrustedDomainsOnly = false;
946 Globals.bWinbindNestedGroups = true;
947 Globals.winbind_expand_groups = 1;
948 Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
949 Globals.bWinbindRefreshTickets = false;
950 Globals.bWinbindOfflineLogon = false;
952 Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
953 Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
955 Globals.bPassdbExpandExplicit = false;
957 Globals.name_cache_timeout = 660; /* In seconds */
959 Globals.bUseSpnego = true;
960 Globals.bClientUseSpnego = true;
962 Globals.client_signing = SMB_SIGNING_DEFAULT;
963 Globals.server_signing = SMB_SIGNING_DEFAULT;
965 Globals.bDeferSharingViolations = true;
966 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
968 Globals.bEnablePrivileges = true;
969 Globals.bHostMSDfs = true;
970 Globals.bASUSupport = false;
972 /* User defined shares. */
973 if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
974 smb_panic("init_globals: ENOMEM");
976 string_set(&Globals.szUsersharePath, s);
977 SAFE_FREE(s);
978 string_set(&Globals.szUsershareTemplateShare, "");
979 Globals.iUsershareMaxShares = 0;
980 /* By default disallow sharing of directories not owned by the sharer. */
981 Globals.bUsershareOwnerOnly = true;
982 /* By default disallow guest access to usershares. */
983 Globals.bUsershareAllowGuests = false;
985 Globals.iKeepalive = DEFAULT_KEEPALIVE;
987 /* By default no shares out of the registry */
988 Globals.bRegistryShares = false;
990 Globals.iminreceivefile = 0;
992 Globals.bMapUntrustedToDomain = false;
993 Globals.bMulticastDnsRegister = true;
995 Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
996 Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
997 Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
998 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1000 string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1002 /* Now put back the settings that were set with lp_set_cmdline() */
1003 apply_lp_set_cmdline();
1006 /*******************************************************************
1007 Convenience routine to grab string parameters into talloced memory
1008 and run standard_sub_basic on them. The buffers can be written to by
1009 callers without affecting the source string.
1010 ********************************************************************/
1012 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1014 char *ret;
1016 /* The follow debug is useful for tracking down memory problems
1017 especially if you have an inner loop that is calling a lp_*()
1018 function that returns a string. Perhaps this debug should be
1019 present all the time? */
1021 #if 0
1022 DEBUG(10, ("lp_string(%s)\n", s));
1023 #endif
1024 if (!s) {
1025 return NULL;
1028 ret = talloc_sub_basic(ctx,
1029 get_current_username(),
1030 current_user_info.domain,
1032 if (trim_char(ret, '\"', '\"')) {
1033 if (strchr(ret,'\"') != NULL) {
1034 TALLOC_FREE(ret);
1035 ret = talloc_sub_basic(ctx,
1036 get_current_username(),
1037 current_user_info.domain,
1041 return ret;
1045 In this section all the functions that are used to access the
1046 parameters from the rest of the program are defined
1049 #define FN_GLOBAL_STRING(fn_name,ptr) \
1050 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1051 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1052 const char *lp_ ## fn_name(void) {return(*(const char **)(&Globals.ptr) ? *(const char **)(&Globals.ptr) : "");}
1053 #define FN_GLOBAL_LIST(fn_name,ptr) \
1054 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1055 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1056 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1057 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1058 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1059 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1060 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1062 #define FN_LOCAL_STRING(fn_name,val) \
1063 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));}
1064 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1065 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1066 #define FN_LOCAL_LIST(fn_name,val) \
1067 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1068 #define FN_LOCAL_BOOL(fn_name,val) \
1069 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1070 #define FN_LOCAL_INTEGER(fn_name,val) \
1071 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1073 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1074 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1075 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1076 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1077 #define FN_LOCAL_CHAR(fn_name,val) \
1078 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1081 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1082 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1084 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1085 * build process or in smb.conf, we use that value. Otherwise they
1086 * default to the value of lp_lockdir(). */
1087 const char *lp_statedir(void) {
1088 if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1089 (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1090 return(*(char **)(&Globals.szStateDir) ?
1091 *(char **)(&Globals.szStateDir) : "");
1092 else
1093 return(*(char **)(&Globals.szLockDir) ?
1094 *(char **)(&Globals.szLockDir) : "");
1096 const char *lp_cachedir(void) {
1097 if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1098 (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1099 return(*(char **)(&Globals.szCacheDir) ?
1100 *(char **)(&Globals.szCacheDir) : "");
1101 else
1102 return(*(char **)(&Globals.szLockDir) ?
1103 *(char **)(&Globals.szLockDir) : "");
1105 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1106 winbindMaxDomainConnections)
1108 int lp_winbind_max_domain_connections(void)
1110 if (lp_winbind_offline_logon() &&
1111 lp_winbind_max_domain_connections_int() > 1) {
1112 DEBUG(1, ("offline logons active, restricting max domain "
1113 "connections to 1\n"));
1114 return 1;
1116 return MAX(1, lp_winbind_max_domain_connections_int());
1119 int lp_smb2_max_credits(void)
1121 if (Globals.ismb2_max_credits == 0) {
1122 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1124 return Globals.ismb2_max_credits;
1126 int lp_cups_encrypt(void)
1128 int result = 0;
1129 #ifdef HAVE_HTTPCONNECTENCRYPT
1130 switch (Globals.CupsEncrypt) {
1131 case Auto:
1132 result = HTTP_ENCRYPT_REQUIRED;
1133 break;
1134 case true:
1135 result = HTTP_ENCRYPT_ALWAYS;
1136 break;
1137 case false:
1138 result = HTTP_ENCRYPT_NEVER;
1139 break;
1141 #endif
1142 return result;
1145 /* These functions remain in source3/param for now */
1147 FN_GLOBAL_STRING(configfile, szConfigFile)
1149 #include "lib/param/param_functions.c"
1151 FN_LOCAL_STRING(servicename, szService)
1152 FN_LOCAL_CONST_STRING(const_servicename, szService)
1154 /* local prototypes */
1156 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1157 static const char *get_boolean(bool bool_value);
1158 static int getservicebyname(const char *pszServiceName,
1159 struct loadparm_service *pserviceDest);
1160 static void copy_service(struct loadparm_service *pserviceDest,
1161 struct loadparm_service *pserviceSource,
1162 struct bitmap *pcopymapDest);
1163 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1164 void *userdata);
1165 static bool do_section(const char *pszSectionName, void *userdata);
1166 static void init_copymap(struct loadparm_service *pservice);
1167 static bool hash_a_service(const char *name, int number);
1168 static void free_service_byindex(int iService);
1169 static void show_parameter(int parmIndex);
1170 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1173 * This is a helper function for parametrical options support. It returns a
1174 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1175 * parametrical functions are quite simple
1177 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1178 const char *option)
1180 bool global_section = false;
1181 char* param_key;
1182 struct parmlist_entry *data;
1184 if (service == NULL) {
1185 data = Globals.param_opt;
1186 global_section = true;
1187 } else {
1188 data = service->param_opt;
1191 if (asprintf(&param_key, "%s:%s", type, option) == -1) {
1192 DEBUG(0,("asprintf failed!\n"));
1193 return NULL;
1196 while (data) {
1197 if (strwicmp(data->key, param_key) == 0) {
1198 string_free(&param_key);
1199 return data;
1201 data = data->next;
1204 if (!global_section) {
1205 /* Try to fetch the same option but from globals */
1206 /* but only if we are not already working with Globals */
1207 data = Globals.param_opt;
1208 while (data) {
1209 if (strwicmp(data->key, param_key) == 0) {
1210 string_free(&param_key);
1211 return data;
1213 data = data->next;
1217 string_free(&param_key);
1219 return NULL;
1223 * This is a helper function for parametrical options support. It returns a
1224 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1225 * parametrical functions are quite simple
1227 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1228 const char *option)
1230 if (snum >= iNumServices) return NULL;
1232 if (snum < 0) {
1233 return get_parametrics_by_service(NULL, type, option);
1234 } else {
1235 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1240 #define MISSING_PARAMETER(name) \
1241 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1243 /*******************************************************************
1244 convenience routine to return int parameters.
1245 ********************************************************************/
1246 static int lp_int(const char *s)
1249 if (!s || !*s) {
1250 MISSING_PARAMETER(lp_int);
1251 return (-1);
1254 return (int)strtol(s, NULL, 0);
1257 /*******************************************************************
1258 convenience routine to return unsigned long parameters.
1259 ********************************************************************/
1260 static unsigned long lp_ulong(const char *s)
1263 if (!s || !*s) {
1264 MISSING_PARAMETER(lp_ulong);
1265 return (0);
1268 return strtoul(s, NULL, 0);
1271 /*******************************************************************
1272 convenience routine to return boolean parameters.
1273 ********************************************************************/
1274 static bool lp_bool(const char *s)
1276 bool ret = false;
1278 if (!s || !*s) {
1279 MISSING_PARAMETER(lp_bool);
1280 return false;
1283 if (!set_boolean(s, &ret)) {
1284 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1285 return false;
1288 return ret;
1291 /*******************************************************************
1292 convenience routine to return enum parameters.
1293 ********************************************************************/
1294 static int lp_enum(const char *s,const struct enum_list *_enum)
1296 int i;
1298 if (!s || !*s || !_enum) {
1299 MISSING_PARAMETER(lp_enum);
1300 return (-1);
1303 for (i=0; _enum[i].name; i++) {
1304 if (strequal(_enum[i].name,s))
1305 return _enum[i].value;
1308 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1309 return (-1);
1312 #undef MISSING_PARAMETER
1314 /* Return parametric option from a given service. Type is a part of option before ':' */
1315 /* Parametric option has following syntax: 'Type: option = value' */
1316 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1318 struct parmlist_entry *data = get_parametrics(snum, type, option);
1320 if (data == NULL||data->value==NULL) {
1321 if (def) {
1322 return lp_string(ctx, def);
1323 } else {
1324 return NULL;
1328 return lp_string(ctx, data->value);
1331 /* Return parametric option from a given service. Type is a part of option before ':' */
1332 /* Parametric option has following syntax: 'Type: option = value' */
1333 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1335 struct parmlist_entry *data = get_parametrics(snum, type, option);
1337 if (data == NULL||data->value==NULL)
1338 return def;
1340 return data->value;
1343 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1345 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1347 if (data == NULL||data->value==NULL)
1348 return NULL;
1350 return data->value;
1354 /* Return parametric option from a given service. Type is a part of option before ':' */
1355 /* Parametric option has following syntax: 'Type: option = value' */
1357 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1359 struct parmlist_entry *data = get_parametrics(snum, type, option);
1361 if (data == NULL||data->value==NULL)
1362 return (const char **)def;
1364 if (data->list==NULL) {
1365 data->list = str_list_make_v3(NULL, data->value, NULL);
1368 return (const char **)data->list;
1371 /* Return parametric option from a given service. Type is a part of option before ':' */
1372 /* Parametric option has following syntax: 'Type: option = value' */
1374 int lp_parm_int(int snum, const char *type, const char *option, int def)
1376 struct parmlist_entry *data = get_parametrics(snum, type, option);
1378 if (data && data->value && *data->value)
1379 return lp_int(data->value);
1381 return def;
1384 /* Return parametric option from a given service. Type is a part of option before ':' */
1385 /* Parametric option has following syntax: 'Type: option = value' */
1387 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1389 struct parmlist_entry *data = get_parametrics(snum, type, option);
1391 if (data && data->value && *data->value)
1392 return lp_ulong(data->value);
1394 return def;
1397 /* Return parametric option from a given service. Type is a part of option before ':' */
1398 /* Parametric option has following syntax: 'Type: option = value' */
1400 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1402 struct parmlist_entry *data = get_parametrics(snum, type, option);
1404 if (data && data->value && *data->value)
1405 return lp_bool(data->value);
1407 return def;
1410 /* Return parametric option from a given service. Type is a part of option before ':' */
1411 /* Parametric option has following syntax: 'Type: option = value' */
1413 int lp_parm_enum(int snum, const char *type, const char *option,
1414 const struct enum_list *_enum, int def)
1416 struct parmlist_entry *data = get_parametrics(snum, type, option);
1418 if (data && data->value && *data->value && _enum)
1419 return lp_enum(data->value, _enum);
1421 return def;
1425 /***************************************************************************
1426 Initialise a service to the defaults.
1427 ***************************************************************************/
1429 static void init_service(struct loadparm_service *pservice)
1431 memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1432 copy_service(pservice, &sDefault, NULL);
1437 * free a param_opts structure.
1438 * param_opts handling should be moved to talloc;
1439 * then this whole functions reduces to a TALLOC_FREE().
1442 static void free_param_opts(struct parmlist_entry **popts)
1444 struct parmlist_entry *opt, *next_opt;
1446 if (popts == NULL) {
1447 return;
1450 if (*popts != NULL) {
1451 DEBUG(5, ("Freeing parametrics:\n"));
1453 opt = *popts;
1454 while (opt != NULL) {
1455 string_free(&opt->key);
1456 string_free(&opt->value);
1457 TALLOC_FREE(opt->list);
1458 next_opt = opt->next;
1459 SAFE_FREE(opt);
1460 opt = next_opt;
1462 *popts = NULL;
1465 /***************************************************************************
1466 Free the dynamically allocated parts of a service struct.
1467 ***************************************************************************/
1469 static void free_service(struct loadparm_service *pservice)
1471 if (!pservice)
1472 return;
1474 if (pservice->szService)
1475 DEBUG(5, ("free_service: Freeing service %s\n",
1476 pservice->szService));
1478 free_parameters(pservice);
1480 string_free(&pservice->szService);
1481 TALLOC_FREE(pservice->copymap);
1483 free_param_opts(&pservice->param_opt);
1485 ZERO_STRUCTP(pservice);
1489 /***************************************************************************
1490 remove a service indexed in the ServicePtrs array from the ServiceHash
1491 and free the dynamically allocated parts
1492 ***************************************************************************/
1494 static void free_service_byindex(int idx)
1496 if ( !LP_SNUM_OK(idx) )
1497 return;
1499 ServicePtrs[idx]->valid = false;
1500 invalid_services[num_invalid_services++] = idx;
1502 /* we have to cleanup the hash record */
1504 if (ServicePtrs[idx]->szService) {
1505 char *canon_name = canonicalize_servicename(
1506 talloc_tos(),
1507 ServicePtrs[idx]->szService );
1509 dbwrap_delete_bystring(ServiceHash, canon_name );
1510 TALLOC_FREE(canon_name);
1513 free_service(ServicePtrs[idx]);
1516 /***************************************************************************
1517 Add a new service to the services array initialising it with the given
1518 service.
1519 ***************************************************************************/
1521 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1523 int i;
1524 struct loadparm_service tservice;
1525 int num_to_alloc = iNumServices + 1;
1527 tservice = *pservice;
1529 /* it might already exist */
1530 if (name) {
1531 i = getservicebyname(name, NULL);
1532 if (i >= 0) {
1533 return (i);
1537 /* find an invalid one */
1538 i = iNumServices;
1539 if (num_invalid_services > 0) {
1540 i = invalid_services[--num_invalid_services];
1543 /* if not, then create one */
1544 if (i == iNumServices) {
1545 struct loadparm_service **tsp;
1546 int *tinvalid;
1548 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1549 if (tsp == NULL) {
1550 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1551 return (-1);
1553 ServicePtrs = tsp;
1554 ServicePtrs[iNumServices] = SMB_MALLOC_P(struct loadparm_service);
1555 if (!ServicePtrs[iNumServices]) {
1556 DEBUG(0,("add_a_service: out of memory!\n"));
1557 return (-1);
1559 iNumServices++;
1561 /* enlarge invalid_services here for now... */
1562 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
1563 num_to_alloc);
1564 if (tinvalid == NULL) {
1565 DEBUG(0,("add_a_service: failed to enlarge "
1566 "invalid_services!\n"));
1567 return (-1);
1569 invalid_services = tinvalid;
1570 } else {
1571 free_service_byindex(i);
1574 ServicePtrs[i]->valid = true;
1576 init_service(ServicePtrs[i]);
1577 copy_service(ServicePtrs[i], &tservice, NULL);
1578 if (name)
1579 string_set(&ServicePtrs[i]->szService, name);
1581 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1582 i, ServicePtrs[i]->szService));
1584 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1585 return (-1);
1588 return (i);
1591 /***************************************************************************
1592 Convert a string to uppercase and remove whitespaces.
1593 ***************************************************************************/
1595 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1597 char *result;
1599 if ( !src ) {
1600 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1601 return NULL;
1604 result = talloc_strdup(ctx, src);
1605 SMB_ASSERT(result != NULL);
1607 strlower_m(result);
1608 return result;
1611 /***************************************************************************
1612 Add a name/index pair for the services array to the hash table.
1613 ***************************************************************************/
1615 static bool hash_a_service(const char *name, int idx)
1617 char *canon_name;
1619 if ( !ServiceHash ) {
1620 DEBUG(10,("hash_a_service: creating servicehash\n"));
1621 ServiceHash = db_open_rbt(NULL);
1622 if ( !ServiceHash ) {
1623 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1624 return false;
1628 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1629 idx, name));
1631 canon_name = canonicalize_servicename(talloc_tos(), name );
1633 dbwrap_store_bystring(ServiceHash, canon_name,
1634 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1635 TDB_REPLACE);
1637 TALLOC_FREE(canon_name);
1639 return true;
1642 /***************************************************************************
1643 Add a new home service, with the specified home directory, defaults coming
1644 from service ifrom.
1645 ***************************************************************************/
1647 bool lp_add_home(const char *pszHomename, int iDefaultService,
1648 const char *user, const char *pszHomedir)
1650 int i;
1652 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1653 pszHomedir[0] == '\0') {
1654 return false;
1657 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1659 if (i < 0)
1660 return false;
1662 if (!(*(ServicePtrs[iDefaultService]->szPath))
1663 || strequal(ServicePtrs[iDefaultService]->szPath,
1664 lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1665 string_set(&ServicePtrs[i]->szPath, pszHomedir);
1668 if (!(*(ServicePtrs[i]->comment))) {
1669 char *comment = NULL;
1670 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1671 return false;
1673 string_set(&ServicePtrs[i]->comment, comment);
1674 SAFE_FREE(comment);
1677 /* set the browseable flag from the global default */
1679 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1680 ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
1682 ServicePtrs[i]->autoloaded = true;
1684 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1685 user, ServicePtrs[i]->szPath ));
1687 return true;
1690 /***************************************************************************
1691 Add a new service, based on an old one.
1692 ***************************************************************************/
1694 int lp_add_service(const char *pszService, int iDefaultService)
1696 if (iDefaultService < 0) {
1697 return add_a_service(&sDefault, pszService);
1700 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1703 /***************************************************************************
1704 Add the IPC service.
1705 ***************************************************************************/
1707 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1709 char *comment = NULL;
1710 int i = add_a_service(&sDefault, ipc_name);
1712 if (i < 0)
1713 return false;
1715 if (asprintf(&comment, "IPC Service (%s)",
1716 Globals.szServerString) < 0) {
1717 return false;
1720 string_set(&ServicePtrs[i]->szPath, tmpdir());
1721 string_set(&ServicePtrs[i]->szUsername, "");
1722 string_set(&ServicePtrs[i]->comment, comment);
1723 string_set(&ServicePtrs[i]->fstype, "IPC");
1724 ServicePtrs[i]->iMaxConnections = 0;
1725 ServicePtrs[i]->bAvailable = true;
1726 ServicePtrs[i]->bRead_only = true;
1727 ServicePtrs[i]->bGuest_only = false;
1728 ServicePtrs[i]->bAdministrative_share = true;
1729 ServicePtrs[i]->bGuest_ok = guest_ok;
1730 ServicePtrs[i]->bPrint_ok = false;
1731 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1733 DEBUG(3, ("adding IPC service\n"));
1735 SAFE_FREE(comment);
1736 return true;
1739 /***************************************************************************
1740 Add a new printer service, with defaults coming from service iFrom.
1741 ***************************************************************************/
1743 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1745 const char *comment = "From Printcap";
1746 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1748 if (i < 0)
1749 return false;
1751 /* note that we do NOT default the availability flag to true - */
1752 /* we take it from the default service passed. This allows all */
1753 /* dynamic printers to be disabled by disabling the [printers] */
1754 /* entry (if/when the 'available' keyword is implemented!). */
1756 /* the printer name is set to the service name. */
1757 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1758 string_set(&ServicePtrs[i]->comment, comment);
1760 /* set the browseable flag from the gloabl default */
1761 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1763 /* Printers cannot be read_only. */
1764 ServicePtrs[i]->bRead_only = false;
1765 /* No share modes on printer services. */
1766 ServicePtrs[i]->bShareModes = false;
1767 /* No oplocks on printer services. */
1768 ServicePtrs[i]->bOpLocks = false;
1769 /* Printer services must be printable. */
1770 ServicePtrs[i]->bPrint_ok = true;
1772 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1774 return true;
1778 /***************************************************************************
1779 Check whether the given parameter name is valid.
1780 Parametric options (names containing a colon) are considered valid.
1781 ***************************************************************************/
1783 bool lp_parameter_is_valid(const char *pszParmName)
1785 return ((map_parameter(pszParmName) != -1) ||
1786 (strchr(pszParmName, ':') != NULL));
1789 /***************************************************************************
1790 Check whether the given name is the name of a global parameter.
1791 Returns true for strings belonging to parameters of class
1792 P_GLOBAL, false for all other strings, also for parametric options
1793 and strings not belonging to any option.
1794 ***************************************************************************/
1796 bool lp_parameter_is_global(const char *pszParmName)
1798 int num = map_parameter(pszParmName);
1800 if (num >= 0) {
1801 return (parm_table[num].p_class == P_GLOBAL);
1804 return false;
1807 /**************************************************************************
1808 Check whether the given name is the canonical name of a parameter.
1809 Returns false if it is not a valid parameter Name.
1810 For parametric options, true is returned.
1811 **************************************************************************/
1813 bool lp_parameter_is_canonical(const char *parm_name)
1815 if (!lp_parameter_is_valid(parm_name)) {
1816 return false;
1819 return (map_parameter(parm_name) ==
1820 map_parameter_canonical(parm_name, NULL));
1823 /**************************************************************************
1824 Determine the canonical name for a parameter.
1825 Indicate when it is an inverse (boolean) synonym instead of a
1826 "usual" synonym.
1827 **************************************************************************/
1829 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1830 bool *inverse)
1832 int num;
1834 if (!lp_parameter_is_valid(parm_name)) {
1835 *canon_parm = NULL;
1836 return false;
1839 num = map_parameter_canonical(parm_name, inverse);
1840 if (num < 0) {
1841 /* parametric option */
1842 *canon_parm = parm_name;
1843 } else {
1844 *canon_parm = parm_table[num].label;
1847 return true;
1851 /**************************************************************************
1852 Determine the canonical name for a parameter.
1853 Turn the value given into the inverse boolean expression when
1854 the synonym is an invers boolean synonym.
1856 Return true if parm_name is a valid parameter name and
1857 in case it is an invers boolean synonym, if the val string could
1858 successfully be converted to the reverse bool.
1859 Return false in all other cases.
1860 **************************************************************************/
1862 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1863 const char *val,
1864 const char **canon_parm,
1865 const char **canon_val)
1867 int num;
1868 bool inverse;
1870 if (!lp_parameter_is_valid(parm_name)) {
1871 *canon_parm = NULL;
1872 *canon_val = NULL;
1873 return false;
1876 num = map_parameter_canonical(parm_name, &inverse);
1877 if (num < 0) {
1878 /* parametric option */
1879 *canon_parm = parm_name;
1880 *canon_val = val;
1881 } else {
1882 *canon_parm = parm_table[num].label;
1883 if (inverse) {
1884 if (!lp_invert_boolean(val, canon_val)) {
1885 *canon_val = NULL;
1886 return false;
1888 } else {
1889 *canon_val = val;
1893 return true;
1896 /***************************************************************************
1897 Map a parameter's string representation to something we can use.
1898 Returns false if the parameter string is not recognised, else TRUE.
1899 ***************************************************************************/
1901 static int map_parameter(const char *pszParmName)
1903 int iIndex;
1905 if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
1906 return (-1);
1908 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1909 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1910 return (iIndex);
1912 /* Warn only if it isn't parametric option */
1913 if (strchr(pszParmName, ':') == NULL)
1914 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1915 /* We do return 'fail' for parametric options as well because they are
1916 stored in different storage
1918 return (-1);
1921 /***************************************************************************
1922 Map a parameter's string representation to the index of the canonical
1923 form of the parameter (it might be a synonym).
1924 Returns -1 if the parameter string is not recognised.
1925 ***************************************************************************/
1927 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1929 int parm_num, canon_num;
1930 bool loc_inverse = false;
1932 parm_num = map_parameter(pszParmName);
1933 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1934 /* invalid, parametric or no canidate for synonyms ... */
1935 goto done;
1938 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1939 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1940 parm_num = canon_num;
1941 goto done;
1945 done:
1946 if (inverse != NULL) {
1947 *inverse = loc_inverse;
1949 return parm_num;
1952 /***************************************************************************
1953 return true if parameter number parm1 is a synonym of parameter
1954 number parm2 (parm2 being the principal name).
1955 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1956 false otherwise.
1957 ***************************************************************************/
1959 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
1961 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
1962 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
1963 (parm_table[parm1].flags & FLAG_HIDE) &&
1964 !(parm_table[parm2].flags & FLAG_HIDE))
1966 if (inverse != NULL) {
1967 if ((parm_table[parm1].type == P_BOOLREV) &&
1968 (parm_table[parm2].type == P_BOOL))
1970 *inverse = true;
1971 } else {
1972 *inverse = false;
1975 return true;
1977 return false;
1980 /***************************************************************************
1981 Show one parameter's name, type, [values,] and flags.
1982 (helper functions for show_parameter_list)
1983 ***************************************************************************/
1985 static void show_parameter(int parmIndex)
1987 int enumIndex, flagIndex;
1988 int parmIndex2;
1989 bool hadFlag;
1990 bool hadSyn;
1991 bool inverse;
1992 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
1993 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
1994 "P_ENUM", "P_SEP"};
1995 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
1996 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
1997 FLAG_HIDE};
1998 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
1999 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2000 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2002 printf("%s=%s", parm_table[parmIndex].label,
2003 type[parm_table[parmIndex].type]);
2004 if (parm_table[parmIndex].type == P_ENUM) {
2005 printf(",");
2006 for (enumIndex=0;
2007 parm_table[parmIndex].enum_list[enumIndex].name;
2008 enumIndex++)
2010 printf("%s%s",
2011 enumIndex ? "|" : "",
2012 parm_table[parmIndex].enum_list[enumIndex].name);
2015 printf(",");
2016 hadFlag = false;
2017 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2018 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2019 printf("%s%s",
2020 hadFlag ? "|" : "",
2021 flag_names[flagIndex]);
2022 hadFlag = true;
2026 /* output synonyms */
2027 hadSyn = false;
2028 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2029 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2030 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2031 parm_table[parmIndex2].label);
2032 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2033 if (!hadSyn) {
2034 printf(" (synonyms: ");
2035 hadSyn = true;
2036 } else {
2037 printf(", ");
2039 printf("%s%s", parm_table[parmIndex2].label,
2040 inverse ? "[i]" : "");
2043 if (hadSyn) {
2044 printf(")");
2047 printf("\n");
2050 /***************************************************************************
2051 Show all parameter's name, type, [values,] and flags.
2052 ***************************************************************************/
2054 void show_parameter_list(void)
2056 int classIndex, parmIndex;
2057 const char *section_names[] = { "local", "global", NULL};
2059 for (classIndex=0; section_names[classIndex]; classIndex++) {
2060 printf("[%s]\n", section_names[classIndex]);
2061 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2062 if (parm_table[parmIndex].p_class == classIndex) {
2063 show_parameter(parmIndex);
2069 /***************************************************************************
2070 Check if a given string correctly represents a boolean value.
2071 ***************************************************************************/
2073 bool lp_string_is_valid_boolean(const char *parm_value)
2075 return set_boolean(parm_value, NULL);
2078 /***************************************************************************
2079 Get the standard string representation of a boolean value ("yes" or "no")
2080 ***************************************************************************/
2082 static const char *get_boolean(bool bool_value)
2084 static const char *yes_str = "yes";
2085 static const char *no_str = "no";
2087 return (bool_value ? yes_str : no_str);
2090 /***************************************************************************
2091 Provide the string of the negated boolean value associated to the boolean
2092 given as a string. Returns false if the passed string does not correctly
2093 represent a boolean.
2094 ***************************************************************************/
2096 bool lp_invert_boolean(const char *str, const char **inverse_str)
2098 bool val;
2100 if (!set_boolean(str, &val)) {
2101 return false;
2104 *inverse_str = get_boolean(!val);
2105 return true;
2108 /***************************************************************************
2109 Provide the canonical string representation of a boolean value given
2110 as a string. Return true on success, false if the string given does
2111 not correctly represent a boolean.
2112 ***************************************************************************/
2114 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2116 bool val;
2118 if (!set_boolean(str, &val)) {
2119 return false;
2122 *canon_str = get_boolean(val);
2123 return true;
2126 /***************************************************************************
2127 Find a service by name. Otherwise works like get_service.
2128 ***************************************************************************/
2130 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2132 int iService = -1;
2133 char *canon_name;
2134 TDB_DATA data;
2135 NTSTATUS status;
2137 if (ServiceHash == NULL) {
2138 return -1;
2141 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2143 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2144 &data);
2146 if (NT_STATUS_IS_OK(status) &&
2147 (data.dptr != NULL) &&
2148 (data.dsize == sizeof(iService)))
2150 iService = *(int *)data.dptr;
2153 TALLOC_FREE(canon_name);
2155 if ((iService != -1) && (LP_SNUM_OK(iService))
2156 && (pserviceDest != NULL)) {
2157 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2160 return (iService);
2163 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2164 struct loadparm_service *lp_service(const char *pszServiceName)
2166 int iService = getservicebyname(pszServiceName, NULL);
2167 if (iService == -1 || !LP_SNUM_OK(iService)) {
2168 return NULL;
2170 return ServicePtrs[iService];
2173 struct loadparm_service *lp_servicebynum(int snum)
2175 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2176 return NULL;
2178 return ServicePtrs[snum];
2181 struct loadparm_service *lp_default_loadparm_service()
2183 return &sDefault;
2187 /***************************************************************************
2188 Copy a service structure to another.
2189 If pcopymapDest is NULL then copy all fields
2190 ***************************************************************************/
2193 * Add a parametric option to a parmlist_entry,
2194 * replacing old value, if already present.
2196 static void set_param_opt(struct parmlist_entry **opt_list,
2197 const char *opt_name,
2198 const char *opt_value,
2199 unsigned priority)
2201 struct parmlist_entry *new_opt, *opt;
2202 bool not_added;
2204 if (opt_list == NULL) {
2205 return;
2208 opt = *opt_list;
2209 not_added = true;
2211 /* Traverse destination */
2212 while (opt) {
2213 /* If we already have same option, override it */
2214 if (strwicmp(opt->key, opt_name) == 0) {
2215 if ((opt->priority & FLAG_CMDLINE) &&
2216 !(priority & FLAG_CMDLINE)) {
2217 /* it's been marked as not to be
2218 overridden */
2219 return;
2221 string_free(&opt->value);
2222 TALLOC_FREE(opt->list);
2223 opt->value = SMB_STRDUP(opt_value);
2224 opt->priority = priority;
2225 not_added = false;
2226 break;
2228 opt = opt->next;
2230 if (not_added) {
2231 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2232 new_opt->key = SMB_STRDUP(opt_name);
2233 new_opt->value = SMB_STRDUP(opt_value);
2234 new_opt->list = NULL;
2235 new_opt->priority = priority;
2236 DLIST_ADD(*opt_list, new_opt);
2240 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2241 struct bitmap *pcopymapDest)
2243 int i;
2244 bool bcopyall = (pcopymapDest == NULL);
2245 struct parmlist_entry *data;
2247 for (i = 0; parm_table[i].label; i++)
2248 if (parm_table[i].p_class == P_LOCAL &&
2249 (bcopyall || bitmap_query(pcopymapDest,i))) {
2250 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2251 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2253 switch (parm_table[i].type) {
2254 case P_BOOL:
2255 case P_BOOLREV:
2256 *(bool *)dest_ptr = *(bool *)src_ptr;
2257 break;
2259 case P_INTEGER:
2260 case P_ENUM:
2261 case P_OCTAL:
2262 case P_BYTES:
2263 *(int *)dest_ptr = *(int *)src_ptr;
2264 break;
2266 case P_CHAR:
2267 *(char *)dest_ptr = *(char *)src_ptr;
2268 break;
2270 case P_STRING:
2271 string_set((char **)dest_ptr,
2272 *(char **)src_ptr);
2273 break;
2275 case P_USTRING:
2277 char *upper_string = strupper_talloc(talloc_tos(),
2278 *(char **)src_ptr);
2279 string_set((char **)dest_ptr,
2280 upper_string);
2281 TALLOC_FREE(upper_string);
2282 break;
2284 case P_LIST:
2285 TALLOC_FREE(*((char ***)dest_ptr));
2286 *((char ***)dest_ptr) = str_list_copy(NULL,
2287 *(const char ***)src_ptr);
2288 break;
2289 default:
2290 break;
2294 if (bcopyall) {
2295 init_copymap(pserviceDest);
2296 if (pserviceSource->copymap)
2297 bitmap_copy(pserviceDest->copymap,
2298 pserviceSource->copymap);
2301 data = pserviceSource->param_opt;
2302 while (data) {
2303 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2304 data = data->next;
2308 /***************************************************************************
2309 Check a service for consistency. Return false if the service is in any way
2310 incomplete or faulty, else true.
2311 ***************************************************************************/
2313 bool service_ok(int iService)
2315 bool bRetval;
2317 bRetval = true;
2318 if (ServicePtrs[iService]->szService[0] == '\0') {
2319 DEBUG(0, ("The following message indicates an internal error:\n"));
2320 DEBUG(0, ("No service name in service entry.\n"));
2321 bRetval = false;
2324 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2325 /* I can't see why you'd want a non-printable printer service... */
2326 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2327 if (!ServicePtrs[iService]->bPrint_ok) {
2328 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2329 ServicePtrs[iService]->szService));
2330 ServicePtrs[iService]->bPrint_ok = true;
2332 /* [printers] service must also be non-browsable. */
2333 if (ServicePtrs[iService]->bBrowseable)
2334 ServicePtrs[iService]->bBrowseable = false;
2337 if (ServicePtrs[iService]->szPath[0] == '\0' &&
2338 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2339 ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2341 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2342 ServicePtrs[iService]->szService));
2343 ServicePtrs[iService]->bAvailable = false;
2346 /* If a service is flagged unavailable, log the fact at level 1. */
2347 if (!ServicePtrs[iService]->bAvailable)
2348 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2349 ServicePtrs[iService]->szService));
2351 return (bRetval);
2354 static struct smbconf_ctx *lp_smbconf_ctx(void)
2356 sbcErr err;
2357 static struct smbconf_ctx *conf_ctx = NULL;
2359 if (conf_ctx == NULL) {
2360 err = smbconf_init(NULL, &conf_ctx, "registry:");
2361 if (!SBC_ERROR_IS_OK(err)) {
2362 DEBUG(1, ("error initializing registry configuration: "
2363 "%s\n", sbcErrorString(err)));
2364 conf_ctx = NULL;
2368 return conf_ctx;
2371 static bool process_smbconf_service(struct smbconf_service *service)
2373 uint32_t count;
2374 bool ret;
2376 if (service == NULL) {
2377 return false;
2380 ret = do_section(service->name, NULL);
2381 if (ret != true) {
2382 return false;
2384 for (count = 0; count < service->num_params; count++) {
2385 ret = do_parameter(service->param_names[count],
2386 service->param_values[count],
2387 NULL);
2388 if (ret != true) {
2389 return false;
2392 if (iServiceIndex >= 0) {
2393 return service_ok(iServiceIndex);
2395 return true;
2399 * load a service from registry and activate it
2401 bool process_registry_service(const char *service_name)
2403 sbcErr err;
2404 struct smbconf_service *service = NULL;
2405 TALLOC_CTX *mem_ctx = talloc_stackframe();
2406 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2407 bool ret = false;
2409 if (conf_ctx == NULL) {
2410 goto done;
2413 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2415 if (!smbconf_share_exists(conf_ctx, service_name)) {
2417 * Registry does not contain data for this service (yet),
2418 * but make sure lp_load doesn't return false.
2420 ret = true;
2421 goto done;
2424 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2425 if (!SBC_ERROR_IS_OK(err)) {
2426 goto done;
2429 ret = process_smbconf_service(service);
2430 if (!ret) {
2431 goto done;
2434 /* store the csn */
2435 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2437 done:
2438 TALLOC_FREE(mem_ctx);
2439 return ret;
2443 * process_registry_globals
2445 static bool process_registry_globals(void)
2447 bool ret;
2449 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2451 ret = do_parameter("registry shares", "yes", NULL);
2452 if (!ret) {
2453 return ret;
2456 return process_registry_service(GLOBAL_NAME);
2459 bool process_registry_shares(void)
2461 sbcErr err;
2462 uint32_t count;
2463 struct smbconf_service **service = NULL;
2464 uint32_t num_shares = 0;
2465 TALLOC_CTX *mem_ctx = talloc_stackframe();
2466 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2467 bool ret = false;
2469 if (conf_ctx == NULL) {
2470 goto done;
2473 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2474 if (!SBC_ERROR_IS_OK(err)) {
2475 goto done;
2478 ret = true;
2480 for (count = 0; count < num_shares; count++) {
2481 if (strequal(service[count]->name, GLOBAL_NAME)) {
2482 continue;
2484 ret = process_smbconf_service(service[count]);
2485 if (!ret) {
2486 goto done;
2490 /* store the csn */
2491 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2493 done:
2494 TALLOC_FREE(mem_ctx);
2495 return ret;
2499 * reload those shares from registry that are already
2500 * activated in the services array.
2502 static bool reload_registry_shares(void)
2504 int i;
2505 bool ret = true;
2507 for (i = 0; i < iNumServices; i++) {
2508 if (!VALID(i)) {
2509 continue;
2512 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2513 continue;
2516 ret = process_registry_service(ServicePtrs[i]->szService);
2517 if (!ret) {
2518 goto done;
2522 done:
2523 return ret;
2527 #define MAX_INCLUDE_DEPTH 100
2529 static uint8_t include_depth;
2531 static struct file_lists {
2532 struct file_lists *next;
2533 char *name;
2534 char *subfname;
2535 time_t modtime;
2536 } *file_lists = NULL;
2538 /*******************************************************************
2539 Keep a linked list of all config files so we know when one has changed
2540 it's date and needs to be reloaded.
2541 ********************************************************************/
2543 static void add_to_file_list(const char *fname, const char *subfname)
2545 struct file_lists *f = file_lists;
2547 while (f) {
2548 if (f->name && !strcmp(f->name, fname))
2549 break;
2550 f = f->next;
2553 if (!f) {
2554 f = SMB_MALLOC_P(struct file_lists);
2555 if (!f)
2556 return;
2557 f->next = file_lists;
2558 f->name = SMB_STRDUP(fname);
2559 if (!f->name) {
2560 SAFE_FREE(f);
2561 return;
2563 f->subfname = SMB_STRDUP(subfname);
2564 if (!f->subfname) {
2565 SAFE_FREE(f->name);
2566 SAFE_FREE(f);
2567 return;
2569 file_lists = f;
2570 f->modtime = file_modtime(subfname);
2571 } else {
2572 time_t t = file_modtime(subfname);
2573 if (t)
2574 f->modtime = t;
2576 return;
2580 * Free the file lists
2582 static void free_file_list(void)
2584 struct file_lists *f;
2585 struct file_lists *next;
2587 f = file_lists;
2588 while( f ) {
2589 next = f->next;
2590 SAFE_FREE( f->name );
2591 SAFE_FREE( f->subfname );
2592 SAFE_FREE( f );
2593 f = next;
2595 file_lists = NULL;
2600 * Utility function for outsiders to check if we're running on registry.
2602 bool lp_config_backend_is_registry(void)
2604 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2608 * Utility function to check if the config backend is FILE.
2610 bool lp_config_backend_is_file(void)
2612 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2615 /*******************************************************************
2616 Check if a config file has changed date.
2617 ********************************************************************/
2619 bool lp_file_list_changed(void)
2621 struct file_lists *f = file_lists;
2623 DEBUG(6, ("lp_file_list_changed()\n"));
2625 while (f) {
2626 time_t mod_time;
2628 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2629 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2631 if (conf_ctx == NULL) {
2632 return false;
2634 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2635 NULL))
2637 DEBUGADD(6, ("registry config changed\n"));
2638 return true;
2640 } else {
2641 char *n2 = NULL;
2642 n2 = talloc_sub_basic(talloc_tos(),
2643 get_current_username(),
2644 current_user_info.domain,
2645 f->name);
2646 if (!n2) {
2647 return false;
2649 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2650 f->name, n2, ctime(&f->modtime)));
2652 mod_time = file_modtime(n2);
2654 if (mod_time &&
2655 ((f->modtime != mod_time) ||
2656 (f->subfname == NULL) ||
2657 (strcmp(n2, f->subfname) != 0)))
2659 DEBUGADD(6,
2660 ("file %s modified: %s\n", n2,
2661 ctime(&mod_time)));
2662 f->modtime = mod_time;
2663 SAFE_FREE(f->subfname);
2664 f->subfname = SMB_STRDUP(n2);
2665 TALLOC_FREE(n2);
2666 return true;
2668 TALLOC_FREE(n2);
2670 f = f->next;
2672 return false;
2677 * Initialize iconv conversion descriptors.
2679 * This is called the first time it is needed, and also called again
2680 * every time the configuration is reloaded, because the charset or
2681 * codepage might have changed.
2683 static void init_iconv(void)
2685 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2686 lp_unix_charset(),
2687 true, global_iconv_handle);
2690 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2692 if (strcmp(*ptr, pszParmValue) != 0) {
2693 string_set(ptr, pszParmValue);
2694 init_iconv();
2696 return true;
2699 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2701 bool is_utf8 = false;
2702 size_t len = strlen(pszParmValue);
2704 if (len == 4 || len == 5) {
2705 /* Don't use StrCaseCmp here as we don't want to
2706 initialize iconv. */
2707 if ((toupper_m(pszParmValue[0]) == 'U') &&
2708 (toupper_m(pszParmValue[1]) == 'T') &&
2709 (toupper_m(pszParmValue[2]) == 'F')) {
2710 if (len == 4) {
2711 if (pszParmValue[3] == '8') {
2712 is_utf8 = true;
2714 } else {
2715 if (pszParmValue[3] == '-' &&
2716 pszParmValue[4] == '8') {
2717 is_utf8 = true;
2723 if (strcmp(*ptr, pszParmValue) != 0) {
2724 if (is_utf8) {
2725 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2726 "be UTF8, using (default value) %s instead.\n",
2727 DEFAULT_DOS_CHARSET));
2728 pszParmValue = DEFAULT_DOS_CHARSET;
2730 string_set(ptr, pszParmValue);
2731 init_iconv();
2733 return true;
2736 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2738 bool ret = true;
2739 char *realm = strupper_talloc(talloc_tos(), pszParmValue);
2740 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2742 ret &= string_set(&Globals.szRealm, pszParmValue);
2743 ret &= string_set(&Globals.szRealm_upper, realm);
2744 ret &= string_set(&Globals.szRealm_lower, dnsdomain);
2745 TALLOC_FREE(realm);
2747 return ret;
2750 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2752 TALLOC_FREE(Globals.szNetbiosAliases);
2753 Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2754 return set_netbios_aliases(Globals.szNetbiosAliases);
2757 /***************************************************************************
2758 Handle the include operation.
2759 ***************************************************************************/
2760 static bool bAllowIncludeRegistry = true;
2762 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2764 char *fname;
2766 if (include_depth >= MAX_INCLUDE_DEPTH) {
2767 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2768 include_depth));
2769 return false;
2772 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2773 if (!bAllowIncludeRegistry) {
2774 return true;
2776 if (bInGlobalSection) {
2777 bool ret;
2778 include_depth++;
2779 ret = process_registry_globals();
2780 include_depth--;
2781 return ret;
2782 } else {
2783 DEBUG(1, ("\"include = registry\" only effective "
2784 "in %s section\n", GLOBAL_NAME));
2785 return false;
2789 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2790 current_user_info.domain,
2791 pszParmValue);
2793 add_to_file_list(pszParmValue, fname);
2795 string_set(ptr, fname);
2797 if (file_exist(fname)) {
2798 bool ret;
2799 include_depth++;
2800 ret = pm_process(fname, do_section, do_parameter, NULL);
2801 include_depth--;
2802 TALLOC_FREE(fname);
2803 return ret;
2806 DEBUG(2, ("Can't find include file %s\n", fname));
2807 TALLOC_FREE(fname);
2808 return true;
2811 /***************************************************************************
2812 Handle the interpretation of the copy parameter.
2813 ***************************************************************************/
2815 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2817 bool bRetval;
2818 int iTemp;
2819 struct loadparm_service serviceTemp;
2821 string_set(ptr, pszParmValue);
2823 init_service(&serviceTemp);
2825 bRetval = false;
2827 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2829 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2830 if (iTemp == iServiceIndex) {
2831 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2832 } else {
2833 copy_service(ServicePtrs[iServiceIndex],
2834 &serviceTemp,
2835 ServicePtrs[iServiceIndex]->copymap);
2836 bRetval = true;
2838 } else {
2839 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2840 bRetval = false;
2843 free_service(&serviceTemp);
2844 return (bRetval);
2847 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2849 Globals.ldap_debug_level = lp_int(pszParmValue);
2850 init_ldap_debugging();
2851 return true;
2854 /***************************************************************************
2855 Handle idmap/non unix account uid and gid allocation parameters. The format of these
2856 parameters is:
2858 [global]
2860 idmap uid = 1000-1999
2861 idmap gid = 700-899
2863 We only do simple parsing checks here. The strings are parsed into useful
2864 structures in the idmap daemon code.
2866 ***************************************************************************/
2868 /* Some lp_ routines to return idmap [ug]id information */
2870 static uid_t idmap_uid_low, idmap_uid_high;
2871 static gid_t idmap_gid_low, idmap_gid_high;
2873 bool lp_idmap_uid(uid_t *low, uid_t *high)
2875 if (idmap_uid_low == 0 || idmap_uid_high == 0)
2876 return false;
2878 if (low)
2879 *low = idmap_uid_low;
2881 if (high)
2882 *high = idmap_uid_high;
2884 return true;
2887 bool lp_idmap_gid(gid_t *low, gid_t *high)
2889 if (idmap_gid_low == 0 || idmap_gid_high == 0)
2890 return false;
2892 if (low)
2893 *low = idmap_gid_low;
2895 if (high)
2896 *high = idmap_gid_high;
2898 return true;
2901 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2903 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2905 return true;
2908 /* Do some simple checks on "idmap [ug]id" parameter values */
2910 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2912 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2914 return true;
2917 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2919 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2921 return true;
2924 /***************************************************************************
2925 Handle the DEBUG level list.
2926 ***************************************************************************/
2928 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2930 string_set(ptr, pszParmValueIn);
2931 return debug_parse_levels(pszParmValueIn);
2934 /***************************************************************************
2935 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2936 ***************************************************************************/
2938 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2940 const char *suffix_string;
2942 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2943 Globals.szLdapSuffix );
2944 if ( !suffix_string ) {
2945 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2946 return "";
2949 return suffix_string;
2952 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2954 if (Globals.szLdapMachineSuffix[0])
2955 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
2957 return lp_string(ctx, Globals.szLdapSuffix);
2960 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
2962 if (Globals.szLdapUserSuffix[0])
2963 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
2965 return lp_string(ctx, Globals.szLdapSuffix);
2968 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
2970 if (Globals.szLdapGroupSuffix[0])
2971 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
2973 return lp_string(ctx, Globals.szLdapSuffix);
2976 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
2978 if (Globals.szLdapIdmapSuffix[0])
2979 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
2981 return lp_string(ctx, Globals.szLdapSuffix);
2984 /****************************************************************************
2985 set the value for a P_ENUM
2986 ***************************************************************************/
2988 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
2989 int *ptr )
2991 int i;
2993 for (i = 0; parm->enum_list[i].name; i++) {
2994 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
2995 *ptr = parm->enum_list[i].value;
2996 return;
2999 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3000 pszParmValue, parm->label));
3003 /***************************************************************************
3004 ***************************************************************************/
3006 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3008 static int parm_num = -1;
3009 struct loadparm_service *s;
3011 if ( parm_num == -1 )
3012 parm_num = map_parameter( "printing" );
3014 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3016 if ( snum < 0 )
3017 s = &sDefault;
3018 else
3019 s = ServicePtrs[snum];
3021 init_printer_values( s );
3023 return true;
3027 /***************************************************************************
3028 Initialise a copymap.
3029 ***************************************************************************/
3031 static void init_copymap(struct loadparm_service *pservice)
3033 int i;
3035 TALLOC_FREE(pservice->copymap);
3037 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3038 if (!pservice->copymap)
3039 DEBUG(0,
3040 ("Couldn't allocate copymap!! (size %d)\n",
3041 (int)NUMPARAMETERS));
3042 else
3043 for (i = 0; i < NUMPARAMETERS; i++)
3044 bitmap_set(pservice->copymap, i);
3048 return the parameter pointer for a parameter
3050 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3052 if (service == NULL) {
3053 if (parm->p_class == P_LOCAL)
3054 return (void *)(((char *)&sDefault)+parm->offset);
3055 else if (parm->p_class == P_GLOBAL)
3056 return (void *)(((char *)&Globals)+parm->offset);
3057 else return NULL;
3058 } else {
3059 return (void *)(((char *)service) + parm->offset);
3063 /***************************************************************************
3064 Return the local pointer to a parameter given the service number and parameter
3065 ***************************************************************************/
3067 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3069 return lp_parm_ptr(ServicePtrs[snum], parm);
3072 /***************************************************************************
3073 Process a parameter for a particular service number. If snum < 0
3074 then assume we are in the globals.
3075 ***************************************************************************/
3077 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3079 int parmnum, i;
3080 void *parm_ptr = NULL; /* where we are going to store the result */
3081 struct parmlist_entry **opt_list;
3083 parmnum = map_parameter(pszParmName);
3085 if (parmnum < 0) {
3086 if (strchr(pszParmName, ':') == NULL) {
3087 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3088 pszParmName));
3089 return true;
3093 * We've got a parametric option
3096 opt_list = (snum < 0)
3097 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3098 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3100 return true;
3103 /* if it's already been set by the command line, then we don't
3104 override here */
3105 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3106 return true;
3109 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3110 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3111 pszParmName));
3114 /* we might point at a service, the default service or a global */
3115 if (snum < 0) {
3116 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3117 } else {
3118 if (parm_table[parmnum].p_class == P_GLOBAL) {
3119 DEBUG(0,
3120 ("Global parameter %s found in service section!\n",
3121 pszParmName));
3122 return true;
3124 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3127 if (snum >= 0) {
3128 if (!ServicePtrs[snum]->copymap)
3129 init_copymap(ServicePtrs[snum]);
3131 /* this handles the aliases - set the copymap for other entries with
3132 the same data pointer */
3133 for (i = 0; parm_table[i].label; i++) {
3134 if ((parm_table[i].offset == parm_table[parmnum].offset)
3135 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3136 bitmap_clear(ServicePtrs[snum]->copymap, i);
3141 /* if it is a special case then go ahead */
3142 if (parm_table[parmnum].special) {
3143 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3144 (char **)parm_ptr);
3147 /* now switch on the type of variable it is */
3148 switch (parm_table[parmnum].type)
3150 case P_BOOL:
3151 *(bool *)parm_ptr = lp_bool(pszParmValue);
3152 break;
3154 case P_BOOLREV:
3155 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3156 break;
3158 case P_INTEGER:
3159 *(int *)parm_ptr = lp_int(pszParmValue);
3160 break;
3162 case P_CHAR:
3163 *(char *)parm_ptr = *pszParmValue;
3164 break;
3166 case P_OCTAL:
3167 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3168 if ( i != 1 ) {
3169 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3171 break;
3173 case P_BYTES:
3175 uint64_t val;
3176 if (conv_str_size_error(pszParmValue, &val)) {
3177 if (val <= INT_MAX) {
3178 *(int *)parm_ptr = (int)val;
3179 break;
3183 DEBUG(0,("lp_do_parameter(%s): value is not "
3184 "a valid size specifier!\n", pszParmValue));
3185 return false;
3188 case P_LIST:
3189 case P_CMDLIST:
3190 TALLOC_FREE(*((char ***)parm_ptr));
3191 *(char ***)parm_ptr = str_list_make_v3(
3192 NULL, pszParmValue, NULL);
3193 break;
3195 case P_STRING:
3196 string_set((char **)parm_ptr, pszParmValue);
3197 break;
3199 case P_USTRING:
3201 char *upper_string = strupper_talloc(talloc_tos(),
3202 pszParmValue);
3203 string_set((char **)parm_ptr, upper_string);
3204 TALLOC_FREE(upper_string);
3205 break;
3207 case P_ENUM:
3208 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3209 break;
3210 case P_SEP:
3211 break;
3214 return true;
3217 /***************************************************************************
3218 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3219 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3220 ***************************************************************************/
3222 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3224 int parmnum, i;
3225 parmnum = map_parameter(pszParmName);
3226 if (parmnum >= 0) {
3227 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3228 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3229 return false;
3231 parm_table[parmnum].flags |= FLAG_CMDLINE;
3233 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3234 * be grouped in the table, so we don't have to search the
3235 * whole table */
3236 for (i=parmnum-1;
3237 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3238 && parm_table[i].p_class == parm_table[parmnum].p_class;
3239 i--) {
3240 parm_table[i].flags |= FLAG_CMDLINE;
3242 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3243 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3244 parm_table[i].flags |= FLAG_CMDLINE;
3247 if (store_values) {
3248 store_lp_set_cmdline(pszParmName, pszParmValue);
3250 return true;
3253 /* it might be parametric */
3254 if (strchr(pszParmName, ':') != NULL) {
3255 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3256 if (store_values) {
3257 store_lp_set_cmdline(pszParmName, pszParmValue);
3259 return true;
3262 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3263 return true;
3266 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3268 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3271 /***************************************************************************
3272 Process a parameter.
3273 ***************************************************************************/
3275 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3276 void *userdata)
3278 if (!bInGlobalSection && bGlobalOnly)
3279 return true;
3281 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3283 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3284 pszParmName, pszParmValue));
3288 set a option from the commandline in 'a=b' format. Use to support --option
3290 bool lp_set_option(const char *option)
3292 char *p, *s;
3293 bool ret;
3295 s = talloc_strdup(NULL, option);
3296 if (!s) {
3297 return false;
3300 p = strchr(s, '=');
3301 if (!p) {
3302 talloc_free(s);
3303 return false;
3306 *p = 0;
3308 /* skip white spaces after the = sign */
3309 do {
3310 p++;
3311 } while (*p == ' ');
3313 ret = lp_set_cmdline(s, p);
3314 talloc_free(s);
3315 return ret;
3318 /**************************************************************************
3319 Print a parameter of the specified type.
3320 ***************************************************************************/
3322 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3324 /* For the seperation of lists values that we print below */
3325 const char *list_sep = ", ";
3326 int i;
3327 switch (p->type)
3329 case P_ENUM:
3330 for (i = 0; p->enum_list[i].name; i++) {
3331 if (*(int *)ptr == p->enum_list[i].value) {
3332 fprintf(f, "%s",
3333 p->enum_list[i].name);
3334 break;
3337 break;
3339 case P_BOOL:
3340 fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3341 break;
3343 case P_BOOLREV:
3344 fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3345 break;
3347 case P_INTEGER:
3348 case P_BYTES:
3349 fprintf(f, "%d", *(int *)ptr);
3350 break;
3352 case P_CHAR:
3353 fprintf(f, "%c", *(char *)ptr);
3354 break;
3356 case P_OCTAL: {
3357 int val = *(int *)ptr;
3358 if (val == -1) {
3359 fprintf(f, "-1");
3360 } else {
3361 fprintf(f, "0%o", val);
3363 break;
3366 case P_CMDLIST:
3367 list_sep = " ";
3368 /* fall through */
3369 case P_LIST:
3370 if ((char ***)ptr && *(char ***)ptr) {
3371 char **list = *(char ***)ptr;
3372 for (; *list; list++) {
3373 /* surround strings with whitespace in double quotes */
3374 if (*(list+1) == NULL) {
3375 /* last item, no extra separator */
3376 list_sep = "";
3378 if ( strchr_m( *list, ' ' ) ) {
3379 fprintf(f, "\"%s\"%s", *list, list_sep);
3380 } else {
3381 fprintf(f, "%s%s", *list, list_sep);
3385 break;
3387 case P_STRING:
3388 case P_USTRING:
3389 if (*(char **)ptr) {
3390 fprintf(f, "%s", *(char **)ptr);
3392 break;
3393 case P_SEP:
3394 break;
3398 /***************************************************************************
3399 Check if two parameters are equal.
3400 ***************************************************************************/
3402 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3404 switch (type) {
3405 case P_BOOL:
3406 case P_BOOLREV:
3407 return (*((bool *)ptr1) == *((bool *)ptr2));
3409 case P_INTEGER:
3410 case P_ENUM:
3411 case P_OCTAL:
3412 case P_BYTES:
3413 return (*((int *)ptr1) == *((int *)ptr2));
3415 case P_CHAR:
3416 return (*((char *)ptr1) == *((char *)ptr2));
3418 case P_LIST:
3419 case P_CMDLIST:
3420 return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3422 case P_STRING:
3423 case P_USTRING:
3425 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3426 if (p1 && !*p1)
3427 p1 = NULL;
3428 if (p2 && !*p2)
3429 p2 = NULL;
3430 return (p1 == p2 || strequal(p1, p2));
3432 case P_SEP:
3433 break;
3435 return false;
3438 /***************************************************************************
3439 Initialize any local varients in the sDefault table.
3440 ***************************************************************************/
3442 void init_locals(void)
3444 /* None as yet. */
3447 /***************************************************************************
3448 Process a new section (service). At this stage all sections are services.
3449 Later we'll have special sections that permit server parameters to be set.
3450 Returns true on success, false on failure.
3451 ***************************************************************************/
3453 static bool do_section(const char *pszSectionName, void *userdata)
3455 bool bRetval;
3456 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3457 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3458 bRetval = false;
3460 /* if we were in a global section then do the local inits */
3461 if (bInGlobalSection && !isglobal)
3462 init_locals();
3464 /* if we've just struck a global section, note the fact. */
3465 bInGlobalSection = isglobal;
3467 /* check for multiple global sections */
3468 if (bInGlobalSection) {
3469 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3470 return true;
3473 if (!bInGlobalSection && bGlobalOnly)
3474 return true;
3476 /* if we have a current service, tidy it up before moving on */
3477 bRetval = true;
3479 if (iServiceIndex >= 0)
3480 bRetval = service_ok(iServiceIndex);
3482 /* if all is still well, move to the next record in the services array */
3483 if (bRetval) {
3484 /* We put this here to avoid an odd message order if messages are */
3485 /* issued by the post-processing of a previous section. */
3486 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3488 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3489 if (iServiceIndex < 0) {
3490 DEBUG(0, ("Failed to add a new service\n"));
3491 return false;
3493 /* Clean all parametric options for service */
3494 /* They will be added during parsing again */
3495 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3498 return bRetval;
3502 /***************************************************************************
3503 Determine if a partcular base parameter is currentl set to the default value.
3504 ***************************************************************************/
3506 static bool is_default(int i)
3508 if (!defaults_saved)
3509 return false;
3510 switch (parm_table[i].type) {
3511 case P_LIST:
3512 case P_CMDLIST:
3513 return str_list_equal((const char **)parm_table[i].def.lvalue,
3514 *(const char ***)lp_parm_ptr(NULL,
3515 &parm_table[i]));
3516 case P_STRING:
3517 case P_USTRING:
3518 return strequal(parm_table[i].def.svalue,
3519 *(char **)lp_parm_ptr(NULL,
3520 &parm_table[i]));
3521 case P_BOOL:
3522 case P_BOOLREV:
3523 return parm_table[i].def.bvalue ==
3524 *(bool *)lp_parm_ptr(NULL,
3525 &parm_table[i]);
3526 case P_CHAR:
3527 return parm_table[i].def.cvalue ==
3528 *(char *)lp_parm_ptr(NULL,
3529 &parm_table[i]);
3530 case P_INTEGER:
3531 case P_OCTAL:
3532 case P_ENUM:
3533 case P_BYTES:
3534 return parm_table[i].def.ivalue ==
3535 *(int *)lp_parm_ptr(NULL,
3536 &parm_table[i]);
3537 case P_SEP:
3538 break;
3540 return false;
3543 /***************************************************************************
3544 Display the contents of the global structure.
3545 ***************************************************************************/
3547 static void dump_globals(FILE *f)
3549 int i;
3550 struct parmlist_entry *data;
3552 fprintf(f, "[global]\n");
3554 for (i = 0; parm_table[i].label; i++)
3555 if (parm_table[i].p_class == P_GLOBAL &&
3556 !(parm_table[i].flags & FLAG_META) &&
3557 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3558 if (defaults_saved && is_default(i))
3559 continue;
3560 fprintf(f, "\t%s = ", parm_table[i].label);
3561 print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3562 &parm_table[i]),
3564 fprintf(f, "\n");
3566 if (Globals.param_opt != NULL) {
3567 data = Globals.param_opt;
3568 while(data) {
3569 fprintf(f, "\t%s = %s\n", data->key, data->value);
3570 data = data->next;
3576 /***************************************************************************
3577 Return true if a local parameter is currently set to the global default.
3578 ***************************************************************************/
3580 bool lp_is_default(int snum, struct parm_struct *parm)
3582 return equal_parameter(parm->type,
3583 lp_parm_ptr(ServicePtrs[snum], parm),
3584 lp_parm_ptr(NULL, parm));
3587 /***************************************************************************
3588 Display the contents of a single services record.
3589 ***************************************************************************/
3591 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3593 int i;
3594 struct parmlist_entry *data;
3596 if (pService != &sDefault)
3597 fprintf(f, "[%s]\n", pService->szService);
3599 for (i = 0; parm_table[i].label; i++) {
3601 if (parm_table[i].p_class == P_LOCAL &&
3602 !(parm_table[i].flags & FLAG_META) &&
3603 (*parm_table[i].label != '-') &&
3604 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3606 if (pService == &sDefault) {
3607 if (defaults_saved && is_default(i))
3608 continue;
3609 } else {
3610 if (equal_parameter(parm_table[i].type,
3611 lp_parm_ptr(pService, &parm_table[i]),
3612 lp_parm_ptr(NULL, &parm_table[i])))
3613 continue;
3616 fprintf(f, "\t%s = ", parm_table[i].label);
3617 print_parameter(&parm_table[i],
3618 lp_parm_ptr(pService, &parm_table[i]),
3620 fprintf(f, "\n");
3624 if (pService->param_opt != NULL) {
3625 data = pService->param_opt;
3626 while(data) {
3627 fprintf(f, "\t%s = %s\n", data->key, data->value);
3628 data = data->next;
3633 /***************************************************************************
3634 Display the contents of a parameter of a single services record.
3635 ***************************************************************************/
3637 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3639 int i;
3640 bool result = false;
3641 parm_class p_class;
3642 unsigned flag = 0;
3643 fstring local_parm_name;
3644 char *parm_opt;
3645 const char *parm_opt_value;
3647 /* check for parametrical option */
3648 fstrcpy( local_parm_name, parm_name);
3649 parm_opt = strchr( local_parm_name, ':');
3651 if (parm_opt) {
3652 *parm_opt = '\0';
3653 parm_opt++;
3654 if (strlen(parm_opt)) {
3655 parm_opt_value = lp_parm_const_string( snum,
3656 local_parm_name, parm_opt, NULL);
3657 if (parm_opt_value) {
3658 printf( "%s\n", parm_opt_value);
3659 result = true;
3662 return result;
3665 /* check for a key and print the value */
3666 if (isGlobal) {
3667 p_class = P_GLOBAL;
3668 flag = FLAG_GLOBAL;
3669 } else
3670 p_class = P_LOCAL;
3672 for (i = 0; parm_table[i].label; i++) {
3673 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3674 !(parm_table[i].flags & FLAG_META) &&
3675 (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3676 (*parm_table[i].label != '-') &&
3677 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3679 void *ptr;
3681 if (isGlobal) {
3682 ptr = lp_parm_ptr(NULL,
3683 &parm_table[i]);
3684 } else {
3685 ptr = lp_parm_ptr(ServicePtrs[snum],
3686 &parm_table[i]);
3689 print_parameter(&parm_table[i],
3690 ptr, f);
3691 fprintf(f, "\n");
3692 result = true;
3693 break;
3697 return result;
3700 /***************************************************************************
3701 Return info about the requested parameter (given as a string).
3702 Return NULL when the string is not a valid parameter name.
3703 ***************************************************************************/
3705 struct parm_struct *lp_get_parameter(const char *param_name)
3707 int num = map_parameter(param_name);
3709 if (num < 0) {
3710 return NULL;
3713 return &parm_table[num];
3716 /***************************************************************************
3717 Return info about the next parameter in a service.
3718 snum==GLOBAL_SECTION_SNUM gives the globals.
3719 Return NULL when out of parameters.
3720 ***************************************************************************/
3722 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3724 if (snum < 0) {
3725 /* do the globals */
3726 for (; parm_table[*i].label; (*i)++) {
3727 if (parm_table[*i].p_class == P_SEPARATOR)
3728 return &parm_table[(*i)++];
3730 if ((*parm_table[*i].label == '-'))
3731 continue;
3733 if ((*i) > 0
3734 && (parm_table[*i].offset ==
3735 parm_table[(*i) - 1].offset)
3736 && (parm_table[*i].p_class ==
3737 parm_table[(*i) - 1].p_class))
3738 continue;
3740 if (is_default(*i) && !allparameters)
3741 continue;
3743 return &parm_table[(*i)++];
3745 } else {
3746 struct loadparm_service *pService = ServicePtrs[snum];
3748 for (; parm_table[*i].label; (*i)++) {
3749 if (parm_table[*i].p_class == P_SEPARATOR)
3750 return &parm_table[(*i)++];
3752 if (parm_table[*i].p_class == P_LOCAL &&
3753 (*parm_table[*i].label != '-') &&
3754 ((*i) == 0 ||
3755 (parm_table[*i].offset !=
3756 parm_table[(*i) - 1].offset)))
3758 if (allparameters ||
3759 !equal_parameter(parm_table[*i].type,
3760 lp_parm_ptr(pService,
3761 &parm_table[*i]),
3762 lp_parm_ptr(NULL,
3763 &parm_table[*i])))
3765 return &parm_table[(*i)++];
3771 return NULL;
3775 #if 0
3776 /***************************************************************************
3777 Display the contents of a single copy structure.
3778 ***************************************************************************/
3779 static void dump_copy_map(bool *pcopymap)
3781 int i;
3782 if (!pcopymap)
3783 return;
3785 printf("\n\tNon-Copied parameters:\n");
3787 for (i = 0; parm_table[i].label; i++)
3788 if (parm_table[i].p_class == P_LOCAL &&
3789 parm_table[i].ptr && !pcopymap[i] &&
3790 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3792 printf("\t\t%s\n", parm_table[i].label);
3795 #endif
3797 /***************************************************************************
3798 Return TRUE if the passed service number is within range.
3799 ***************************************************************************/
3801 bool lp_snum_ok(int iService)
3803 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3806 /***************************************************************************
3807 Auto-load some home services.
3808 ***************************************************************************/
3810 static void lp_add_auto_services(char *str)
3812 char *s;
3813 char *p;
3814 int homes;
3815 char *saveptr;
3817 if (!str)
3818 return;
3820 s = SMB_STRDUP(str);
3821 if (!s)
3822 return;
3824 homes = lp_servicenumber(HOMES_NAME);
3826 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3827 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3828 char *home;
3830 if (lp_servicenumber(p) >= 0)
3831 continue;
3833 home = get_user_home_dir(talloc_tos(), p);
3835 if (home && home[0] && homes >= 0)
3836 lp_add_home(p, homes, p, home);
3838 TALLOC_FREE(home);
3840 SAFE_FREE(s);
3843 /***************************************************************************
3844 Auto-load one printer.
3845 ***************************************************************************/
3847 void lp_add_one_printer(const char *name, const char *comment,
3848 const char *location, void *pdata)
3850 int printers = lp_servicenumber(PRINTERS_NAME);
3851 int i;
3853 if (lp_servicenumber(name) < 0) {
3854 lp_add_printer(name, printers);
3855 if ((i = lp_servicenumber(name)) >= 0) {
3856 string_set(&ServicePtrs[i]->comment, comment);
3857 ServicePtrs[i]->autoloaded = true;
3862 /***************************************************************************
3863 Have we loaded a services file yet?
3864 ***************************************************************************/
3866 bool lp_loaded(void)
3868 return (bLoaded);
3871 /***************************************************************************
3872 Unload unused services.
3873 ***************************************************************************/
3875 void lp_killunused(struct smbd_server_connection *sconn,
3876 bool (*snumused) (struct smbd_server_connection *, int))
3878 int i;
3879 for (i = 0; i < iNumServices; i++) {
3880 if (!VALID(i))
3881 continue;
3883 /* don't kill autoloaded or usershare services */
3884 if ( ServicePtrs[i]->autoloaded ||
3885 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3886 continue;
3889 if (!snumused || !snumused(sconn, i)) {
3890 free_service_byindex(i);
3896 * Kill all except autoloaded and usershare services - convenience wrapper
3898 void lp_kill_all_services(void)
3900 lp_killunused(NULL, NULL);
3903 /***************************************************************************
3904 Unload a service.
3905 ***************************************************************************/
3907 void lp_killservice(int iServiceIn)
3909 if (VALID(iServiceIn)) {
3910 free_service_byindex(iServiceIn);
3914 /***************************************************************************
3915 Save the curent values of all global and sDefault parameters into the
3916 defaults union. This allows swat and testparm to show only the
3917 changed (ie. non-default) parameters.
3918 ***************************************************************************/
3920 static void lp_save_defaults(void)
3922 int i;
3923 for (i = 0; parm_table[i].label; i++) {
3924 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3925 && parm_table[i].p_class == parm_table[i - 1].p_class)
3926 continue;
3927 switch (parm_table[i].type) {
3928 case P_LIST:
3929 case P_CMDLIST:
3930 parm_table[i].def.lvalue = str_list_copy(
3931 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3932 break;
3933 case P_STRING:
3934 case P_USTRING:
3935 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3936 break;
3937 case P_BOOL:
3938 case P_BOOLREV:
3939 parm_table[i].def.bvalue =
3940 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3941 break;
3942 case P_CHAR:
3943 parm_table[i].def.cvalue =
3944 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3945 break;
3946 case P_INTEGER:
3947 case P_OCTAL:
3948 case P_ENUM:
3949 case P_BYTES:
3950 parm_table[i].def.ivalue =
3951 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3952 break;
3953 case P_SEP:
3954 break;
3957 defaults_saved = true;
3960 /***********************************************************
3961 If we should send plaintext/LANMAN passwords in the clinet
3962 ************************************************************/
3964 static void set_allowed_client_auth(void)
3966 if (Globals.bClientNTLMv2Auth) {
3967 Globals.bClientLanManAuth = false;
3969 if (!Globals.bClientLanManAuth) {
3970 Globals.bClientPlaintextAuth = false;
3974 /***************************************************************************
3975 JRA.
3976 The following code allows smbd to read a user defined share file.
3977 Yes, this is my intent. Yes, I'm comfortable with that...
3979 THE FOLLOWING IS SECURITY CRITICAL CODE.
3981 It washes your clothes, it cleans your house, it guards you while you sleep...
3982 Do not f%^k with it....
3983 ***************************************************************************/
3985 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3987 /***************************************************************************
3988 Check allowed stat state of a usershare file.
3989 Ensure we print out who is dicking with us so the admin can
3990 get their sorry ass fired.
3991 ***************************************************************************/
3993 static bool check_usershare_stat(const char *fname,
3994 const SMB_STRUCT_STAT *psbuf)
3996 if (!S_ISREG(psbuf->st_ex_mode)) {
3997 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3998 "not a regular file\n",
3999 fname, (unsigned int)psbuf->st_ex_uid ));
4000 return false;
4003 /* Ensure this doesn't have the other write bit set. */
4004 if (psbuf->st_ex_mode & S_IWOTH) {
4005 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4006 "public write. Refusing to allow as a usershare file.\n",
4007 fname, (unsigned int)psbuf->st_ex_uid ));
4008 return false;
4011 /* Should be 10k or less. */
4012 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4013 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4014 "too large (%u) to be a user share file.\n",
4015 fname, (unsigned int)psbuf->st_ex_uid,
4016 (unsigned int)psbuf->st_ex_size ));
4017 return false;
4020 return true;
4023 /***************************************************************************
4024 Parse the contents of a usershare file.
4025 ***************************************************************************/
4027 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4028 SMB_STRUCT_STAT *psbuf,
4029 const char *servicename,
4030 int snum,
4031 char **lines,
4032 int numlines,
4033 char **pp_sharepath,
4034 char **pp_comment,
4035 char **pp_cp_servicename,
4036 struct security_descriptor **ppsd,
4037 bool *pallow_guest)
4039 const char **prefixallowlist = lp_usershare_prefix_allow_list();
4040 const char **prefixdenylist = lp_usershare_prefix_deny_list();
4041 int us_vers;
4042 DIR *dp;
4043 SMB_STRUCT_STAT sbuf;
4044 char *sharepath = NULL;
4045 char *comment = NULL;
4047 *pp_sharepath = NULL;
4048 *pp_comment = NULL;
4050 *pallow_guest = false;
4052 if (numlines < 4) {
4053 return USERSHARE_MALFORMED_FILE;
4056 if (strcmp(lines[0], "#VERSION 1") == 0) {
4057 us_vers = 1;
4058 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4059 us_vers = 2;
4060 if (numlines < 5) {
4061 return USERSHARE_MALFORMED_FILE;
4063 } else {
4064 return USERSHARE_BAD_VERSION;
4067 if (strncmp(lines[1], "path=", 5) != 0) {
4068 return USERSHARE_MALFORMED_PATH;
4071 sharepath = talloc_strdup(ctx, &lines[1][5]);
4072 if (!sharepath) {
4073 return USERSHARE_POSIX_ERR;
4075 trim_string(sharepath, " ", " ");
4077 if (strncmp(lines[2], "comment=", 8) != 0) {
4078 return USERSHARE_MALFORMED_COMMENT_DEF;
4081 comment = talloc_strdup(ctx, &lines[2][8]);
4082 if (!comment) {
4083 return USERSHARE_POSIX_ERR;
4085 trim_string(comment, " ", " ");
4086 trim_char(comment, '"', '"');
4088 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4089 return USERSHARE_MALFORMED_ACL_DEF;
4092 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4093 return USERSHARE_ACL_ERR;
4096 if (us_vers == 2) {
4097 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4098 return USERSHARE_MALFORMED_ACL_DEF;
4100 if (lines[4][9] == 'y') {
4101 *pallow_guest = true;
4104 /* Backwards compatible extension to file version #2. */
4105 if (numlines > 5) {
4106 if (strncmp(lines[5], "sharename=", 10) != 0) {
4107 return USERSHARE_MALFORMED_SHARENAME_DEF;
4109 if (!strequal(&lines[5][10], servicename)) {
4110 return USERSHARE_BAD_SHARENAME;
4112 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4113 if (!*pp_cp_servicename) {
4114 return USERSHARE_POSIX_ERR;
4119 if (*pp_cp_servicename == NULL) {
4120 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4121 if (!*pp_cp_servicename) {
4122 return USERSHARE_POSIX_ERR;
4126 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4127 /* Path didn't change, no checks needed. */
4128 *pp_sharepath = sharepath;
4129 *pp_comment = comment;
4130 return USERSHARE_OK;
4133 /* The path *must* be absolute. */
4134 if (sharepath[0] != '/') {
4135 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4136 servicename, sharepath));
4137 return USERSHARE_PATH_NOT_ABSOLUTE;
4140 /* If there is a usershare prefix deny list ensure one of these paths
4141 doesn't match the start of the user given path. */
4142 if (prefixdenylist) {
4143 int i;
4144 for ( i=0; prefixdenylist[i]; i++ ) {
4145 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4146 servicename, i, prefixdenylist[i], sharepath ));
4147 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4148 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4149 "usershare prefix deny list entries.\n",
4150 servicename, sharepath));
4151 return USERSHARE_PATH_IS_DENIED;
4156 /* If there is a usershare prefix allow list ensure one of these paths
4157 does match the start of the user given path. */
4159 if (prefixallowlist) {
4160 int i;
4161 for ( i=0; prefixallowlist[i]; i++ ) {
4162 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4163 servicename, i, prefixallowlist[i], sharepath ));
4164 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4165 break;
4168 if (prefixallowlist[i] == NULL) {
4169 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4170 "usershare prefix allow list entries.\n",
4171 servicename, sharepath));
4172 return USERSHARE_PATH_NOT_ALLOWED;
4176 /* Ensure this is pointing to a directory. */
4177 dp = opendir(sharepath);
4179 if (!dp) {
4180 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4181 servicename, sharepath));
4182 return USERSHARE_PATH_NOT_DIRECTORY;
4185 /* Ensure the owner of the usershare file has permission to share
4186 this directory. */
4188 if (sys_stat(sharepath, &sbuf, false) == -1) {
4189 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4190 servicename, sharepath, strerror(errno) ));
4191 closedir(dp);
4192 return USERSHARE_POSIX_ERR;
4195 closedir(dp);
4197 if (!S_ISDIR(sbuf.st_ex_mode)) {
4198 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4199 servicename, sharepath ));
4200 return USERSHARE_PATH_NOT_DIRECTORY;
4203 /* Check if sharing is restricted to owner-only. */
4204 /* psbuf is the stat of the usershare definition file,
4205 sbuf is the stat of the target directory to be shared. */
4207 if (lp_usershare_owner_only()) {
4208 /* root can share anything. */
4209 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4210 return USERSHARE_PATH_NOT_ALLOWED;
4214 *pp_sharepath = sharepath;
4215 *pp_comment = comment;
4216 return USERSHARE_OK;
4219 /***************************************************************************
4220 Deal with a usershare file.
4221 Returns:
4222 >= 0 - snum
4223 -1 - Bad name, invalid contents.
4224 - service name already existed and not a usershare, problem
4225 with permissions to share directory etc.
4226 ***************************************************************************/
4228 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4230 SMB_STRUCT_STAT sbuf;
4231 SMB_STRUCT_STAT lsbuf;
4232 char *fname = NULL;
4233 char *sharepath = NULL;
4234 char *comment = NULL;
4235 char *cp_service_name = NULL;
4236 char **lines = NULL;
4237 int numlines = 0;
4238 int fd = -1;
4239 int iService = -1;
4240 TALLOC_CTX *ctx = talloc_stackframe();
4241 struct security_descriptor *psd = NULL;
4242 bool guest_ok = false;
4243 char *canon_name = NULL;
4244 bool added_service = false;
4245 int ret = -1;
4247 /* Ensure share name doesn't contain invalid characters. */
4248 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4249 DEBUG(0,("process_usershare_file: share name %s contains "
4250 "invalid characters (any of %s)\n",
4251 file_name, INVALID_SHARENAME_CHARS ));
4252 goto out;
4255 canon_name = canonicalize_servicename(ctx, file_name);
4256 if (!canon_name) {
4257 goto out;
4260 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4261 if (!fname) {
4262 goto out;
4265 /* Minimize the race condition by doing an lstat before we
4266 open and fstat. Ensure this isn't a symlink link. */
4268 if (sys_lstat(fname, &lsbuf, false) != 0) {
4269 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4270 fname, strerror(errno) ));
4271 goto out;
4274 /* This must be a regular file, not a symlink, directory or
4275 other strange filetype. */
4276 if (!check_usershare_stat(fname, &lsbuf)) {
4277 goto out;
4281 TDB_DATA data;
4282 NTSTATUS status;
4284 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4285 canon_name, &data);
4287 iService = -1;
4289 if (NT_STATUS_IS_OK(status) &&
4290 (data.dptr != NULL) &&
4291 (data.dsize == sizeof(iService))) {
4292 memcpy(&iService, data.dptr, sizeof(iService));
4296 if (iService != -1 &&
4297 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4298 &lsbuf.st_ex_mtime) == 0) {
4299 /* Nothing changed - Mark valid and return. */
4300 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4301 canon_name ));
4302 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4303 ret = iService;
4304 goto out;
4307 /* Try and open the file read only - no symlinks allowed. */
4308 #ifdef O_NOFOLLOW
4309 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4310 #else
4311 fd = open(fname, O_RDONLY, 0);
4312 #endif
4314 if (fd == -1) {
4315 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4316 fname, strerror(errno) ));
4317 goto out;
4320 /* Now fstat to be *SURE* it's a regular file. */
4321 if (sys_fstat(fd, &sbuf, false) != 0) {
4322 close(fd);
4323 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4324 fname, strerror(errno) ));
4325 goto out;
4328 /* Is it the same dev/inode as was lstated ? */
4329 if (!check_same_stat(&lsbuf, &sbuf)) {
4330 close(fd);
4331 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4332 "Symlink spoofing going on ?\n", fname ));
4333 goto out;
4336 /* This must be a regular file, not a symlink, directory or
4337 other strange filetype. */
4338 if (!check_usershare_stat(fname, &sbuf)) {
4339 goto out;
4342 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4344 close(fd);
4345 if (lines == NULL) {
4346 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4347 fname, (unsigned int)sbuf.st_ex_uid ));
4348 goto out;
4351 if (parse_usershare_file(ctx, &sbuf, file_name,
4352 iService, lines, numlines, &sharepath,
4353 &comment, &cp_service_name,
4354 &psd, &guest_ok) != USERSHARE_OK) {
4355 goto out;
4358 /* Everything ok - add the service possibly using a template. */
4359 if (iService < 0) {
4360 const struct loadparm_service *sp = &sDefault;
4361 if (snum_template != -1) {
4362 sp = ServicePtrs[snum_template];
4365 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4366 DEBUG(0, ("process_usershare_file: Failed to add "
4367 "new service %s\n", cp_service_name));
4368 goto out;
4371 added_service = true;
4373 /* Read only is controlled by usershare ACL below. */
4374 ServicePtrs[iService]->bRead_only = false;
4377 /* Write the ACL of the new/modified share. */
4378 if (!set_share_security(canon_name, psd)) {
4379 DEBUG(0, ("process_usershare_file: Failed to set share "
4380 "security for user share %s\n",
4381 canon_name ));
4382 goto out;
4385 /* If from a template it may be marked invalid. */
4386 ServicePtrs[iService]->valid = true;
4388 /* Set the service as a valid usershare. */
4389 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4391 /* Set guest access. */
4392 if (lp_usershare_allow_guests()) {
4393 ServicePtrs[iService]->bGuest_ok = guest_ok;
4396 /* And note when it was loaded. */
4397 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4398 string_set(&ServicePtrs[iService]->szPath, sharepath);
4399 string_set(&ServicePtrs[iService]->comment, comment);
4401 ret = iService;
4403 out:
4405 if (ret == -1 && iService != -1 && added_service) {
4406 lp_remove_service(iService);
4409 TALLOC_FREE(lines);
4410 TALLOC_FREE(ctx);
4411 return ret;
4414 /***************************************************************************
4415 Checks if a usershare entry has been modified since last load.
4416 ***************************************************************************/
4418 static bool usershare_exists(int iService, struct timespec *last_mod)
4420 SMB_STRUCT_STAT lsbuf;
4421 const char *usersharepath = Globals.szUsersharePath;
4422 char *fname;
4424 if (asprintf(&fname, "%s/%s",
4425 usersharepath,
4426 ServicePtrs[iService]->szService) < 0) {
4427 return false;
4430 if (sys_lstat(fname, &lsbuf, false) != 0) {
4431 SAFE_FREE(fname);
4432 return false;
4435 if (!S_ISREG(lsbuf.st_ex_mode)) {
4436 SAFE_FREE(fname);
4437 return false;
4440 SAFE_FREE(fname);
4441 *last_mod = lsbuf.st_ex_mtime;
4442 return true;
4445 /***************************************************************************
4446 Load a usershare service by name. Returns a valid servicenumber or -1.
4447 ***************************************************************************/
4449 int load_usershare_service(const char *servicename)
4451 SMB_STRUCT_STAT sbuf;
4452 const char *usersharepath = Globals.szUsersharePath;
4453 int max_user_shares = Globals.iUsershareMaxShares;
4454 int snum_template = -1;
4456 if (*usersharepath == 0 || max_user_shares == 0) {
4457 return -1;
4460 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4461 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4462 usersharepath, strerror(errno) ));
4463 return -1;
4466 if (!S_ISDIR(sbuf.st_ex_mode)) {
4467 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4468 usersharepath ));
4469 return -1;
4473 * This directory must be owned by root, and have the 't' bit set.
4474 * It also must not be writable by "other".
4477 #ifdef S_ISVTX
4478 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4479 #else
4480 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4481 #endif
4482 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4483 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4484 usersharepath ));
4485 return -1;
4488 /* Ensure the template share exists if it's set. */
4489 if (Globals.szUsershareTemplateShare[0]) {
4490 /* We can't use lp_servicenumber here as we are recommending that
4491 template shares have -valid=false set. */
4492 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4493 if (ServicePtrs[snum_template]->szService &&
4494 strequal(ServicePtrs[snum_template]->szService,
4495 Globals.szUsershareTemplateShare)) {
4496 break;
4500 if (snum_template == -1) {
4501 DEBUG(0,("load_usershare_service: usershare template share %s "
4502 "does not exist.\n",
4503 Globals.szUsershareTemplateShare ));
4504 return -1;
4508 return process_usershare_file(usersharepath, servicename, snum_template);
4511 /***************************************************************************
4512 Load all user defined shares from the user share directory.
4513 We only do this if we're enumerating the share list.
4514 This is the function that can delete usershares that have
4515 been removed.
4516 ***************************************************************************/
4518 int load_usershare_shares(struct smbd_server_connection *sconn,
4519 bool (*snumused) (struct smbd_server_connection *, int))
4521 DIR *dp;
4522 SMB_STRUCT_STAT sbuf;
4523 struct dirent *de;
4524 int num_usershares = 0;
4525 int max_user_shares = Globals.iUsershareMaxShares;
4526 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4527 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4528 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4529 int iService;
4530 int snum_template = -1;
4531 const char *usersharepath = Globals.szUsersharePath;
4532 int ret = lp_numservices();
4533 TALLOC_CTX *tmp_ctx;
4535 if (max_user_shares == 0 || *usersharepath == '\0') {
4536 return lp_numservices();
4539 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4540 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4541 usersharepath, strerror(errno) ));
4542 return ret;
4546 * This directory must be owned by root, and have the 't' bit set.
4547 * It also must not be writable by "other".
4550 #ifdef S_ISVTX
4551 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4552 #else
4553 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4554 #endif
4555 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4556 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4557 usersharepath ));
4558 return ret;
4561 /* Ensure the template share exists if it's set. */
4562 if (Globals.szUsershareTemplateShare[0]) {
4563 /* We can't use lp_servicenumber here as we are recommending that
4564 template shares have -valid=false set. */
4565 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4566 if (ServicePtrs[snum_template]->szService &&
4567 strequal(ServicePtrs[snum_template]->szService,
4568 Globals.szUsershareTemplateShare)) {
4569 break;
4573 if (snum_template == -1) {
4574 DEBUG(0,("load_usershare_shares: usershare template share %s "
4575 "does not exist.\n",
4576 Globals.szUsershareTemplateShare ));
4577 return ret;
4581 /* Mark all existing usershares as pending delete. */
4582 for (iService = iNumServices - 1; iService >= 0; iService--) {
4583 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4584 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4588 dp = opendir(usersharepath);
4589 if (!dp) {
4590 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4591 usersharepath, strerror(errno) ));
4592 return ret;
4595 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4596 (de = readdir(dp));
4597 num_dir_entries++ ) {
4598 int r;
4599 const char *n = de->d_name;
4601 /* Ignore . and .. */
4602 if (*n == '.') {
4603 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4604 continue;
4608 if (n[0] == ':') {
4609 /* Temporary file used when creating a share. */
4610 num_tmp_dir_entries++;
4613 /* Allow 20% tmp entries. */
4614 if (num_tmp_dir_entries > allowed_tmp_entries) {
4615 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4616 "in directory %s\n",
4617 num_tmp_dir_entries, usersharepath));
4618 break;
4621 r = process_usershare_file(usersharepath, n, snum_template);
4622 if (r == 0) {
4623 /* Update the services count. */
4624 num_usershares++;
4625 if (num_usershares >= max_user_shares) {
4626 DEBUG(0,("load_usershare_shares: max user shares reached "
4627 "on file %s in directory %s\n",
4628 n, usersharepath ));
4629 break;
4631 } else if (r == -1) {
4632 num_bad_dir_entries++;
4635 /* Allow 20% bad entries. */
4636 if (num_bad_dir_entries > allowed_bad_entries) {
4637 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4638 "in directory %s\n",
4639 num_bad_dir_entries, usersharepath));
4640 break;
4643 /* Allow 20% bad entries. */
4644 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4645 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4646 "in directory %s\n",
4647 num_dir_entries, usersharepath));
4648 break;
4652 closedir(dp);
4654 /* Sweep through and delete any non-refreshed usershares that are
4655 not currently in use. */
4656 tmp_ctx = talloc_stackframe();
4657 for (iService = iNumServices - 1; iService >= 0; iService--) {
4658 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4659 char *servname;
4661 if (snumused && snumused(sconn, iService)) {
4662 continue;
4665 servname = lp_servicename(tmp_ctx, iService);
4667 /* Remove from the share ACL db. */
4668 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4669 servname ));
4670 delete_share_security(servname);
4671 free_service_byindex(iService);
4674 talloc_free(tmp_ctx);
4676 return lp_numservices();
4679 /********************************************************
4680 Destroy global resources allocated in this file
4681 ********************************************************/
4683 void gfree_loadparm(void)
4685 int i;
4687 free_file_list();
4689 /* Free resources allocated to services */
4691 for ( i = 0; i < iNumServices; i++ ) {
4692 if ( VALID(i) ) {
4693 free_service_byindex(i);
4697 SAFE_FREE( ServicePtrs );
4698 iNumServices = 0;
4700 /* Now release all resources allocated to global
4701 parameters and the default service */
4703 free_global_parameters();
4707 /***************************************************************************
4708 Allow client apps to specify that they are a client
4709 ***************************************************************************/
4710 static void lp_set_in_client(bool b)
4712 in_client = b;
4716 /***************************************************************************
4717 Determine if we're running in a client app
4718 ***************************************************************************/
4719 static bool lp_is_in_client(void)
4721 return in_client;
4724 /***************************************************************************
4725 Load the services array from the services file. Return true on success,
4726 false on failure.
4727 ***************************************************************************/
4729 static bool lp_load_ex(const char *pszFname,
4730 bool global_only,
4731 bool save_defaults,
4732 bool add_ipc,
4733 bool initialize_globals,
4734 bool allow_include_registry,
4735 bool load_all_shares)
4737 char *n2 = NULL;
4738 bool bRetval;
4740 bRetval = false;
4742 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4744 bInGlobalSection = true;
4745 bGlobalOnly = global_only;
4746 bAllowIncludeRegistry = allow_include_registry;
4748 init_globals(initialize_globals);
4750 free_file_list();
4752 if (save_defaults) {
4753 init_locals();
4754 lp_save_defaults();
4757 if (!initialize_globals) {
4758 free_param_opts(&Globals.param_opt);
4759 apply_lp_set_cmdline();
4762 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4764 /* We get sections first, so have to start 'behind' to make up */
4765 iServiceIndex = -1;
4767 if (lp_config_backend_is_file()) {
4768 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4769 current_user_info.domain,
4770 pszFname);
4771 if (!n2) {
4772 smb_panic("lp_load_ex: out of memory");
4775 add_to_file_list(pszFname, n2);
4777 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4778 TALLOC_FREE(n2);
4780 /* finish up the last section */
4781 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4782 if (bRetval) {
4783 if (iServiceIndex >= 0) {
4784 bRetval = service_ok(iServiceIndex);
4788 if (lp_config_backend_is_registry()) {
4789 /* config backend changed to registry in config file */
4791 * We need to use this extra global variable here to
4792 * survive restart: init_globals uses this as a default
4793 * for ConfigBackend. Otherwise, init_globals would
4794 * send us into an endless loop here.
4796 config_backend = CONFIG_BACKEND_REGISTRY;
4797 /* start over */
4798 DEBUG(1, ("lp_load_ex: changing to config backend "
4799 "registry\n"));
4800 init_globals(true);
4801 lp_kill_all_services();
4802 return lp_load_ex(pszFname, global_only, save_defaults,
4803 add_ipc, initialize_globals,
4804 allow_include_registry,
4805 load_all_shares);
4807 } else if (lp_config_backend_is_registry()) {
4808 bRetval = process_registry_globals();
4809 } else {
4810 DEBUG(0, ("Illegal config backend given: %d\n",
4811 lp_config_backend()));
4812 bRetval = false;
4815 if (bRetval && lp_registry_shares()) {
4816 if (load_all_shares) {
4817 bRetval = process_registry_shares();
4818 } else {
4819 bRetval = reload_registry_shares();
4824 char *serv = lp_auto_services(talloc_tos());
4825 lp_add_auto_services(serv);
4826 TALLOC_FREE(serv);
4829 if (add_ipc) {
4830 /* When 'restrict anonymous = 2' guest connections to ipc$
4831 are denied */
4832 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4833 if ( lp_enable_asu_support() ) {
4834 lp_add_ipc("ADMIN$", false);
4838 set_allowed_client_auth();
4840 if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4841 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4842 lp_passwordserver()));
4845 bLoaded = true;
4847 /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4848 /* if bWINSsupport is true and we are in the client */
4849 if (lp_is_in_client() && Globals.bWINSsupport) {
4850 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4853 init_iconv();
4855 fault_configure(smb_panic_s3);
4857 bAllowIncludeRegistry = true;
4859 return (bRetval);
4862 bool lp_load(const char *pszFname,
4863 bool global_only,
4864 bool save_defaults,
4865 bool add_ipc,
4866 bool initialize_globals)
4868 return lp_load_ex(pszFname,
4869 global_only,
4870 save_defaults,
4871 add_ipc,
4872 initialize_globals,
4873 true, /* allow_include_registry */
4874 false); /* load_all_shares*/
4877 bool lp_load_initial_only(const char *pszFname)
4879 return lp_load_ex(pszFname,
4880 true, /* global only */
4881 false, /* save_defaults */
4882 false, /* add_ipc */
4883 true, /* initialize_globals */
4884 false, /* allow_include_registry */
4885 false); /* load_all_shares*/
4889 * most common lp_load wrapper, loading only the globals
4891 bool lp_load_global(const char *file_name)
4893 return lp_load_ex(file_name,
4894 true, /* global_only */
4895 false, /* save_defaults */
4896 false, /* add_ipc */
4897 true, /* initialize_globals */
4898 true, /* allow_include_registry */
4899 false); /* load_all_shares*/
4903 * lp_load wrapper, especially for clients
4905 bool lp_load_client(const char *file_name)
4907 lp_set_in_client(true);
4909 return lp_load_global(file_name);
4913 * lp_load wrapper, loading only globals, but intended
4914 * for subsequent calls, not reinitializing the globals
4915 * to default values
4917 bool lp_load_global_no_reinit(const char *file_name)
4919 return lp_load_ex(file_name,
4920 true, /* global_only */
4921 false, /* save_defaults */
4922 false, /* add_ipc */
4923 false, /* initialize_globals */
4924 true, /* allow_include_registry */
4925 false); /* load_all_shares*/
4929 * lp_load wrapper, especially for clients, no reinitialization
4931 bool lp_load_client_no_reinit(const char *file_name)
4933 lp_set_in_client(true);
4935 return lp_load_global_no_reinit(file_name);
4938 bool lp_load_with_registry_shares(const char *pszFname,
4939 bool global_only,
4940 bool save_defaults,
4941 bool add_ipc,
4942 bool initialize_globals)
4944 return lp_load_ex(pszFname,
4945 global_only,
4946 save_defaults,
4947 add_ipc,
4948 initialize_globals,
4949 true, /* allow_include_registry */
4950 true); /* load_all_shares*/
4953 /***************************************************************************
4954 Return the max number of services.
4955 ***************************************************************************/
4957 int lp_numservices(void)
4959 return (iNumServices);
4962 /***************************************************************************
4963 Display the contents of the services array in human-readable form.
4964 ***************************************************************************/
4966 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
4968 int iService;
4970 if (show_defaults)
4971 defaults_saved = false;
4973 dump_globals(f);
4975 dump_a_service(&sDefault, f);
4977 for (iService = 0; iService < maxtoprint; iService++) {
4978 fprintf(f,"\n");
4979 lp_dump_one(f, show_defaults, iService);
4983 /***************************************************************************
4984 Display the contents of one service in human-readable form.
4985 ***************************************************************************/
4987 void lp_dump_one(FILE * f, bool show_defaults, int snum)
4989 if (VALID(snum)) {
4990 if (ServicePtrs[snum]->szService[0] == '\0')
4991 return;
4992 dump_a_service(ServicePtrs[snum], f);
4996 /***************************************************************************
4997 Return the number of the service with the given name, or -1 if it doesn't
4998 exist. Note that this is a DIFFERENT ANIMAL from the internal function
4999 getservicebyname()! This works ONLY if all services have been loaded, and
5000 does not copy the found service.
5001 ***************************************************************************/
5003 int lp_servicenumber(const char *pszServiceName)
5005 int iService;
5006 fstring serviceName;
5008 if (!pszServiceName) {
5009 return GLOBAL_SECTION_SNUM;
5012 for (iService = iNumServices - 1; iService >= 0; iService--) {
5013 if (VALID(iService) && ServicePtrs[iService]->szService) {
5015 * The substitution here is used to support %U is
5016 * service names
5018 fstrcpy(serviceName, ServicePtrs[iService]->szService);
5019 standard_sub_basic(get_current_username(),
5020 current_user_info.domain,
5021 serviceName,sizeof(serviceName));
5022 if (strequal(serviceName, pszServiceName)) {
5023 break;
5028 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5029 struct timespec last_mod;
5031 if (!usershare_exists(iService, &last_mod)) {
5032 /* Remove the share security tdb entry for it. */
5033 delete_share_security(lp_servicename(talloc_tos(), iService));
5034 /* Remove it from the array. */
5035 free_service_byindex(iService);
5036 /* Doesn't exist anymore. */
5037 return GLOBAL_SECTION_SNUM;
5040 /* Has it been modified ? If so delete and reload. */
5041 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5042 &last_mod) < 0) {
5043 /* Remove it from the array. */
5044 free_service_byindex(iService);
5045 /* and now reload it. */
5046 iService = load_usershare_service(pszServiceName);
5050 if (iService < 0) {
5051 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5052 return GLOBAL_SECTION_SNUM;
5055 return (iService);
5058 /*******************************************************************
5059 A useful volume label function.
5060 ********************************************************************/
5062 const char *volume_label(TALLOC_CTX *ctx, int snum)
5064 char *ret;
5065 const char *label = lp_volume(ctx, snum);
5066 if (!*label) {
5067 label = lp_servicename(ctx, snum);
5070 /* This returns a 33 byte guarenteed null terminated string. */
5071 ret = talloc_strndup(ctx, label, 32);
5072 if (!ret) {
5073 return "";
5075 return ret;
5078 /*******************************************************************
5079 Get the default server type we will announce as via nmbd.
5080 ********************************************************************/
5082 int lp_default_server_announce(void)
5084 int default_server_announce = 0;
5085 default_server_announce |= SV_TYPE_WORKSTATION;
5086 default_server_announce |= SV_TYPE_SERVER;
5087 default_server_announce |= SV_TYPE_SERVER_UNIX;
5089 /* note that the flag should be set only if we have a
5090 printer service but nmbd doesn't actually load the
5091 services so we can't tell --jerry */
5093 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5095 default_server_announce |= SV_TYPE_SERVER_NT;
5096 default_server_announce |= SV_TYPE_NT;
5098 switch (lp_server_role()) {
5099 case ROLE_DOMAIN_MEMBER:
5100 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5101 break;
5102 case ROLE_DOMAIN_PDC:
5103 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5104 break;
5105 case ROLE_DOMAIN_BDC:
5106 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5107 break;
5108 case ROLE_STANDALONE:
5109 default:
5110 break;
5112 if (lp_time_server())
5113 default_server_announce |= SV_TYPE_TIME_SOURCE;
5115 if (lp_host_msdfs())
5116 default_server_announce |= SV_TYPE_DFS_SERVER;
5118 return default_server_announce;
5121 /***********************************************************
5122 If we are PDC then prefer us as DMB
5123 ************************************************************/
5125 bool lp_domain_master(void)
5127 if (Globals.domain_master == Auto)
5128 return (lp_server_role() == ROLE_DOMAIN_PDC);
5130 return (bool)Globals.domain_master;
5133 /***********************************************************
5134 If we are PDC then prefer us as DMB
5135 ************************************************************/
5137 static bool lp_domain_master_true_or_auto(void)
5139 if (Globals.domain_master) /* auto or yes */
5140 return true;
5142 return false;
5145 /***********************************************************
5146 If we are DMB then prefer us as LMB
5147 ************************************************************/
5149 bool lp_preferred_master(void)
5151 if (Globals.iPreferredMaster == Auto)
5152 return (lp_local_master() && lp_domain_master());
5154 return (bool)Globals.iPreferredMaster;
5157 /*******************************************************************
5158 Remove a service.
5159 ********************************************************************/
5161 void lp_remove_service(int snum)
5163 ServicePtrs[snum]->valid = false;
5164 invalid_services[num_invalid_services++] = snum;
5167 /*******************************************************************
5168 Copy a service.
5169 ********************************************************************/
5171 void lp_copy_service(int snum, const char *new_name)
5173 do_section(new_name, NULL);
5174 if (snum >= 0) {
5175 snum = lp_servicenumber(new_name);
5176 if (snum >= 0) {
5177 char *name = lp_servicename(talloc_tos(), snum);
5178 lp_do_parameter(snum, "copy", name);
5183 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5185 const char *ret = lp__printername(talloc_tos(), snum);
5186 if (ret == NULL || *ret == '\0') {
5187 ret = lp_const_servicename(snum);
5190 return ret;
5194 /***********************************************************
5195 Allow daemons such as winbindd to fix their logfile name.
5196 ************************************************************/
5198 void lp_set_logfile(const char *name)
5200 string_set(&Globals.logfile, name);
5201 debug_set_logfile(name);
5204 /*******************************************************************
5205 Return the max print jobs per queue.
5206 ********************************************************************/
5208 int lp_maxprintjobs(int snum)
5210 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5211 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5212 maxjobs = PRINT_MAX_JOBID - 1;
5214 return maxjobs;
5217 const char *lp_printcapname(void)
5219 if ((Globals.szPrintcapname != NULL) &&
5220 (Globals.szPrintcapname[0] != '\0'))
5221 return Globals.szPrintcapname;
5223 if (sDefault.iPrinting == PRINT_CUPS) {
5224 #ifdef HAVE_CUPS
5225 return "cups";
5226 #else
5227 return "lpstat";
5228 #endif
5231 if (sDefault.iPrinting == PRINT_BSD)
5232 return "/etc/printcap";
5234 return PRINTCAP_NAME;
5237 static uint32 spoolss_state;
5239 bool lp_disable_spoolss( void )
5241 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5242 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5244 return spoolss_state == SVCCTL_STOPPED ? true : false;
5247 void lp_set_spoolss_state( uint32 state )
5249 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5251 spoolss_state = state;
5254 uint32 lp_get_spoolss_state( void )
5256 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5259 /*******************************************************************
5260 Ensure we don't use sendfile if server smb signing is active.
5261 ********************************************************************/
5263 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5265 bool sign_active = false;
5267 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5268 if (get_Protocol() < PROTOCOL_NT1) {
5269 return false;
5271 if (signing_state) {
5272 sign_active = smb_signing_is_active(signing_state);
5274 return (lp__use_sendfile(snum) &&
5275 (get_remote_arch() != RA_WIN95) &&
5276 !sign_active);
5279 /*******************************************************************
5280 Turn off sendfile if we find the underlying OS doesn't support it.
5281 ********************************************************************/
5283 void set_use_sendfile(int snum, bool val)
5285 if (LP_SNUM_OK(snum))
5286 ServicePtrs[snum]->bUseSendfile = val;
5287 else
5288 sDefault.bUseSendfile = val;
5291 /*******************************************************************
5292 Turn off storing DOS attributes if this share doesn't support it.
5293 ********************************************************************/
5295 void set_store_dos_attributes(int snum, bool val)
5297 if (!LP_SNUM_OK(snum))
5298 return;
5299 ServicePtrs[(snum)]->bStoreDosAttributes = val;
5302 void lp_set_mangling_method(const char *new_method)
5304 string_set(&Globals.szManglingMethod, new_method);
5307 /*******************************************************************
5308 Global state for POSIX pathname processing.
5309 ********************************************************************/
5311 static bool posix_pathnames;
5313 bool lp_posix_pathnames(void)
5315 return posix_pathnames;
5318 /*******************************************************************
5319 Change everything needed to ensure POSIX pathname processing (currently
5320 not much).
5321 ********************************************************************/
5323 void lp_set_posix_pathnames(void)
5325 posix_pathnames = true;
5328 /*******************************************************************
5329 Global state for POSIX lock processing - CIFS unix extensions.
5330 ********************************************************************/
5332 bool posix_default_lock_was_set;
5333 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5335 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5337 if (posix_default_lock_was_set) {
5338 return posix_cifsx_locktype;
5339 } else {
5340 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5344 /*******************************************************************
5345 ********************************************************************/
5347 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5349 posix_default_lock_was_set = true;
5350 posix_cifsx_locktype = val;
5353 int lp_min_receive_file_size(void)
5355 if (Globals.iminreceivefile < 0) {
5356 return 0;
5358 return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5361 /*******************************************************************
5362 If socket address is an empty character string, it is necessary to
5363 define it as "0.0.0.0".
5364 ********************************************************************/
5366 const char *lp_socket_address(void)
5368 char *sock_addr = Globals.szSocketAddress;
5370 if (sock_addr[0] == '\0'){
5371 string_set(&Globals.szSocketAddress, "0.0.0.0");
5373 return Globals.szSocketAddress;
5376 /*******************************************************************
5377 Safe wide links checks.
5378 This helper function always verify the validity of wide links,
5379 even after a configuration file reload.
5380 ********************************************************************/
5382 static bool lp_widelinks_internal(int snum)
5384 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5385 sDefault.bWidelinks);
5388 void widelinks_warning(int snum)
5390 if (lp_allow_insecure_widelinks()) {
5391 return;
5394 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5395 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5396 "These parameters are incompatible. "
5397 "Wide links will be disabled for this share.\n",
5398 lp_servicename(talloc_tos(), snum) ));
5402 bool lp_widelinks(int snum)
5404 /* wide links is always incompatible with unix extensions */
5405 if (lp_unix_extensions()) {
5407 * Unless we have "allow insecure widelinks"
5408 * turned on.
5410 if (!lp_allow_insecure_widelinks()) {
5411 return false;
5415 return lp_widelinks_internal(snum);
5418 bool lp_writeraw(void)
5420 if (lp_async_smb_echo_handler()) {
5421 return false;
5423 return lp__writeraw();
5426 bool lp_readraw(void)
5428 if (lp_async_smb_echo_handler()) {
5429 return false;
5431 return lp__readraw();
5434 int lp_server_role(void)
5436 return lp_find_server_role(lp__server_role(),
5437 lp__security(),
5438 lp__domain_logons(),
5439 lp_domain_master_true_or_auto());
5442 int lp_security(void)
5444 return lp_find_security(lp__server_role(),
5445 lp__security());