s4:winbind: add a netlogon_queue (tevent_queue)
[Samba/gebeck_regimport.git] / source3 / param / loadparm.c
blobd9ce4b4b5840047ba57881b9b811474dbcebe805
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 = SMB_SIGNING_DEFAULT,
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)
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 * const *)(&Globals.ptr) ? *(const char * const *)(&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 DEBUG(5, ("Freeing parametrics:\n"));
1501 opt = *popts;
1502 while (opt != NULL) {
1503 string_free(&opt->key);
1504 string_free(&opt->value);
1505 TALLOC_FREE(opt->list);
1506 next_opt = opt->next;
1507 SAFE_FREE(opt);
1508 opt = next_opt;
1510 *popts = NULL;
1513 /***************************************************************************
1514 Free the dynamically allocated parts of a service struct.
1515 ***************************************************************************/
1517 static void free_service(struct loadparm_service *pservice)
1519 if (!pservice)
1520 return;
1522 if (pservice->szService)
1523 DEBUG(5, ("free_service: Freeing service %s\n",
1524 pservice->szService));
1526 free_parameters(pservice);
1528 string_free(&pservice->szService);
1529 TALLOC_FREE(pservice->copymap);
1531 free_param_opts(&pservice->param_opt);
1533 ZERO_STRUCTP(pservice);
1537 /***************************************************************************
1538 remove a service indexed in the ServicePtrs array from the ServiceHash
1539 and free the dynamically allocated parts
1540 ***************************************************************************/
1542 static void free_service_byindex(int idx)
1544 if ( !LP_SNUM_OK(idx) )
1545 return;
1547 ServicePtrs[idx]->valid = false;
1548 invalid_services[num_invalid_services++] = idx;
1550 /* we have to cleanup the hash record */
1552 if (ServicePtrs[idx]->szService) {
1553 char *canon_name = canonicalize_servicename(
1554 talloc_tos(),
1555 ServicePtrs[idx]->szService );
1557 dbwrap_delete_bystring(ServiceHash, canon_name );
1558 TALLOC_FREE(canon_name);
1561 free_service(ServicePtrs[idx]);
1562 talloc_free_children(ServicePtrs[idx]);
1565 /***************************************************************************
1566 Add a new service to the services array initialising it with the given
1567 service.
1568 ***************************************************************************/
1570 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1572 int i;
1573 struct loadparm_service tservice;
1574 int num_to_alloc = iNumServices + 1;
1576 tservice = *pservice;
1578 /* it might already exist */
1579 if (name) {
1580 i = getservicebyname(name, NULL);
1581 if (i >= 0) {
1582 return (i);
1586 /* find an invalid one */
1587 i = iNumServices;
1588 if (num_invalid_services > 0) {
1589 i = invalid_services[--num_invalid_services];
1592 /* if not, then create one */
1593 if (i == iNumServices) {
1594 struct loadparm_service **tsp;
1595 int *tinvalid;
1597 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1598 if (tsp == NULL) {
1599 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1600 return (-1);
1602 ServicePtrs = tsp;
1603 ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1604 if (!ServicePtrs[iNumServices]) {
1605 DEBUG(0,("add_a_service: out of memory!\n"));
1606 return (-1);
1608 iNumServices++;
1610 /* enlarge invalid_services here for now... */
1611 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
1612 num_to_alloc);
1613 if (tinvalid == NULL) {
1614 DEBUG(0,("add_a_service: failed to enlarge "
1615 "invalid_services!\n"));
1616 return (-1);
1618 invalid_services = tinvalid;
1619 } else {
1620 free_service_byindex(i);
1623 ServicePtrs[i]->valid = true;
1625 init_service(ServicePtrs[i]);
1626 copy_service(ServicePtrs[i], &tservice, NULL);
1627 if (name)
1628 string_set(&ServicePtrs[i]->szService, name);
1630 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1631 i, ServicePtrs[i]->szService));
1633 if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1634 return (-1);
1637 return (i);
1640 /***************************************************************************
1641 Convert a string to uppercase and remove whitespaces.
1642 ***************************************************************************/
1644 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1646 char *result;
1648 if ( !src ) {
1649 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1650 return NULL;
1653 result = talloc_strdup(ctx, src);
1654 SMB_ASSERT(result != NULL);
1656 if (!strlower_m(result)) {
1657 TALLOC_FREE(result);
1658 return NULL;
1660 return result;
1663 /***************************************************************************
1664 Add a name/index pair for the services array to the hash table.
1665 ***************************************************************************/
1667 static bool hash_a_service(const char *name, int idx)
1669 char *canon_name;
1671 if ( !ServiceHash ) {
1672 DEBUG(10,("hash_a_service: creating servicehash\n"));
1673 ServiceHash = db_open_rbt(NULL);
1674 if ( !ServiceHash ) {
1675 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1676 return false;
1680 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1681 idx, name));
1683 canon_name = canonicalize_servicename(talloc_tos(), name );
1685 dbwrap_store_bystring(ServiceHash, canon_name,
1686 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1687 TDB_REPLACE);
1689 TALLOC_FREE(canon_name);
1691 return true;
1694 /***************************************************************************
1695 Add a new home service, with the specified home directory, defaults coming
1696 from service ifrom.
1697 ***************************************************************************/
1699 bool lp_add_home(const char *pszHomename, int iDefaultService,
1700 const char *user, const char *pszHomedir)
1702 int i;
1704 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1705 pszHomedir[0] == '\0') {
1706 return false;
1709 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1711 if (i < 0)
1712 return false;
1714 if (!(*(ServicePtrs[iDefaultService]->szPath))
1715 || strequal(ServicePtrs[iDefaultService]->szPath,
1716 lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1717 string_set(&ServicePtrs[i]->szPath, pszHomedir);
1720 if (!(*(ServicePtrs[i]->comment))) {
1721 char *comment = NULL;
1722 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1723 return false;
1725 string_set(&ServicePtrs[i]->comment, comment);
1726 SAFE_FREE(comment);
1729 /* set the browseable flag from the global default */
1731 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1732 ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
1734 ServicePtrs[i]->autoloaded = true;
1736 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1737 user, ServicePtrs[i]->szPath ));
1739 return true;
1742 /***************************************************************************
1743 Add a new service, based on an old one.
1744 ***************************************************************************/
1746 int lp_add_service(const char *pszService, int iDefaultService)
1748 if (iDefaultService < 0) {
1749 return add_a_service(&sDefault, pszService);
1752 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1755 /***************************************************************************
1756 Add the IPC service.
1757 ***************************************************************************/
1759 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1761 char *comment = NULL;
1762 int i = add_a_service(&sDefault, ipc_name);
1764 if (i < 0)
1765 return false;
1767 if (asprintf(&comment, "IPC Service (%s)",
1768 Globals.szServerString) < 0) {
1769 return false;
1772 string_set(&ServicePtrs[i]->szPath, tmpdir());
1773 string_set(&ServicePtrs[i]->szUsername, "");
1774 string_set(&ServicePtrs[i]->comment, comment);
1775 string_set(&ServicePtrs[i]->fstype, "IPC");
1776 ServicePtrs[i]->iMaxConnections = 0;
1777 ServicePtrs[i]->bAvailable = true;
1778 ServicePtrs[i]->bRead_only = true;
1779 ServicePtrs[i]->bGuest_only = false;
1780 ServicePtrs[i]->bAdministrative_share = true;
1781 ServicePtrs[i]->bGuest_ok = guest_ok;
1782 ServicePtrs[i]->bPrint_ok = false;
1783 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1785 DEBUG(3, ("adding IPC service\n"));
1787 SAFE_FREE(comment);
1788 return true;
1791 /***************************************************************************
1792 Add a new printer service, with defaults coming from service iFrom.
1793 ***************************************************************************/
1795 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1797 const char *comment = "From Printcap";
1798 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1800 if (i < 0)
1801 return false;
1803 /* note that we do NOT default the availability flag to true - */
1804 /* we take it from the default service passed. This allows all */
1805 /* dynamic printers to be disabled by disabling the [printers] */
1806 /* entry (if/when the 'available' keyword is implemented!). */
1808 /* the printer name is set to the service name. */
1809 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1810 string_set(&ServicePtrs[i]->comment, comment);
1812 /* set the browseable flag from the gloabl default */
1813 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1815 /* Printers cannot be read_only. */
1816 ServicePtrs[i]->bRead_only = false;
1817 /* No share modes on printer services. */
1818 ServicePtrs[i]->bShareModes = false;
1819 /* No oplocks on printer services. */
1820 ServicePtrs[i]->bOpLocks = false;
1821 /* Printer services must be printable. */
1822 ServicePtrs[i]->bPrint_ok = true;
1824 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1826 return true;
1830 /***************************************************************************
1831 Check whether the given parameter name is valid.
1832 Parametric options (names containing a colon) are considered valid.
1833 ***************************************************************************/
1835 bool lp_parameter_is_valid(const char *pszParmName)
1837 return ((map_parameter(pszParmName) != -1) ||
1838 (strchr(pszParmName, ':') != NULL));
1841 /***************************************************************************
1842 Check whether the given name is the name of a global parameter.
1843 Returns true for strings belonging to parameters of class
1844 P_GLOBAL, false for all other strings, also for parametric options
1845 and strings not belonging to any option.
1846 ***************************************************************************/
1848 bool lp_parameter_is_global(const char *pszParmName)
1850 int num = map_parameter(pszParmName);
1852 if (num >= 0) {
1853 return (parm_table[num].p_class == P_GLOBAL);
1856 return false;
1859 /**************************************************************************
1860 Check whether the given name is the canonical name of a parameter.
1861 Returns false if it is not a valid parameter Name.
1862 For parametric options, true is returned.
1863 **************************************************************************/
1865 bool lp_parameter_is_canonical(const char *parm_name)
1867 if (!lp_parameter_is_valid(parm_name)) {
1868 return false;
1871 return (map_parameter(parm_name) ==
1872 map_parameter_canonical(parm_name, NULL));
1875 /**************************************************************************
1876 Determine the canonical name for a parameter.
1877 Indicate when it is an inverse (boolean) synonym instead of a
1878 "usual" synonym.
1879 **************************************************************************/
1881 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1882 bool *inverse)
1884 int num;
1886 if (!lp_parameter_is_valid(parm_name)) {
1887 *canon_parm = NULL;
1888 return false;
1891 num = map_parameter_canonical(parm_name, inverse);
1892 if (num < 0) {
1893 /* parametric option */
1894 *canon_parm = parm_name;
1895 } else {
1896 *canon_parm = parm_table[num].label;
1899 return true;
1903 /**************************************************************************
1904 Determine the canonical name for a parameter.
1905 Turn the value given into the inverse boolean expression when
1906 the synonym is an invers boolean synonym.
1908 Return true if parm_name is a valid parameter name and
1909 in case it is an invers boolean synonym, if the val string could
1910 successfully be converted to the reverse bool.
1911 Return false in all other cases.
1912 **************************************************************************/
1914 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1915 const char *val,
1916 const char **canon_parm,
1917 const char **canon_val)
1919 int num;
1920 bool inverse;
1922 if (!lp_parameter_is_valid(parm_name)) {
1923 *canon_parm = NULL;
1924 *canon_val = NULL;
1925 return false;
1928 num = map_parameter_canonical(parm_name, &inverse);
1929 if (num < 0) {
1930 /* parametric option */
1931 *canon_parm = parm_name;
1932 *canon_val = val;
1933 } else {
1934 *canon_parm = parm_table[num].label;
1935 if (inverse) {
1936 if (!lp_invert_boolean(val, canon_val)) {
1937 *canon_val = NULL;
1938 return false;
1940 } else {
1941 *canon_val = val;
1945 return true;
1948 /***************************************************************************
1949 Map a parameter's string representation to something we can use.
1950 Returns false if the parameter string is not recognised, else TRUE.
1951 ***************************************************************************/
1953 static int map_parameter(const char *pszParmName)
1955 int iIndex;
1957 if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
1958 return (-1);
1960 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1961 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1962 return (iIndex);
1964 /* Warn only if it isn't parametric option */
1965 if (strchr(pszParmName, ':') == NULL)
1966 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1967 /* We do return 'fail' for parametric options as well because they are
1968 stored in different storage
1970 return (-1);
1973 /***************************************************************************
1974 Map a parameter's string representation to the index of the canonical
1975 form of the parameter (it might be a synonym).
1976 Returns -1 if the parameter string is not recognised.
1977 ***************************************************************************/
1979 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1981 int parm_num, canon_num;
1982 bool loc_inverse = false;
1984 parm_num = map_parameter(pszParmName);
1985 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1986 /* invalid, parametric or no canidate for synonyms ... */
1987 goto done;
1990 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1991 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1992 parm_num = canon_num;
1993 goto done;
1997 done:
1998 if (inverse != NULL) {
1999 *inverse = loc_inverse;
2001 return parm_num;
2004 /***************************************************************************
2005 return true if parameter number parm1 is a synonym of parameter
2006 number parm2 (parm2 being the principal name).
2007 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
2008 false otherwise.
2009 ***************************************************************************/
2011 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
2013 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
2014 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
2015 (parm_table[parm1].flags & FLAG_HIDE) &&
2016 !(parm_table[parm2].flags & FLAG_HIDE))
2018 if (inverse != NULL) {
2019 if ((parm_table[parm1].type == P_BOOLREV) &&
2020 (parm_table[parm2].type == P_BOOL))
2022 *inverse = true;
2023 } else {
2024 *inverse = false;
2027 return true;
2029 return false;
2032 /***************************************************************************
2033 Show one parameter's name, type, [values,] and flags.
2034 (helper functions for show_parameter_list)
2035 ***************************************************************************/
2037 static void show_parameter(int parmIndex)
2039 int enumIndex, flagIndex;
2040 int parmIndex2;
2041 bool hadFlag;
2042 bool hadSyn;
2043 bool inverse;
2044 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2045 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2046 "P_ENUM", "P_SEP"};
2047 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2048 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2049 FLAG_HIDE};
2050 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2051 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2052 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2054 printf("%s=%s", parm_table[parmIndex].label,
2055 type[parm_table[parmIndex].type]);
2056 if (parm_table[parmIndex].type == P_ENUM) {
2057 printf(",");
2058 for (enumIndex=0;
2059 parm_table[parmIndex].enum_list[enumIndex].name;
2060 enumIndex++)
2062 printf("%s%s",
2063 enumIndex ? "|" : "",
2064 parm_table[parmIndex].enum_list[enumIndex].name);
2067 printf(",");
2068 hadFlag = false;
2069 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2070 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2071 printf("%s%s",
2072 hadFlag ? "|" : "",
2073 flag_names[flagIndex]);
2074 hadFlag = true;
2078 /* output synonyms */
2079 hadSyn = false;
2080 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2081 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2082 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2083 parm_table[parmIndex2].label);
2084 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2085 if (!hadSyn) {
2086 printf(" (synonyms: ");
2087 hadSyn = true;
2088 } else {
2089 printf(", ");
2091 printf("%s%s", parm_table[parmIndex2].label,
2092 inverse ? "[i]" : "");
2095 if (hadSyn) {
2096 printf(")");
2099 printf("\n");
2102 /***************************************************************************
2103 Show all parameter's name, type, [values,] and flags.
2104 ***************************************************************************/
2106 void show_parameter_list(void)
2108 int classIndex, parmIndex;
2109 const char *section_names[] = { "local", "global", NULL};
2111 for (classIndex=0; section_names[classIndex]; classIndex++) {
2112 printf("[%s]\n", section_names[classIndex]);
2113 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2114 if (parm_table[parmIndex].p_class == classIndex) {
2115 show_parameter(parmIndex);
2121 /***************************************************************************
2122 Check if a given string correctly represents a boolean value.
2123 ***************************************************************************/
2125 bool lp_string_is_valid_boolean(const char *parm_value)
2127 return set_boolean(parm_value, NULL);
2130 /***************************************************************************
2131 Get the standard string representation of a boolean value ("yes" or "no")
2132 ***************************************************************************/
2134 static const char *get_boolean(bool bool_value)
2136 static const char *yes_str = "yes";
2137 static const char *no_str = "no";
2139 return (bool_value ? yes_str : no_str);
2142 /***************************************************************************
2143 Provide the string of the negated boolean value associated to the boolean
2144 given as a string. Returns false if the passed string does not correctly
2145 represent a boolean.
2146 ***************************************************************************/
2148 bool lp_invert_boolean(const char *str, const char **inverse_str)
2150 bool val;
2152 if (!set_boolean(str, &val)) {
2153 return false;
2156 *inverse_str = get_boolean(!val);
2157 return true;
2160 /***************************************************************************
2161 Provide the canonical string representation of a boolean value given
2162 as a string. Return true on success, false if the string given does
2163 not correctly represent a boolean.
2164 ***************************************************************************/
2166 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2168 bool val;
2170 if (!set_boolean(str, &val)) {
2171 return false;
2174 *canon_str = get_boolean(val);
2175 return true;
2178 /***************************************************************************
2179 Find a service by name. Otherwise works like get_service.
2180 ***************************************************************************/
2182 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2184 int iService = -1;
2185 char *canon_name;
2186 TDB_DATA data;
2187 NTSTATUS status;
2189 if (ServiceHash == NULL) {
2190 return -1;
2193 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2195 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2196 &data);
2198 if (NT_STATUS_IS_OK(status) &&
2199 (data.dptr != NULL) &&
2200 (data.dsize == sizeof(iService)))
2202 iService = *(int *)data.dptr;
2205 TALLOC_FREE(canon_name);
2207 if ((iService != -1) && (LP_SNUM_OK(iService))
2208 && (pserviceDest != NULL)) {
2209 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2212 return (iService);
2215 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2216 struct loadparm_service *lp_service(const char *pszServiceName)
2218 int iService = getservicebyname(pszServiceName, NULL);
2219 if (iService == -1 || !LP_SNUM_OK(iService)) {
2220 return NULL;
2222 return ServicePtrs[iService];
2225 struct loadparm_service *lp_servicebynum(int snum)
2227 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2228 return NULL;
2230 return ServicePtrs[snum];
2233 struct loadparm_service *lp_default_loadparm_service()
2235 return &sDefault;
2239 /***************************************************************************
2240 Copy a service structure to another.
2241 If pcopymapDest is NULL then copy all fields
2242 ***************************************************************************/
2245 * Add a parametric option to a parmlist_entry,
2246 * replacing old value, if already present.
2248 static void set_param_opt(struct parmlist_entry **opt_list,
2249 const char *opt_name,
2250 const char *opt_value,
2251 unsigned priority)
2253 struct parmlist_entry *new_opt, *opt;
2254 bool not_added;
2256 opt = *opt_list;
2257 not_added = true;
2259 /* Traverse destination */
2260 while (opt) {
2261 /* If we already have same option, override it */
2262 if (strwicmp(opt->key, opt_name) == 0) {
2263 if ((opt->priority & FLAG_CMDLINE) &&
2264 !(priority & FLAG_CMDLINE)) {
2265 /* it's been marked as not to be
2266 overridden */
2267 return;
2269 string_free(&opt->value);
2270 TALLOC_FREE(opt->list);
2271 opt->value = SMB_STRDUP(opt_value);
2272 opt->priority = priority;
2273 not_added = false;
2274 break;
2276 opt = opt->next;
2278 if (not_added) {
2279 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2280 new_opt->key = SMB_STRDUP(opt_name);
2281 new_opt->value = SMB_STRDUP(opt_value);
2282 new_opt->list = NULL;
2283 new_opt->priority = priority;
2284 DLIST_ADD(*opt_list, new_opt);
2288 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2289 struct bitmap *pcopymapDest)
2291 int i;
2292 bool bcopyall = (pcopymapDest == NULL);
2293 struct parmlist_entry *data;
2295 for (i = 0; parm_table[i].label; i++)
2296 if (parm_table[i].p_class == P_LOCAL &&
2297 (bcopyall || bitmap_query(pcopymapDest,i))) {
2298 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2299 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2301 switch (parm_table[i].type) {
2302 case P_BOOL:
2303 case P_BOOLREV:
2304 *(bool *)dest_ptr = *(bool *)src_ptr;
2305 break;
2307 case P_INTEGER:
2308 case P_ENUM:
2309 case P_OCTAL:
2310 case P_BYTES:
2311 *(int *)dest_ptr = *(int *)src_ptr;
2312 break;
2314 case P_CHAR:
2315 *(char *)dest_ptr = *(char *)src_ptr;
2316 break;
2318 case P_STRING:
2319 string_set((char **)dest_ptr,
2320 *(char **)src_ptr);
2321 break;
2323 case P_USTRING:
2325 char *upper_string = strupper_talloc(talloc_tos(),
2326 *(char **)src_ptr);
2327 string_set((char **)dest_ptr,
2328 upper_string);
2329 TALLOC_FREE(upper_string);
2330 break;
2332 case P_LIST:
2333 TALLOC_FREE(*((char ***)dest_ptr));
2334 *((char ***)dest_ptr) = str_list_copy(NULL,
2335 *(const char ***)src_ptr);
2336 break;
2337 default:
2338 break;
2342 if (bcopyall) {
2343 init_copymap(pserviceDest);
2344 if (pserviceSource->copymap)
2345 bitmap_copy(pserviceDest->copymap,
2346 pserviceSource->copymap);
2349 data = pserviceSource->param_opt;
2350 while (data) {
2351 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2352 data = data->next;
2356 /***************************************************************************
2357 Check a service for consistency. Return false if the service is in any way
2358 incomplete or faulty, else true.
2359 ***************************************************************************/
2361 bool service_ok(int iService)
2363 bool bRetval;
2365 bRetval = true;
2366 if (ServicePtrs[iService]->szService[0] == '\0') {
2367 DEBUG(0, ("The following message indicates an internal error:\n"));
2368 DEBUG(0, ("No service name in service entry.\n"));
2369 bRetval = false;
2372 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2373 /* I can't see why you'd want a non-printable printer service... */
2374 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2375 if (!ServicePtrs[iService]->bPrint_ok) {
2376 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2377 ServicePtrs[iService]->szService));
2378 ServicePtrs[iService]->bPrint_ok = true;
2380 /* [printers] service must also be non-browsable. */
2381 if (ServicePtrs[iService]->bBrowseable)
2382 ServicePtrs[iService]->bBrowseable = false;
2385 if (ServicePtrs[iService]->szPath[0] == '\0' &&
2386 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2387 ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2389 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2390 ServicePtrs[iService]->szService));
2391 ServicePtrs[iService]->bAvailable = false;
2394 /* If a service is flagged unavailable, log the fact at level 1. */
2395 if (!ServicePtrs[iService]->bAvailable)
2396 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2397 ServicePtrs[iService]->szService));
2399 return (bRetval);
2402 static struct smbconf_ctx *lp_smbconf_ctx(void)
2404 sbcErr err;
2405 static struct smbconf_ctx *conf_ctx = NULL;
2407 if (conf_ctx == NULL) {
2408 err = smbconf_init(NULL, &conf_ctx, "registry:");
2409 if (!SBC_ERROR_IS_OK(err)) {
2410 DEBUG(1, ("error initializing registry configuration: "
2411 "%s\n", sbcErrorString(err)));
2412 conf_ctx = NULL;
2416 return conf_ctx;
2419 static bool process_smbconf_service(struct smbconf_service *service)
2421 uint32_t count;
2422 bool ret;
2424 if (service == NULL) {
2425 return false;
2428 ret = do_section(service->name, NULL);
2429 if (ret != true) {
2430 return false;
2432 for (count = 0; count < service->num_params; count++) {
2433 ret = do_parameter(service->param_names[count],
2434 service->param_values[count],
2435 NULL);
2436 if (ret != true) {
2437 return false;
2440 if (iServiceIndex >= 0) {
2441 return service_ok(iServiceIndex);
2443 return true;
2447 * load a service from registry and activate it
2449 bool process_registry_service(const char *service_name)
2451 sbcErr err;
2452 struct smbconf_service *service = NULL;
2453 TALLOC_CTX *mem_ctx = talloc_stackframe();
2454 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2455 bool ret = false;
2457 if (conf_ctx == NULL) {
2458 goto done;
2461 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2463 if (!smbconf_share_exists(conf_ctx, service_name)) {
2465 * Registry does not contain data for this service (yet),
2466 * but make sure lp_load doesn't return false.
2468 ret = true;
2469 goto done;
2472 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2473 if (!SBC_ERROR_IS_OK(err)) {
2474 goto done;
2477 ret = process_smbconf_service(service);
2478 if (!ret) {
2479 goto done;
2482 /* store the csn */
2483 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2485 done:
2486 TALLOC_FREE(mem_ctx);
2487 return ret;
2491 * process_registry_globals
2493 static bool process_registry_globals(void)
2495 bool ret;
2497 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2499 ret = do_parameter("registry shares", "yes", NULL);
2500 if (!ret) {
2501 return ret;
2504 return process_registry_service(GLOBAL_NAME);
2507 bool process_registry_shares(void)
2509 sbcErr err;
2510 uint32_t count;
2511 struct smbconf_service **service = NULL;
2512 uint32_t num_shares = 0;
2513 TALLOC_CTX *mem_ctx = talloc_stackframe();
2514 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2515 bool ret = false;
2517 if (conf_ctx == NULL) {
2518 goto done;
2521 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2522 if (!SBC_ERROR_IS_OK(err)) {
2523 goto done;
2526 ret = true;
2528 for (count = 0; count < num_shares; count++) {
2529 if (strequal(service[count]->name, GLOBAL_NAME)) {
2530 continue;
2532 ret = process_smbconf_service(service[count]);
2533 if (!ret) {
2534 goto done;
2538 /* store the csn */
2539 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2541 done:
2542 TALLOC_FREE(mem_ctx);
2543 return ret;
2547 * reload those shares from registry that are already
2548 * activated in the services array.
2550 static bool reload_registry_shares(void)
2552 int i;
2553 bool ret = true;
2555 for (i = 0; i < iNumServices; i++) {
2556 if (!VALID(i)) {
2557 continue;
2560 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2561 continue;
2564 ret = process_registry_service(ServicePtrs[i]->szService);
2565 if (!ret) {
2566 goto done;
2570 done:
2571 return ret;
2575 #define MAX_INCLUDE_DEPTH 100
2577 static uint8_t include_depth;
2579 static struct file_lists {
2580 struct file_lists *next;
2581 char *name;
2582 char *subfname;
2583 time_t modtime;
2584 } *file_lists = NULL;
2586 /*******************************************************************
2587 Keep a linked list of all config files so we know when one has changed
2588 it's date and needs to be reloaded.
2589 ********************************************************************/
2591 static void add_to_file_list(const char *fname, const char *subfname)
2593 struct file_lists *f = file_lists;
2595 while (f) {
2596 if (f->name && !strcmp(f->name, fname))
2597 break;
2598 f = f->next;
2601 if (!f) {
2602 f = SMB_MALLOC_P(struct file_lists);
2603 if (!f)
2604 return;
2605 f->next = file_lists;
2606 f->name = SMB_STRDUP(fname);
2607 if (!f->name) {
2608 SAFE_FREE(f);
2609 return;
2611 f->subfname = SMB_STRDUP(subfname);
2612 if (!f->subfname) {
2613 SAFE_FREE(f->name);
2614 SAFE_FREE(f);
2615 return;
2617 file_lists = f;
2618 f->modtime = file_modtime(subfname);
2619 } else {
2620 time_t t = file_modtime(subfname);
2621 if (t)
2622 f->modtime = t;
2624 return;
2628 * Free the file lists
2630 static void free_file_list(void)
2632 struct file_lists *f;
2633 struct file_lists *next;
2635 f = file_lists;
2636 while( f ) {
2637 next = f->next;
2638 SAFE_FREE( f->name );
2639 SAFE_FREE( f->subfname );
2640 SAFE_FREE( f );
2641 f = next;
2643 file_lists = NULL;
2648 * Utility function for outsiders to check if we're running on registry.
2650 bool lp_config_backend_is_registry(void)
2652 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2656 * Utility function to check if the config backend is FILE.
2658 bool lp_config_backend_is_file(void)
2660 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2663 /*******************************************************************
2664 Check if a config file has changed date.
2665 ********************************************************************/
2667 bool lp_file_list_changed(void)
2669 struct file_lists *f = file_lists;
2671 DEBUG(6, ("lp_file_list_changed()\n"));
2673 while (f) {
2674 time_t mod_time;
2676 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2677 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2679 if (conf_ctx == NULL) {
2680 return false;
2682 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2683 NULL))
2685 DEBUGADD(6, ("registry config changed\n"));
2686 return true;
2688 } else {
2689 char *n2 = NULL;
2690 n2 = talloc_sub_basic(talloc_tos(),
2691 get_current_username(),
2692 current_user_info.domain,
2693 f->name);
2694 if (!n2) {
2695 return false;
2697 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2698 f->name, n2, ctime(&f->modtime)));
2700 mod_time = file_modtime(n2);
2702 if (mod_time &&
2703 ((f->modtime != mod_time) ||
2704 (f->subfname == NULL) ||
2705 (strcmp(n2, f->subfname) != 0)))
2707 DEBUGADD(6,
2708 ("file %s modified: %s\n", n2,
2709 ctime(&mod_time)));
2710 f->modtime = mod_time;
2711 SAFE_FREE(f->subfname);
2712 f->subfname = SMB_STRDUP(n2);
2713 TALLOC_FREE(n2);
2714 return true;
2716 TALLOC_FREE(n2);
2718 f = f->next;
2720 return false;
2725 * Initialize iconv conversion descriptors.
2727 * This is called the first time it is needed, and also called again
2728 * every time the configuration is reloaded, because the charset or
2729 * codepage might have changed.
2731 static void init_iconv(void)
2733 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2734 lp_unix_charset(),
2735 true, global_iconv_handle);
2738 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2740 if (strcmp(*ptr, pszParmValue) != 0) {
2741 string_set(ptr, pszParmValue);
2742 init_iconv();
2744 return true;
2747 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2749 bool is_utf8 = false;
2750 size_t len = strlen(pszParmValue);
2752 if (len == 4 || len == 5) {
2753 /* Don't use StrCaseCmp here as we don't want to
2754 initialize iconv. */
2755 if ((toupper_m(pszParmValue[0]) == 'U') &&
2756 (toupper_m(pszParmValue[1]) == 'T') &&
2757 (toupper_m(pszParmValue[2]) == 'F')) {
2758 if (len == 4) {
2759 if (pszParmValue[3] == '8') {
2760 is_utf8 = true;
2762 } else {
2763 if (pszParmValue[3] == '-' &&
2764 pszParmValue[4] == '8') {
2765 is_utf8 = true;
2771 if (strcmp(*ptr, pszParmValue) != 0) {
2772 if (is_utf8) {
2773 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2774 "be UTF8, using (default value) %s instead.\n",
2775 DEFAULT_DOS_CHARSET));
2776 pszParmValue = DEFAULT_DOS_CHARSET;
2778 string_set(ptr, pszParmValue);
2779 init_iconv();
2781 return true;
2784 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2786 bool ret = true;
2787 char *realm = strupper_talloc(talloc_tos(), pszParmValue);
2788 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2790 ret &= string_set(&Globals.szRealm, pszParmValue);
2791 ret &= string_set(&Globals.szRealm_upper, realm);
2792 ret &= string_set(&Globals.szRealm_lower, dnsdomain);
2793 TALLOC_FREE(realm);
2795 return ret;
2798 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2800 TALLOC_FREE(Globals.szNetbiosAliases);
2801 Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2802 return set_netbios_aliases(Globals.szNetbiosAliases);
2805 /***************************************************************************
2806 Handle the include operation.
2807 ***************************************************************************/
2808 static bool bAllowIncludeRegistry = true;
2810 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2812 char *fname;
2814 if (include_depth >= MAX_INCLUDE_DEPTH) {
2815 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2816 include_depth));
2817 return false;
2820 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2821 if (!bAllowIncludeRegistry) {
2822 return true;
2824 if (bInGlobalSection) {
2825 bool ret;
2826 include_depth++;
2827 ret = process_registry_globals();
2828 include_depth--;
2829 return ret;
2830 } else {
2831 DEBUG(1, ("\"include = registry\" only effective "
2832 "in %s section\n", GLOBAL_NAME));
2833 return false;
2837 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2838 current_user_info.domain,
2839 pszParmValue);
2841 add_to_file_list(pszParmValue, fname);
2843 string_set(ptr, fname);
2845 if (file_exist(fname)) {
2846 bool ret;
2847 include_depth++;
2848 ret = pm_process(fname, do_section, do_parameter, NULL);
2849 include_depth--;
2850 TALLOC_FREE(fname);
2851 return ret;
2854 DEBUG(2, ("Can't find include file %s\n", fname));
2855 TALLOC_FREE(fname);
2856 return true;
2859 /***************************************************************************
2860 Handle the interpretation of the copy parameter.
2861 ***************************************************************************/
2863 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2865 bool bRetval;
2866 int iTemp;
2867 struct loadparm_service serviceTemp;
2869 string_set(ptr, pszParmValue);
2871 init_service(&serviceTemp);
2873 bRetval = false;
2875 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2877 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2878 if (iTemp == iServiceIndex) {
2879 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2880 } else {
2881 copy_service(ServicePtrs[iServiceIndex],
2882 &serviceTemp,
2883 ServicePtrs[iServiceIndex]->copymap);
2884 bRetval = true;
2886 } else {
2887 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2888 bRetval = false;
2891 free_service(&serviceTemp);
2892 return (bRetval);
2895 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2897 Globals.ldap_debug_level = lp_int(pszParmValue);
2898 init_ldap_debugging();
2899 return true;
2902 /***************************************************************************
2903 Handle idmap/non unix account uid and gid allocation parameters. The format of these
2904 parameters is:
2906 [global]
2908 idmap uid = 1000-1999
2909 idmap gid = 700-899
2911 We only do simple parsing checks here. The strings are parsed into useful
2912 structures in the idmap daemon code.
2914 ***************************************************************************/
2916 /* Some lp_ routines to return idmap [ug]id information */
2918 static uid_t idmap_uid_low, idmap_uid_high;
2919 static gid_t idmap_gid_low, idmap_gid_high;
2921 bool lp_idmap_uid(uid_t *low, uid_t *high)
2923 if (idmap_uid_low == 0 || idmap_uid_high == 0)
2924 return false;
2926 if (low)
2927 *low = idmap_uid_low;
2929 if (high)
2930 *high = idmap_uid_high;
2932 return true;
2935 bool lp_idmap_gid(gid_t *low, gid_t *high)
2937 if (idmap_gid_low == 0 || idmap_gid_high == 0)
2938 return false;
2940 if (low)
2941 *low = idmap_gid_low;
2943 if (high)
2944 *high = idmap_gid_high;
2946 return true;
2949 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2951 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2953 return true;
2956 /* Do some simple checks on "idmap [ug]id" parameter values */
2958 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2960 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2962 return true;
2965 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2967 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2969 return true;
2972 /***************************************************************************
2973 Handle the DEBUG level list.
2974 ***************************************************************************/
2976 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2978 string_set(ptr, pszParmValueIn);
2979 return debug_parse_levels(pszParmValueIn);
2982 /***************************************************************************
2983 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2984 ***************************************************************************/
2986 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2988 const char *suffix_string;
2990 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2991 Globals.szLdapSuffix );
2992 if ( !suffix_string ) {
2993 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2994 return "";
2997 return suffix_string;
3000 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
3002 if (Globals.szLdapMachineSuffix[0])
3003 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
3005 return lp_string(ctx, Globals.szLdapSuffix);
3008 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
3010 if (Globals.szLdapUserSuffix[0])
3011 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3013 return lp_string(ctx, Globals.szLdapSuffix);
3016 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3018 if (Globals.szLdapGroupSuffix[0])
3019 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3021 return lp_string(ctx, Globals.szLdapSuffix);
3024 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3026 if (Globals.szLdapIdmapSuffix[0])
3027 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3029 return lp_string(ctx, Globals.szLdapSuffix);
3032 /****************************************************************************
3033 set the value for a P_ENUM
3034 ***************************************************************************/
3036 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3037 int *ptr )
3039 int i;
3041 for (i = 0; parm->enum_list[i].name; i++) {
3042 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3043 *ptr = parm->enum_list[i].value;
3044 return;
3047 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3048 pszParmValue, parm->label));
3051 /***************************************************************************
3052 ***************************************************************************/
3054 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3056 static int parm_num = -1;
3057 struct loadparm_service *s;
3059 if ( parm_num == -1 )
3060 parm_num = map_parameter( "printing" );
3062 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3064 if ( snum < 0 )
3065 s = &sDefault;
3066 else
3067 s = ServicePtrs[snum];
3069 init_printer_values( s );
3071 return true;
3075 /***************************************************************************
3076 Initialise a copymap.
3077 ***************************************************************************/
3079 static void init_copymap(struct loadparm_service *pservice)
3081 int i;
3083 TALLOC_FREE(pservice->copymap);
3085 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3086 if (!pservice->copymap)
3087 DEBUG(0,
3088 ("Couldn't allocate copymap!! (size %d)\n",
3089 (int)NUMPARAMETERS));
3090 else
3091 for (i = 0; i < NUMPARAMETERS; i++)
3092 bitmap_set(pservice->copymap, i);
3096 return the parameter pointer for a parameter
3098 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3100 if (service == NULL) {
3101 if (parm->p_class == P_LOCAL)
3102 return (void *)(((char *)&sDefault)+parm->offset);
3103 else if (parm->p_class == P_GLOBAL)
3104 return (void *)(((char *)&Globals)+parm->offset);
3105 else return NULL;
3106 } else {
3107 return (void *)(((char *)service) + parm->offset);
3111 /***************************************************************************
3112 Return the local pointer to a parameter given the service number and parameter
3113 ***************************************************************************/
3115 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3117 return lp_parm_ptr(ServicePtrs[snum], parm);
3120 /***************************************************************************
3121 Process a parameter for a particular service number. If snum < 0
3122 then assume we are in the globals.
3123 ***************************************************************************/
3125 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3127 int parmnum, i;
3128 void *parm_ptr = NULL; /* where we are going to store the result */
3129 struct parmlist_entry **opt_list;
3131 parmnum = map_parameter(pszParmName);
3133 if (parmnum < 0) {
3134 if (strchr(pszParmName, ':') == NULL) {
3135 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3136 pszParmName));
3137 return true;
3141 * We've got a parametric option
3144 opt_list = (snum < 0)
3145 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3146 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3148 return true;
3151 /* if it's already been set by the command line, then we don't
3152 override here */
3153 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3154 return true;
3157 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3158 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3159 pszParmName));
3162 /* we might point at a service, the default service or a global */
3163 if (snum < 0) {
3164 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3165 } else {
3166 if (parm_table[parmnum].p_class == P_GLOBAL) {
3167 DEBUG(0,
3168 ("Global parameter %s found in service section!\n",
3169 pszParmName));
3170 return true;
3172 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3175 if (snum >= 0) {
3176 if (!ServicePtrs[snum]->copymap)
3177 init_copymap(ServicePtrs[snum]);
3179 /* this handles the aliases - set the copymap for other entries with
3180 the same data pointer */
3181 for (i = 0; parm_table[i].label; i++) {
3182 if ((parm_table[i].offset == parm_table[parmnum].offset)
3183 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3184 bitmap_clear(ServicePtrs[snum]->copymap, i);
3189 /* if it is a special case then go ahead */
3190 if (parm_table[parmnum].special) {
3191 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3192 (char **)parm_ptr);
3195 /* now switch on the type of variable it is */
3196 switch (parm_table[parmnum].type)
3198 case P_BOOL:
3199 *(bool *)parm_ptr = lp_bool(pszParmValue);
3200 break;
3202 case P_BOOLREV:
3203 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3204 break;
3206 case P_INTEGER:
3207 *(int *)parm_ptr = lp_int(pszParmValue);
3208 break;
3210 case P_CHAR:
3211 *(char *)parm_ptr = *pszParmValue;
3212 break;
3214 case P_OCTAL:
3215 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3216 if ( i != 1 ) {
3217 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3219 break;
3221 case P_BYTES:
3223 uint64_t val;
3224 if (conv_str_size_error(pszParmValue, &val)) {
3225 if (val <= INT_MAX) {
3226 *(int *)parm_ptr = (int)val;
3227 break;
3231 DEBUG(0,("lp_do_parameter(%s): value is not "
3232 "a valid size specifier!\n", pszParmValue));
3233 return false;
3236 case P_LIST:
3237 case P_CMDLIST:
3238 TALLOC_FREE(*((char ***)parm_ptr));
3239 *(char ***)parm_ptr = str_list_make_v3(
3240 NULL, pszParmValue, NULL);
3241 break;
3243 case P_STRING:
3244 string_set((char **)parm_ptr, pszParmValue);
3245 break;
3247 case P_USTRING:
3249 char *upper_string = strupper_talloc(talloc_tos(),
3250 pszParmValue);
3251 string_set((char **)parm_ptr, upper_string);
3252 TALLOC_FREE(upper_string);
3253 break;
3255 case P_ENUM:
3256 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3257 break;
3258 case P_SEP:
3259 break;
3262 return true;
3265 /***************************************************************************
3266 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3267 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3268 ***************************************************************************/
3270 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3272 int parmnum, i;
3273 parmnum = map_parameter(pszParmName);
3274 if (parmnum >= 0) {
3275 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3276 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3277 return false;
3279 parm_table[parmnum].flags |= FLAG_CMDLINE;
3281 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3282 * be grouped in the table, so we don't have to search the
3283 * whole table */
3284 for (i=parmnum-1;
3285 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3286 && parm_table[i].p_class == parm_table[parmnum].p_class;
3287 i--) {
3288 parm_table[i].flags |= FLAG_CMDLINE;
3290 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3291 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3292 parm_table[i].flags |= FLAG_CMDLINE;
3295 if (store_values) {
3296 store_lp_set_cmdline(pszParmName, pszParmValue);
3298 return true;
3301 /* it might be parametric */
3302 if (strchr(pszParmName, ':') != NULL) {
3303 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3304 if (store_values) {
3305 store_lp_set_cmdline(pszParmName, pszParmValue);
3307 return true;
3310 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3311 return true;
3314 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3316 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3319 /***************************************************************************
3320 Process a parameter.
3321 ***************************************************************************/
3323 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3324 void *userdata)
3326 if (!bInGlobalSection && bGlobalOnly)
3327 return true;
3329 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3331 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3332 pszParmName, pszParmValue));
3336 set a option from the commandline in 'a=b' format. Use to support --option
3338 bool lp_set_option(const char *option)
3340 char *p, *s;
3341 bool ret;
3343 s = talloc_strdup(NULL, option);
3344 if (!s) {
3345 return false;
3348 p = strchr(s, '=');
3349 if (!p) {
3350 talloc_free(s);
3351 return false;
3354 *p = 0;
3356 /* skip white spaces after the = sign */
3357 do {
3358 p++;
3359 } while (*p == ' ');
3361 ret = lp_set_cmdline(s, p);
3362 talloc_free(s);
3363 return ret;
3366 /**************************************************************************
3367 Print a parameter of the specified type.
3368 ***************************************************************************/
3370 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3372 /* For the seperation of lists values that we print below */
3373 const char *list_sep = ", ";
3374 int i;
3375 switch (p->type)
3377 case P_ENUM:
3378 for (i = 0; p->enum_list[i].name; i++) {
3379 if (*(int *)ptr == p->enum_list[i].value) {
3380 fprintf(f, "%s",
3381 p->enum_list[i].name);
3382 break;
3385 break;
3387 case P_BOOL:
3388 fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3389 break;
3391 case P_BOOLREV:
3392 fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3393 break;
3395 case P_INTEGER:
3396 case P_BYTES:
3397 fprintf(f, "%d", *(int *)ptr);
3398 break;
3400 case P_CHAR:
3401 fprintf(f, "%c", *(char *)ptr);
3402 break;
3404 case P_OCTAL: {
3405 int val = *(int *)ptr;
3406 if (val == -1) {
3407 fprintf(f, "-1");
3408 } else {
3409 fprintf(f, "0%o", val);
3411 break;
3414 case P_CMDLIST:
3415 list_sep = " ";
3416 /* fall through */
3417 case P_LIST:
3418 if ((char ***)ptr && *(char ***)ptr) {
3419 char **list = *(char ***)ptr;
3420 for (; *list; list++) {
3421 /* surround strings with whitespace in double quotes */
3422 if (*(list+1) == NULL) {
3423 /* last item, no extra separator */
3424 list_sep = "";
3426 if ( strchr_m( *list, ' ' ) ) {
3427 fprintf(f, "\"%s\"%s", *list, list_sep);
3428 } else {
3429 fprintf(f, "%s%s", *list, list_sep);
3433 break;
3435 case P_STRING:
3436 case P_USTRING:
3437 if (*(char **)ptr) {
3438 fprintf(f, "%s", *(char **)ptr);
3440 break;
3441 case P_SEP:
3442 break;
3446 /***************************************************************************
3447 Check if two parameters are equal.
3448 ***************************************************************************/
3450 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3452 switch (type) {
3453 case P_BOOL:
3454 case P_BOOLREV:
3455 return (*((bool *)ptr1) == *((bool *)ptr2));
3457 case P_INTEGER:
3458 case P_ENUM:
3459 case P_OCTAL:
3460 case P_BYTES:
3461 return (*((int *)ptr1) == *((int *)ptr2));
3463 case P_CHAR:
3464 return (*((char *)ptr1) == *((char *)ptr2));
3466 case P_LIST:
3467 case P_CMDLIST:
3468 return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3470 case P_STRING:
3471 case P_USTRING:
3473 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3474 if (p1 && !*p1)
3475 p1 = NULL;
3476 if (p2 && !*p2)
3477 p2 = NULL;
3478 return (p1 == p2 || strequal(p1, p2));
3480 case P_SEP:
3481 break;
3483 return false;
3486 /***************************************************************************
3487 Initialize any local varients in the sDefault table.
3488 ***************************************************************************/
3490 void init_locals(void)
3492 /* None as yet. */
3495 /***************************************************************************
3496 Process a new section (service). At this stage all sections are services.
3497 Later we'll have special sections that permit server parameters to be set.
3498 Returns true on success, false on failure.
3499 ***************************************************************************/
3501 static bool do_section(const char *pszSectionName, void *userdata)
3503 bool bRetval;
3504 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3505 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3506 bRetval = false;
3508 /* if we were in a global section then do the local inits */
3509 if (bInGlobalSection && !isglobal)
3510 init_locals();
3512 /* if we've just struck a global section, note the fact. */
3513 bInGlobalSection = isglobal;
3515 /* check for multiple global sections */
3516 if (bInGlobalSection) {
3517 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3518 return true;
3521 if (!bInGlobalSection && bGlobalOnly)
3522 return true;
3524 /* if we have a current service, tidy it up before moving on */
3525 bRetval = true;
3527 if (iServiceIndex >= 0)
3528 bRetval = service_ok(iServiceIndex);
3530 /* if all is still well, move to the next record in the services array */
3531 if (bRetval) {
3532 /* We put this here to avoid an odd message order if messages are */
3533 /* issued by the post-processing of a previous section. */
3534 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3536 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3537 if (iServiceIndex < 0) {
3538 DEBUG(0, ("Failed to add a new service\n"));
3539 return false;
3541 /* Clean all parametric options for service */
3542 /* They will be added during parsing again */
3543 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3546 return bRetval;
3550 /***************************************************************************
3551 Determine if a partcular base parameter is currentl set to the default value.
3552 ***************************************************************************/
3554 static bool is_default(int i)
3556 if (!defaults_saved)
3557 return false;
3558 switch (parm_table[i].type) {
3559 case P_LIST:
3560 case P_CMDLIST:
3561 return str_list_equal((const char **)parm_table[i].def.lvalue,
3562 *(const char ***)lp_parm_ptr(NULL,
3563 &parm_table[i]));
3564 case P_STRING:
3565 case P_USTRING:
3566 return strequal(parm_table[i].def.svalue,
3567 *(char **)lp_parm_ptr(NULL,
3568 &parm_table[i]));
3569 case P_BOOL:
3570 case P_BOOLREV:
3571 return parm_table[i].def.bvalue ==
3572 *(bool *)lp_parm_ptr(NULL,
3573 &parm_table[i]);
3574 case P_CHAR:
3575 return parm_table[i].def.cvalue ==
3576 *(char *)lp_parm_ptr(NULL,
3577 &parm_table[i]);
3578 case P_INTEGER:
3579 case P_OCTAL:
3580 case P_ENUM:
3581 case P_BYTES:
3582 return parm_table[i].def.ivalue ==
3583 *(int *)lp_parm_ptr(NULL,
3584 &parm_table[i]);
3585 case P_SEP:
3586 break;
3588 return false;
3591 /***************************************************************************
3592 Display the contents of the global structure.
3593 ***************************************************************************/
3595 static void dump_globals(FILE *f)
3597 int i;
3598 struct parmlist_entry *data;
3600 fprintf(f, "[global]\n");
3602 for (i = 0; parm_table[i].label; i++)
3603 if (parm_table[i].p_class == P_GLOBAL &&
3604 !(parm_table[i].flags & FLAG_META) &&
3605 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3606 if (defaults_saved && is_default(i))
3607 continue;
3608 fprintf(f, "\t%s = ", parm_table[i].label);
3609 print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3610 &parm_table[i]),
3612 fprintf(f, "\n");
3614 if (Globals.param_opt != NULL) {
3615 data = Globals.param_opt;
3616 while(data) {
3617 fprintf(f, "\t%s = %s\n", data->key, data->value);
3618 data = data->next;
3624 /***************************************************************************
3625 Return true if a local parameter is currently set to the global default.
3626 ***************************************************************************/
3628 bool lp_is_default(int snum, struct parm_struct *parm)
3630 return equal_parameter(parm->type,
3631 lp_parm_ptr(ServicePtrs[snum], parm),
3632 lp_parm_ptr(NULL, parm));
3635 /***************************************************************************
3636 Display the contents of a single services record.
3637 ***************************************************************************/
3639 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3641 int i;
3642 struct parmlist_entry *data;
3644 if (pService != &sDefault)
3645 fprintf(f, "[%s]\n", pService->szService);
3647 for (i = 0; parm_table[i].label; i++) {
3649 if (parm_table[i].p_class == P_LOCAL &&
3650 !(parm_table[i].flags & FLAG_META) &&
3651 (*parm_table[i].label != '-') &&
3652 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3654 if (pService == &sDefault) {
3655 if (defaults_saved && is_default(i))
3656 continue;
3657 } else {
3658 if (equal_parameter(parm_table[i].type,
3659 lp_parm_ptr(pService, &parm_table[i]),
3660 lp_parm_ptr(NULL, &parm_table[i])))
3661 continue;
3664 fprintf(f, "\t%s = ", parm_table[i].label);
3665 print_parameter(&parm_table[i],
3666 lp_parm_ptr(pService, &parm_table[i]),
3668 fprintf(f, "\n");
3672 if (pService->param_opt != NULL) {
3673 data = pService->param_opt;
3674 while(data) {
3675 fprintf(f, "\t%s = %s\n", data->key, data->value);
3676 data = data->next;
3681 /***************************************************************************
3682 Display the contents of a parameter of a single services record.
3683 ***************************************************************************/
3685 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3687 int i;
3688 bool result = false;
3689 parm_class p_class;
3690 unsigned flag = 0;
3691 fstring local_parm_name;
3692 char *parm_opt;
3693 const char *parm_opt_value;
3695 /* check for parametrical option */
3696 fstrcpy( local_parm_name, parm_name);
3697 parm_opt = strchr( local_parm_name, ':');
3699 if (parm_opt) {
3700 *parm_opt = '\0';
3701 parm_opt++;
3702 if (strlen(parm_opt)) {
3703 parm_opt_value = lp_parm_const_string( snum,
3704 local_parm_name, parm_opt, NULL);
3705 if (parm_opt_value) {
3706 printf( "%s\n", parm_opt_value);
3707 result = true;
3710 return result;
3713 /* check for a key and print the value */
3714 if (isGlobal) {
3715 p_class = P_GLOBAL;
3716 flag = FLAG_GLOBAL;
3717 } else
3718 p_class = P_LOCAL;
3720 for (i = 0; parm_table[i].label; i++) {
3721 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3722 !(parm_table[i].flags & FLAG_META) &&
3723 (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3724 (*parm_table[i].label != '-') &&
3725 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3727 void *ptr;
3729 if (isGlobal) {
3730 ptr = lp_parm_ptr(NULL,
3731 &parm_table[i]);
3732 } else {
3733 ptr = lp_parm_ptr(ServicePtrs[snum],
3734 &parm_table[i]);
3737 print_parameter(&parm_table[i],
3738 ptr, f);
3739 fprintf(f, "\n");
3740 result = true;
3741 break;
3745 return result;
3748 /***************************************************************************
3749 Return info about the requested parameter (given as a string).
3750 Return NULL when the string is not a valid parameter name.
3751 ***************************************************************************/
3753 struct parm_struct *lp_get_parameter(const char *param_name)
3755 int num = map_parameter(param_name);
3757 if (num < 0) {
3758 return NULL;
3761 return &parm_table[num];
3764 /***************************************************************************
3765 Return info about the next parameter in a service.
3766 snum==GLOBAL_SECTION_SNUM gives the globals.
3767 Return NULL when out of parameters.
3768 ***************************************************************************/
3770 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3772 if (snum < 0) {
3773 /* do the globals */
3774 for (; parm_table[*i].label; (*i)++) {
3775 if (parm_table[*i].p_class == P_SEPARATOR)
3776 return &parm_table[(*i)++];
3778 if ((*parm_table[*i].label == '-'))
3779 continue;
3781 if ((*i) > 0
3782 && (parm_table[*i].offset ==
3783 parm_table[(*i) - 1].offset)
3784 && (parm_table[*i].p_class ==
3785 parm_table[(*i) - 1].p_class))
3786 continue;
3788 if (is_default(*i) && !allparameters)
3789 continue;
3791 return &parm_table[(*i)++];
3793 } else {
3794 struct loadparm_service *pService = ServicePtrs[snum];
3796 for (; parm_table[*i].label; (*i)++) {
3797 if (parm_table[*i].p_class == P_SEPARATOR)
3798 return &parm_table[(*i)++];
3800 if (parm_table[*i].p_class == P_LOCAL &&
3801 (*parm_table[*i].label != '-') &&
3802 ((*i) == 0 ||
3803 (parm_table[*i].offset !=
3804 parm_table[(*i) - 1].offset)))
3806 if (allparameters ||
3807 !equal_parameter(parm_table[*i].type,
3808 lp_parm_ptr(pService,
3809 &parm_table[*i]),
3810 lp_parm_ptr(NULL,
3811 &parm_table[*i])))
3813 return &parm_table[(*i)++];
3819 return NULL;
3823 #if 0
3824 /***************************************************************************
3825 Display the contents of a single copy structure.
3826 ***************************************************************************/
3827 static void dump_copy_map(bool *pcopymap)
3829 int i;
3830 if (!pcopymap)
3831 return;
3833 printf("\n\tNon-Copied parameters:\n");
3835 for (i = 0; parm_table[i].label; i++)
3836 if (parm_table[i].p_class == P_LOCAL &&
3837 parm_table[i].ptr && !pcopymap[i] &&
3838 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3840 printf("\t\t%s\n", parm_table[i].label);
3843 #endif
3845 /***************************************************************************
3846 Return TRUE if the passed service number is within range.
3847 ***************************************************************************/
3849 bool lp_snum_ok(int iService)
3851 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3854 /***************************************************************************
3855 Auto-load some home services.
3856 ***************************************************************************/
3858 static void lp_add_auto_services(char *str)
3860 char *s;
3861 char *p;
3862 int homes;
3863 char *saveptr;
3865 if (!str)
3866 return;
3868 s = SMB_STRDUP(str);
3869 if (!s)
3870 return;
3872 homes = lp_servicenumber(HOMES_NAME);
3874 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3875 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3876 char *home;
3878 if (lp_servicenumber(p) >= 0)
3879 continue;
3881 home = get_user_home_dir(talloc_tos(), p);
3883 if (home && home[0] && homes >= 0)
3884 lp_add_home(p, homes, p, home);
3886 TALLOC_FREE(home);
3888 SAFE_FREE(s);
3891 /***************************************************************************
3892 Auto-load one printer.
3893 ***************************************************************************/
3895 void lp_add_one_printer(const char *name, const char *comment,
3896 const char *location, void *pdata)
3898 int printers = lp_servicenumber(PRINTERS_NAME);
3899 int i;
3901 if (lp_servicenumber(name) < 0) {
3902 lp_add_printer(name, printers);
3903 if ((i = lp_servicenumber(name)) >= 0) {
3904 string_set(&ServicePtrs[i]->comment, comment);
3905 ServicePtrs[i]->autoloaded = true;
3910 /***************************************************************************
3911 Have we loaded a services file yet?
3912 ***************************************************************************/
3914 bool lp_loaded(void)
3916 return (bLoaded);
3919 /***************************************************************************
3920 Unload unused services.
3921 ***************************************************************************/
3923 void lp_killunused(struct smbd_server_connection *sconn,
3924 bool (*snumused) (struct smbd_server_connection *, int))
3926 int i;
3927 for (i = 0; i < iNumServices; i++) {
3928 if (!VALID(i))
3929 continue;
3931 /* don't kill autoloaded or usershare services */
3932 if ( ServicePtrs[i]->autoloaded ||
3933 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3934 continue;
3937 if (!snumused || !snumused(sconn, i)) {
3938 free_service_byindex(i);
3944 * Kill all except autoloaded and usershare services - convenience wrapper
3946 void lp_kill_all_services(void)
3948 lp_killunused(NULL, NULL);
3951 /***************************************************************************
3952 Unload a service.
3953 ***************************************************************************/
3955 void lp_killservice(int iServiceIn)
3957 if (VALID(iServiceIn)) {
3958 free_service_byindex(iServiceIn);
3962 /***************************************************************************
3963 Save the curent values of all global and sDefault parameters into the
3964 defaults union. This allows swat and testparm to show only the
3965 changed (ie. non-default) parameters.
3966 ***************************************************************************/
3968 static void lp_save_defaults(void)
3970 int i;
3971 for (i = 0; parm_table[i].label; i++) {
3972 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3973 && parm_table[i].p_class == parm_table[i - 1].p_class)
3974 continue;
3975 switch (parm_table[i].type) {
3976 case P_LIST:
3977 case P_CMDLIST:
3978 parm_table[i].def.lvalue = str_list_copy(
3979 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3980 break;
3981 case P_STRING:
3982 case P_USTRING:
3983 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3984 break;
3985 case P_BOOL:
3986 case P_BOOLREV:
3987 parm_table[i].def.bvalue =
3988 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3989 break;
3990 case P_CHAR:
3991 parm_table[i].def.cvalue =
3992 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3993 break;
3994 case P_INTEGER:
3995 case P_OCTAL:
3996 case P_ENUM:
3997 case P_BYTES:
3998 parm_table[i].def.ivalue =
3999 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
4000 break;
4001 case P_SEP:
4002 break;
4005 defaults_saved = true;
4008 /***********************************************************
4009 If we should send plaintext/LANMAN passwords in the clinet
4010 ************************************************************/
4012 static void set_allowed_client_auth(void)
4014 if (Globals.bClientNTLMv2Auth) {
4015 Globals.bClientLanManAuth = false;
4017 if (!Globals.bClientLanManAuth) {
4018 Globals.bClientPlaintextAuth = false;
4022 /***************************************************************************
4023 JRA.
4024 The following code allows smbd to read a user defined share file.
4025 Yes, this is my intent. Yes, I'm comfortable with that...
4027 THE FOLLOWING IS SECURITY CRITICAL CODE.
4029 It washes your clothes, it cleans your house, it guards you while you sleep...
4030 Do not f%^k with it....
4031 ***************************************************************************/
4033 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4035 /***************************************************************************
4036 Check allowed stat state of a usershare file.
4037 Ensure we print out who is dicking with us so the admin can
4038 get their sorry ass fired.
4039 ***************************************************************************/
4041 static bool check_usershare_stat(const char *fname,
4042 const SMB_STRUCT_STAT *psbuf)
4044 if (!S_ISREG(psbuf->st_ex_mode)) {
4045 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4046 "not a regular file\n",
4047 fname, (unsigned int)psbuf->st_ex_uid ));
4048 return false;
4051 /* Ensure this doesn't have the other write bit set. */
4052 if (psbuf->st_ex_mode & S_IWOTH) {
4053 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4054 "public write. Refusing to allow as a usershare file.\n",
4055 fname, (unsigned int)psbuf->st_ex_uid ));
4056 return false;
4059 /* Should be 10k or less. */
4060 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4061 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4062 "too large (%u) to be a user share file.\n",
4063 fname, (unsigned int)psbuf->st_ex_uid,
4064 (unsigned int)psbuf->st_ex_size ));
4065 return false;
4068 return true;
4071 /***************************************************************************
4072 Parse the contents of a usershare file.
4073 ***************************************************************************/
4075 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4076 SMB_STRUCT_STAT *psbuf,
4077 const char *servicename,
4078 int snum,
4079 char **lines,
4080 int numlines,
4081 char **pp_sharepath,
4082 char **pp_comment,
4083 char **pp_cp_servicename,
4084 struct security_descriptor **ppsd,
4085 bool *pallow_guest)
4087 const char **prefixallowlist = lp_usershare_prefix_allow_list();
4088 const char **prefixdenylist = lp_usershare_prefix_deny_list();
4089 int us_vers;
4090 DIR *dp;
4091 SMB_STRUCT_STAT sbuf;
4092 char *sharepath = NULL;
4093 char *comment = NULL;
4095 *pp_sharepath = NULL;
4096 *pp_comment = NULL;
4098 *pallow_guest = false;
4100 if (numlines < 4) {
4101 return USERSHARE_MALFORMED_FILE;
4104 if (strcmp(lines[0], "#VERSION 1") == 0) {
4105 us_vers = 1;
4106 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4107 us_vers = 2;
4108 if (numlines < 5) {
4109 return USERSHARE_MALFORMED_FILE;
4111 } else {
4112 return USERSHARE_BAD_VERSION;
4115 if (strncmp(lines[1], "path=", 5) != 0) {
4116 return USERSHARE_MALFORMED_PATH;
4119 sharepath = talloc_strdup(ctx, &lines[1][5]);
4120 if (!sharepath) {
4121 return USERSHARE_POSIX_ERR;
4123 trim_string(sharepath, " ", " ");
4125 if (strncmp(lines[2], "comment=", 8) != 0) {
4126 return USERSHARE_MALFORMED_COMMENT_DEF;
4129 comment = talloc_strdup(ctx, &lines[2][8]);
4130 if (!comment) {
4131 return USERSHARE_POSIX_ERR;
4133 trim_string(comment, " ", " ");
4134 trim_char(comment, '"', '"');
4136 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4137 return USERSHARE_MALFORMED_ACL_DEF;
4140 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4141 return USERSHARE_ACL_ERR;
4144 if (us_vers == 2) {
4145 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4146 return USERSHARE_MALFORMED_ACL_DEF;
4148 if (lines[4][9] == 'y') {
4149 *pallow_guest = true;
4152 /* Backwards compatible extension to file version #2. */
4153 if (numlines > 5) {
4154 if (strncmp(lines[5], "sharename=", 10) != 0) {
4155 return USERSHARE_MALFORMED_SHARENAME_DEF;
4157 if (!strequal(&lines[5][10], servicename)) {
4158 return USERSHARE_BAD_SHARENAME;
4160 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4161 if (!*pp_cp_servicename) {
4162 return USERSHARE_POSIX_ERR;
4167 if (*pp_cp_servicename == NULL) {
4168 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4169 if (!*pp_cp_servicename) {
4170 return USERSHARE_POSIX_ERR;
4174 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4175 /* Path didn't change, no checks needed. */
4176 *pp_sharepath = sharepath;
4177 *pp_comment = comment;
4178 return USERSHARE_OK;
4181 /* The path *must* be absolute. */
4182 if (sharepath[0] != '/') {
4183 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4184 servicename, sharepath));
4185 return USERSHARE_PATH_NOT_ABSOLUTE;
4188 /* If there is a usershare prefix deny list ensure one of these paths
4189 doesn't match the start of the user given path. */
4190 if (prefixdenylist) {
4191 int i;
4192 for ( i=0; prefixdenylist[i]; i++ ) {
4193 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4194 servicename, i, prefixdenylist[i], sharepath ));
4195 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4196 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4197 "usershare prefix deny list entries.\n",
4198 servicename, sharepath));
4199 return USERSHARE_PATH_IS_DENIED;
4204 /* If there is a usershare prefix allow list ensure one of these paths
4205 does match the start of the user given path. */
4207 if (prefixallowlist) {
4208 int i;
4209 for ( i=0; prefixallowlist[i]; i++ ) {
4210 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4211 servicename, i, prefixallowlist[i], sharepath ));
4212 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4213 break;
4216 if (prefixallowlist[i] == NULL) {
4217 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4218 "usershare prefix allow list entries.\n",
4219 servicename, sharepath));
4220 return USERSHARE_PATH_NOT_ALLOWED;
4224 /* Ensure this is pointing to a directory. */
4225 dp = opendir(sharepath);
4227 if (!dp) {
4228 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4229 servicename, sharepath));
4230 return USERSHARE_PATH_NOT_DIRECTORY;
4233 /* Ensure the owner of the usershare file has permission to share
4234 this directory. */
4236 if (sys_stat(sharepath, &sbuf, false) == -1) {
4237 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4238 servicename, sharepath, strerror(errno) ));
4239 closedir(dp);
4240 return USERSHARE_POSIX_ERR;
4243 closedir(dp);
4245 if (!S_ISDIR(sbuf.st_ex_mode)) {
4246 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4247 servicename, sharepath ));
4248 return USERSHARE_PATH_NOT_DIRECTORY;
4251 /* Check if sharing is restricted to owner-only. */
4252 /* psbuf is the stat of the usershare definition file,
4253 sbuf is the stat of the target directory to be shared. */
4255 if (lp_usershare_owner_only()) {
4256 /* root can share anything. */
4257 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4258 return USERSHARE_PATH_NOT_ALLOWED;
4262 *pp_sharepath = sharepath;
4263 *pp_comment = comment;
4264 return USERSHARE_OK;
4267 /***************************************************************************
4268 Deal with a usershare file.
4269 Returns:
4270 >= 0 - snum
4271 -1 - Bad name, invalid contents.
4272 - service name already existed and not a usershare, problem
4273 with permissions to share directory etc.
4274 ***************************************************************************/
4276 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4278 SMB_STRUCT_STAT sbuf;
4279 SMB_STRUCT_STAT lsbuf;
4280 char *fname = NULL;
4281 char *sharepath = NULL;
4282 char *comment = NULL;
4283 char *cp_service_name = NULL;
4284 char **lines = NULL;
4285 int numlines = 0;
4286 int fd = -1;
4287 int iService = -1;
4288 TALLOC_CTX *ctx = talloc_stackframe();
4289 struct security_descriptor *psd = NULL;
4290 bool guest_ok = false;
4291 char *canon_name = NULL;
4292 bool added_service = false;
4293 int ret = -1;
4295 /* Ensure share name doesn't contain invalid characters. */
4296 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4297 DEBUG(0,("process_usershare_file: share name %s contains "
4298 "invalid characters (any of %s)\n",
4299 file_name, INVALID_SHARENAME_CHARS ));
4300 goto out;
4303 canon_name = canonicalize_servicename(ctx, file_name);
4304 if (!canon_name) {
4305 goto out;
4308 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4309 if (!fname) {
4310 goto out;
4313 /* Minimize the race condition by doing an lstat before we
4314 open and fstat. Ensure this isn't a symlink link. */
4316 if (sys_lstat(fname, &lsbuf, false) != 0) {
4317 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4318 fname, strerror(errno) ));
4319 goto out;
4322 /* This must be a regular file, not a symlink, directory or
4323 other strange filetype. */
4324 if (!check_usershare_stat(fname, &lsbuf)) {
4325 goto out;
4329 TDB_DATA data;
4330 NTSTATUS status;
4332 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4333 canon_name, &data);
4335 iService = -1;
4337 if (NT_STATUS_IS_OK(status) &&
4338 (data.dptr != NULL) &&
4339 (data.dsize == sizeof(iService))) {
4340 memcpy(&iService, data.dptr, sizeof(iService));
4344 if (iService != -1 &&
4345 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4346 &lsbuf.st_ex_mtime) == 0) {
4347 /* Nothing changed - Mark valid and return. */
4348 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4349 canon_name ));
4350 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4351 ret = iService;
4352 goto out;
4355 /* Try and open the file read only - no symlinks allowed. */
4356 #ifdef O_NOFOLLOW
4357 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4358 #else
4359 fd = open(fname, O_RDONLY, 0);
4360 #endif
4362 if (fd == -1) {
4363 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4364 fname, strerror(errno) ));
4365 goto out;
4368 /* Now fstat to be *SURE* it's a regular file. */
4369 if (sys_fstat(fd, &sbuf, false) != 0) {
4370 close(fd);
4371 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4372 fname, strerror(errno) ));
4373 goto out;
4376 /* Is it the same dev/inode as was lstated ? */
4377 if (!check_same_stat(&lsbuf, &sbuf)) {
4378 close(fd);
4379 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4380 "Symlink spoofing going on ?\n", fname ));
4381 goto out;
4384 /* This must be a regular file, not a symlink, directory or
4385 other strange filetype. */
4386 if (!check_usershare_stat(fname, &sbuf)) {
4387 goto out;
4390 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4392 close(fd);
4393 if (lines == NULL) {
4394 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4395 fname, (unsigned int)sbuf.st_ex_uid ));
4396 goto out;
4399 if (parse_usershare_file(ctx, &sbuf, file_name,
4400 iService, lines, numlines, &sharepath,
4401 &comment, &cp_service_name,
4402 &psd, &guest_ok) != USERSHARE_OK) {
4403 goto out;
4406 /* Everything ok - add the service possibly using a template. */
4407 if (iService < 0) {
4408 const struct loadparm_service *sp = &sDefault;
4409 if (snum_template != -1) {
4410 sp = ServicePtrs[snum_template];
4413 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4414 DEBUG(0, ("process_usershare_file: Failed to add "
4415 "new service %s\n", cp_service_name));
4416 goto out;
4419 added_service = true;
4421 /* Read only is controlled by usershare ACL below. */
4422 ServicePtrs[iService]->bRead_only = false;
4425 /* Write the ACL of the new/modified share. */
4426 if (!set_share_security(canon_name, psd)) {
4427 DEBUG(0, ("process_usershare_file: Failed to set share "
4428 "security for user share %s\n",
4429 canon_name ));
4430 goto out;
4433 /* If from a template it may be marked invalid. */
4434 ServicePtrs[iService]->valid = true;
4436 /* Set the service as a valid usershare. */
4437 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4439 /* Set guest access. */
4440 if (lp_usershare_allow_guests()) {
4441 ServicePtrs[iService]->bGuest_ok = guest_ok;
4444 /* And note when it was loaded. */
4445 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4446 string_set(&ServicePtrs[iService]->szPath, sharepath);
4447 string_set(&ServicePtrs[iService]->comment, comment);
4449 ret = iService;
4451 out:
4453 if (ret == -1 && iService != -1 && added_service) {
4454 lp_remove_service(iService);
4457 TALLOC_FREE(lines);
4458 TALLOC_FREE(ctx);
4459 return ret;
4462 /***************************************************************************
4463 Checks if a usershare entry has been modified since last load.
4464 ***************************************************************************/
4466 static bool usershare_exists(int iService, struct timespec *last_mod)
4468 SMB_STRUCT_STAT lsbuf;
4469 const char *usersharepath = Globals.szUsersharePath;
4470 char *fname;
4472 if (asprintf(&fname, "%s/%s",
4473 usersharepath,
4474 ServicePtrs[iService]->szService) < 0) {
4475 return false;
4478 if (sys_lstat(fname, &lsbuf, false) != 0) {
4479 SAFE_FREE(fname);
4480 return false;
4483 if (!S_ISREG(lsbuf.st_ex_mode)) {
4484 SAFE_FREE(fname);
4485 return false;
4488 SAFE_FREE(fname);
4489 *last_mod = lsbuf.st_ex_mtime;
4490 return true;
4493 /***************************************************************************
4494 Load a usershare service by name. Returns a valid servicenumber or -1.
4495 ***************************************************************************/
4497 int load_usershare_service(const char *servicename)
4499 SMB_STRUCT_STAT sbuf;
4500 const char *usersharepath = Globals.szUsersharePath;
4501 int max_user_shares = Globals.iUsershareMaxShares;
4502 int snum_template = -1;
4504 if (*usersharepath == 0 || max_user_shares == 0) {
4505 return -1;
4508 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4509 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4510 usersharepath, strerror(errno) ));
4511 return -1;
4514 if (!S_ISDIR(sbuf.st_ex_mode)) {
4515 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4516 usersharepath ));
4517 return -1;
4521 * This directory must be owned by root, and have the 't' bit set.
4522 * It also must not be writable by "other".
4525 #ifdef S_ISVTX
4526 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4527 #else
4528 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4529 #endif
4530 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4531 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4532 usersharepath ));
4533 return -1;
4536 /* Ensure the template share exists if it's set. */
4537 if (Globals.szUsershareTemplateShare[0]) {
4538 /* We can't use lp_servicenumber here as we are recommending that
4539 template shares have -valid=false set. */
4540 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4541 if (ServicePtrs[snum_template]->szService &&
4542 strequal(ServicePtrs[snum_template]->szService,
4543 Globals.szUsershareTemplateShare)) {
4544 break;
4548 if (snum_template == -1) {
4549 DEBUG(0,("load_usershare_service: usershare template share %s "
4550 "does not exist.\n",
4551 Globals.szUsershareTemplateShare ));
4552 return -1;
4556 return process_usershare_file(usersharepath, servicename, snum_template);
4559 /***************************************************************************
4560 Load all user defined shares from the user share directory.
4561 We only do this if we're enumerating the share list.
4562 This is the function that can delete usershares that have
4563 been removed.
4564 ***************************************************************************/
4566 int load_usershare_shares(struct smbd_server_connection *sconn,
4567 bool (*snumused) (struct smbd_server_connection *, int))
4569 DIR *dp;
4570 SMB_STRUCT_STAT sbuf;
4571 struct dirent *de;
4572 int num_usershares = 0;
4573 int max_user_shares = Globals.iUsershareMaxShares;
4574 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4575 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4576 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4577 int iService;
4578 int snum_template = -1;
4579 const char *usersharepath = Globals.szUsersharePath;
4580 int ret = lp_numservices();
4581 TALLOC_CTX *tmp_ctx;
4583 if (max_user_shares == 0 || *usersharepath == '\0') {
4584 return lp_numservices();
4587 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4588 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4589 usersharepath, strerror(errno) ));
4590 return ret;
4594 * This directory must be owned by root, and have the 't' bit set.
4595 * It also must not be writable by "other".
4598 #ifdef S_ISVTX
4599 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4600 #else
4601 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4602 #endif
4603 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4604 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4605 usersharepath ));
4606 return ret;
4609 /* Ensure the template share exists if it's set. */
4610 if (Globals.szUsershareTemplateShare[0]) {
4611 /* We can't use lp_servicenumber here as we are recommending that
4612 template shares have -valid=false set. */
4613 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4614 if (ServicePtrs[snum_template]->szService &&
4615 strequal(ServicePtrs[snum_template]->szService,
4616 Globals.szUsershareTemplateShare)) {
4617 break;
4621 if (snum_template == -1) {
4622 DEBUG(0,("load_usershare_shares: usershare template share %s "
4623 "does not exist.\n",
4624 Globals.szUsershareTemplateShare ));
4625 return ret;
4629 /* Mark all existing usershares as pending delete. */
4630 for (iService = iNumServices - 1; iService >= 0; iService--) {
4631 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4632 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4636 dp = opendir(usersharepath);
4637 if (!dp) {
4638 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4639 usersharepath, strerror(errno) ));
4640 return ret;
4643 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4644 (de = readdir(dp));
4645 num_dir_entries++ ) {
4646 int r;
4647 const char *n = de->d_name;
4649 /* Ignore . and .. */
4650 if (*n == '.') {
4651 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4652 continue;
4656 if (n[0] == ':') {
4657 /* Temporary file used when creating a share. */
4658 num_tmp_dir_entries++;
4661 /* Allow 20% tmp entries. */
4662 if (num_tmp_dir_entries > allowed_tmp_entries) {
4663 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4664 "in directory %s\n",
4665 num_tmp_dir_entries, usersharepath));
4666 break;
4669 r = process_usershare_file(usersharepath, n, snum_template);
4670 if (r == 0) {
4671 /* Update the services count. */
4672 num_usershares++;
4673 if (num_usershares >= max_user_shares) {
4674 DEBUG(0,("load_usershare_shares: max user shares reached "
4675 "on file %s in directory %s\n",
4676 n, usersharepath ));
4677 break;
4679 } else if (r == -1) {
4680 num_bad_dir_entries++;
4683 /* Allow 20% bad entries. */
4684 if (num_bad_dir_entries > allowed_bad_entries) {
4685 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4686 "in directory %s\n",
4687 num_bad_dir_entries, usersharepath));
4688 break;
4691 /* Allow 20% bad entries. */
4692 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4693 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4694 "in directory %s\n",
4695 num_dir_entries, usersharepath));
4696 break;
4700 closedir(dp);
4702 /* Sweep through and delete any non-refreshed usershares that are
4703 not currently in use. */
4704 tmp_ctx = talloc_stackframe();
4705 for (iService = iNumServices - 1; iService >= 0; iService--) {
4706 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4707 char *servname;
4709 if (snumused && snumused(sconn, iService)) {
4710 continue;
4713 servname = lp_servicename(tmp_ctx, iService);
4715 /* Remove from the share ACL db. */
4716 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4717 servname ));
4718 delete_share_security(servname);
4719 free_service_byindex(iService);
4722 talloc_free(tmp_ctx);
4724 return lp_numservices();
4727 /********************************************************
4728 Destroy global resources allocated in this file
4729 ********************************************************/
4731 void gfree_loadparm(void)
4733 int i;
4735 free_file_list();
4737 /* Free resources allocated to services */
4739 for ( i = 0; i < iNumServices; i++ ) {
4740 if ( VALID(i) ) {
4741 free_service_byindex(i);
4745 SAFE_FREE( ServicePtrs );
4746 iNumServices = 0;
4748 /* Now release all resources allocated to global
4749 parameters and the default service */
4751 free_global_parameters();
4755 /***************************************************************************
4756 Allow client apps to specify that they are a client
4757 ***************************************************************************/
4758 static void lp_set_in_client(bool b)
4760 in_client = b;
4764 /***************************************************************************
4765 Determine if we're running in a client app
4766 ***************************************************************************/
4767 static bool lp_is_in_client(void)
4769 return in_client;
4772 /***************************************************************************
4773 Load the services array from the services file. Return true on success,
4774 false on failure.
4775 ***************************************************************************/
4777 static bool lp_load_ex(const char *pszFname,
4778 bool global_only,
4779 bool save_defaults,
4780 bool add_ipc,
4781 bool initialize_globals,
4782 bool allow_include_registry,
4783 bool load_all_shares)
4785 char *n2 = NULL;
4786 bool bRetval;
4788 bRetval = false;
4790 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4792 bInGlobalSection = true;
4793 bGlobalOnly = global_only;
4794 bAllowIncludeRegistry = allow_include_registry;
4796 init_globals(initialize_globals);
4798 free_file_list();
4800 if (save_defaults) {
4801 init_locals();
4802 lp_save_defaults();
4805 if (!initialize_globals) {
4806 free_param_opts(&Globals.param_opt);
4807 apply_lp_set_cmdline();
4810 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4812 /* We get sections first, so have to start 'behind' to make up */
4813 iServiceIndex = -1;
4815 if (lp_config_backend_is_file()) {
4816 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4817 current_user_info.domain,
4818 pszFname);
4819 if (!n2) {
4820 smb_panic("lp_load_ex: out of memory");
4823 add_to_file_list(pszFname, n2);
4825 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4826 TALLOC_FREE(n2);
4828 /* finish up the last section */
4829 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4830 if (bRetval) {
4831 if (iServiceIndex >= 0) {
4832 bRetval = service_ok(iServiceIndex);
4836 if (lp_config_backend_is_registry()) {
4837 /* config backend changed to registry in config file */
4839 * We need to use this extra global variable here to
4840 * survive restart: init_globals uses this as a default
4841 * for ConfigBackend. Otherwise, init_globals would
4842 * send us into an endless loop here.
4844 config_backend = CONFIG_BACKEND_REGISTRY;
4845 /* start over */
4846 DEBUG(1, ("lp_load_ex: changing to config backend "
4847 "registry\n"));
4848 init_globals(true);
4849 lp_kill_all_services();
4850 return lp_load_ex(pszFname, global_only, save_defaults,
4851 add_ipc, initialize_globals,
4852 allow_include_registry,
4853 load_all_shares);
4855 } else if (lp_config_backend_is_registry()) {
4856 bRetval = process_registry_globals();
4857 } else {
4858 DEBUG(0, ("Illegal config backend given: %d\n",
4859 lp_config_backend()));
4860 bRetval = false;
4863 if (bRetval && lp_registry_shares()) {
4864 if (load_all_shares) {
4865 bRetval = process_registry_shares();
4866 } else {
4867 bRetval = reload_registry_shares();
4872 char *serv = lp_auto_services(talloc_tos());
4873 lp_add_auto_services(serv);
4874 TALLOC_FREE(serv);
4877 if (add_ipc) {
4878 /* When 'restrict anonymous = 2' guest connections to ipc$
4879 are denied */
4880 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4881 if ( lp_enable_asu_support() ) {
4882 lp_add_ipc("ADMIN$", false);
4886 set_allowed_client_auth();
4888 if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4889 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4890 lp_passwordserver()));
4893 bLoaded = true;
4895 /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4896 /* if bWINSsupport is true and we are in the client */
4897 if (lp_is_in_client() && Globals.bWINSsupport) {
4898 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4901 init_iconv();
4903 fault_configure(smb_panic_s3);
4905 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4906 const char **vfs_objects = lp_vfs_objects(-1);
4907 if (!vfs_objects || !vfs_objects[0]) {
4908 if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
4909 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
4910 } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
4911 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
4912 } else {
4913 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
4918 bAllowIncludeRegistry = true;
4920 return (bRetval);
4923 bool lp_load(const char *pszFname,
4924 bool global_only,
4925 bool save_defaults,
4926 bool add_ipc,
4927 bool initialize_globals)
4929 return lp_load_ex(pszFname,
4930 global_only,
4931 save_defaults,
4932 add_ipc,
4933 initialize_globals,
4934 true, /* allow_include_registry */
4935 false); /* load_all_shares*/
4938 bool lp_load_initial_only(const char *pszFname)
4940 return lp_load_ex(pszFname,
4941 true, /* global only */
4942 false, /* save_defaults */
4943 false, /* add_ipc */
4944 true, /* initialize_globals */
4945 false, /* allow_include_registry */
4946 false); /* load_all_shares*/
4950 * most common lp_load wrapper, loading only the globals
4952 bool lp_load_global(const char *file_name)
4954 return lp_load_ex(file_name,
4955 true, /* global_only */
4956 false, /* save_defaults */
4957 false, /* add_ipc */
4958 true, /* initialize_globals */
4959 true, /* allow_include_registry */
4960 false); /* load_all_shares*/
4964 * lp_load wrapper, especially for clients
4966 bool lp_load_client(const char *file_name)
4968 lp_set_in_client(true);
4970 return lp_load_global(file_name);
4974 * lp_load wrapper, loading only globals, but intended
4975 * for subsequent calls, not reinitializing the globals
4976 * to default values
4978 bool lp_load_global_no_reinit(const char *file_name)
4980 return lp_load_ex(file_name,
4981 true, /* global_only */
4982 false, /* save_defaults */
4983 false, /* add_ipc */
4984 false, /* initialize_globals */
4985 true, /* allow_include_registry */
4986 false); /* load_all_shares*/
4990 * lp_load wrapper, especially for clients, no reinitialization
4992 bool lp_load_client_no_reinit(const char *file_name)
4994 lp_set_in_client(true);
4996 return lp_load_global_no_reinit(file_name);
4999 bool lp_load_with_registry_shares(const char *pszFname,
5000 bool global_only,
5001 bool save_defaults,
5002 bool add_ipc,
5003 bool initialize_globals)
5005 return lp_load_ex(pszFname,
5006 global_only,
5007 save_defaults,
5008 add_ipc,
5009 initialize_globals,
5010 true, /* allow_include_registry */
5011 true); /* load_all_shares*/
5014 /***************************************************************************
5015 Return the max number of services.
5016 ***************************************************************************/
5018 int lp_numservices(void)
5020 return (iNumServices);
5023 /***************************************************************************
5024 Display the contents of the services array in human-readable form.
5025 ***************************************************************************/
5027 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5029 int iService;
5031 if (show_defaults)
5032 defaults_saved = false;
5034 dump_globals(f);
5036 dump_a_service(&sDefault, f);
5038 for (iService = 0; iService < maxtoprint; iService++) {
5039 fprintf(f,"\n");
5040 lp_dump_one(f, show_defaults, iService);
5044 /***************************************************************************
5045 Display the contents of one service in human-readable form.
5046 ***************************************************************************/
5048 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5050 if (VALID(snum)) {
5051 if (ServicePtrs[snum]->szService[0] == '\0')
5052 return;
5053 dump_a_service(ServicePtrs[snum], f);
5057 /***************************************************************************
5058 Return the number of the service with the given name, or -1 if it doesn't
5059 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5060 getservicebyname()! This works ONLY if all services have been loaded, and
5061 does not copy the found service.
5062 ***************************************************************************/
5064 int lp_servicenumber(const char *pszServiceName)
5066 int iService;
5067 fstring serviceName;
5069 if (!pszServiceName) {
5070 return GLOBAL_SECTION_SNUM;
5073 for (iService = iNumServices - 1; iService >= 0; iService--) {
5074 if (VALID(iService) && ServicePtrs[iService]->szService) {
5076 * The substitution here is used to support %U is
5077 * service names
5079 fstrcpy(serviceName, ServicePtrs[iService]->szService);
5080 standard_sub_basic(get_current_username(),
5081 current_user_info.domain,
5082 serviceName,sizeof(serviceName));
5083 if (strequal(serviceName, pszServiceName)) {
5084 break;
5089 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5090 struct timespec last_mod;
5092 if (!usershare_exists(iService, &last_mod)) {
5093 /* Remove the share security tdb entry for it. */
5094 delete_share_security(lp_servicename(talloc_tos(), iService));
5095 /* Remove it from the array. */
5096 free_service_byindex(iService);
5097 /* Doesn't exist anymore. */
5098 return GLOBAL_SECTION_SNUM;
5101 /* Has it been modified ? If so delete and reload. */
5102 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5103 &last_mod) < 0) {
5104 /* Remove it from the array. */
5105 free_service_byindex(iService);
5106 /* and now reload it. */
5107 iService = load_usershare_service(pszServiceName);
5111 if (iService < 0) {
5112 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5113 return GLOBAL_SECTION_SNUM;
5116 return (iService);
5119 /*******************************************************************
5120 A useful volume label function.
5121 ********************************************************************/
5123 const char *volume_label(TALLOC_CTX *ctx, int snum)
5125 char *ret;
5126 const char *label = lp_volume(ctx, snum);
5127 if (!*label) {
5128 label = lp_servicename(ctx, snum);
5131 /* This returns a 33 byte guarenteed null terminated string. */
5132 ret = talloc_strndup(ctx, label, 32);
5133 if (!ret) {
5134 return "";
5136 return ret;
5139 /*******************************************************************
5140 Get the default server type we will announce as via nmbd.
5141 ********************************************************************/
5143 int lp_default_server_announce(void)
5145 int default_server_announce = 0;
5146 default_server_announce |= SV_TYPE_WORKSTATION;
5147 default_server_announce |= SV_TYPE_SERVER;
5148 default_server_announce |= SV_TYPE_SERVER_UNIX;
5150 /* note that the flag should be set only if we have a
5151 printer service but nmbd doesn't actually load the
5152 services so we can't tell --jerry */
5154 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5156 default_server_announce |= SV_TYPE_SERVER_NT;
5157 default_server_announce |= SV_TYPE_NT;
5159 switch (lp_server_role()) {
5160 case ROLE_DOMAIN_MEMBER:
5161 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5162 break;
5163 case ROLE_DOMAIN_PDC:
5164 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5165 break;
5166 case ROLE_DOMAIN_BDC:
5167 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5168 break;
5169 case ROLE_STANDALONE:
5170 default:
5171 break;
5173 if (lp_time_server())
5174 default_server_announce |= SV_TYPE_TIME_SOURCE;
5176 if (lp_host_msdfs())
5177 default_server_announce |= SV_TYPE_DFS_SERVER;
5179 return default_server_announce;
5182 /***********************************************************
5183 If we are PDC then prefer us as DMB
5184 ************************************************************/
5186 bool lp_domain_master(void)
5188 if (Globals.domain_master == Auto)
5189 return (lp_server_role() == ROLE_DOMAIN_PDC);
5191 return (bool)Globals.domain_master;
5194 /***********************************************************
5195 If we are PDC then prefer us as DMB
5196 ************************************************************/
5198 static bool lp_domain_master_true_or_auto(void)
5200 if (Globals.domain_master) /* auto or yes */
5201 return true;
5203 return false;
5206 /***********************************************************
5207 If we are DMB then prefer us as LMB
5208 ************************************************************/
5210 bool lp_preferred_master(void)
5212 if (Globals.iPreferredMaster == Auto)
5213 return (lp_local_master() && lp_domain_master());
5215 return (bool)Globals.iPreferredMaster;
5218 /*******************************************************************
5219 Remove a service.
5220 ********************************************************************/
5222 void lp_remove_service(int snum)
5224 ServicePtrs[snum]->valid = false;
5225 invalid_services[num_invalid_services++] = snum;
5228 /*******************************************************************
5229 Copy a service.
5230 ********************************************************************/
5232 void lp_copy_service(int snum, const char *new_name)
5234 do_section(new_name, NULL);
5235 if (snum >= 0) {
5236 snum = lp_servicenumber(new_name);
5237 if (snum >= 0) {
5238 char *name = lp_servicename(talloc_tos(), snum);
5239 lp_do_parameter(snum, "copy", name);
5244 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5246 const char *ret = lp__printername(talloc_tos(), snum);
5247 if (ret == NULL || *ret == '\0') {
5248 ret = lp_const_servicename(snum);
5251 return ret;
5255 /***********************************************************
5256 Allow daemons such as winbindd to fix their logfile name.
5257 ************************************************************/
5259 void lp_set_logfile(const char *name)
5261 string_set(&Globals.logfile, name);
5262 debug_set_logfile(name);
5265 /*******************************************************************
5266 Return the max print jobs per queue.
5267 ********************************************************************/
5269 int lp_maxprintjobs(int snum)
5271 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5272 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5273 maxjobs = PRINT_MAX_JOBID - 1;
5275 return maxjobs;
5278 const char *lp_printcapname(void)
5280 if ((Globals.szPrintcapname != NULL) &&
5281 (Globals.szPrintcapname[0] != '\0'))
5282 return Globals.szPrintcapname;
5284 if (sDefault.iPrinting == PRINT_CUPS) {
5285 #ifdef HAVE_CUPS
5286 return "cups";
5287 #else
5288 return "lpstat";
5289 #endif
5292 if (sDefault.iPrinting == PRINT_BSD)
5293 return "/etc/printcap";
5295 return PRINTCAP_NAME;
5298 static uint32 spoolss_state;
5300 bool lp_disable_spoolss( void )
5302 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5303 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5305 return spoolss_state == SVCCTL_STOPPED ? true : false;
5308 void lp_set_spoolss_state( uint32 state )
5310 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5312 spoolss_state = state;
5315 uint32 lp_get_spoolss_state( void )
5317 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5320 /*******************************************************************
5321 Ensure we don't use sendfile if server smb signing is active.
5322 ********************************************************************/
5324 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5326 bool sign_active = false;
5328 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5329 if (get_Protocol() < PROTOCOL_NT1) {
5330 return false;
5332 if (signing_state) {
5333 sign_active = smb_signing_is_active(signing_state);
5335 return (lp__use_sendfile(snum) &&
5336 (get_remote_arch() != RA_WIN95) &&
5337 !sign_active);
5340 /*******************************************************************
5341 Turn off sendfile if we find the underlying OS doesn't support it.
5342 ********************************************************************/
5344 void set_use_sendfile(int snum, bool val)
5346 if (LP_SNUM_OK(snum))
5347 ServicePtrs[snum]->bUseSendfile = val;
5348 else
5349 sDefault.bUseSendfile = val;
5352 /*******************************************************************
5353 Turn off storing DOS attributes if this share doesn't support it.
5354 ********************************************************************/
5356 void set_store_dos_attributes(int snum, bool val)
5358 if (!LP_SNUM_OK(snum))
5359 return;
5360 ServicePtrs[(snum)]->bStoreDosAttributes = val;
5363 void lp_set_mangling_method(const char *new_method)
5365 string_set(&Globals.szManglingMethod, new_method);
5368 /*******************************************************************
5369 Global state for POSIX pathname processing.
5370 ********************************************************************/
5372 static bool posix_pathnames;
5374 bool lp_posix_pathnames(void)
5376 return posix_pathnames;
5379 /*******************************************************************
5380 Change everything needed to ensure POSIX pathname processing (currently
5381 not much).
5382 ********************************************************************/
5384 void lp_set_posix_pathnames(void)
5386 posix_pathnames = true;
5389 /*******************************************************************
5390 Global state for POSIX lock processing - CIFS unix extensions.
5391 ********************************************************************/
5393 bool posix_default_lock_was_set;
5394 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5396 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5398 if (posix_default_lock_was_set) {
5399 return posix_cifsx_locktype;
5400 } else {
5401 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5405 /*******************************************************************
5406 ********************************************************************/
5408 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5410 posix_default_lock_was_set = true;
5411 posix_cifsx_locktype = val;
5414 int lp_min_receive_file_size(void)
5416 if (Globals.iminreceivefile < 0) {
5417 return 0;
5419 return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5422 /*******************************************************************
5423 Safe wide links checks.
5424 This helper function always verify the validity of wide links,
5425 even after a configuration file reload.
5426 ********************************************************************/
5428 static bool lp_widelinks_internal(int snum)
5430 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5431 sDefault.bWidelinks);
5434 void widelinks_warning(int snum)
5436 if (lp_allow_insecure_widelinks()) {
5437 return;
5440 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5441 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5442 "These parameters are incompatible. "
5443 "Wide links will be disabled for this share.\n",
5444 lp_servicename(talloc_tos(), snum) ));
5448 bool lp_widelinks(int snum)
5450 /* wide links is always incompatible with unix extensions */
5451 if (lp_unix_extensions()) {
5453 * Unless we have "allow insecure widelinks"
5454 * turned on.
5456 if (!lp_allow_insecure_widelinks()) {
5457 return false;
5461 return lp_widelinks_internal(snum);
5464 bool lp_writeraw(void)
5466 if (lp_async_smb_echo_handler()) {
5467 return false;
5469 return lp__writeraw();
5472 bool lp_readraw(void)
5474 if (lp_async_smb_echo_handler()) {
5475 return false;
5477 return lp__readraw();
5480 int lp_server_role(void)
5482 return lp_find_server_role(lp__server_role(),
5483 lp__security(),
5484 lp__domain_logons(),
5485 lp_domain_master_true_or_auto());
5488 int lp_security(void)
5490 return lp_find_security(lp__server_role(),
5491 lp__security());