s3-param: Remove never-reached condition for opt_list == NULL
[Samba/bjacke.git] / source3 / param / loadparm.c
blob6895ebe4d07e05c5eaa38e17c49d9c11a9a18313
1 /*
2 Unix SMB/CIFS implementation.
3 Parameter loading functions
4 Copyright (C) Karl Auer 1993-1998
6 Largely re-written by Andrew Tridgell, September 1994
8 Copyright (C) Simo Sorce 2001
9 Copyright (C) Alexander Bokovoy 2002
10 Copyright (C) Stefan (metze) Metzmacher 2002
11 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12 Copyright (C) Michael Adam 2008
13 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14 Copyright (C) Andrew Bartlett 2011
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 3 of the License, or
19 (at your option) any later version.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
31 * Load parameters.
33 * This module provides suitable callback functions for the params
34 * module. It builds the internal table of service details which is
35 * then used by the rest of the server.
37 * To add a parameter:
39 * 1) add it to the global or service structure definition
40 * 2) add it to the parm_table
41 * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42 * 4) If it's a global then initialise it in init_globals. If a local
43 * (ie. service) parameter then initialise it in the sDefault structure
46 * Notes:
47 * The configuration file is processed sequentially for speed. It is NOT
48 * accessed randomly as happens in 'real' Windows. For this reason, there
49 * is a fair bit of sequence-dependent code here - ie., code which assumes
50 * that certain things happen before others. In particular, the code which
51 * happens at the boundary between sections is delicately poised, so be
52 * careful!
56 #include "includes.h"
57 #include "system/filesys.h"
58 #include "util_tdb.h"
59 #include "lib/param/loadparm.h"
60 #include "printing.h"
61 #include "lib/smbconf/smbconf.h"
62 #include "lib/smbconf/smbconf_init.h"
64 #include "ads.h"
65 #include "../librpc/gen_ndr/svcctl.h"
66 #include "intl.h"
67 #include "../libcli/smb/smb_signing.h"
68 #include "dbwrap/dbwrap.h"
69 #include "dbwrap/dbwrap_rbt.h"
70 #include "../lib/util/bitmap.h"
72 #ifdef HAVE_SYS_SYSCTL_H
73 #include <sys/sysctl.h>
74 #endif
76 #ifdef HAVE_HTTPCONNECTENCRYPT
77 #include <cups/http.h>
78 #endif
80 #ifdef CLUSTER_SUPPORT
81 #include "ctdb_private.h"
82 #endif
84 bool bLoaded = false;
86 extern userdom_struct current_user_info;
88 /* the special value for the include parameter
89 * to be interpreted not as a file name but to
90 * trigger loading of the global smb.conf options
91 * from registry. */
92 #ifndef INCLUDE_REGISTRY_NAME
93 #define INCLUDE_REGISTRY_NAME "registry"
94 #endif
96 static bool in_client = false; /* Not in the client by default */
97 static struct smbconf_csn conf_last_csn;
99 static int config_backend = CONFIG_BACKEND_FILE;
101 /* some helpful bits */
102 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
103 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
105 #define USERSHARE_VALID 1
106 #define USERSHARE_PENDING_DELETE 2
108 static bool defaults_saved = false;
110 #define LOADPARM_EXTRA_GLOBALS \
111 struct parmlist_entry *param_opt; \
112 char *szRealm; \
113 char *loglevel; \
114 int iminreceivefile; \
115 char *szPrintcapname; \
116 int CupsEncrypt; \
117 int iPreferredMaster; \
118 char *szLdapMachineSuffix; \
119 char *szLdapUserSuffix; \
120 char *szLdapIdmapSuffix; \
121 char *szLdapGroupSuffix; \
122 char *szStateDir; \
123 char *szCacheDir; \
124 char *szUsershareTemplateShare; \
125 char *szIdmapUID; \
126 char *szIdmapGID; \
127 int winbindMaxDomainConnections; \
128 int ismb2_max_credits; \
129 char *tls_keyfile; \
130 char *tls_certfile; \
131 char *tls_cafile; \
132 char *tls_crlfile; \
133 char *tls_dhpfile; \
134 char *panic_action; \
135 int bPreferredMaster;
137 #include "param/param_global.h"
139 static struct loadparm_global Globals;
141 /* This is a default service used to prime a services structure */
142 static struct loadparm_service sDefault =
144 .valid = true,
145 .autoloaded = false,
146 .usershare = 0,
147 .usershare_last_mod = {0, 0},
148 .szService = NULL,
149 .szPath = NULL,
150 .szUsername = NULL,
151 .szInvalidUsers = NULL,
152 .szValidUsers = NULL,
153 .szAdminUsers = NULL,
154 .szCopy = NULL,
155 .szInclude = NULL,
156 .szPreExec = NULL,
157 .szPostExec = NULL,
158 .szRootPreExec = NULL,
159 .szRootPostExec = NULL,
160 .szCupsOptions = NULL,
161 .szPrintcommand = NULL,
162 .szLpqcommand = NULL,
163 .szLprmcommand = NULL,
164 .szLppausecommand = NULL,
165 .szLpresumecommand = NULL,
166 .szQueuepausecommand = NULL,
167 .szQueueresumecommand = NULL,
168 .szPrintername = NULL,
169 .szPrintjobUsername = NULL,
170 .szDontdescend = NULL,
171 .szHostsallow = NULL,
172 .szHostsdeny = NULL,
173 .szMagicScript = NULL,
174 .szMagicOutput = NULL,
175 .szVetoFiles = NULL,
176 .szHideFiles = NULL,
177 .szVetoOplockFiles = NULL,
178 .comment = NULL,
179 .force_user = NULL,
180 .force_group = NULL,
181 .readlist = NULL,
182 .writelist = NULL,
183 .volume = NULL,
184 .fstype = NULL,
185 .szVfsObjects = NULL,
186 .szMSDfsProxy = NULL,
187 .szAioWriteBehind = NULL,
188 .szDfree = NULL,
189 .iMinPrintSpace = 0,
190 .iMaxPrintJobs = 1000,
191 .iMaxReportedPrintJobs = 0,
192 .iWriteCacheSize = 0,
193 .iCreate_mask = 0744,
194 .iCreate_force_mode = 0,
195 .iSecurity_mask = 0777,
196 .iSecurity_force_mode = 0,
197 .iDir_mask = 0755,
198 .iDir_force_mode = 0,
199 .iDir_Security_mask = 0777,
200 .iDir_Security_force_mode = 0,
201 .iMaxConnections = 0,
202 .iDefaultCase = CASE_LOWER,
203 .iPrinting = DEFAULT_PRINTING,
204 .iOplockContentionLimit = 2,
205 .iCSCPolicy = 0,
206 .iBlock_size = 1024,
207 .iDfreeCacheTime = 0,
208 .bPreexecClose = false,
209 .bRootpreexecClose = false,
210 .iCaseSensitive = Auto,
211 .bCasePreserve = true,
212 .bShortCasePreserve = true,
213 .bHideDotFiles = true,
214 .bHideSpecialFiles = false,
215 .bHideUnReadable = false,
216 .bHideUnWriteableFiles = false,
217 .bBrowseable = true,
218 .bAccessBasedShareEnum = false,
219 .bAvailable = true,
220 .bRead_only = true,
221 .bNo_set_dir = true,
222 .bGuest_only = false,
223 .bAdministrative_share = false,
224 .bGuest_ok = false,
225 .bPrint_ok = false,
226 .bPrintNotifyBackchannel = true,
227 .bMap_system = false,
228 .bMap_hidden = false,
229 .bMap_archive = true,
230 .bStoreDosAttributes = false,
231 .bDmapiSupport = false,
232 .bLocking = true,
233 .iStrictLocking = Auto,
234 .bPosixLocking = true,
235 .bShareModes = true,
236 .bOpLocks = true,
237 .bKernelOplocks = false,
238 .bLevel2OpLocks = true,
239 .bOnlyUser = false,
240 .bMangledNames = true,
241 .bWidelinks = false,
242 .bSymlinks = true,
243 .bSyncAlways = false,
244 .bStrictAllocate = false,
245 .bStrictSync = false,
246 .magic_char = '~',
247 .copymap = NULL,
248 .bDeleteReadonly = false,
249 .bFakeOplocks = false,
250 .bDeleteVetoFiles = false,
251 .bDosFilemode = false,
252 .bDosFiletimes = true,
253 .bDosFiletimeResolution = false,
254 .bFakeDirCreateTimes = false,
255 .bBlockingLocks = true,
256 .bInheritPerms = false,
257 .bInheritACLS = false,
258 .bInheritOwner = false,
259 .bMSDfsRoot = false,
260 .bUseClientDriver = false,
261 .bDefaultDevmode = true,
262 .bForcePrintername = false,
263 .bNTAclSupport = true,
264 .bForceUnknownAclUser = false,
265 .bUseSendfile = false,
266 .bProfileAcls = false,
267 .bMap_acl_inherit = false,
268 .bAfs_Share = false,
269 .bEASupport = false,
270 .bAclCheckPermissions = true,
271 .bAclMapFullControl = true,
272 .bAclGroupControl = false,
273 .bChangeNotify = true,
274 .bKernelChangeNotify = true,
275 .iallocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
276 .iAioReadSize = 0,
277 .iAioWriteSize = 0,
278 .iMap_readonly = MAP_READONLY_YES,
279 #ifdef BROKEN_DIRECTORY_HANDLING
280 .iDirectoryNameCacheSize = 0,
281 #else
282 .iDirectoryNameCacheSize = 100,
283 #endif
284 .ismb_encrypt = Auto,
285 .param_opt = NULL,
286 .dummy = ""
289 /* local variables */
290 static struct loadparm_service **ServicePtrs = NULL;
291 static int iNumServices = 0;
292 static int iServiceIndex = 0;
293 static struct db_context *ServiceHash;
294 static int *invalid_services = NULL;
295 static int num_invalid_services = 0;
296 static bool bInGlobalSection = true;
297 static bool bGlobalOnly = false;
299 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
301 /* prototypes for the special type handlers */
302 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
303 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
304 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
305 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
306 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
307 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
308 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
309 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
310 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
311 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
312 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
313 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
315 /* these are parameter handlers which are not needed in the
316 * source3 code
319 #define handle_logfile NULL
321 static void set_allowed_client_auth(void);
323 static void add_to_file_list(const char *fname, const char *subfname);
324 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
325 static void free_param_opts(struct parmlist_entry **popts);
327 #include "lib/param/param_table.c"
329 /* this is used to prevent lots of mallocs of size 1 */
330 static const char null_string[] = "";
333 Set a string value, allocing the space for the string
336 static bool string_init(char **dest,const char *src)
338 size_t l;
340 if (!src)
341 src = "";
343 l = strlen(src);
345 if (l == 0) {
346 *dest = discard_const_p(char, null_string);
347 } else {
348 (*dest) = SMB_STRDUP(src);
349 if ((*dest) == NULL) {
350 DEBUG(0,("Out of memory in string_init\n"));
351 return false;
354 return(true);
358 Free a string value.
361 static void string_free(char **s)
363 if (!s || !(*s))
364 return;
365 if (*s == null_string)
366 *s = NULL;
367 SAFE_FREE(*s);
371 Set a string value, deallocating any existing space, and allocing the space
372 for the string
375 static bool string_set(char **dest,const char *src)
377 string_free(dest);
378 return(string_init(dest,src));
381 /***************************************************************************
382 Initialise the sDefault parameter structure for the printer values.
383 ***************************************************************************/
385 static void init_printer_values(struct loadparm_service *pService)
387 /* choose defaults depending on the type of printing */
388 switch (pService->iPrinting) {
389 case PRINT_BSD:
390 case PRINT_AIX:
391 case PRINT_LPRNT:
392 case PRINT_LPROS2:
393 string_set(&pService->szLpqcommand, "lpq -P'%p'");
394 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
395 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
396 break;
398 case PRINT_LPRNG:
399 case PRINT_PLP:
400 string_set(&pService->szLpqcommand, "lpq -P'%p'");
401 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
402 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
403 string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
404 string_set(&pService->szQueueresumecommand, "lpc start '%p'");
405 string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
406 string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
407 break;
409 case PRINT_CUPS:
410 case PRINT_IPRINT:
411 #ifdef HAVE_CUPS
412 /* set the lpq command to contain the destination printer
413 name only. This is used by cups_queue_get() */
414 string_set(&pService->szLpqcommand, "%p");
415 string_set(&pService->szLprmcommand, "");
416 string_set(&pService->szPrintcommand, "");
417 string_set(&pService->szLppausecommand, "");
418 string_set(&pService->szLpresumecommand, "");
419 string_set(&pService->szQueuepausecommand, "");
420 string_set(&pService->szQueueresumecommand, "");
421 #else
422 string_set(&pService->szLpqcommand, "lpq -P'%p'");
423 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
424 string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
425 string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
426 string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
427 string_set(&pService->szQueuepausecommand, "disable '%p'");
428 string_set(&pService->szQueueresumecommand, "enable '%p'");
429 #endif /* HAVE_CUPS */
430 break;
432 case PRINT_SYSV:
433 case PRINT_HPUX:
434 string_set(&pService->szLpqcommand, "lpstat -o%p");
435 string_set(&pService->szLprmcommand, "cancel %p-%j");
436 string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
437 string_set(&pService->szQueuepausecommand, "disable %p");
438 string_set(&pService->szQueueresumecommand, "enable %p");
439 #ifndef HPUX
440 string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
441 string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
442 #endif /* HPUX */
443 break;
445 case PRINT_QNX:
446 string_set(&pService->szLpqcommand, "lpq -P%p");
447 string_set(&pService->szLprmcommand, "lprm -P%p %j");
448 string_set(&pService->szPrintcommand, "lp -r -P%p %s");
449 break;
451 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST) || defined(ENABLE_BUILD_FARM_HACKS)
453 case PRINT_TEST:
454 case PRINT_VLP: {
455 const char *tdbfile;
456 TALLOC_CTX *tmp_ctx = talloc_stackframe();
457 char *tmp;
459 tdbfile = talloc_asprintf(
460 tmp_ctx, "tdbfile=%s",
461 lp_parm_const_string(-1, "vlp", "tdbfile",
462 "/tmp/vlp.tdb"));
463 if (tdbfile == NULL) {
464 tdbfile="tdbfile=/tmp/vlp.tdb";
467 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
468 tdbfile);
469 string_set(&pService->szPrintcommand,
470 tmp ? tmp : "vlp print %p %s");
472 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
473 tdbfile);
474 string_set(&pService->szLpqcommand,
475 tmp ? tmp : "vlp lpq %p");
477 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
478 tdbfile);
479 string_set(&pService->szLprmcommand,
480 tmp ? tmp : "vlp lprm %p %j");
482 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
483 tdbfile);
484 string_set(&pService->szLppausecommand,
485 tmp ? tmp : "vlp lppause %p %j");
487 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
488 tdbfile);
489 string_set(&pService->szLpresumecommand,
490 tmp ? tmp : "vlp lpresume %p %j");
492 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
493 tdbfile);
494 string_set(&pService->szQueuepausecommand,
495 tmp ? tmp : "vlp queuepause %p");
497 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
498 tdbfile);
499 string_set(&pService->szQueueresumecommand,
500 tmp ? tmp : "vlp queueresume %p");
501 TALLOC_FREE(tmp_ctx);
503 break;
505 #endif /* DEVELOPER */
510 * Function to return the default value for the maximum number of open
511 * file descriptors permitted. This function tries to consult the
512 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
513 * the smaller of those.
515 static int max_open_files(void)
517 int sysctl_max = MAX_OPEN_FILES;
518 int rlimit_max = MAX_OPEN_FILES;
520 #ifdef HAVE_SYSCTLBYNAME
522 size_t size = sizeof(sysctl_max);
523 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
526 #endif
528 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
530 struct rlimit rl;
532 ZERO_STRUCT(rl);
534 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
535 rlimit_max = rl.rlim_cur;
537 #if defined(RLIM_INFINITY)
538 if(rl.rlim_cur == RLIM_INFINITY)
539 rlimit_max = MAX_OPEN_FILES;
540 #endif
542 #endif
544 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
545 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
546 "minimum Windows limit (%d)\n",
547 sysctl_max,
548 MIN_OPEN_FILES_WINDOWS));
549 sysctl_max = MIN_OPEN_FILES_WINDOWS;
552 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
553 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
554 "minimum Windows limit (%d)\n",
555 rlimit_max,
556 MIN_OPEN_FILES_WINDOWS));
557 rlimit_max = MIN_OPEN_FILES_WINDOWS;
560 return MIN(sysctl_max, rlimit_max);
564 * Common part of freeing allocated data for one parameter.
566 static void free_one_parameter_common(void *parm_ptr,
567 struct parm_struct parm)
569 if ((parm.type == P_STRING) ||
570 (parm.type == P_USTRING))
572 string_free((char**)parm_ptr);
573 } else if (parm.type == P_LIST) {
574 TALLOC_FREE(*((char***)parm_ptr));
579 * Free the allocated data for one parameter for a share
580 * given as a service struct.
582 static void free_one_parameter(struct loadparm_service *service,
583 struct parm_struct parm)
585 void *parm_ptr;
587 if (parm.p_class != P_LOCAL) {
588 return;
591 parm_ptr = lp_parm_ptr(service, &parm);
593 free_one_parameter_common(parm_ptr, parm);
597 * Free the allocated parameter data of a share given
598 * as a service struct.
600 static void free_parameters(struct loadparm_service *service)
602 uint32_t i;
604 for (i=0; parm_table[i].label; i++) {
605 free_one_parameter(service, parm_table[i]);
610 * Free the allocated data for one parameter for a given share
611 * specified by an snum.
613 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
615 void *parm_ptr;
617 if (snum < 0) {
618 parm_ptr = lp_parm_ptr(NULL, &parm);
619 } else if (parm.p_class != P_LOCAL) {
620 return;
621 } else {
622 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
625 free_one_parameter_common(parm_ptr, parm);
629 * Free the allocated parameter data for a share specified
630 * by an snum.
632 static void free_parameters_by_snum(int snum)
634 uint32_t i;
636 for (i=0; parm_table[i].label; i++) {
637 free_one_parameter_by_snum(snum, parm_table[i]);
642 * Free the allocated global parameters.
644 static void free_global_parameters(void)
646 free_param_opts(&Globals.param_opt);
647 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
648 TALLOC_FREE(Globals.ctx);
651 static int map_parameter(const char *pszParmName);
653 struct lp_stored_option {
654 struct lp_stored_option *prev, *next;
655 const char *label;
656 const char *value;
659 static struct lp_stored_option *stored_options;
662 save options set by lp_set_cmdline() into a list. This list is
663 re-applied when we do a globals reset, so that cmdline set options
664 are sticky across reloads of smb.conf
666 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
668 struct lp_stored_option *entry, *entry_next;
669 for (entry = stored_options; entry != NULL; entry = entry_next) {
670 entry_next = entry->next;
671 if (strcmp(pszParmName, entry->label) == 0) {
672 DLIST_REMOVE(stored_options, entry);
673 talloc_free(entry);
674 break;
678 entry = talloc(NULL, struct lp_stored_option);
679 if (!entry) {
680 return false;
683 entry->label = talloc_strdup(entry, pszParmName);
684 if (!entry->label) {
685 talloc_free(entry);
686 return false;
689 entry->value = talloc_strdup(entry, pszParmValue);
690 if (!entry->value) {
691 talloc_free(entry);
692 return false;
695 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
697 return true;
700 static bool apply_lp_set_cmdline(void)
702 struct lp_stored_option *entry = NULL;
703 for (entry = stored_options; entry != NULL; entry = entry->next) {
704 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
705 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
706 entry->label, entry->value));
707 return false;
710 return true;
713 /***************************************************************************
714 Initialise the global parameter structure.
715 ***************************************************************************/
717 static void init_globals(bool reinit_globals)
719 static bool done_init = false;
720 char *s = NULL;
721 int i;
723 /* If requested to initialize only once and we've already done it... */
724 if (!reinit_globals && done_init) {
725 /* ... then we have nothing more to do */
726 return;
729 if (!done_init) {
730 /* The logfile can be set before this is invoked. Free it if so. */
731 if (Globals.logfile != NULL) {
732 string_free(&Globals.logfile);
733 Globals.logfile = NULL;
735 done_init = true;
736 } else {
737 free_global_parameters();
740 /* This memset and the free_global_parameters() above will
741 * wipe out smb.conf options set with lp_set_cmdline(). The
742 * apply_lp_set_cmdline() call puts these values back in the
743 * table once the defaults are set */
744 ZERO_STRUCT(Globals);
746 Globals.ctx = talloc_new(NULL);
748 for (i = 0; parm_table[i].label; i++) {
749 if ((parm_table[i].type == P_STRING ||
750 parm_table[i].type == P_USTRING))
752 string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
757 string_set(&sDefault.fstype, FSTYPE_STRING);
758 string_set(&sDefault.szPrintjobUsername, "%U");
760 init_printer_values(&sDefault);
763 DEBUG(3, ("Initialising global parameters\n"));
765 /* Must manually force to upper case here, as this does not go via the handler */
766 string_set(&Globals.szNetbiosName, myhostname_upper());
768 string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
769 string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
771 /* use the new 'hash2' method by default, with a prefix of 1 */
772 string_set(&Globals.szManglingMethod, "hash2");
773 Globals.mangle_prefix = 1;
775 string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
777 /* using UTF8 by default allows us to support all chars */
778 string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
780 /* Use codepage 850 as a default for the dos character set */
781 string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
784 * Allow the default PASSWD_CHAT to be overridden in local.h.
786 string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
788 string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
790 string_set(&Globals.szPasswdProgram, "");
791 string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
792 string_set(&Globals.szStateDir, get_dyn_STATEDIR());
793 string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
794 string_set(&Globals.szPidDir, get_dyn_PIDDIR());
795 string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
797 * By default support explicit binding to broadcast
798 * addresses.
800 Globals.bNmbdBindExplicitBroadcast = true;
802 if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
803 smb_panic("init_globals: ENOMEM");
805 string_set(&Globals.szServerString, s);
806 SAFE_FREE(s);
807 #ifdef DEVELOPER
808 string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
809 #endif
811 string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
813 string_set(&Globals.szLogonDrive, "");
814 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
815 string_set(&Globals.szLogonHome, "\\\\%N\\%U");
816 string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
818 Globals.szNameResolveOrder = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
819 string_set(&Globals.szPasswordServer, "*");
821 Globals.AlgorithmicRidBase = BASE_RID;
823 Globals.bLoadPrinters = true;
824 Globals.PrintcapCacheTime = 750; /* 12.5 minutes */
826 Globals.ConfigBackend = config_backend;
827 Globals.server_role = ROLE_AUTO;
829 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
830 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
831 Globals.max_xmit = 0x4104;
832 Globals.max_mux = 50; /* This is *needed* for profile support. */
833 Globals.lpqcachetime = 30; /* changed to handle large print servers better -- jerry */
834 Globals.bDisableSpoolss = false;
835 Globals.iMaxSmbdProcesses = 0;/* no limit specified */
836 Globals.pwordlevel = 0;
837 Globals.unamelevel = 0;
838 Globals.deadtime = 0;
839 Globals.getwd_cache = true;
840 Globals.bLargeReadwrite = true;
841 Globals.max_log_size = 5000;
842 Globals.max_open_files = max_open_files();
843 Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
844 Globals.srv_maxprotocol = PROTOCOL_SMB2_10;
845 Globals.srv_minprotocol = PROTOCOL_LANMAN1;
846 Globals.security = SEC_USER;
847 Globals.bEncryptPasswords = true;
848 Globals.clientSchannel = Auto;
849 Globals.serverSchannel = Auto;
850 Globals.bReadRaw = true;
851 Globals.bWriteRaw = true;
852 Globals.bNullPasswords = false;
853 Globals.bObeyPamRestrictions = false;
854 Globals.syslog = 1;
855 Globals.bSyslogOnly = false;
856 Globals.bTimestampLogs = true;
857 string_set(&Globals.loglevel, "0");
858 Globals.bDebugPrefixTimestamp = false;
859 Globals.bDebugHiresTimestamp = true;
860 Globals.bDebugPid = false;
861 Globals.bDebugUid = false;
862 Globals.bDebugClass = false;
863 Globals.bEnableCoreFiles = true;
864 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
865 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
866 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
867 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
868 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
869 Globals.lm_interval = 60;
870 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
871 Globals.bNISHomeMap = false;
872 #ifdef WITH_NISPLUS_HOME
873 string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
874 #else
875 string_set(&Globals.szNISHomeMapName, "auto.home");
876 #endif
877 #endif
878 Globals.bTimeServer = false;
879 Globals.bBindInterfacesOnly = false;
880 Globals.bUnixPasswdSync = false;
881 Globals.bPamPasswordChange = false;
882 Globals.bPasswdChatDebug = false;
883 Globals.iPasswdChatTimeout = 2; /* 2 second default. */
884 Globals.bNTPipeSupport = true; /* Do NT pipes by default. */
885 Globals.bNTStatusSupport = true; /* Use NT status by default. */
886 Globals.bStatCache = true; /* use stat cache by default */
887 Globals.iMaxStatCacheSize = 256; /* 256k by default */
888 Globals.restrict_anonymous = 0;
889 Globals.bClientLanManAuth = false; /* Do NOT use the LanMan hash if it is available */
890 Globals.bClientPlaintextAuth = false; /* Do NOT use a plaintext password even if is requested by the server */
891 Globals.bLanmanAuth = false; /* Do NOT use the LanMan hash, even if it is supplied */
892 Globals.bNTLMAuth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
893 Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
894 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
896 Globals.map_to_guest = 0; /* By Default, "Never" */
897 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
898 Globals.enhanced_browsing = true;
899 Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
900 #ifdef MMAP_BLACKLIST
901 Globals.bUseMmap = false;
902 #else
903 Globals.bUseMmap = true;
904 #endif
905 Globals.bUnicode = true;
906 Globals.bUnixExtensions = true;
907 Globals.bResetOnZeroVC = false;
908 Globals.bLogWriteableFilesOnExit = false;
909 Globals.bCreateKrb5Conf = true;
910 Globals.winbindMaxDomainConnections = 1;
912 /* hostname lookups can be very expensive and are broken on
913 a large number of sites (tridge) */
914 Globals.bHostnameLookups = false;
916 string_set(&Globals.passdb_backend, "tdbsam");
917 string_set(&Globals.szLdapSuffix, "");
918 string_set(&Globals.szLdapMachineSuffix, "");
919 string_set(&Globals.szLdapUserSuffix, "");
920 string_set(&Globals.szLdapGroupSuffix, "");
921 string_set(&Globals.szLdapIdmapSuffix, "");
923 string_set(&Globals.szLdapAdminDn, "");
924 Globals.ldap_ssl = LDAP_SSL_START_TLS;
925 Globals.ldap_ssl_ads = false;
926 Globals.ldap_deref = -1;
927 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
928 Globals.ldap_delete_dn = false;
929 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
930 Globals.ldap_follow_referral = Auto;
931 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
932 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
933 Globals.ldap_page_size = LDAP_PAGE_SIZE;
935 Globals.ldap_debug_level = 0;
936 Globals.ldap_debug_threshold = 10;
938 /* This is what we tell the afs client. in reality we set the token
939 * to never expire, though, when this runs out the afs client will
940 * forget the token. Set to 0 to get NEVERDATE.*/
941 Globals.iAfsTokenLifetime = 604800;
942 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
944 /* these parameters are set to defaults that are more appropriate
945 for the increasing samba install base:
947 as a member of the workgroup, that will possibly become a
948 _local_ master browser (lm = true). this is opposed to a forced
949 local master browser startup (pm = true).
951 doesn't provide WINS server service by default (wsupp = false),
952 and doesn't provide domain master browser services by default, either.
956 Globals.bMsAddPrinterWizard = true;
957 Globals.os_level = 20;
958 Globals.bLocalMaster = true;
959 Globals.domain_master = Auto; /* depending on bDomainLogons */
960 Globals.bDomainLogons = false;
961 Globals.bBrowseList = true;
962 Globals.bWINSsupport = false;
963 Globals.bWINSproxy = false;
965 TALLOC_FREE(Globals.szInitLogonDelayedHosts);
966 Globals.InitLogonDelay = 100; /* 100 ms default delay */
968 Globals.bWINSdnsProxy = true;
970 Globals.bAllowTrustedDomains = true;
971 string_set(&Globals.szIdmapBackend, "tdb");
973 string_set(&Globals.szTemplateShell, "/bin/false");
974 string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
975 string_set(&Globals.szWinbindSeparator, "\\");
977 string_set(&Globals.szCupsServer, "");
978 string_set(&Globals.szIPrintServer, "");
980 #ifdef CLUSTER_SUPPORT
981 string_set(&Globals.ctdbdSocket, CTDB_PATH);
982 #else
983 string_set(&Globals.ctdbdSocket, "");
984 #endif
986 Globals.szClusterAddresses = NULL;
987 Globals.clustering = false;
988 Globals.ctdb_timeout = 0;
989 Globals.ctdb_locktime_warn_threshold = 0;
991 Globals.winbind_cache_time = 300; /* 5 minutes */
992 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
993 Globals.winbind_max_clients = 200;
994 Globals.bWinbindEnumUsers = false;
995 Globals.bWinbindEnumGroups = false;
996 Globals.bWinbindUseDefaultDomain = false;
997 Globals.bWinbindTrustedDomainsOnly = false;
998 Globals.bWinbindNestedGroups = true;
999 Globals.winbind_expand_groups = 1;
1000 Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
1001 Globals.bWinbindRefreshTickets = false;
1002 Globals.bWinbindOfflineLogon = false;
1004 Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
1005 Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
1007 Globals.bPassdbExpandExplicit = false;
1009 Globals.name_cache_timeout = 660; /* In seconds */
1011 Globals.bUseSpnego = true;
1012 Globals.bClientUseSpnego = true;
1014 Globals.client_signing = SMB_SIGNING_DEFAULT;
1015 Globals.server_signing = SMB_SIGNING_DEFAULT;
1017 Globals.bDeferSharingViolations = true;
1018 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
1020 Globals.bEnablePrivileges = true;
1021 Globals.bHostMSDfs = true;
1022 Globals.bASUSupport = false;
1024 /* User defined shares. */
1025 if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
1026 smb_panic("init_globals: ENOMEM");
1028 string_set(&Globals.szUsersharePath, s);
1029 SAFE_FREE(s);
1030 string_set(&Globals.szUsershareTemplateShare, "");
1031 Globals.iUsershareMaxShares = 0;
1032 /* By default disallow sharing of directories not owned by the sharer. */
1033 Globals.bUsershareOwnerOnly = true;
1034 /* By default disallow guest access to usershares. */
1035 Globals.bUsershareAllowGuests = false;
1037 Globals.iKeepalive = DEFAULT_KEEPALIVE;
1039 /* By default no shares out of the registry */
1040 Globals.bRegistryShares = false;
1042 Globals.iminreceivefile = 0;
1044 Globals.bMapUntrustedToDomain = false;
1045 Globals.bMulticastDnsRegister = true;
1047 Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
1048 Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
1049 Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
1050 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1052 string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1054 /* Now put back the settings that were set with lp_set_cmdline() */
1055 apply_lp_set_cmdline();
1058 /*******************************************************************
1059 Convenience routine to grab string parameters into talloced memory
1060 and run standard_sub_basic on them. The buffers can be written to by
1061 callers without affecting the source string.
1062 ********************************************************************/
1064 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1066 char *ret;
1068 /* The follow debug is useful for tracking down memory problems
1069 especially if you have an inner loop that is calling a lp_*()
1070 function that returns a string. Perhaps this debug should be
1071 present all the time? */
1073 #if 0
1074 DEBUG(10, ("lp_string(%s)\n", s));
1075 #endif
1076 if (!s) {
1077 return NULL;
1080 ret = talloc_sub_basic(ctx,
1081 get_current_username(),
1082 current_user_info.domain,
1084 if (trim_char(ret, '\"', '\"')) {
1085 if (strchr(ret,'\"') != NULL) {
1086 TALLOC_FREE(ret);
1087 ret = talloc_sub_basic(ctx,
1088 get_current_username(),
1089 current_user_info.domain,
1093 return ret;
1097 In this section all the functions that are used to access the
1098 parameters from the rest of the program are defined
1101 #define FN_GLOBAL_STRING(fn_name,ptr) \
1102 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1103 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1104 const char *lp_ ## fn_name(void) {return(*(const char **)(&Globals.ptr) ? *(const char **)(&Globals.ptr) : "");}
1105 #define FN_GLOBAL_LIST(fn_name,ptr) \
1106 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1107 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1108 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1109 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1110 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1111 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1112 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1114 #define FN_LOCAL_STRING(fn_name,val) \
1115 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));}
1116 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1117 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1118 #define FN_LOCAL_LIST(fn_name,val) \
1119 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1120 #define FN_LOCAL_BOOL(fn_name,val) \
1121 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1122 #define FN_LOCAL_INTEGER(fn_name,val) \
1123 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1125 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1126 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1127 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1128 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1129 #define FN_LOCAL_CHAR(fn_name,val) \
1130 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1133 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1134 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1136 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1137 * build process or in smb.conf, we use that value. Otherwise they
1138 * default to the value of lp_lockdir(). */
1139 const char *lp_statedir(void) {
1140 if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1141 (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1142 return(*(char **)(&Globals.szStateDir) ?
1143 *(char **)(&Globals.szStateDir) : "");
1144 else
1145 return(*(char **)(&Globals.szLockDir) ?
1146 *(char **)(&Globals.szLockDir) : "");
1148 const char *lp_cachedir(void) {
1149 if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1150 (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1151 return(*(char **)(&Globals.szCacheDir) ?
1152 *(char **)(&Globals.szCacheDir) : "");
1153 else
1154 return(*(char **)(&Globals.szLockDir) ?
1155 *(char **)(&Globals.szLockDir) : "");
1157 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1158 winbindMaxDomainConnections)
1160 int lp_winbind_max_domain_connections(void)
1162 if (lp_winbind_offline_logon() &&
1163 lp_winbind_max_domain_connections_int() > 1) {
1164 DEBUG(1, ("offline logons active, restricting max domain "
1165 "connections to 1\n"));
1166 return 1;
1168 return MAX(1, lp_winbind_max_domain_connections_int());
1171 int lp_smb2_max_credits(void)
1173 if (Globals.ismb2_max_credits == 0) {
1174 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1176 return Globals.ismb2_max_credits;
1178 int lp_cups_encrypt(void)
1180 int result = 0;
1181 #ifdef HAVE_HTTPCONNECTENCRYPT
1182 switch (Globals.CupsEncrypt) {
1183 case Auto:
1184 result = HTTP_ENCRYPT_REQUIRED;
1185 break;
1186 case true:
1187 result = HTTP_ENCRYPT_ALWAYS;
1188 break;
1189 case false:
1190 result = HTTP_ENCRYPT_NEVER;
1191 break;
1193 #endif
1194 return result;
1197 /* These functions remain in source3/param for now */
1199 FN_GLOBAL_STRING(configfile, szConfigFile)
1201 #include "lib/param/param_functions.c"
1203 FN_LOCAL_STRING(servicename, szService)
1204 FN_LOCAL_CONST_STRING(const_servicename, szService)
1206 /* local prototypes */
1208 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1209 static const char *get_boolean(bool bool_value);
1210 static int getservicebyname(const char *pszServiceName,
1211 struct loadparm_service *pserviceDest);
1212 static void copy_service(struct loadparm_service *pserviceDest,
1213 struct loadparm_service *pserviceSource,
1214 struct bitmap *pcopymapDest);
1215 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1216 void *userdata);
1217 static bool do_section(const char *pszSectionName, void *userdata);
1218 static void init_copymap(struct loadparm_service *pservice);
1219 static bool hash_a_service(const char *name, int number);
1220 static void free_service_byindex(int iService);
1221 static void show_parameter(int parmIndex);
1222 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1225 * This is a helper function for parametrical options support. It returns a
1226 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1227 * parametrical functions are quite simple
1229 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1230 const char *option)
1232 bool global_section = false;
1233 char* param_key;
1234 struct parmlist_entry *data;
1236 if (service == NULL) {
1237 data = Globals.param_opt;
1238 global_section = true;
1239 } else {
1240 data = service->param_opt;
1243 if (asprintf(&param_key, "%s:%s", type, option) == -1) {
1244 DEBUG(0,("asprintf failed!\n"));
1245 return NULL;
1248 while (data) {
1249 if (strwicmp(data->key, param_key) == 0) {
1250 string_free(&param_key);
1251 return data;
1253 data = data->next;
1256 if (!global_section) {
1257 /* Try to fetch the same option but from globals */
1258 /* but only if we are not already working with Globals */
1259 data = Globals.param_opt;
1260 while (data) {
1261 if (strwicmp(data->key, param_key) == 0) {
1262 string_free(&param_key);
1263 return data;
1265 data = data->next;
1269 string_free(&param_key);
1271 return NULL;
1275 * This is a helper function for parametrical options support. It returns a
1276 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1277 * parametrical functions are quite simple
1279 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1280 const char *option)
1282 if (snum >= iNumServices) return NULL;
1284 if (snum < 0) {
1285 return get_parametrics_by_service(NULL, type, option);
1286 } else {
1287 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1292 #define MISSING_PARAMETER(name) \
1293 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1295 /*******************************************************************
1296 convenience routine to return int parameters.
1297 ********************************************************************/
1298 static int lp_int(const char *s)
1301 if (!s || !*s) {
1302 MISSING_PARAMETER(lp_int);
1303 return (-1);
1306 return (int)strtol(s, NULL, 0);
1309 /*******************************************************************
1310 convenience routine to return unsigned long parameters.
1311 ********************************************************************/
1312 static unsigned long lp_ulong(const char *s)
1315 if (!s || !*s) {
1316 MISSING_PARAMETER(lp_ulong);
1317 return (0);
1320 return strtoul(s, NULL, 0);
1323 /*******************************************************************
1324 convenience routine to return boolean parameters.
1325 ********************************************************************/
1326 static bool lp_bool(const char *s)
1328 bool ret = false;
1330 if (!s || !*s) {
1331 MISSING_PARAMETER(lp_bool);
1332 return false;
1335 if (!set_boolean(s, &ret)) {
1336 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1337 return false;
1340 return ret;
1343 /*******************************************************************
1344 convenience routine to return enum parameters.
1345 ********************************************************************/
1346 static int lp_enum(const char *s,const struct enum_list *_enum)
1348 int i;
1350 if (!s || !*s || !_enum) {
1351 MISSING_PARAMETER(lp_enum);
1352 return (-1);
1355 for (i=0; _enum[i].name; i++) {
1356 if (strequal(_enum[i].name,s))
1357 return _enum[i].value;
1360 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1361 return (-1);
1364 #undef MISSING_PARAMETER
1366 /* Return parametric option from a given service. Type is a part of option before ':' */
1367 /* Parametric option has following syntax: 'Type: option = value' */
1368 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1370 struct parmlist_entry *data = get_parametrics(snum, type, option);
1372 if (data == NULL||data->value==NULL) {
1373 if (def) {
1374 return lp_string(ctx, def);
1375 } else {
1376 return NULL;
1380 return lp_string(ctx, data->value);
1383 /* Return parametric option from a given service. Type is a part of option before ':' */
1384 /* Parametric option has following syntax: 'Type: option = value' */
1385 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1387 struct parmlist_entry *data = get_parametrics(snum, type, option);
1389 if (data == NULL||data->value==NULL)
1390 return def;
1392 return data->value;
1395 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1397 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1399 if (data == NULL||data->value==NULL)
1400 return NULL;
1402 return data->value;
1406 /* Return parametric option from a given service. Type is a part of option before ':' */
1407 /* Parametric option has following syntax: 'Type: option = value' */
1409 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1411 struct parmlist_entry *data = get_parametrics(snum, type, option);
1413 if (data == NULL||data->value==NULL)
1414 return (const char **)def;
1416 if (data->list==NULL) {
1417 data->list = str_list_make_v3(NULL, data->value, NULL);
1420 return (const char **)data->list;
1423 /* Return parametric option from a given service. Type is a part of option before ':' */
1424 /* Parametric option has following syntax: 'Type: option = value' */
1426 int lp_parm_int(int snum, const char *type, const char *option, int def)
1428 struct parmlist_entry *data = get_parametrics(snum, type, option);
1430 if (data && data->value && *data->value)
1431 return lp_int(data->value);
1433 return def;
1436 /* Return parametric option from a given service. Type is a part of option before ':' */
1437 /* Parametric option has following syntax: 'Type: option = value' */
1439 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1441 struct parmlist_entry *data = get_parametrics(snum, type, option);
1443 if (data && data->value && *data->value)
1444 return lp_ulong(data->value);
1446 return def;
1449 /* Return parametric option from a given service. Type is a part of option before ':' */
1450 /* Parametric option has following syntax: 'Type: option = value' */
1452 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1454 struct parmlist_entry *data = get_parametrics(snum, type, option);
1456 if (data && data->value && *data->value)
1457 return lp_bool(data->value);
1459 return def;
1462 /* Return parametric option from a given service. Type is a part of option before ':' */
1463 /* Parametric option has following syntax: 'Type: option = value' */
1465 int lp_parm_enum(int snum, const char *type, const char *option,
1466 const struct enum_list *_enum, int def)
1468 struct parmlist_entry *data = get_parametrics(snum, type, option);
1470 if (data && data->value && *data->value && _enum)
1471 return lp_enum(data->value, _enum);
1473 return def;
1477 /***************************************************************************
1478 Initialise a service to the defaults.
1479 ***************************************************************************/
1481 static void init_service(struct loadparm_service *pservice)
1483 memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1484 copy_service(pservice, &sDefault, NULL);
1489 * free a param_opts structure.
1490 * param_opts handling should be moved to talloc;
1491 * then this whole functions reduces to a TALLOC_FREE().
1494 static void free_param_opts(struct parmlist_entry **popts)
1496 struct parmlist_entry *opt, *next_opt;
1498 if (popts == NULL) {
1499 return;
1502 if (*popts != NULL) {
1503 DEBUG(5, ("Freeing parametrics:\n"));
1505 opt = *popts;
1506 while (opt != NULL) {
1507 string_free(&opt->key);
1508 string_free(&opt->value);
1509 TALLOC_FREE(opt->list);
1510 next_opt = opt->next;
1511 SAFE_FREE(opt);
1512 opt = next_opt;
1514 *popts = NULL;
1517 /***************************************************************************
1518 Free the dynamically allocated parts of a service struct.
1519 ***************************************************************************/
1521 static void free_service(struct loadparm_service *pservice)
1523 if (!pservice)
1524 return;
1526 if (pservice->szService)
1527 DEBUG(5, ("free_service: Freeing service %s\n",
1528 pservice->szService));
1530 free_parameters(pservice);
1532 string_free(&pservice->szService);
1533 TALLOC_FREE(pservice->copymap);
1535 free_param_opts(&pservice->param_opt);
1537 ZERO_STRUCTP(pservice);
1541 /***************************************************************************
1542 remove a service indexed in the ServicePtrs array from the ServiceHash
1543 and free the dynamically allocated parts
1544 ***************************************************************************/
1546 static void free_service_byindex(int idx)
1548 if ( !LP_SNUM_OK(idx) )
1549 return;
1551 ServicePtrs[idx]->valid = false;
1552 invalid_services[num_invalid_services++] = idx;
1554 /* we have to cleanup the hash record */
1556 if (ServicePtrs[idx]->szService) {
1557 char *canon_name = canonicalize_servicename(
1558 talloc_tos(),
1559 ServicePtrs[idx]->szService );
1561 dbwrap_delete_bystring(ServiceHash, canon_name );
1562 TALLOC_FREE(canon_name);
1565 free_service(ServicePtrs[idx]);
1566 talloc_free_children(ServicePtrs[idx]);
1569 /***************************************************************************
1570 Add a new service to the services array initialising it with the given
1571 service.
1572 ***************************************************************************/
1574 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1576 int i;
1577 struct loadparm_service tservice;
1578 int num_to_alloc = iNumServices + 1;
1580 tservice = *pservice;
1582 /* it might already exist */
1583 if (name) {
1584 i = getservicebyname(name, NULL);
1585 if (i >= 0) {
1586 return (i);
1590 /* find an invalid one */
1591 i = iNumServices;
1592 if (num_invalid_services > 0) {
1593 i = invalid_services[--num_invalid_services];
1596 /* if not, then create one */
1597 if (i == iNumServices) {
1598 struct loadparm_service **tsp;
1599 int *tinvalid;
1601 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1602 if (tsp == NULL) {
1603 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1604 return (-1);
1606 ServicePtrs = tsp;
1607 ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1608 if (!ServicePtrs[iNumServices]) {
1609 DEBUG(0,("add_a_service: out of memory!\n"));
1610 return (-1);
1612 iNumServices++;
1614 /* enlarge invalid_services here for now... */
1615 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
1616 num_to_alloc);
1617 if (tinvalid == NULL) {
1618 DEBUG(0,("add_a_service: failed to enlarge "
1619 "invalid_services!\n"));
1620 return (-1);
1622 invalid_services = tinvalid;
1623 } else {
1624 free_service_byindex(i);
1627 ServicePtrs[i]->valid = true;
1629 init_service(ServicePtrs[i]);
1630 copy_service(ServicePtrs[i], &tservice, NULL);
1631 if (name)
1632 string_set(&ServicePtrs[i]->szService, name);
1634 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1635 i, ServicePtrs[i]->szService));
1637 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1638 return (-1);
1641 return (i);
1644 /***************************************************************************
1645 Convert a string to uppercase and remove whitespaces.
1646 ***************************************************************************/
1648 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1650 char *result;
1652 if ( !src ) {
1653 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1654 return NULL;
1657 result = talloc_strdup(ctx, src);
1658 SMB_ASSERT(result != NULL);
1660 strlower_m(result);
1661 return result;
1664 /***************************************************************************
1665 Add a name/index pair for the services array to the hash table.
1666 ***************************************************************************/
1668 static bool hash_a_service(const char *name, int idx)
1670 char *canon_name;
1672 if ( !ServiceHash ) {
1673 DEBUG(10,("hash_a_service: creating servicehash\n"));
1674 ServiceHash = db_open_rbt(NULL);
1675 if ( !ServiceHash ) {
1676 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1677 return false;
1681 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1682 idx, name));
1684 canon_name = canonicalize_servicename(talloc_tos(), name );
1686 dbwrap_store_bystring(ServiceHash, canon_name,
1687 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1688 TDB_REPLACE);
1690 TALLOC_FREE(canon_name);
1692 return true;
1695 /***************************************************************************
1696 Add a new home service, with the specified home directory, defaults coming
1697 from service ifrom.
1698 ***************************************************************************/
1700 bool lp_add_home(const char *pszHomename, int iDefaultService,
1701 const char *user, const char *pszHomedir)
1703 int i;
1705 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1706 pszHomedir[0] == '\0') {
1707 return false;
1710 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1712 if (i < 0)
1713 return false;
1715 if (!(*(ServicePtrs[iDefaultService]->szPath))
1716 || strequal(ServicePtrs[iDefaultService]->szPath,
1717 lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1718 string_set(&ServicePtrs[i]->szPath, pszHomedir);
1721 if (!(*(ServicePtrs[i]->comment))) {
1722 char *comment = NULL;
1723 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1724 return false;
1726 string_set(&ServicePtrs[i]->comment, comment);
1727 SAFE_FREE(comment);
1730 /* set the browseable flag from the global default */
1732 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1733 ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
1735 ServicePtrs[i]->autoloaded = true;
1737 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1738 user, ServicePtrs[i]->szPath ));
1740 return true;
1743 /***************************************************************************
1744 Add a new service, based on an old one.
1745 ***************************************************************************/
1747 int lp_add_service(const char *pszService, int iDefaultService)
1749 if (iDefaultService < 0) {
1750 return add_a_service(&sDefault, pszService);
1753 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1756 /***************************************************************************
1757 Add the IPC service.
1758 ***************************************************************************/
1760 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1762 char *comment = NULL;
1763 int i = add_a_service(&sDefault, ipc_name);
1765 if (i < 0)
1766 return false;
1768 if (asprintf(&comment, "IPC Service (%s)",
1769 Globals.szServerString) < 0) {
1770 return false;
1773 string_set(&ServicePtrs[i]->szPath, tmpdir());
1774 string_set(&ServicePtrs[i]->szUsername, "");
1775 string_set(&ServicePtrs[i]->comment, comment);
1776 string_set(&ServicePtrs[i]->fstype, "IPC");
1777 ServicePtrs[i]->iMaxConnections = 0;
1778 ServicePtrs[i]->bAvailable = true;
1779 ServicePtrs[i]->bRead_only = true;
1780 ServicePtrs[i]->bGuest_only = false;
1781 ServicePtrs[i]->bAdministrative_share = true;
1782 ServicePtrs[i]->bGuest_ok = guest_ok;
1783 ServicePtrs[i]->bPrint_ok = false;
1784 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1786 DEBUG(3, ("adding IPC service\n"));
1788 SAFE_FREE(comment);
1789 return true;
1792 /***************************************************************************
1793 Add a new printer service, with defaults coming from service iFrom.
1794 ***************************************************************************/
1796 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1798 const char *comment = "From Printcap";
1799 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1801 if (i < 0)
1802 return false;
1804 /* note that we do NOT default the availability flag to true - */
1805 /* we take it from the default service passed. This allows all */
1806 /* dynamic printers to be disabled by disabling the [printers] */
1807 /* entry (if/when the 'available' keyword is implemented!). */
1809 /* the printer name is set to the service name. */
1810 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1811 string_set(&ServicePtrs[i]->comment, comment);
1813 /* set the browseable flag from the gloabl default */
1814 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1816 /* Printers cannot be read_only. */
1817 ServicePtrs[i]->bRead_only = false;
1818 /* No share modes on printer services. */
1819 ServicePtrs[i]->bShareModes = false;
1820 /* No oplocks on printer services. */
1821 ServicePtrs[i]->bOpLocks = false;
1822 /* Printer services must be printable. */
1823 ServicePtrs[i]->bPrint_ok = true;
1825 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1827 return true;
1831 /***************************************************************************
1832 Check whether the given parameter name is valid.
1833 Parametric options (names containing a colon) are considered valid.
1834 ***************************************************************************/
1836 bool lp_parameter_is_valid(const char *pszParmName)
1838 return ((map_parameter(pszParmName) != -1) ||
1839 (strchr(pszParmName, ':') != NULL));
1842 /***************************************************************************
1843 Check whether the given name is the name of a global parameter.
1844 Returns true for strings belonging to parameters of class
1845 P_GLOBAL, false for all other strings, also for parametric options
1846 and strings not belonging to any option.
1847 ***************************************************************************/
1849 bool lp_parameter_is_global(const char *pszParmName)
1851 int num = map_parameter(pszParmName);
1853 if (num >= 0) {
1854 return (parm_table[num].p_class == P_GLOBAL);
1857 return false;
1860 /**************************************************************************
1861 Check whether the given name is the canonical name of a parameter.
1862 Returns false if it is not a valid parameter Name.
1863 For parametric options, true is returned.
1864 **************************************************************************/
1866 bool lp_parameter_is_canonical(const char *parm_name)
1868 if (!lp_parameter_is_valid(parm_name)) {
1869 return false;
1872 return (map_parameter(parm_name) ==
1873 map_parameter_canonical(parm_name, NULL));
1876 /**************************************************************************
1877 Determine the canonical name for a parameter.
1878 Indicate when it is an inverse (boolean) synonym instead of a
1879 "usual" synonym.
1880 **************************************************************************/
1882 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1883 bool *inverse)
1885 int num;
1887 if (!lp_parameter_is_valid(parm_name)) {
1888 *canon_parm = NULL;
1889 return false;
1892 num = map_parameter_canonical(parm_name, inverse);
1893 if (num < 0) {
1894 /* parametric option */
1895 *canon_parm = parm_name;
1896 } else {
1897 *canon_parm = parm_table[num].label;
1900 return true;
1904 /**************************************************************************
1905 Determine the canonical name for a parameter.
1906 Turn the value given into the inverse boolean expression when
1907 the synonym is an invers boolean synonym.
1909 Return true if parm_name is a valid parameter name and
1910 in case it is an invers boolean synonym, if the val string could
1911 successfully be converted to the reverse bool.
1912 Return false in all other cases.
1913 **************************************************************************/
1915 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1916 const char *val,
1917 const char **canon_parm,
1918 const char **canon_val)
1920 int num;
1921 bool inverse;
1923 if (!lp_parameter_is_valid(parm_name)) {
1924 *canon_parm = NULL;
1925 *canon_val = NULL;
1926 return false;
1929 num = map_parameter_canonical(parm_name, &inverse);
1930 if (num < 0) {
1931 /* parametric option */
1932 *canon_parm = parm_name;
1933 *canon_val = val;
1934 } else {
1935 *canon_parm = parm_table[num].label;
1936 if (inverse) {
1937 if (!lp_invert_boolean(val, canon_val)) {
1938 *canon_val = NULL;
1939 return false;
1941 } else {
1942 *canon_val = val;
1946 return true;
1949 /***************************************************************************
1950 Map a parameter's string representation to something we can use.
1951 Returns false if the parameter string is not recognised, else TRUE.
1952 ***************************************************************************/
1954 static int map_parameter(const char *pszParmName)
1956 int iIndex;
1958 if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
1959 return (-1);
1961 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1962 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1963 return (iIndex);
1965 /* Warn only if it isn't parametric option */
1966 if (strchr(pszParmName, ':') == NULL)
1967 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1968 /* We do return 'fail' for parametric options as well because they are
1969 stored in different storage
1971 return (-1);
1974 /***************************************************************************
1975 Map a parameter's string representation to the index of the canonical
1976 form of the parameter (it might be a synonym).
1977 Returns -1 if the parameter string is not recognised.
1978 ***************************************************************************/
1980 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1982 int parm_num, canon_num;
1983 bool loc_inverse = false;
1985 parm_num = map_parameter(pszParmName);
1986 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1987 /* invalid, parametric or no canidate for synonyms ... */
1988 goto done;
1991 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1992 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1993 parm_num = canon_num;
1994 goto done;
1998 done:
1999 if (inverse != NULL) {
2000 *inverse = loc_inverse;
2002 return parm_num;
2005 /***************************************************************************
2006 return true if parameter number parm1 is a synonym of parameter
2007 number parm2 (parm2 being the principal name).
2008 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
2009 false otherwise.
2010 ***************************************************************************/
2012 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
2014 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
2015 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
2016 (parm_table[parm1].flags & FLAG_HIDE) &&
2017 !(parm_table[parm2].flags & FLAG_HIDE))
2019 if (inverse != NULL) {
2020 if ((parm_table[parm1].type == P_BOOLREV) &&
2021 (parm_table[parm2].type == P_BOOL))
2023 *inverse = true;
2024 } else {
2025 *inverse = false;
2028 return true;
2030 return false;
2033 /***************************************************************************
2034 Show one parameter's name, type, [values,] and flags.
2035 (helper functions for show_parameter_list)
2036 ***************************************************************************/
2038 static void show_parameter(int parmIndex)
2040 int enumIndex, flagIndex;
2041 int parmIndex2;
2042 bool hadFlag;
2043 bool hadSyn;
2044 bool inverse;
2045 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2046 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2047 "P_ENUM", "P_SEP"};
2048 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2049 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2050 FLAG_HIDE};
2051 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2052 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2053 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2055 printf("%s=%s", parm_table[parmIndex].label,
2056 type[parm_table[parmIndex].type]);
2057 if (parm_table[parmIndex].type == P_ENUM) {
2058 printf(",");
2059 for (enumIndex=0;
2060 parm_table[parmIndex].enum_list[enumIndex].name;
2061 enumIndex++)
2063 printf("%s%s",
2064 enumIndex ? "|" : "",
2065 parm_table[parmIndex].enum_list[enumIndex].name);
2068 printf(",");
2069 hadFlag = false;
2070 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2071 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2072 printf("%s%s",
2073 hadFlag ? "|" : "",
2074 flag_names[flagIndex]);
2075 hadFlag = true;
2079 /* output synonyms */
2080 hadSyn = false;
2081 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2082 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2083 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2084 parm_table[parmIndex2].label);
2085 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2086 if (!hadSyn) {
2087 printf(" (synonyms: ");
2088 hadSyn = true;
2089 } else {
2090 printf(", ");
2092 printf("%s%s", parm_table[parmIndex2].label,
2093 inverse ? "[i]" : "");
2096 if (hadSyn) {
2097 printf(")");
2100 printf("\n");
2103 /***************************************************************************
2104 Show all parameter's name, type, [values,] and flags.
2105 ***************************************************************************/
2107 void show_parameter_list(void)
2109 int classIndex, parmIndex;
2110 const char *section_names[] = { "local", "global", NULL};
2112 for (classIndex=0; section_names[classIndex]; classIndex++) {
2113 printf("[%s]\n", section_names[classIndex]);
2114 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2115 if (parm_table[parmIndex].p_class == classIndex) {
2116 show_parameter(parmIndex);
2122 /***************************************************************************
2123 Check if a given string correctly represents a boolean value.
2124 ***************************************************************************/
2126 bool lp_string_is_valid_boolean(const char *parm_value)
2128 return set_boolean(parm_value, NULL);
2131 /***************************************************************************
2132 Get the standard string representation of a boolean value ("yes" or "no")
2133 ***************************************************************************/
2135 static const char *get_boolean(bool bool_value)
2137 static const char *yes_str = "yes";
2138 static const char *no_str = "no";
2140 return (bool_value ? yes_str : no_str);
2143 /***************************************************************************
2144 Provide the string of the negated boolean value associated to the boolean
2145 given as a string. Returns false if the passed string does not correctly
2146 represent a boolean.
2147 ***************************************************************************/
2149 bool lp_invert_boolean(const char *str, const char **inverse_str)
2151 bool val;
2153 if (!set_boolean(str, &val)) {
2154 return false;
2157 *inverse_str = get_boolean(!val);
2158 return true;
2161 /***************************************************************************
2162 Provide the canonical string representation of a boolean value given
2163 as a string. Return true on success, false if the string given does
2164 not correctly represent a boolean.
2165 ***************************************************************************/
2167 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2169 bool val;
2171 if (!set_boolean(str, &val)) {
2172 return false;
2175 *canon_str = get_boolean(val);
2176 return true;
2179 /***************************************************************************
2180 Find a service by name. Otherwise works like get_service.
2181 ***************************************************************************/
2183 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2185 int iService = -1;
2186 char *canon_name;
2187 TDB_DATA data;
2188 NTSTATUS status;
2190 if (ServiceHash == NULL) {
2191 return -1;
2194 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2196 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2197 &data);
2199 if (NT_STATUS_IS_OK(status) &&
2200 (data.dptr != NULL) &&
2201 (data.dsize == sizeof(iService)))
2203 iService = *(int *)data.dptr;
2206 TALLOC_FREE(canon_name);
2208 if ((iService != -1) && (LP_SNUM_OK(iService))
2209 && (pserviceDest != NULL)) {
2210 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2213 return (iService);
2216 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2217 struct loadparm_service *lp_service(const char *pszServiceName)
2219 int iService = getservicebyname(pszServiceName, NULL);
2220 if (iService == -1 || !LP_SNUM_OK(iService)) {
2221 return NULL;
2223 return ServicePtrs[iService];
2226 struct loadparm_service *lp_servicebynum(int snum)
2228 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2229 return NULL;
2231 return ServicePtrs[snum];
2234 struct loadparm_service *lp_default_loadparm_service()
2236 return &sDefault;
2240 /***************************************************************************
2241 Copy a service structure to another.
2242 If pcopymapDest is NULL then copy all fields
2243 ***************************************************************************/
2246 * Add a parametric option to a parmlist_entry,
2247 * replacing old value, if already present.
2249 static void set_param_opt(struct parmlist_entry **opt_list,
2250 const char *opt_name,
2251 const char *opt_value,
2252 unsigned priority)
2254 struct parmlist_entry *new_opt, *opt;
2255 bool not_added;
2257 opt = *opt_list;
2258 not_added = true;
2260 /* Traverse destination */
2261 while (opt) {
2262 /* If we already have same option, override it */
2263 if (strwicmp(opt->key, opt_name) == 0) {
2264 if ((opt->priority & FLAG_CMDLINE) &&
2265 !(priority & FLAG_CMDLINE)) {
2266 /* it's been marked as not to be
2267 overridden */
2268 return;
2270 string_free(&opt->value);
2271 TALLOC_FREE(opt->list);
2272 opt->value = SMB_STRDUP(opt_value);
2273 opt->priority = priority;
2274 not_added = false;
2275 break;
2277 opt = opt->next;
2279 if (not_added) {
2280 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2281 new_opt->key = SMB_STRDUP(opt_name);
2282 new_opt->value = SMB_STRDUP(opt_value);
2283 new_opt->list = NULL;
2284 new_opt->priority = priority;
2285 DLIST_ADD(*opt_list, new_opt);
2289 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2290 struct bitmap *pcopymapDest)
2292 int i;
2293 bool bcopyall = (pcopymapDest == NULL);
2294 struct parmlist_entry *data;
2296 for (i = 0; parm_table[i].label; i++)
2297 if (parm_table[i].p_class == P_LOCAL &&
2298 (bcopyall || bitmap_query(pcopymapDest,i))) {
2299 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2300 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2302 switch (parm_table[i].type) {
2303 case P_BOOL:
2304 case P_BOOLREV:
2305 *(bool *)dest_ptr = *(bool *)src_ptr;
2306 break;
2308 case P_INTEGER:
2309 case P_ENUM:
2310 case P_OCTAL:
2311 case P_BYTES:
2312 *(int *)dest_ptr = *(int *)src_ptr;
2313 break;
2315 case P_CHAR:
2316 *(char *)dest_ptr = *(char *)src_ptr;
2317 break;
2319 case P_STRING:
2320 string_set((char **)dest_ptr,
2321 *(char **)src_ptr);
2322 break;
2324 case P_USTRING:
2326 char *upper_string = strupper_talloc(talloc_tos(),
2327 *(char **)src_ptr);
2328 string_set((char **)dest_ptr,
2329 upper_string);
2330 TALLOC_FREE(upper_string);
2331 break;
2333 case P_LIST:
2334 TALLOC_FREE(*((char ***)dest_ptr));
2335 *((char ***)dest_ptr) = str_list_copy(NULL,
2336 *(const char ***)src_ptr);
2337 break;
2338 default:
2339 break;
2343 if (bcopyall) {
2344 init_copymap(pserviceDest);
2345 if (pserviceSource->copymap)
2346 bitmap_copy(pserviceDest->copymap,
2347 pserviceSource->copymap);
2350 data = pserviceSource->param_opt;
2351 while (data) {
2352 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2353 data = data->next;
2357 /***************************************************************************
2358 Check a service for consistency. Return false if the service is in any way
2359 incomplete or faulty, else true.
2360 ***************************************************************************/
2362 bool service_ok(int iService)
2364 bool bRetval;
2366 bRetval = true;
2367 if (ServicePtrs[iService]->szService[0] == '\0') {
2368 DEBUG(0, ("The following message indicates an internal error:\n"));
2369 DEBUG(0, ("No service name in service entry.\n"));
2370 bRetval = false;
2373 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2374 /* I can't see why you'd want a non-printable printer service... */
2375 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2376 if (!ServicePtrs[iService]->bPrint_ok) {
2377 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2378 ServicePtrs[iService]->szService));
2379 ServicePtrs[iService]->bPrint_ok = true;
2381 /* [printers] service must also be non-browsable. */
2382 if (ServicePtrs[iService]->bBrowseable)
2383 ServicePtrs[iService]->bBrowseable = false;
2386 if (ServicePtrs[iService]->szPath[0] == '\0' &&
2387 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2388 ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2390 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2391 ServicePtrs[iService]->szService));
2392 ServicePtrs[iService]->bAvailable = false;
2395 /* If a service is flagged unavailable, log the fact at level 1. */
2396 if (!ServicePtrs[iService]->bAvailable)
2397 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2398 ServicePtrs[iService]->szService));
2400 return (bRetval);
2403 static struct smbconf_ctx *lp_smbconf_ctx(void)
2405 sbcErr err;
2406 static struct smbconf_ctx *conf_ctx = NULL;
2408 if (conf_ctx == NULL) {
2409 err = smbconf_init(NULL, &conf_ctx, "registry:");
2410 if (!SBC_ERROR_IS_OK(err)) {
2411 DEBUG(1, ("error initializing registry configuration: "
2412 "%s\n", sbcErrorString(err)));
2413 conf_ctx = NULL;
2417 return conf_ctx;
2420 static bool process_smbconf_service(struct smbconf_service *service)
2422 uint32_t count;
2423 bool ret;
2425 if (service == NULL) {
2426 return false;
2429 ret = do_section(service->name, NULL);
2430 if (ret != true) {
2431 return false;
2433 for (count = 0; count < service->num_params; count++) {
2434 ret = do_parameter(service->param_names[count],
2435 service->param_values[count],
2436 NULL);
2437 if (ret != true) {
2438 return false;
2441 if (iServiceIndex >= 0) {
2442 return service_ok(iServiceIndex);
2444 return true;
2448 * load a service from registry and activate it
2450 bool process_registry_service(const char *service_name)
2452 sbcErr err;
2453 struct smbconf_service *service = NULL;
2454 TALLOC_CTX *mem_ctx = talloc_stackframe();
2455 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2456 bool ret = false;
2458 if (conf_ctx == NULL) {
2459 goto done;
2462 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2464 if (!smbconf_share_exists(conf_ctx, service_name)) {
2466 * Registry does not contain data for this service (yet),
2467 * but make sure lp_load doesn't return false.
2469 ret = true;
2470 goto done;
2473 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2474 if (!SBC_ERROR_IS_OK(err)) {
2475 goto done;
2478 ret = process_smbconf_service(service);
2479 if (!ret) {
2480 goto done;
2483 /* store the csn */
2484 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2486 done:
2487 TALLOC_FREE(mem_ctx);
2488 return ret;
2492 * process_registry_globals
2494 static bool process_registry_globals(void)
2496 bool ret;
2498 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2500 ret = do_parameter("registry shares", "yes", NULL);
2501 if (!ret) {
2502 return ret;
2505 return process_registry_service(GLOBAL_NAME);
2508 bool process_registry_shares(void)
2510 sbcErr err;
2511 uint32_t count;
2512 struct smbconf_service **service = NULL;
2513 uint32_t num_shares = 0;
2514 TALLOC_CTX *mem_ctx = talloc_stackframe();
2515 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2516 bool ret = false;
2518 if (conf_ctx == NULL) {
2519 goto done;
2522 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2523 if (!SBC_ERROR_IS_OK(err)) {
2524 goto done;
2527 ret = true;
2529 for (count = 0; count < num_shares; count++) {
2530 if (strequal(service[count]->name, GLOBAL_NAME)) {
2531 continue;
2533 ret = process_smbconf_service(service[count]);
2534 if (!ret) {
2535 goto done;
2539 /* store the csn */
2540 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2542 done:
2543 TALLOC_FREE(mem_ctx);
2544 return ret;
2548 * reload those shares from registry that are already
2549 * activated in the services array.
2551 static bool reload_registry_shares(void)
2553 int i;
2554 bool ret = true;
2556 for (i = 0; i < iNumServices; i++) {
2557 if (!VALID(i)) {
2558 continue;
2561 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2562 continue;
2565 ret = process_registry_service(ServicePtrs[i]->szService);
2566 if (!ret) {
2567 goto done;
2571 done:
2572 return ret;
2576 #define MAX_INCLUDE_DEPTH 100
2578 static uint8_t include_depth;
2580 static struct file_lists {
2581 struct file_lists *next;
2582 char *name;
2583 char *subfname;
2584 time_t modtime;
2585 } *file_lists = NULL;
2587 /*******************************************************************
2588 Keep a linked list of all config files so we know when one has changed
2589 it's date and needs to be reloaded.
2590 ********************************************************************/
2592 static void add_to_file_list(const char *fname, const char *subfname)
2594 struct file_lists *f = file_lists;
2596 while (f) {
2597 if (f->name && !strcmp(f->name, fname))
2598 break;
2599 f = f->next;
2602 if (!f) {
2603 f = SMB_MALLOC_P(struct file_lists);
2604 if (!f)
2605 return;
2606 f->next = file_lists;
2607 f->name = SMB_STRDUP(fname);
2608 if (!f->name) {
2609 SAFE_FREE(f);
2610 return;
2612 f->subfname = SMB_STRDUP(subfname);
2613 if (!f->subfname) {
2614 SAFE_FREE(f->name);
2615 SAFE_FREE(f);
2616 return;
2618 file_lists = f;
2619 f->modtime = file_modtime(subfname);
2620 } else {
2621 time_t t = file_modtime(subfname);
2622 if (t)
2623 f->modtime = t;
2625 return;
2629 * Free the file lists
2631 static void free_file_list(void)
2633 struct file_lists *f;
2634 struct file_lists *next;
2636 f = file_lists;
2637 while( f ) {
2638 next = f->next;
2639 SAFE_FREE( f->name );
2640 SAFE_FREE( f->subfname );
2641 SAFE_FREE( f );
2642 f = next;
2644 file_lists = NULL;
2649 * Utility function for outsiders to check if we're running on registry.
2651 bool lp_config_backend_is_registry(void)
2653 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2657 * Utility function to check if the config backend is FILE.
2659 bool lp_config_backend_is_file(void)
2661 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2664 /*******************************************************************
2665 Check if a config file has changed date.
2666 ********************************************************************/
2668 bool lp_file_list_changed(void)
2670 struct file_lists *f = file_lists;
2672 DEBUG(6, ("lp_file_list_changed()\n"));
2674 while (f) {
2675 time_t mod_time;
2677 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2678 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2680 if (conf_ctx == NULL) {
2681 return false;
2683 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2684 NULL))
2686 DEBUGADD(6, ("registry config changed\n"));
2687 return true;
2689 } else {
2690 char *n2 = NULL;
2691 n2 = talloc_sub_basic(talloc_tos(),
2692 get_current_username(),
2693 current_user_info.domain,
2694 f->name);
2695 if (!n2) {
2696 return false;
2698 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2699 f->name, n2, ctime(&f->modtime)));
2701 mod_time = file_modtime(n2);
2703 if (mod_time &&
2704 ((f->modtime != mod_time) ||
2705 (f->subfname == NULL) ||
2706 (strcmp(n2, f->subfname) != 0)))
2708 DEBUGADD(6,
2709 ("file %s modified: %s\n", n2,
2710 ctime(&mod_time)));
2711 f->modtime = mod_time;
2712 SAFE_FREE(f->subfname);
2713 f->subfname = SMB_STRDUP(n2);
2714 TALLOC_FREE(n2);
2715 return true;
2717 TALLOC_FREE(n2);
2719 f = f->next;
2721 return false;
2726 * Initialize iconv conversion descriptors.
2728 * This is called the first time it is needed, and also called again
2729 * every time the configuration is reloaded, because the charset or
2730 * codepage might have changed.
2732 static void init_iconv(void)
2734 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2735 lp_unix_charset(),
2736 true, global_iconv_handle);
2739 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2741 if (strcmp(*ptr, pszParmValue) != 0) {
2742 string_set(ptr, pszParmValue);
2743 init_iconv();
2745 return true;
2748 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2750 bool is_utf8 = false;
2751 size_t len = strlen(pszParmValue);
2753 if (len == 4 || len == 5) {
2754 /* Don't use StrCaseCmp here as we don't want to
2755 initialize iconv. */
2756 if ((toupper_m(pszParmValue[0]) == 'U') &&
2757 (toupper_m(pszParmValue[1]) == 'T') &&
2758 (toupper_m(pszParmValue[2]) == 'F')) {
2759 if (len == 4) {
2760 if (pszParmValue[3] == '8') {
2761 is_utf8 = true;
2763 } else {
2764 if (pszParmValue[3] == '-' &&
2765 pszParmValue[4] == '8') {
2766 is_utf8 = true;
2772 if (strcmp(*ptr, pszParmValue) != 0) {
2773 if (is_utf8) {
2774 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2775 "be UTF8, using (default value) %s instead.\n",
2776 DEFAULT_DOS_CHARSET));
2777 pszParmValue = DEFAULT_DOS_CHARSET;
2779 string_set(ptr, pszParmValue);
2780 init_iconv();
2782 return true;
2785 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2787 bool ret = true;
2788 char *realm = strupper_talloc(talloc_tos(), pszParmValue);
2789 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2791 ret &= string_set(&Globals.szRealm, pszParmValue);
2792 ret &= string_set(&Globals.szRealm_upper, realm);
2793 ret &= string_set(&Globals.szRealm_lower, dnsdomain);
2794 TALLOC_FREE(realm);
2796 return ret;
2799 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2801 TALLOC_FREE(Globals.szNetbiosAliases);
2802 Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2803 return set_netbios_aliases(Globals.szNetbiosAliases);
2806 /***************************************************************************
2807 Handle the include operation.
2808 ***************************************************************************/
2809 static bool bAllowIncludeRegistry = true;
2811 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2813 char *fname;
2815 if (include_depth >= MAX_INCLUDE_DEPTH) {
2816 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2817 include_depth));
2818 return false;
2821 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2822 if (!bAllowIncludeRegistry) {
2823 return true;
2825 if (bInGlobalSection) {
2826 bool ret;
2827 include_depth++;
2828 ret = process_registry_globals();
2829 include_depth--;
2830 return ret;
2831 } else {
2832 DEBUG(1, ("\"include = registry\" only effective "
2833 "in %s section\n", GLOBAL_NAME));
2834 return false;
2838 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2839 current_user_info.domain,
2840 pszParmValue);
2842 add_to_file_list(pszParmValue, fname);
2844 string_set(ptr, fname);
2846 if (file_exist(fname)) {
2847 bool ret;
2848 include_depth++;
2849 ret = pm_process(fname, do_section, do_parameter, NULL);
2850 include_depth--;
2851 TALLOC_FREE(fname);
2852 return ret;
2855 DEBUG(2, ("Can't find include file %s\n", fname));
2856 TALLOC_FREE(fname);
2857 return true;
2860 /***************************************************************************
2861 Handle the interpretation of the copy parameter.
2862 ***************************************************************************/
2864 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2866 bool bRetval;
2867 int iTemp;
2868 struct loadparm_service serviceTemp;
2870 string_set(ptr, pszParmValue);
2872 init_service(&serviceTemp);
2874 bRetval = false;
2876 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2878 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2879 if (iTemp == iServiceIndex) {
2880 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2881 } else {
2882 copy_service(ServicePtrs[iServiceIndex],
2883 &serviceTemp,
2884 ServicePtrs[iServiceIndex]->copymap);
2885 bRetval = true;
2887 } else {
2888 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2889 bRetval = false;
2892 free_service(&serviceTemp);
2893 return (bRetval);
2896 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2898 Globals.ldap_debug_level = lp_int(pszParmValue);
2899 init_ldap_debugging();
2900 return true;
2903 /***************************************************************************
2904 Handle idmap/non unix account uid and gid allocation parameters. The format of these
2905 parameters is:
2907 [global]
2909 idmap uid = 1000-1999
2910 idmap gid = 700-899
2912 We only do simple parsing checks here. The strings are parsed into useful
2913 structures in the idmap daemon code.
2915 ***************************************************************************/
2917 /* Some lp_ routines to return idmap [ug]id information */
2919 static uid_t idmap_uid_low, idmap_uid_high;
2920 static gid_t idmap_gid_low, idmap_gid_high;
2922 bool lp_idmap_uid(uid_t *low, uid_t *high)
2924 if (idmap_uid_low == 0 || idmap_uid_high == 0)
2925 return false;
2927 if (low)
2928 *low = idmap_uid_low;
2930 if (high)
2931 *high = idmap_uid_high;
2933 return true;
2936 bool lp_idmap_gid(gid_t *low, gid_t *high)
2938 if (idmap_gid_low == 0 || idmap_gid_high == 0)
2939 return false;
2941 if (low)
2942 *low = idmap_gid_low;
2944 if (high)
2945 *high = idmap_gid_high;
2947 return true;
2950 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2952 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2954 return true;
2957 /* Do some simple checks on "idmap [ug]id" parameter values */
2959 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2961 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2963 return true;
2966 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2968 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2970 return true;
2973 /***************************************************************************
2974 Handle the DEBUG level list.
2975 ***************************************************************************/
2977 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2979 string_set(ptr, pszParmValueIn);
2980 return debug_parse_levels(pszParmValueIn);
2983 /***************************************************************************
2984 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2985 ***************************************************************************/
2987 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2989 const char *suffix_string;
2991 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2992 Globals.szLdapSuffix );
2993 if ( !suffix_string ) {
2994 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2995 return "";
2998 return suffix_string;
3001 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
3003 if (Globals.szLdapMachineSuffix[0])
3004 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
3006 return lp_string(ctx, Globals.szLdapSuffix);
3009 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
3011 if (Globals.szLdapUserSuffix[0])
3012 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3014 return lp_string(ctx, Globals.szLdapSuffix);
3017 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3019 if (Globals.szLdapGroupSuffix[0])
3020 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3022 return lp_string(ctx, Globals.szLdapSuffix);
3025 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3027 if (Globals.szLdapIdmapSuffix[0])
3028 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3030 return lp_string(ctx, Globals.szLdapSuffix);
3033 /****************************************************************************
3034 set the value for a P_ENUM
3035 ***************************************************************************/
3037 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3038 int *ptr )
3040 int i;
3042 for (i = 0; parm->enum_list[i].name; i++) {
3043 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3044 *ptr = parm->enum_list[i].value;
3045 return;
3048 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3049 pszParmValue, parm->label));
3052 /***************************************************************************
3053 ***************************************************************************/
3055 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3057 static int parm_num = -1;
3058 struct loadparm_service *s;
3060 if ( parm_num == -1 )
3061 parm_num = map_parameter( "printing" );
3063 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3065 if ( snum < 0 )
3066 s = &sDefault;
3067 else
3068 s = ServicePtrs[snum];
3070 init_printer_values( s );
3072 return true;
3076 /***************************************************************************
3077 Initialise a copymap.
3078 ***************************************************************************/
3080 static void init_copymap(struct loadparm_service *pservice)
3082 int i;
3084 TALLOC_FREE(pservice->copymap);
3086 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3087 if (!pservice->copymap)
3088 DEBUG(0,
3089 ("Couldn't allocate copymap!! (size %d)\n",
3090 (int)NUMPARAMETERS));
3091 else
3092 for (i = 0; i < NUMPARAMETERS; i++)
3093 bitmap_set(pservice->copymap, i);
3097 return the parameter pointer for a parameter
3099 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3101 if (service == NULL) {
3102 if (parm->p_class == P_LOCAL)
3103 return (void *)(((char *)&sDefault)+parm->offset);
3104 else if (parm->p_class == P_GLOBAL)
3105 return (void *)(((char *)&Globals)+parm->offset);
3106 else return NULL;
3107 } else {
3108 return (void *)(((char *)service) + parm->offset);
3112 /***************************************************************************
3113 Return the local pointer to a parameter given the service number and parameter
3114 ***************************************************************************/
3116 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3118 return lp_parm_ptr(ServicePtrs[snum], parm);
3121 /***************************************************************************
3122 Process a parameter for a particular service number. If snum < 0
3123 then assume we are in the globals.
3124 ***************************************************************************/
3126 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3128 int parmnum, i;
3129 void *parm_ptr = NULL; /* where we are going to store the result */
3130 struct parmlist_entry **opt_list;
3132 parmnum = map_parameter(pszParmName);
3134 if (parmnum < 0) {
3135 if (strchr(pszParmName, ':') == NULL) {
3136 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3137 pszParmName));
3138 return true;
3142 * We've got a parametric option
3145 opt_list = (snum < 0)
3146 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3147 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3149 return true;
3152 /* if it's already been set by the command line, then we don't
3153 override here */
3154 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3155 return true;
3158 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3159 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3160 pszParmName));
3163 /* we might point at a service, the default service or a global */
3164 if (snum < 0) {
3165 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3166 } else {
3167 if (parm_table[parmnum].p_class == P_GLOBAL) {
3168 DEBUG(0,
3169 ("Global parameter %s found in service section!\n",
3170 pszParmName));
3171 return true;
3173 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3176 if (snum >= 0) {
3177 if (!ServicePtrs[snum]->copymap)
3178 init_copymap(ServicePtrs[snum]);
3180 /* this handles the aliases - set the copymap for other entries with
3181 the same data pointer */
3182 for (i = 0; parm_table[i].label; i++) {
3183 if ((parm_table[i].offset == parm_table[parmnum].offset)
3184 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3185 bitmap_clear(ServicePtrs[snum]->copymap, i);
3190 /* if it is a special case then go ahead */
3191 if (parm_table[parmnum].special) {
3192 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3193 (char **)parm_ptr);
3196 /* now switch on the type of variable it is */
3197 switch (parm_table[parmnum].type)
3199 case P_BOOL:
3200 *(bool *)parm_ptr = lp_bool(pszParmValue);
3201 break;
3203 case P_BOOLREV:
3204 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3205 break;
3207 case P_INTEGER:
3208 *(int *)parm_ptr = lp_int(pszParmValue);
3209 break;
3211 case P_CHAR:
3212 *(char *)parm_ptr = *pszParmValue;
3213 break;
3215 case P_OCTAL:
3216 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3217 if ( i != 1 ) {
3218 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3220 break;
3222 case P_BYTES:
3224 uint64_t val;
3225 if (conv_str_size_error(pszParmValue, &val)) {
3226 if (val <= INT_MAX) {
3227 *(int *)parm_ptr = (int)val;
3228 break;
3232 DEBUG(0,("lp_do_parameter(%s): value is not "
3233 "a valid size specifier!\n", pszParmValue));
3234 return false;
3237 case P_LIST:
3238 case P_CMDLIST:
3239 TALLOC_FREE(*((char ***)parm_ptr));
3240 *(char ***)parm_ptr = str_list_make_v3(
3241 NULL, pszParmValue, NULL);
3242 break;
3244 case P_STRING:
3245 string_set((char **)parm_ptr, pszParmValue);
3246 break;
3248 case P_USTRING:
3250 char *upper_string = strupper_talloc(talloc_tos(),
3251 pszParmValue);
3252 string_set((char **)parm_ptr, upper_string);
3253 TALLOC_FREE(upper_string);
3254 break;
3256 case P_ENUM:
3257 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3258 break;
3259 case P_SEP:
3260 break;
3263 return true;
3266 /***************************************************************************
3267 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3268 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3269 ***************************************************************************/
3271 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3273 int parmnum, i;
3274 parmnum = map_parameter(pszParmName);
3275 if (parmnum >= 0) {
3276 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3277 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3278 return false;
3280 parm_table[parmnum].flags |= FLAG_CMDLINE;
3282 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3283 * be grouped in the table, so we don't have to search the
3284 * whole table */
3285 for (i=parmnum-1;
3286 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3287 && parm_table[i].p_class == parm_table[parmnum].p_class;
3288 i--) {
3289 parm_table[i].flags |= FLAG_CMDLINE;
3291 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3292 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3293 parm_table[i].flags |= FLAG_CMDLINE;
3296 if (store_values) {
3297 store_lp_set_cmdline(pszParmName, pszParmValue);
3299 return true;
3302 /* it might be parametric */
3303 if (strchr(pszParmName, ':') != NULL) {
3304 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3305 if (store_values) {
3306 store_lp_set_cmdline(pszParmName, pszParmValue);
3308 return true;
3311 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3312 return true;
3315 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3317 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3320 /***************************************************************************
3321 Process a parameter.
3322 ***************************************************************************/
3324 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3325 void *userdata)
3327 if (!bInGlobalSection && bGlobalOnly)
3328 return true;
3330 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3332 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3333 pszParmName, pszParmValue));
3337 set a option from the commandline in 'a=b' format. Use to support --option
3339 bool lp_set_option(const char *option)
3341 char *p, *s;
3342 bool ret;
3344 s = talloc_strdup(NULL, option);
3345 if (!s) {
3346 return false;
3349 p = strchr(s, '=');
3350 if (!p) {
3351 talloc_free(s);
3352 return false;
3355 *p = 0;
3357 /* skip white spaces after the = sign */
3358 do {
3359 p++;
3360 } while (*p == ' ');
3362 ret = lp_set_cmdline(s, p);
3363 talloc_free(s);
3364 return ret;
3367 /**************************************************************************
3368 Print a parameter of the specified type.
3369 ***************************************************************************/
3371 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3373 /* For the seperation of lists values that we print below */
3374 const char *list_sep = ", ";
3375 int i;
3376 switch (p->type)
3378 case P_ENUM:
3379 for (i = 0; p->enum_list[i].name; i++) {
3380 if (*(int *)ptr == p->enum_list[i].value) {
3381 fprintf(f, "%s",
3382 p->enum_list[i].name);
3383 break;
3386 break;
3388 case P_BOOL:
3389 fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3390 break;
3392 case P_BOOLREV:
3393 fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3394 break;
3396 case P_INTEGER:
3397 case P_BYTES:
3398 fprintf(f, "%d", *(int *)ptr);
3399 break;
3401 case P_CHAR:
3402 fprintf(f, "%c", *(char *)ptr);
3403 break;
3405 case P_OCTAL: {
3406 int val = *(int *)ptr;
3407 if (val == -1) {
3408 fprintf(f, "-1");
3409 } else {
3410 fprintf(f, "0%o", val);
3412 break;
3415 case P_CMDLIST:
3416 list_sep = " ";
3417 /* fall through */
3418 case P_LIST:
3419 if ((char ***)ptr && *(char ***)ptr) {
3420 char **list = *(char ***)ptr;
3421 for (; *list; list++) {
3422 /* surround strings with whitespace in double quotes */
3423 if (*(list+1) == NULL) {
3424 /* last item, no extra separator */
3425 list_sep = "";
3427 if ( strchr_m( *list, ' ' ) ) {
3428 fprintf(f, "\"%s\"%s", *list, list_sep);
3429 } else {
3430 fprintf(f, "%s%s", *list, list_sep);
3434 break;
3436 case P_STRING:
3437 case P_USTRING:
3438 if (*(char **)ptr) {
3439 fprintf(f, "%s", *(char **)ptr);
3441 break;
3442 case P_SEP:
3443 break;
3447 /***************************************************************************
3448 Check if two parameters are equal.
3449 ***************************************************************************/
3451 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3453 switch (type) {
3454 case P_BOOL:
3455 case P_BOOLREV:
3456 return (*((bool *)ptr1) == *((bool *)ptr2));
3458 case P_INTEGER:
3459 case P_ENUM:
3460 case P_OCTAL:
3461 case P_BYTES:
3462 return (*((int *)ptr1) == *((int *)ptr2));
3464 case P_CHAR:
3465 return (*((char *)ptr1) == *((char *)ptr2));
3467 case P_LIST:
3468 case P_CMDLIST:
3469 return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3471 case P_STRING:
3472 case P_USTRING:
3474 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3475 if (p1 && !*p1)
3476 p1 = NULL;
3477 if (p2 && !*p2)
3478 p2 = NULL;
3479 return (p1 == p2 || strequal(p1, p2));
3481 case P_SEP:
3482 break;
3484 return false;
3487 /***************************************************************************
3488 Initialize any local varients in the sDefault table.
3489 ***************************************************************************/
3491 void init_locals(void)
3493 /* None as yet. */
3496 /***************************************************************************
3497 Process a new section (service). At this stage all sections are services.
3498 Later we'll have special sections that permit server parameters to be set.
3499 Returns true on success, false on failure.
3500 ***************************************************************************/
3502 static bool do_section(const char *pszSectionName, void *userdata)
3504 bool bRetval;
3505 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3506 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3507 bRetval = false;
3509 /* if we were in a global section then do the local inits */
3510 if (bInGlobalSection && !isglobal)
3511 init_locals();
3513 /* if we've just struck a global section, note the fact. */
3514 bInGlobalSection = isglobal;
3516 /* check for multiple global sections */
3517 if (bInGlobalSection) {
3518 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3519 return true;
3522 if (!bInGlobalSection && bGlobalOnly)
3523 return true;
3525 /* if we have a current service, tidy it up before moving on */
3526 bRetval = true;
3528 if (iServiceIndex >= 0)
3529 bRetval = service_ok(iServiceIndex);
3531 /* if all is still well, move to the next record in the services array */
3532 if (bRetval) {
3533 /* We put this here to avoid an odd message order if messages are */
3534 /* issued by the post-processing of a previous section. */
3535 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3537 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3538 if (iServiceIndex < 0) {
3539 DEBUG(0, ("Failed to add a new service\n"));
3540 return false;
3542 /* Clean all parametric options for service */
3543 /* They will be added during parsing again */
3544 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3547 return bRetval;
3551 /***************************************************************************
3552 Determine if a partcular base parameter is currentl set to the default value.
3553 ***************************************************************************/
3555 static bool is_default(int i)
3557 if (!defaults_saved)
3558 return false;
3559 switch (parm_table[i].type) {
3560 case P_LIST:
3561 case P_CMDLIST:
3562 return str_list_equal((const char **)parm_table[i].def.lvalue,
3563 *(const char ***)lp_parm_ptr(NULL,
3564 &parm_table[i]));
3565 case P_STRING:
3566 case P_USTRING:
3567 return strequal(parm_table[i].def.svalue,
3568 *(char **)lp_parm_ptr(NULL,
3569 &parm_table[i]));
3570 case P_BOOL:
3571 case P_BOOLREV:
3572 return parm_table[i].def.bvalue ==
3573 *(bool *)lp_parm_ptr(NULL,
3574 &parm_table[i]);
3575 case P_CHAR:
3576 return parm_table[i].def.cvalue ==
3577 *(char *)lp_parm_ptr(NULL,
3578 &parm_table[i]);
3579 case P_INTEGER:
3580 case P_OCTAL:
3581 case P_ENUM:
3582 case P_BYTES:
3583 return parm_table[i].def.ivalue ==
3584 *(int *)lp_parm_ptr(NULL,
3585 &parm_table[i]);
3586 case P_SEP:
3587 break;
3589 return false;
3592 /***************************************************************************
3593 Display the contents of the global structure.
3594 ***************************************************************************/
3596 static void dump_globals(FILE *f)
3598 int i;
3599 struct parmlist_entry *data;
3601 fprintf(f, "[global]\n");
3603 for (i = 0; parm_table[i].label; i++)
3604 if (parm_table[i].p_class == P_GLOBAL &&
3605 !(parm_table[i].flags & FLAG_META) &&
3606 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3607 if (defaults_saved && is_default(i))
3608 continue;
3609 fprintf(f, "\t%s = ", parm_table[i].label);
3610 print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3611 &parm_table[i]),
3613 fprintf(f, "\n");
3615 if (Globals.param_opt != NULL) {
3616 data = Globals.param_opt;
3617 while(data) {
3618 fprintf(f, "\t%s = %s\n", data->key, data->value);
3619 data = data->next;
3625 /***************************************************************************
3626 Return true if a local parameter is currently set to the global default.
3627 ***************************************************************************/
3629 bool lp_is_default(int snum, struct parm_struct *parm)
3631 return equal_parameter(parm->type,
3632 lp_parm_ptr(ServicePtrs[snum], parm),
3633 lp_parm_ptr(NULL, parm));
3636 /***************************************************************************
3637 Display the contents of a single services record.
3638 ***************************************************************************/
3640 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3642 int i;
3643 struct parmlist_entry *data;
3645 if (pService != &sDefault)
3646 fprintf(f, "[%s]\n", pService->szService);
3648 for (i = 0; parm_table[i].label; i++) {
3650 if (parm_table[i].p_class == P_LOCAL &&
3651 !(parm_table[i].flags & FLAG_META) &&
3652 (*parm_table[i].label != '-') &&
3653 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3655 if (pService == &sDefault) {
3656 if (defaults_saved && is_default(i))
3657 continue;
3658 } else {
3659 if (equal_parameter(parm_table[i].type,
3660 lp_parm_ptr(pService, &parm_table[i]),
3661 lp_parm_ptr(NULL, &parm_table[i])))
3662 continue;
3665 fprintf(f, "\t%s = ", parm_table[i].label);
3666 print_parameter(&parm_table[i],
3667 lp_parm_ptr(pService, &parm_table[i]),
3669 fprintf(f, "\n");
3673 if (pService->param_opt != NULL) {
3674 data = pService->param_opt;
3675 while(data) {
3676 fprintf(f, "\t%s = %s\n", data->key, data->value);
3677 data = data->next;
3682 /***************************************************************************
3683 Display the contents of a parameter of a single services record.
3684 ***************************************************************************/
3686 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3688 int i;
3689 bool result = false;
3690 parm_class p_class;
3691 unsigned flag = 0;
3692 fstring local_parm_name;
3693 char *parm_opt;
3694 const char *parm_opt_value;
3696 /* check for parametrical option */
3697 fstrcpy( local_parm_name, parm_name);
3698 parm_opt = strchr( local_parm_name, ':');
3700 if (parm_opt) {
3701 *parm_opt = '\0';
3702 parm_opt++;
3703 if (strlen(parm_opt)) {
3704 parm_opt_value = lp_parm_const_string( snum,
3705 local_parm_name, parm_opt, NULL);
3706 if (parm_opt_value) {
3707 printf( "%s\n", parm_opt_value);
3708 result = true;
3711 return result;
3714 /* check for a key and print the value */
3715 if (isGlobal) {
3716 p_class = P_GLOBAL;
3717 flag = FLAG_GLOBAL;
3718 } else
3719 p_class = P_LOCAL;
3721 for (i = 0; parm_table[i].label; i++) {
3722 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3723 !(parm_table[i].flags & FLAG_META) &&
3724 (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3725 (*parm_table[i].label != '-') &&
3726 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3728 void *ptr;
3730 if (isGlobal) {
3731 ptr = lp_parm_ptr(NULL,
3732 &parm_table[i]);
3733 } else {
3734 ptr = lp_parm_ptr(ServicePtrs[snum],
3735 &parm_table[i]);
3738 print_parameter(&parm_table[i],
3739 ptr, f);
3740 fprintf(f, "\n");
3741 result = true;
3742 break;
3746 return result;
3749 /***************************************************************************
3750 Return info about the requested parameter (given as a string).
3751 Return NULL when the string is not a valid parameter name.
3752 ***************************************************************************/
3754 struct parm_struct *lp_get_parameter(const char *param_name)
3756 int num = map_parameter(param_name);
3758 if (num < 0) {
3759 return NULL;
3762 return &parm_table[num];
3765 /***************************************************************************
3766 Return info about the next parameter in a service.
3767 snum==GLOBAL_SECTION_SNUM gives the globals.
3768 Return NULL when out of parameters.
3769 ***************************************************************************/
3771 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3773 if (snum < 0) {
3774 /* do the globals */
3775 for (; parm_table[*i].label; (*i)++) {
3776 if (parm_table[*i].p_class == P_SEPARATOR)
3777 return &parm_table[(*i)++];
3779 if ((*parm_table[*i].label == '-'))
3780 continue;
3782 if ((*i) > 0
3783 && (parm_table[*i].offset ==
3784 parm_table[(*i) - 1].offset)
3785 && (parm_table[*i].p_class ==
3786 parm_table[(*i) - 1].p_class))
3787 continue;
3789 if (is_default(*i) && !allparameters)
3790 continue;
3792 return &parm_table[(*i)++];
3794 } else {
3795 struct loadparm_service *pService = ServicePtrs[snum];
3797 for (; parm_table[*i].label; (*i)++) {
3798 if (parm_table[*i].p_class == P_SEPARATOR)
3799 return &parm_table[(*i)++];
3801 if (parm_table[*i].p_class == P_LOCAL &&
3802 (*parm_table[*i].label != '-') &&
3803 ((*i) == 0 ||
3804 (parm_table[*i].offset !=
3805 parm_table[(*i) - 1].offset)))
3807 if (allparameters ||
3808 !equal_parameter(parm_table[*i].type,
3809 lp_parm_ptr(pService,
3810 &parm_table[*i]),
3811 lp_parm_ptr(NULL,
3812 &parm_table[*i])))
3814 return &parm_table[(*i)++];
3820 return NULL;
3824 #if 0
3825 /***************************************************************************
3826 Display the contents of a single copy structure.
3827 ***************************************************************************/
3828 static void dump_copy_map(bool *pcopymap)
3830 int i;
3831 if (!pcopymap)
3832 return;
3834 printf("\n\tNon-Copied parameters:\n");
3836 for (i = 0; parm_table[i].label; i++)
3837 if (parm_table[i].p_class == P_LOCAL &&
3838 parm_table[i].ptr && !pcopymap[i] &&
3839 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3841 printf("\t\t%s\n", parm_table[i].label);
3844 #endif
3846 /***************************************************************************
3847 Return TRUE if the passed service number is within range.
3848 ***************************************************************************/
3850 bool lp_snum_ok(int iService)
3852 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3855 /***************************************************************************
3856 Auto-load some home services.
3857 ***************************************************************************/
3859 static void lp_add_auto_services(char *str)
3861 char *s;
3862 char *p;
3863 int homes;
3864 char *saveptr;
3866 if (!str)
3867 return;
3869 s = SMB_STRDUP(str);
3870 if (!s)
3871 return;
3873 homes = lp_servicenumber(HOMES_NAME);
3875 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3876 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3877 char *home;
3879 if (lp_servicenumber(p) >= 0)
3880 continue;
3882 home = get_user_home_dir(talloc_tos(), p);
3884 if (home && home[0] && homes >= 0)
3885 lp_add_home(p, homes, p, home);
3887 TALLOC_FREE(home);
3889 SAFE_FREE(s);
3892 /***************************************************************************
3893 Auto-load one printer.
3894 ***************************************************************************/
3896 void lp_add_one_printer(const char *name, const char *comment,
3897 const char *location, void *pdata)
3899 int printers = lp_servicenumber(PRINTERS_NAME);
3900 int i;
3902 if (lp_servicenumber(name) < 0) {
3903 lp_add_printer(name, printers);
3904 if ((i = lp_servicenumber(name)) >= 0) {
3905 string_set(&ServicePtrs[i]->comment, comment);
3906 ServicePtrs[i]->autoloaded = true;
3911 /***************************************************************************
3912 Have we loaded a services file yet?
3913 ***************************************************************************/
3915 bool lp_loaded(void)
3917 return (bLoaded);
3920 /***************************************************************************
3921 Unload unused services.
3922 ***************************************************************************/
3924 void lp_killunused(struct smbd_server_connection *sconn,
3925 bool (*snumused) (struct smbd_server_connection *, int))
3927 int i;
3928 for (i = 0; i < iNumServices; i++) {
3929 if (!VALID(i))
3930 continue;
3932 /* don't kill autoloaded or usershare services */
3933 if ( ServicePtrs[i]->autoloaded ||
3934 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3935 continue;
3938 if (!snumused || !snumused(sconn, i)) {
3939 free_service_byindex(i);
3945 * Kill all except autoloaded and usershare services - convenience wrapper
3947 void lp_kill_all_services(void)
3949 lp_killunused(NULL, NULL);
3952 /***************************************************************************
3953 Unload a service.
3954 ***************************************************************************/
3956 void lp_killservice(int iServiceIn)
3958 if (VALID(iServiceIn)) {
3959 free_service_byindex(iServiceIn);
3963 /***************************************************************************
3964 Save the curent values of all global and sDefault parameters into the
3965 defaults union. This allows swat and testparm to show only the
3966 changed (ie. non-default) parameters.
3967 ***************************************************************************/
3969 static void lp_save_defaults(void)
3971 int i;
3972 for (i = 0; parm_table[i].label; i++) {
3973 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3974 && parm_table[i].p_class == parm_table[i - 1].p_class)
3975 continue;
3976 switch (parm_table[i].type) {
3977 case P_LIST:
3978 case P_CMDLIST:
3979 parm_table[i].def.lvalue = str_list_copy(
3980 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3981 break;
3982 case P_STRING:
3983 case P_USTRING:
3984 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3985 break;
3986 case P_BOOL:
3987 case P_BOOLREV:
3988 parm_table[i].def.bvalue =
3989 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3990 break;
3991 case P_CHAR:
3992 parm_table[i].def.cvalue =
3993 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3994 break;
3995 case P_INTEGER:
3996 case P_OCTAL:
3997 case P_ENUM:
3998 case P_BYTES:
3999 parm_table[i].def.ivalue =
4000 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
4001 break;
4002 case P_SEP:
4003 break;
4006 defaults_saved = true;
4009 /***********************************************************
4010 If we should send plaintext/LANMAN passwords in the clinet
4011 ************************************************************/
4013 static void set_allowed_client_auth(void)
4015 if (Globals.bClientNTLMv2Auth) {
4016 Globals.bClientLanManAuth = false;
4018 if (!Globals.bClientLanManAuth) {
4019 Globals.bClientPlaintextAuth = false;
4023 /***************************************************************************
4024 JRA.
4025 The following code allows smbd to read a user defined share file.
4026 Yes, this is my intent. Yes, I'm comfortable with that...
4028 THE FOLLOWING IS SECURITY CRITICAL CODE.
4030 It washes your clothes, it cleans your house, it guards you while you sleep...
4031 Do not f%^k with it....
4032 ***************************************************************************/
4034 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4036 /***************************************************************************
4037 Check allowed stat state of a usershare file.
4038 Ensure we print out who is dicking with us so the admin can
4039 get their sorry ass fired.
4040 ***************************************************************************/
4042 static bool check_usershare_stat(const char *fname,
4043 const SMB_STRUCT_STAT *psbuf)
4045 if (!S_ISREG(psbuf->st_ex_mode)) {
4046 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4047 "not a regular file\n",
4048 fname, (unsigned int)psbuf->st_ex_uid ));
4049 return false;
4052 /* Ensure this doesn't have the other write bit set. */
4053 if (psbuf->st_ex_mode & S_IWOTH) {
4054 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4055 "public write. Refusing to allow as a usershare file.\n",
4056 fname, (unsigned int)psbuf->st_ex_uid ));
4057 return false;
4060 /* Should be 10k or less. */
4061 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4062 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4063 "too large (%u) to be a user share file.\n",
4064 fname, (unsigned int)psbuf->st_ex_uid,
4065 (unsigned int)psbuf->st_ex_size ));
4066 return false;
4069 return true;
4072 /***************************************************************************
4073 Parse the contents of a usershare file.
4074 ***************************************************************************/
4076 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4077 SMB_STRUCT_STAT *psbuf,
4078 const char *servicename,
4079 int snum,
4080 char **lines,
4081 int numlines,
4082 char **pp_sharepath,
4083 char **pp_comment,
4084 char **pp_cp_servicename,
4085 struct security_descriptor **ppsd,
4086 bool *pallow_guest)
4088 const char **prefixallowlist = lp_usershare_prefix_allow_list();
4089 const char **prefixdenylist = lp_usershare_prefix_deny_list();
4090 int us_vers;
4091 DIR *dp;
4092 SMB_STRUCT_STAT sbuf;
4093 char *sharepath = NULL;
4094 char *comment = NULL;
4096 *pp_sharepath = NULL;
4097 *pp_comment = NULL;
4099 *pallow_guest = false;
4101 if (numlines < 4) {
4102 return USERSHARE_MALFORMED_FILE;
4105 if (strcmp(lines[0], "#VERSION 1") == 0) {
4106 us_vers = 1;
4107 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4108 us_vers = 2;
4109 if (numlines < 5) {
4110 return USERSHARE_MALFORMED_FILE;
4112 } else {
4113 return USERSHARE_BAD_VERSION;
4116 if (strncmp(lines[1], "path=", 5) != 0) {
4117 return USERSHARE_MALFORMED_PATH;
4120 sharepath = talloc_strdup(ctx, &lines[1][5]);
4121 if (!sharepath) {
4122 return USERSHARE_POSIX_ERR;
4124 trim_string(sharepath, " ", " ");
4126 if (strncmp(lines[2], "comment=", 8) != 0) {
4127 return USERSHARE_MALFORMED_COMMENT_DEF;
4130 comment = talloc_strdup(ctx, &lines[2][8]);
4131 if (!comment) {
4132 return USERSHARE_POSIX_ERR;
4134 trim_string(comment, " ", " ");
4135 trim_char(comment, '"', '"');
4137 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4138 return USERSHARE_MALFORMED_ACL_DEF;
4141 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4142 return USERSHARE_ACL_ERR;
4145 if (us_vers == 2) {
4146 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4147 return USERSHARE_MALFORMED_ACL_DEF;
4149 if (lines[4][9] == 'y') {
4150 *pallow_guest = true;
4153 /* Backwards compatible extension to file version #2. */
4154 if (numlines > 5) {
4155 if (strncmp(lines[5], "sharename=", 10) != 0) {
4156 return USERSHARE_MALFORMED_SHARENAME_DEF;
4158 if (!strequal(&lines[5][10], servicename)) {
4159 return USERSHARE_BAD_SHARENAME;
4161 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4162 if (!*pp_cp_servicename) {
4163 return USERSHARE_POSIX_ERR;
4168 if (*pp_cp_servicename == NULL) {
4169 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4170 if (!*pp_cp_servicename) {
4171 return USERSHARE_POSIX_ERR;
4175 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4176 /* Path didn't change, no checks needed. */
4177 *pp_sharepath = sharepath;
4178 *pp_comment = comment;
4179 return USERSHARE_OK;
4182 /* The path *must* be absolute. */
4183 if (sharepath[0] != '/') {
4184 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4185 servicename, sharepath));
4186 return USERSHARE_PATH_NOT_ABSOLUTE;
4189 /* If there is a usershare prefix deny list ensure one of these paths
4190 doesn't match the start of the user given path. */
4191 if (prefixdenylist) {
4192 int i;
4193 for ( i=0; prefixdenylist[i]; i++ ) {
4194 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4195 servicename, i, prefixdenylist[i], sharepath ));
4196 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4197 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4198 "usershare prefix deny list entries.\n",
4199 servicename, sharepath));
4200 return USERSHARE_PATH_IS_DENIED;
4205 /* If there is a usershare prefix allow list ensure one of these paths
4206 does match the start of the user given path. */
4208 if (prefixallowlist) {
4209 int i;
4210 for ( i=0; prefixallowlist[i]; i++ ) {
4211 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4212 servicename, i, prefixallowlist[i], sharepath ));
4213 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4214 break;
4217 if (prefixallowlist[i] == NULL) {
4218 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4219 "usershare prefix allow list entries.\n",
4220 servicename, sharepath));
4221 return USERSHARE_PATH_NOT_ALLOWED;
4225 /* Ensure this is pointing to a directory. */
4226 dp = opendir(sharepath);
4228 if (!dp) {
4229 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4230 servicename, sharepath));
4231 return USERSHARE_PATH_NOT_DIRECTORY;
4234 /* Ensure the owner of the usershare file has permission to share
4235 this directory. */
4237 if (sys_stat(sharepath, &sbuf, false) == -1) {
4238 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4239 servicename, sharepath, strerror(errno) ));
4240 closedir(dp);
4241 return USERSHARE_POSIX_ERR;
4244 closedir(dp);
4246 if (!S_ISDIR(sbuf.st_ex_mode)) {
4247 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4248 servicename, sharepath ));
4249 return USERSHARE_PATH_NOT_DIRECTORY;
4252 /* Check if sharing is restricted to owner-only. */
4253 /* psbuf is the stat of the usershare definition file,
4254 sbuf is the stat of the target directory to be shared. */
4256 if (lp_usershare_owner_only()) {
4257 /* root can share anything. */
4258 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4259 return USERSHARE_PATH_NOT_ALLOWED;
4263 *pp_sharepath = sharepath;
4264 *pp_comment = comment;
4265 return USERSHARE_OK;
4268 /***************************************************************************
4269 Deal with a usershare file.
4270 Returns:
4271 >= 0 - snum
4272 -1 - Bad name, invalid contents.
4273 - service name already existed and not a usershare, problem
4274 with permissions to share directory etc.
4275 ***************************************************************************/
4277 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4279 SMB_STRUCT_STAT sbuf;
4280 SMB_STRUCT_STAT lsbuf;
4281 char *fname = NULL;
4282 char *sharepath = NULL;
4283 char *comment = NULL;
4284 char *cp_service_name = NULL;
4285 char **lines = NULL;
4286 int numlines = 0;
4287 int fd = -1;
4288 int iService = -1;
4289 TALLOC_CTX *ctx = talloc_stackframe();
4290 struct security_descriptor *psd = NULL;
4291 bool guest_ok = false;
4292 char *canon_name = NULL;
4293 bool added_service = false;
4294 int ret = -1;
4296 /* Ensure share name doesn't contain invalid characters. */
4297 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4298 DEBUG(0,("process_usershare_file: share name %s contains "
4299 "invalid characters (any of %s)\n",
4300 file_name, INVALID_SHARENAME_CHARS ));
4301 goto out;
4304 canon_name = canonicalize_servicename(ctx, file_name);
4305 if (!canon_name) {
4306 goto out;
4309 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4310 if (!fname) {
4311 goto out;
4314 /* Minimize the race condition by doing an lstat before we
4315 open and fstat. Ensure this isn't a symlink link. */
4317 if (sys_lstat(fname, &lsbuf, false) != 0) {
4318 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4319 fname, strerror(errno) ));
4320 goto out;
4323 /* This must be a regular file, not a symlink, directory or
4324 other strange filetype. */
4325 if (!check_usershare_stat(fname, &lsbuf)) {
4326 goto out;
4330 TDB_DATA data;
4331 NTSTATUS status;
4333 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4334 canon_name, &data);
4336 iService = -1;
4338 if (NT_STATUS_IS_OK(status) &&
4339 (data.dptr != NULL) &&
4340 (data.dsize == sizeof(iService))) {
4341 memcpy(&iService, data.dptr, sizeof(iService));
4345 if (iService != -1 &&
4346 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4347 &lsbuf.st_ex_mtime) == 0) {
4348 /* Nothing changed - Mark valid and return. */
4349 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4350 canon_name ));
4351 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4352 ret = iService;
4353 goto out;
4356 /* Try and open the file read only - no symlinks allowed. */
4357 #ifdef O_NOFOLLOW
4358 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4359 #else
4360 fd = open(fname, O_RDONLY, 0);
4361 #endif
4363 if (fd == -1) {
4364 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4365 fname, strerror(errno) ));
4366 goto out;
4369 /* Now fstat to be *SURE* it's a regular file. */
4370 if (sys_fstat(fd, &sbuf, false) != 0) {
4371 close(fd);
4372 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4373 fname, strerror(errno) ));
4374 goto out;
4377 /* Is it the same dev/inode as was lstated ? */
4378 if (!check_same_stat(&lsbuf, &sbuf)) {
4379 close(fd);
4380 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4381 "Symlink spoofing going on ?\n", fname ));
4382 goto out;
4385 /* This must be a regular file, not a symlink, directory or
4386 other strange filetype. */
4387 if (!check_usershare_stat(fname, &sbuf)) {
4388 goto out;
4391 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4393 close(fd);
4394 if (lines == NULL) {
4395 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4396 fname, (unsigned int)sbuf.st_ex_uid ));
4397 goto out;
4400 if (parse_usershare_file(ctx, &sbuf, file_name,
4401 iService, lines, numlines, &sharepath,
4402 &comment, &cp_service_name,
4403 &psd, &guest_ok) != USERSHARE_OK) {
4404 goto out;
4407 /* Everything ok - add the service possibly using a template. */
4408 if (iService < 0) {
4409 const struct loadparm_service *sp = &sDefault;
4410 if (snum_template != -1) {
4411 sp = ServicePtrs[snum_template];
4414 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4415 DEBUG(0, ("process_usershare_file: Failed to add "
4416 "new service %s\n", cp_service_name));
4417 goto out;
4420 added_service = true;
4422 /* Read only is controlled by usershare ACL below. */
4423 ServicePtrs[iService]->bRead_only = false;
4426 /* Write the ACL of the new/modified share. */
4427 if (!set_share_security(canon_name, psd)) {
4428 DEBUG(0, ("process_usershare_file: Failed to set share "
4429 "security for user share %s\n",
4430 canon_name ));
4431 goto out;
4434 /* If from a template it may be marked invalid. */
4435 ServicePtrs[iService]->valid = true;
4437 /* Set the service as a valid usershare. */
4438 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4440 /* Set guest access. */
4441 if (lp_usershare_allow_guests()) {
4442 ServicePtrs[iService]->bGuest_ok = guest_ok;
4445 /* And note when it was loaded. */
4446 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4447 string_set(&ServicePtrs[iService]->szPath, sharepath);
4448 string_set(&ServicePtrs[iService]->comment, comment);
4450 ret = iService;
4452 out:
4454 if (ret == -1 && iService != -1 && added_service) {
4455 lp_remove_service(iService);
4458 TALLOC_FREE(lines);
4459 TALLOC_FREE(ctx);
4460 return ret;
4463 /***************************************************************************
4464 Checks if a usershare entry has been modified since last load.
4465 ***************************************************************************/
4467 static bool usershare_exists(int iService, struct timespec *last_mod)
4469 SMB_STRUCT_STAT lsbuf;
4470 const char *usersharepath = Globals.szUsersharePath;
4471 char *fname;
4473 if (asprintf(&fname, "%s/%s",
4474 usersharepath,
4475 ServicePtrs[iService]->szService) < 0) {
4476 return false;
4479 if (sys_lstat(fname, &lsbuf, false) != 0) {
4480 SAFE_FREE(fname);
4481 return false;
4484 if (!S_ISREG(lsbuf.st_ex_mode)) {
4485 SAFE_FREE(fname);
4486 return false;
4489 SAFE_FREE(fname);
4490 *last_mod = lsbuf.st_ex_mtime;
4491 return true;
4494 /***************************************************************************
4495 Load a usershare service by name. Returns a valid servicenumber or -1.
4496 ***************************************************************************/
4498 int load_usershare_service(const char *servicename)
4500 SMB_STRUCT_STAT sbuf;
4501 const char *usersharepath = Globals.szUsersharePath;
4502 int max_user_shares = Globals.iUsershareMaxShares;
4503 int snum_template = -1;
4505 if (*usersharepath == 0 || max_user_shares == 0) {
4506 return -1;
4509 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4510 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4511 usersharepath, strerror(errno) ));
4512 return -1;
4515 if (!S_ISDIR(sbuf.st_ex_mode)) {
4516 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4517 usersharepath ));
4518 return -1;
4522 * This directory must be owned by root, and have the 't' bit set.
4523 * It also must not be writable by "other".
4526 #ifdef S_ISVTX
4527 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4528 #else
4529 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4530 #endif
4531 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4532 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4533 usersharepath ));
4534 return -1;
4537 /* Ensure the template share exists if it's set. */
4538 if (Globals.szUsershareTemplateShare[0]) {
4539 /* We can't use lp_servicenumber here as we are recommending that
4540 template shares have -valid=false set. */
4541 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4542 if (ServicePtrs[snum_template]->szService &&
4543 strequal(ServicePtrs[snum_template]->szService,
4544 Globals.szUsershareTemplateShare)) {
4545 break;
4549 if (snum_template == -1) {
4550 DEBUG(0,("load_usershare_service: usershare template share %s "
4551 "does not exist.\n",
4552 Globals.szUsershareTemplateShare ));
4553 return -1;
4557 return process_usershare_file(usersharepath, servicename, snum_template);
4560 /***************************************************************************
4561 Load all user defined shares from the user share directory.
4562 We only do this if we're enumerating the share list.
4563 This is the function that can delete usershares that have
4564 been removed.
4565 ***************************************************************************/
4567 int load_usershare_shares(struct smbd_server_connection *sconn,
4568 bool (*snumused) (struct smbd_server_connection *, int))
4570 DIR *dp;
4571 SMB_STRUCT_STAT sbuf;
4572 struct dirent *de;
4573 int num_usershares = 0;
4574 int max_user_shares = Globals.iUsershareMaxShares;
4575 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4576 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4577 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4578 int iService;
4579 int snum_template = -1;
4580 const char *usersharepath = Globals.szUsersharePath;
4581 int ret = lp_numservices();
4582 TALLOC_CTX *tmp_ctx;
4584 if (max_user_shares == 0 || *usersharepath == '\0') {
4585 return lp_numservices();
4588 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4589 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4590 usersharepath, strerror(errno) ));
4591 return ret;
4595 * This directory must be owned by root, and have the 't' bit set.
4596 * It also must not be writable by "other".
4599 #ifdef S_ISVTX
4600 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4601 #else
4602 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4603 #endif
4604 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4605 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4606 usersharepath ));
4607 return ret;
4610 /* Ensure the template share exists if it's set. */
4611 if (Globals.szUsershareTemplateShare[0]) {
4612 /* We can't use lp_servicenumber here as we are recommending that
4613 template shares have -valid=false set. */
4614 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4615 if (ServicePtrs[snum_template]->szService &&
4616 strequal(ServicePtrs[snum_template]->szService,
4617 Globals.szUsershareTemplateShare)) {
4618 break;
4622 if (snum_template == -1) {
4623 DEBUG(0,("load_usershare_shares: usershare template share %s "
4624 "does not exist.\n",
4625 Globals.szUsershareTemplateShare ));
4626 return ret;
4630 /* Mark all existing usershares as pending delete. */
4631 for (iService = iNumServices - 1; iService >= 0; iService--) {
4632 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4633 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4637 dp = opendir(usersharepath);
4638 if (!dp) {
4639 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4640 usersharepath, strerror(errno) ));
4641 return ret;
4644 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4645 (de = readdir(dp));
4646 num_dir_entries++ ) {
4647 int r;
4648 const char *n = de->d_name;
4650 /* Ignore . and .. */
4651 if (*n == '.') {
4652 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4653 continue;
4657 if (n[0] == ':') {
4658 /* Temporary file used when creating a share. */
4659 num_tmp_dir_entries++;
4662 /* Allow 20% tmp entries. */
4663 if (num_tmp_dir_entries > allowed_tmp_entries) {
4664 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4665 "in directory %s\n",
4666 num_tmp_dir_entries, usersharepath));
4667 break;
4670 r = process_usershare_file(usersharepath, n, snum_template);
4671 if (r == 0) {
4672 /* Update the services count. */
4673 num_usershares++;
4674 if (num_usershares >= max_user_shares) {
4675 DEBUG(0,("load_usershare_shares: max user shares reached "
4676 "on file %s in directory %s\n",
4677 n, usersharepath ));
4678 break;
4680 } else if (r == -1) {
4681 num_bad_dir_entries++;
4684 /* Allow 20% bad entries. */
4685 if (num_bad_dir_entries > allowed_bad_entries) {
4686 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4687 "in directory %s\n",
4688 num_bad_dir_entries, usersharepath));
4689 break;
4692 /* Allow 20% bad entries. */
4693 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4694 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4695 "in directory %s\n",
4696 num_dir_entries, usersharepath));
4697 break;
4701 closedir(dp);
4703 /* Sweep through and delete any non-refreshed usershares that are
4704 not currently in use. */
4705 tmp_ctx = talloc_stackframe();
4706 for (iService = iNumServices - 1; iService >= 0; iService--) {
4707 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4708 char *servname;
4710 if (snumused && snumused(sconn, iService)) {
4711 continue;
4714 servname = lp_servicename(tmp_ctx, iService);
4716 /* Remove from the share ACL db. */
4717 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4718 servname ));
4719 delete_share_security(servname);
4720 free_service_byindex(iService);
4723 talloc_free(tmp_ctx);
4725 return lp_numservices();
4728 /********************************************************
4729 Destroy global resources allocated in this file
4730 ********************************************************/
4732 void gfree_loadparm(void)
4734 int i;
4736 free_file_list();
4738 /* Free resources allocated to services */
4740 for ( i = 0; i < iNumServices; i++ ) {
4741 if ( VALID(i) ) {
4742 free_service_byindex(i);
4746 SAFE_FREE( ServicePtrs );
4747 iNumServices = 0;
4749 /* Now release all resources allocated to global
4750 parameters and the default service */
4752 free_global_parameters();
4756 /***************************************************************************
4757 Allow client apps to specify that they are a client
4758 ***************************************************************************/
4759 static void lp_set_in_client(bool b)
4761 in_client = b;
4765 /***************************************************************************
4766 Determine if we're running in a client app
4767 ***************************************************************************/
4768 static bool lp_is_in_client(void)
4770 return in_client;
4773 /***************************************************************************
4774 Load the services array from the services file. Return true on success,
4775 false on failure.
4776 ***************************************************************************/
4778 static bool lp_load_ex(const char *pszFname,
4779 bool global_only,
4780 bool save_defaults,
4781 bool add_ipc,
4782 bool initialize_globals,
4783 bool allow_include_registry,
4784 bool load_all_shares)
4786 char *n2 = NULL;
4787 bool bRetval;
4789 bRetval = false;
4791 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4793 bInGlobalSection = true;
4794 bGlobalOnly = global_only;
4795 bAllowIncludeRegistry = allow_include_registry;
4797 init_globals(initialize_globals);
4799 free_file_list();
4801 if (save_defaults) {
4802 init_locals();
4803 lp_save_defaults();
4806 if (!initialize_globals) {
4807 free_param_opts(&Globals.param_opt);
4808 apply_lp_set_cmdline();
4811 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4813 /* We get sections first, so have to start 'behind' to make up */
4814 iServiceIndex = -1;
4816 if (lp_config_backend_is_file()) {
4817 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4818 current_user_info.domain,
4819 pszFname);
4820 if (!n2) {
4821 smb_panic("lp_load_ex: out of memory");
4824 add_to_file_list(pszFname, n2);
4826 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4827 TALLOC_FREE(n2);
4829 /* finish up the last section */
4830 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4831 if (bRetval) {
4832 if (iServiceIndex >= 0) {
4833 bRetval = service_ok(iServiceIndex);
4837 if (lp_config_backend_is_registry()) {
4838 /* config backend changed to registry in config file */
4840 * We need to use this extra global variable here to
4841 * survive restart: init_globals uses this as a default
4842 * for ConfigBackend. Otherwise, init_globals would
4843 * send us into an endless loop here.
4845 config_backend = CONFIG_BACKEND_REGISTRY;
4846 /* start over */
4847 DEBUG(1, ("lp_load_ex: changing to config backend "
4848 "registry\n"));
4849 init_globals(true);
4850 lp_kill_all_services();
4851 return lp_load_ex(pszFname, global_only, save_defaults,
4852 add_ipc, initialize_globals,
4853 allow_include_registry,
4854 load_all_shares);
4856 } else if (lp_config_backend_is_registry()) {
4857 bRetval = process_registry_globals();
4858 } else {
4859 DEBUG(0, ("Illegal config backend given: %d\n",
4860 lp_config_backend()));
4861 bRetval = false;
4864 if (bRetval && lp_registry_shares()) {
4865 if (load_all_shares) {
4866 bRetval = process_registry_shares();
4867 } else {
4868 bRetval = reload_registry_shares();
4873 char *serv = lp_auto_services(talloc_tos());
4874 lp_add_auto_services(serv);
4875 TALLOC_FREE(serv);
4878 if (add_ipc) {
4879 /* When 'restrict anonymous = 2' guest connections to ipc$
4880 are denied */
4881 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4882 if ( lp_enable_asu_support() ) {
4883 lp_add_ipc("ADMIN$", false);
4887 set_allowed_client_auth();
4889 if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4890 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4891 lp_passwordserver()));
4894 bLoaded = true;
4896 /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4897 /* if bWINSsupport is true and we are in the client */
4898 if (lp_is_in_client() && Globals.bWINSsupport) {
4899 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4902 init_iconv();
4904 fault_configure(smb_panic_s3);
4906 bAllowIncludeRegistry = true;
4908 return (bRetval);
4911 bool lp_load(const char *pszFname,
4912 bool global_only,
4913 bool save_defaults,
4914 bool add_ipc,
4915 bool initialize_globals)
4917 return lp_load_ex(pszFname,
4918 global_only,
4919 save_defaults,
4920 add_ipc,
4921 initialize_globals,
4922 true, /* allow_include_registry */
4923 false); /* load_all_shares*/
4926 bool lp_load_initial_only(const char *pszFname)
4928 return lp_load_ex(pszFname,
4929 true, /* global only */
4930 false, /* save_defaults */
4931 false, /* add_ipc */
4932 true, /* initialize_globals */
4933 false, /* allow_include_registry */
4934 false); /* load_all_shares*/
4938 * most common lp_load wrapper, loading only the globals
4940 bool lp_load_global(const char *file_name)
4942 return lp_load_ex(file_name,
4943 true, /* global_only */
4944 false, /* save_defaults */
4945 false, /* add_ipc */
4946 true, /* initialize_globals */
4947 true, /* allow_include_registry */
4948 false); /* load_all_shares*/
4952 * lp_load wrapper, especially for clients
4954 bool lp_load_client(const char *file_name)
4956 lp_set_in_client(true);
4958 return lp_load_global(file_name);
4962 * lp_load wrapper, loading only globals, but intended
4963 * for subsequent calls, not reinitializing the globals
4964 * to default values
4966 bool lp_load_global_no_reinit(const char *file_name)
4968 return lp_load_ex(file_name,
4969 true, /* global_only */
4970 false, /* save_defaults */
4971 false, /* add_ipc */
4972 false, /* initialize_globals */
4973 true, /* allow_include_registry */
4974 false); /* load_all_shares*/
4978 * lp_load wrapper, especially for clients, no reinitialization
4980 bool lp_load_client_no_reinit(const char *file_name)
4982 lp_set_in_client(true);
4984 return lp_load_global_no_reinit(file_name);
4987 bool lp_load_with_registry_shares(const char *pszFname,
4988 bool global_only,
4989 bool save_defaults,
4990 bool add_ipc,
4991 bool initialize_globals)
4993 return lp_load_ex(pszFname,
4994 global_only,
4995 save_defaults,
4996 add_ipc,
4997 initialize_globals,
4998 true, /* allow_include_registry */
4999 true); /* load_all_shares*/
5002 /***************************************************************************
5003 Return the max number of services.
5004 ***************************************************************************/
5006 int lp_numservices(void)
5008 return (iNumServices);
5011 /***************************************************************************
5012 Display the contents of the services array in human-readable form.
5013 ***************************************************************************/
5015 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5017 int iService;
5019 if (show_defaults)
5020 defaults_saved = false;
5022 dump_globals(f);
5024 dump_a_service(&sDefault, f);
5026 for (iService = 0; iService < maxtoprint; iService++) {
5027 fprintf(f,"\n");
5028 lp_dump_one(f, show_defaults, iService);
5032 /***************************************************************************
5033 Display the contents of one service in human-readable form.
5034 ***************************************************************************/
5036 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5038 if (VALID(snum)) {
5039 if (ServicePtrs[snum]->szService[0] == '\0')
5040 return;
5041 dump_a_service(ServicePtrs[snum], f);
5045 /***************************************************************************
5046 Return the number of the service with the given name, or -1 if it doesn't
5047 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5048 getservicebyname()! This works ONLY if all services have been loaded, and
5049 does not copy the found service.
5050 ***************************************************************************/
5052 int lp_servicenumber(const char *pszServiceName)
5054 int iService;
5055 fstring serviceName;
5057 if (!pszServiceName) {
5058 return GLOBAL_SECTION_SNUM;
5061 for (iService = iNumServices - 1; iService >= 0; iService--) {
5062 if (VALID(iService) && ServicePtrs[iService]->szService) {
5064 * The substitution here is used to support %U is
5065 * service names
5067 fstrcpy(serviceName, ServicePtrs[iService]->szService);
5068 standard_sub_basic(get_current_username(),
5069 current_user_info.domain,
5070 serviceName,sizeof(serviceName));
5071 if (strequal(serviceName, pszServiceName)) {
5072 break;
5077 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5078 struct timespec last_mod;
5080 if (!usershare_exists(iService, &last_mod)) {
5081 /* Remove the share security tdb entry for it. */
5082 delete_share_security(lp_servicename(talloc_tos(), iService));
5083 /* Remove it from the array. */
5084 free_service_byindex(iService);
5085 /* Doesn't exist anymore. */
5086 return GLOBAL_SECTION_SNUM;
5089 /* Has it been modified ? If so delete and reload. */
5090 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5091 &last_mod) < 0) {
5092 /* Remove it from the array. */
5093 free_service_byindex(iService);
5094 /* and now reload it. */
5095 iService = load_usershare_service(pszServiceName);
5099 if (iService < 0) {
5100 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5101 return GLOBAL_SECTION_SNUM;
5104 return (iService);
5107 /*******************************************************************
5108 A useful volume label function.
5109 ********************************************************************/
5111 const char *volume_label(TALLOC_CTX *ctx, int snum)
5113 char *ret;
5114 const char *label = lp_volume(ctx, snum);
5115 if (!*label) {
5116 label = lp_servicename(ctx, snum);
5119 /* This returns a 33 byte guarenteed null terminated string. */
5120 ret = talloc_strndup(ctx, label, 32);
5121 if (!ret) {
5122 return "";
5124 return ret;
5127 /*******************************************************************
5128 Get the default server type we will announce as via nmbd.
5129 ********************************************************************/
5131 int lp_default_server_announce(void)
5133 int default_server_announce = 0;
5134 default_server_announce |= SV_TYPE_WORKSTATION;
5135 default_server_announce |= SV_TYPE_SERVER;
5136 default_server_announce |= SV_TYPE_SERVER_UNIX;
5138 /* note that the flag should be set only if we have a
5139 printer service but nmbd doesn't actually load the
5140 services so we can't tell --jerry */
5142 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5144 default_server_announce |= SV_TYPE_SERVER_NT;
5145 default_server_announce |= SV_TYPE_NT;
5147 switch (lp_server_role()) {
5148 case ROLE_DOMAIN_MEMBER:
5149 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5150 break;
5151 case ROLE_DOMAIN_PDC:
5152 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5153 break;
5154 case ROLE_DOMAIN_BDC:
5155 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5156 break;
5157 case ROLE_STANDALONE:
5158 default:
5159 break;
5161 if (lp_time_server())
5162 default_server_announce |= SV_TYPE_TIME_SOURCE;
5164 if (lp_host_msdfs())
5165 default_server_announce |= SV_TYPE_DFS_SERVER;
5167 return default_server_announce;
5170 /***********************************************************
5171 If we are PDC then prefer us as DMB
5172 ************************************************************/
5174 bool lp_domain_master(void)
5176 if (Globals.domain_master == Auto)
5177 return (lp_server_role() == ROLE_DOMAIN_PDC);
5179 return (bool)Globals.domain_master;
5182 /***********************************************************
5183 If we are PDC then prefer us as DMB
5184 ************************************************************/
5186 static bool lp_domain_master_true_or_auto(void)
5188 if (Globals.domain_master) /* auto or yes */
5189 return true;
5191 return false;
5194 /***********************************************************
5195 If we are DMB then prefer us as LMB
5196 ************************************************************/
5198 bool lp_preferred_master(void)
5200 if (Globals.iPreferredMaster == Auto)
5201 return (lp_local_master() && lp_domain_master());
5203 return (bool)Globals.iPreferredMaster;
5206 /*******************************************************************
5207 Remove a service.
5208 ********************************************************************/
5210 void lp_remove_service(int snum)
5212 ServicePtrs[snum]->valid = false;
5213 invalid_services[num_invalid_services++] = snum;
5216 /*******************************************************************
5217 Copy a service.
5218 ********************************************************************/
5220 void lp_copy_service(int snum, const char *new_name)
5222 do_section(new_name, NULL);
5223 if (snum >= 0) {
5224 snum = lp_servicenumber(new_name);
5225 if (snum >= 0) {
5226 char *name = lp_servicename(talloc_tos(), snum);
5227 lp_do_parameter(snum, "copy", name);
5232 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5234 const char *ret = lp__printername(talloc_tos(), snum);
5235 if (ret == NULL || *ret == '\0') {
5236 ret = lp_const_servicename(snum);
5239 return ret;
5243 /***********************************************************
5244 Allow daemons such as winbindd to fix their logfile name.
5245 ************************************************************/
5247 void lp_set_logfile(const char *name)
5249 string_set(&Globals.logfile, name);
5250 debug_set_logfile(name);
5253 /*******************************************************************
5254 Return the max print jobs per queue.
5255 ********************************************************************/
5257 int lp_maxprintjobs(int snum)
5259 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5260 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5261 maxjobs = PRINT_MAX_JOBID - 1;
5263 return maxjobs;
5266 const char *lp_printcapname(void)
5268 if ((Globals.szPrintcapname != NULL) &&
5269 (Globals.szPrintcapname[0] != '\0'))
5270 return Globals.szPrintcapname;
5272 if (sDefault.iPrinting == PRINT_CUPS) {
5273 #ifdef HAVE_CUPS
5274 return "cups";
5275 #else
5276 return "lpstat";
5277 #endif
5280 if (sDefault.iPrinting == PRINT_BSD)
5281 return "/etc/printcap";
5283 return PRINTCAP_NAME;
5286 static uint32 spoolss_state;
5288 bool lp_disable_spoolss( void )
5290 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5291 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5293 return spoolss_state == SVCCTL_STOPPED ? true : false;
5296 void lp_set_spoolss_state( uint32 state )
5298 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5300 spoolss_state = state;
5303 uint32 lp_get_spoolss_state( void )
5305 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5308 /*******************************************************************
5309 Ensure we don't use sendfile if server smb signing is active.
5310 ********************************************************************/
5312 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5314 bool sign_active = false;
5316 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5317 if (get_Protocol() < PROTOCOL_NT1) {
5318 return false;
5320 if (signing_state) {
5321 sign_active = smb_signing_is_active(signing_state);
5323 return (lp__use_sendfile(snum) &&
5324 (get_remote_arch() != RA_WIN95) &&
5325 !sign_active);
5328 /*******************************************************************
5329 Turn off sendfile if we find the underlying OS doesn't support it.
5330 ********************************************************************/
5332 void set_use_sendfile(int snum, bool val)
5334 if (LP_SNUM_OK(snum))
5335 ServicePtrs[snum]->bUseSendfile = val;
5336 else
5337 sDefault.bUseSendfile = val;
5340 /*******************************************************************
5341 Turn off storing DOS attributes if this share doesn't support it.
5342 ********************************************************************/
5344 void set_store_dos_attributes(int snum, bool val)
5346 if (!LP_SNUM_OK(snum))
5347 return;
5348 ServicePtrs[(snum)]->bStoreDosAttributes = val;
5351 void lp_set_mangling_method(const char *new_method)
5353 string_set(&Globals.szManglingMethod, new_method);
5356 /*******************************************************************
5357 Global state for POSIX pathname processing.
5358 ********************************************************************/
5360 static bool posix_pathnames;
5362 bool lp_posix_pathnames(void)
5364 return posix_pathnames;
5367 /*******************************************************************
5368 Change everything needed to ensure POSIX pathname processing (currently
5369 not much).
5370 ********************************************************************/
5372 void lp_set_posix_pathnames(void)
5374 posix_pathnames = true;
5377 /*******************************************************************
5378 Global state for POSIX lock processing - CIFS unix extensions.
5379 ********************************************************************/
5381 bool posix_default_lock_was_set;
5382 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5384 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5386 if (posix_default_lock_was_set) {
5387 return posix_cifsx_locktype;
5388 } else {
5389 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5393 /*******************************************************************
5394 ********************************************************************/
5396 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5398 posix_default_lock_was_set = true;
5399 posix_cifsx_locktype = val;
5402 int lp_min_receive_file_size(void)
5404 if (Globals.iminreceivefile < 0) {
5405 return 0;
5407 return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5410 /*******************************************************************
5411 Safe wide links checks.
5412 This helper function always verify the validity of wide links,
5413 even after a configuration file reload.
5414 ********************************************************************/
5416 static bool lp_widelinks_internal(int snum)
5418 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5419 sDefault.bWidelinks);
5422 void widelinks_warning(int snum)
5424 if (lp_allow_insecure_widelinks()) {
5425 return;
5428 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5429 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5430 "These parameters are incompatible. "
5431 "Wide links will be disabled for this share.\n",
5432 lp_servicename(talloc_tos(), snum) ));
5436 bool lp_widelinks(int snum)
5438 /* wide links is always incompatible with unix extensions */
5439 if (lp_unix_extensions()) {
5441 * Unless we have "allow insecure widelinks"
5442 * turned on.
5444 if (!lp_allow_insecure_widelinks()) {
5445 return false;
5449 return lp_widelinks_internal(snum);
5452 bool lp_writeraw(void)
5454 if (lp_async_smb_echo_handler()) {
5455 return false;
5457 return lp__writeraw();
5460 bool lp_readraw(void)
5462 if (lp_async_smb_echo_handler()) {
5463 return false;
5465 return lp__readraw();
5468 int lp_server_role(void)
5470 return lp_find_server_role(lp__server_role(),
5471 lp__security(),
5472 lp__domain_logons(),
5473 lp_domain_master_true_or_auto());
5476 int lp_security(void)
5478 return lp_find_security(lp__server_role(),
5479 lp__security());