s3:torture:delete: untangle function call from result check
[Samba/gebeck_regimport.git] / source3 / param / loadparm.c
blobd4ee8a22f2b879a2f22ea8f2389909c76cd4f364
1 /*
2 Unix SMB/CIFS implementation.
3 Parameter loading functions
4 Copyright (C) Karl Auer 1993-1998
6 Largely re-written by Andrew Tridgell, September 1994
8 Copyright (C) Simo Sorce 2001
9 Copyright (C) Alexander Bokovoy 2002
10 Copyright (C) Stefan (metze) Metzmacher 2002
11 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12 Copyright (C) Michael Adam 2008
13 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14 Copyright (C) Andrew Bartlett 2011
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 3 of the License, or
19 (at your option) any later version.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
31 * Load parameters.
33 * This module provides suitable callback functions for the params
34 * module. It builds the internal table of service details which is
35 * then used by the rest of the server.
37 * To add a parameter:
39 * 1) add it to the global or service structure definition
40 * 2) add it to the parm_table
41 * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42 * 4) If it's a global then initialise it in init_globals. If a local
43 * (ie. service) parameter then initialise it in the sDefault structure
46 * Notes:
47 * The configuration file is processed sequentially for speed. It is NOT
48 * accessed randomly as happens in 'real' Windows. For this reason, there
49 * is a fair bit of sequence-dependent code here - ie., code which assumes
50 * that certain things happen before others. In particular, the code which
51 * happens at the boundary between sections is delicately poised, so be
52 * careful!
56 #include "includes.h"
57 #include "system/filesys.h"
58 #include "util_tdb.h"
59 #include "lib/param/loadparm.h"
60 #include "printing.h"
61 #include "lib/smbconf/smbconf.h"
62 #include "lib/smbconf/smbconf_init.h"
64 #include "ads.h"
65 #include "../librpc/gen_ndr/svcctl.h"
66 #include "intl.h"
67 #include "../libcli/smb/smb_signing.h"
68 #include "dbwrap/dbwrap.h"
69 #include "dbwrap/dbwrap_rbt.h"
70 #include "../lib/util/bitmap.h"
72 #ifdef HAVE_SYS_SYSCTL_H
73 #include <sys/sysctl.h>
74 #endif
76 #ifdef HAVE_HTTPCONNECTENCRYPT
77 #include <cups/http.h>
78 #endif
80 #ifdef CLUSTER_SUPPORT
81 #include "ctdb_private.h"
82 #endif
84 bool bLoaded = false;
86 extern userdom_struct current_user_info;
88 /* the special value for the include parameter
89 * to be interpreted not as a file name but to
90 * trigger loading of the global smb.conf options
91 * from registry. */
92 #ifndef INCLUDE_REGISTRY_NAME
93 #define INCLUDE_REGISTRY_NAME "registry"
94 #endif
96 static bool in_client = false; /* Not in the client by default */
97 static struct smbconf_csn conf_last_csn;
99 static int config_backend = CONFIG_BACKEND_FILE;
101 /* some helpful bits */
102 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
103 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
105 #define USERSHARE_VALID 1
106 #define USERSHARE_PENDING_DELETE 2
108 static bool defaults_saved = false;
110 #define LOADPARM_EXTRA_GLOBALS \
111 struct parmlist_entry *param_opt; \
112 char *szRealm; \
113 char *loglevel; \
114 int iminreceivefile; \
115 char *szPrintcapname; \
116 int CupsEncrypt; \
117 int iPreferredMaster; \
118 char *szLdapMachineSuffix; \
119 char *szLdapUserSuffix; \
120 char *szLdapIdmapSuffix; \
121 char *szLdapGroupSuffix; \
122 char *szStateDir; \
123 char *szCacheDir; \
124 char *szUsershareTemplateShare; \
125 char *szIdmapUID; \
126 char *szIdmapGID; \
127 int winbindMaxDomainConnections; \
128 int ismb2_max_credits; \
129 char *tls_keyfile; \
130 char *tls_certfile; \
131 char *tls_cafile; \
132 char *tls_crlfile; \
133 char *tls_dhpfile; \
134 char *panic_action; \
135 int bPreferredMaster;
137 #include "param/param_global.h"
139 static struct loadparm_global Globals;
141 /* This is a default service used to prime a services structure */
142 static struct loadparm_service sDefault =
144 .valid = true,
145 .autoloaded = false,
146 .usershare = 0,
147 .usershare_last_mod = {0, 0},
148 .szService = NULL,
149 .szPath = NULL,
150 .szUsername = NULL,
151 .szInvalidUsers = NULL,
152 .szValidUsers = NULL,
153 .szAdminUsers = NULL,
154 .szCopy = NULL,
155 .szInclude = NULL,
156 .szPreExec = NULL,
157 .szPostExec = NULL,
158 .szRootPreExec = NULL,
159 .szRootPostExec = NULL,
160 .szCupsOptions = NULL,
161 .szPrintcommand = NULL,
162 .szLpqcommand = NULL,
163 .szLprmcommand = NULL,
164 .szLppausecommand = NULL,
165 .szLpresumecommand = NULL,
166 .szQueuepausecommand = NULL,
167 .szQueueresumecommand = NULL,
168 .szPrintername = NULL,
169 .szPrintjobUsername = NULL,
170 .szDontdescend = NULL,
171 .szHostsallow = NULL,
172 .szHostsdeny = NULL,
173 .szMagicScript = NULL,
174 .szMagicOutput = NULL,
175 .szVetoFiles = NULL,
176 .szHideFiles = NULL,
177 .szVetoOplockFiles = NULL,
178 .comment = NULL,
179 .force_user = NULL,
180 .force_group = NULL,
181 .readlist = NULL,
182 .writelist = NULL,
183 .volume = NULL,
184 .fstype = NULL,
185 .szVfsObjects = NULL,
186 .szMSDfsProxy = NULL,
187 .szAioWriteBehind = NULL,
188 .szDfree = NULL,
189 .iMinPrintSpace = 0,
190 .iMaxPrintJobs = 1000,
191 .iMaxReportedPrintJobs = 0,
192 .iWriteCacheSize = 0,
193 .iCreate_mask = 0744,
194 .iCreate_force_mode = 0,
195 .iSecurity_mask = 0777,
196 .iSecurity_force_mode = 0,
197 .iDir_mask = 0755,
198 .iDir_force_mode = 0,
199 .iDir_Security_mask = 0777,
200 .iDir_Security_force_mode = 0,
201 .iMaxConnections = 0,
202 .iDefaultCase = CASE_LOWER,
203 .iPrinting = DEFAULT_PRINTING,
204 .iOplockContentionLimit = 2,
205 .iCSCPolicy = 0,
206 .iBlock_size = 1024,
207 .iDfreeCacheTime = 0,
208 .bPreexecClose = false,
209 .bRootpreexecClose = false,
210 .iCaseSensitive = Auto,
211 .bCasePreserve = true,
212 .bShortCasePreserve = true,
213 .bHideDotFiles = true,
214 .bHideSpecialFiles = false,
215 .bHideUnReadable = false,
216 .bHideUnWriteableFiles = false,
217 .bBrowseable = true,
218 .bAccessBasedShareEnum = false,
219 .bAvailable = true,
220 .bRead_only = true,
221 .bNo_set_dir = true,
222 .bGuest_only = false,
223 .bAdministrative_share = false,
224 .bGuest_ok = false,
225 .bPrint_ok = false,
226 .bPrintNotifyBackchannel = true,
227 .bMap_system = false,
228 .bMap_hidden = false,
229 .bMap_archive = true,
230 .bStoreDosAttributes = false,
231 .bDmapiSupport = false,
232 .bLocking = true,
233 .iStrictLocking = Auto,
234 .bPosixLocking = true,
235 .bShareModes = true,
236 .bOpLocks = true,
237 .bKernelOplocks = false,
238 .bLevel2OpLocks = true,
239 .bOnlyUser = false,
240 .bMangledNames = true,
241 .bWidelinks = false,
242 .bSymlinks = true,
243 .bSyncAlways = false,
244 .bStrictAllocate = false,
245 .bStrictSync = false,
246 .magic_char = '~',
247 .copymap = NULL,
248 .bDeleteReadonly = false,
249 .bFakeOplocks = false,
250 .bDeleteVetoFiles = false,
251 .bDosFilemode = false,
252 .bDosFiletimes = true,
253 .bDosFiletimeResolution = false,
254 .bFakeDirCreateTimes = false,
255 .bBlockingLocks = true,
256 .bInheritPerms = false,
257 .bInheritACLS = false,
258 .bInheritOwner = false,
259 .bMSDfsRoot = false,
260 .bUseClientDriver = false,
261 .bDefaultDevmode = true,
262 .bForcePrintername = false,
263 .bNTAclSupport = true,
264 .bForceUnknownAclUser = false,
265 .bUseSendfile = false,
266 .bProfileAcls = false,
267 .bMap_acl_inherit = false,
268 .bAfs_Share = false,
269 .bEASupport = false,
270 .bAclCheckPermissions = true,
271 .bAclMapFullControl = true,
272 .bAclGroupControl = false,
273 .bChangeNotify = true,
274 .bKernelChangeNotify = true,
275 .iallocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
276 .iAioReadSize = 0,
277 .iAioWriteSize = 0,
278 .iMap_readonly = MAP_READONLY_YES,
279 #ifdef BROKEN_DIRECTORY_HANDLING
280 .iDirectoryNameCacheSize = 0,
281 #else
282 .iDirectoryNameCacheSize = 100,
283 #endif
284 .ismb_encrypt = Auto,
285 .param_opt = NULL,
286 .dummy = ""
289 /* local variables */
290 static struct loadparm_service **ServicePtrs = NULL;
291 static int iNumServices = 0;
292 static int iServiceIndex = 0;
293 static struct db_context *ServiceHash;
294 static int *invalid_services = NULL;
295 static int num_invalid_services = 0;
296 static bool bInGlobalSection = true;
297 static bool bGlobalOnly = false;
299 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
301 /* prototypes for the special type handlers */
302 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
303 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
304 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
305 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
306 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
307 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
308 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
309 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
310 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
311 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
312 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
313 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
315 /* these are parameter handlers which are not needed in the
316 * source3 code
319 #define handle_logfile NULL
321 static void set_allowed_client_auth(void);
323 static void add_to_file_list(const char *fname, const char *subfname);
324 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
325 static void free_param_opts(struct parmlist_entry **popts);
327 #include "lib/param/param_table.c"
329 /* this is used to prevent lots of mallocs of size 1 */
330 static const char null_string[] = "";
333 Set a string value, allocing the space for the string
336 static bool string_init(char **dest,const char *src)
338 size_t l;
340 if (!src)
341 src = "";
343 l = strlen(src);
345 if (l == 0) {
346 *dest = discard_const_p(char, null_string);
347 } else {
348 (*dest) = SMB_STRDUP(src);
349 if ((*dest) == NULL) {
350 DEBUG(0,("Out of memory in string_init\n"));
351 return false;
354 return(true);
358 Free a string value.
361 static void string_free(char **s)
363 if (!s || !(*s))
364 return;
365 if (*s == null_string)
366 *s = NULL;
367 SAFE_FREE(*s);
371 Set a string value, deallocating any existing space, and allocing the space
372 for the string
375 static bool string_set(char **dest,const char *src)
377 string_free(dest);
378 return(string_init(dest,src));
381 /***************************************************************************
382 Initialise the sDefault parameter structure for the printer values.
383 ***************************************************************************/
385 static void init_printer_values(struct loadparm_service *pService)
387 /* choose defaults depending on the type of printing */
388 switch (pService->iPrinting) {
389 case PRINT_BSD:
390 case PRINT_AIX:
391 case PRINT_LPRNT:
392 case PRINT_LPROS2:
393 string_set(&pService->szLpqcommand, "lpq -P'%p'");
394 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
395 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
396 break;
398 case PRINT_LPRNG:
399 case PRINT_PLP:
400 string_set(&pService->szLpqcommand, "lpq -P'%p'");
401 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
402 string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
403 string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
404 string_set(&pService->szQueueresumecommand, "lpc start '%p'");
405 string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
406 string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
407 break;
409 case PRINT_CUPS:
410 case PRINT_IPRINT:
411 #ifdef HAVE_CUPS
412 /* set the lpq command to contain the destination printer
413 name only. This is used by cups_queue_get() */
414 string_set(&pService->szLpqcommand, "%p");
415 string_set(&pService->szLprmcommand, "");
416 string_set(&pService->szPrintcommand, "");
417 string_set(&pService->szLppausecommand, "");
418 string_set(&pService->szLpresumecommand, "");
419 string_set(&pService->szQueuepausecommand, "");
420 string_set(&pService->szQueueresumecommand, "");
421 #else
422 string_set(&pService->szLpqcommand, "lpq -P'%p'");
423 string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
424 string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
425 string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
426 string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
427 string_set(&pService->szQueuepausecommand, "disable '%p'");
428 string_set(&pService->szQueueresumecommand, "enable '%p'");
429 #endif /* HAVE_CUPS */
430 break;
432 case PRINT_SYSV:
433 case PRINT_HPUX:
434 string_set(&pService->szLpqcommand, "lpstat -o%p");
435 string_set(&pService->szLprmcommand, "cancel %p-%j");
436 string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
437 string_set(&pService->szQueuepausecommand, "disable %p");
438 string_set(&pService->szQueueresumecommand, "enable %p");
439 #ifndef HPUX
440 string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
441 string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
442 #endif /* HPUX */
443 break;
445 case PRINT_QNX:
446 string_set(&pService->szLpqcommand, "lpq -P%p");
447 string_set(&pService->szLprmcommand, "lprm -P%p %j");
448 string_set(&pService->szPrintcommand, "lp -r -P%p %s");
449 break;
451 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST) || defined(ENABLE_BUILD_FARM_HACKS)
453 case PRINT_TEST:
454 case PRINT_VLP: {
455 const char *tdbfile;
456 TALLOC_CTX *tmp_ctx = talloc_stackframe();
457 char *tmp;
459 tdbfile = talloc_asprintf(
460 tmp_ctx, "tdbfile=%s",
461 lp_parm_const_string(-1, "vlp", "tdbfile",
462 "/tmp/vlp.tdb"));
463 if (tdbfile == NULL) {
464 tdbfile="tdbfile=/tmp/vlp.tdb";
467 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
468 tdbfile);
469 string_set(&pService->szPrintcommand,
470 tmp ? tmp : "vlp print %p %s");
472 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
473 tdbfile);
474 string_set(&pService->szLpqcommand,
475 tmp ? tmp : "vlp lpq %p");
477 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
478 tdbfile);
479 string_set(&pService->szLprmcommand,
480 tmp ? tmp : "vlp lprm %p %j");
482 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
483 tdbfile);
484 string_set(&pService->szLppausecommand,
485 tmp ? tmp : "vlp lppause %p %j");
487 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
488 tdbfile);
489 string_set(&pService->szLpresumecommand,
490 tmp ? tmp : "vlp lpresume %p %j");
492 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
493 tdbfile);
494 string_set(&pService->szQueuepausecommand,
495 tmp ? tmp : "vlp queuepause %p");
497 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
498 tdbfile);
499 string_set(&pService->szQueueresumecommand,
500 tmp ? tmp : "vlp queueresume %p");
501 TALLOC_FREE(tmp_ctx);
503 break;
505 #endif /* DEVELOPER */
510 * Function to return the default value for the maximum number of open
511 * file descriptors permitted. This function tries to consult the
512 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
513 * the smaller of those.
515 static int max_open_files(void)
517 int sysctl_max = MAX_OPEN_FILES;
518 int rlimit_max = MAX_OPEN_FILES;
520 #ifdef HAVE_SYSCTLBYNAME
522 size_t size = sizeof(sysctl_max);
523 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
526 #endif
528 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
530 struct rlimit rl;
532 ZERO_STRUCT(rl);
534 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
535 rlimit_max = rl.rlim_cur;
537 #if defined(RLIM_INFINITY)
538 if(rl.rlim_cur == RLIM_INFINITY)
539 rlimit_max = MAX_OPEN_FILES;
540 #endif
542 #endif
544 if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
545 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
546 "minimum Windows limit (%d)\n",
547 sysctl_max,
548 MIN_OPEN_FILES_WINDOWS));
549 sysctl_max = MIN_OPEN_FILES_WINDOWS;
552 if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
553 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
554 "minimum Windows limit (%d)\n",
555 rlimit_max,
556 MIN_OPEN_FILES_WINDOWS));
557 rlimit_max = MIN_OPEN_FILES_WINDOWS;
560 return MIN(sysctl_max, rlimit_max);
564 * Common part of freeing allocated data for one parameter.
566 static void free_one_parameter_common(void *parm_ptr,
567 struct parm_struct parm)
569 if ((parm.type == P_STRING) ||
570 (parm.type == P_USTRING))
572 string_free((char**)parm_ptr);
573 } else if (parm.type == P_LIST) {
574 TALLOC_FREE(*((char***)parm_ptr));
579 * Free the allocated data for one parameter for a share
580 * given as a service struct.
582 static void free_one_parameter(struct loadparm_service *service,
583 struct parm_struct parm)
585 void *parm_ptr;
587 if (parm.p_class != P_LOCAL) {
588 return;
591 parm_ptr = lp_parm_ptr(service, &parm);
593 free_one_parameter_common(parm_ptr, parm);
597 * Free the allocated parameter data of a share given
598 * as a service struct.
600 static void free_parameters(struct loadparm_service *service)
602 uint32_t i;
604 for (i=0; parm_table[i].label; i++) {
605 free_one_parameter(service, parm_table[i]);
610 * Free the allocated data for one parameter for a given share
611 * specified by an snum.
613 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
615 void *parm_ptr;
617 if (snum < 0) {
618 parm_ptr = lp_parm_ptr(NULL, &parm);
619 } else if (parm.p_class != P_LOCAL) {
620 return;
621 } else {
622 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
625 free_one_parameter_common(parm_ptr, parm);
629 * Free the allocated parameter data for a share specified
630 * by an snum.
632 static void free_parameters_by_snum(int snum)
634 uint32_t i;
636 for (i=0; parm_table[i].label; i++) {
637 free_one_parameter_by_snum(snum, parm_table[i]);
642 * Free the allocated global parameters.
644 static void free_global_parameters(void)
646 free_param_opts(&Globals.param_opt);
647 free_parameters_by_snum(GLOBAL_SECTION_SNUM);
648 TALLOC_FREE(Globals.ctx);
651 static int map_parameter(const char *pszParmName);
653 struct lp_stored_option {
654 struct lp_stored_option *prev, *next;
655 const char *label;
656 const char *value;
659 static struct lp_stored_option *stored_options;
662 save options set by lp_set_cmdline() into a list. This list is
663 re-applied when we do a globals reset, so that cmdline set options
664 are sticky across reloads of smb.conf
666 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
668 struct lp_stored_option *entry, *entry_next;
669 for (entry = stored_options; entry != NULL; entry = entry_next) {
670 entry_next = entry->next;
671 if (strcmp(pszParmName, entry->label) == 0) {
672 DLIST_REMOVE(stored_options, entry);
673 talloc_free(entry);
674 break;
678 entry = talloc(NULL, struct lp_stored_option);
679 if (!entry) {
680 return false;
683 entry->label = talloc_strdup(entry, pszParmName);
684 if (!entry->label) {
685 talloc_free(entry);
686 return false;
689 entry->value = talloc_strdup(entry, pszParmValue);
690 if (!entry->value) {
691 talloc_free(entry);
692 return false;
695 DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
697 return true;
700 static bool apply_lp_set_cmdline(void)
702 struct lp_stored_option *entry = NULL;
703 for (entry = stored_options; entry != NULL; entry = entry->next) {
704 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
705 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
706 entry->label, entry->value));
707 return false;
710 return true;
713 /***************************************************************************
714 Initialise the global parameter structure.
715 ***************************************************************************/
717 static void init_globals(bool reinit_globals)
719 static bool done_init = false;
720 char *s = NULL;
721 int i;
723 /* If requested to initialize only once and we've already done it... */
724 if (!reinit_globals && done_init) {
725 /* ... then we have nothing more to do */
726 return;
729 if (!done_init) {
730 /* The logfile can be set before this is invoked. Free it if so. */
731 if (Globals.logfile != NULL) {
732 string_free(&Globals.logfile);
733 Globals.logfile = NULL;
735 done_init = true;
736 } else {
737 free_global_parameters();
740 /* This memset and the free_global_parameters() above will
741 * wipe out smb.conf options set with lp_set_cmdline(). The
742 * apply_lp_set_cmdline() call puts these values back in the
743 * table once the defaults are set */
744 ZERO_STRUCT(Globals);
746 Globals.ctx = talloc_new(NULL);
748 for (i = 0; parm_table[i].label; i++) {
749 if ((parm_table[i].type == P_STRING ||
750 parm_table[i].type == P_USTRING))
752 string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
757 string_set(&sDefault.fstype, FSTYPE_STRING);
758 string_set(&sDefault.szPrintjobUsername, "%U");
760 init_printer_values(&sDefault);
763 DEBUG(3, ("Initialising global parameters\n"));
765 /* Must manually force to upper case here, as this does not go via the handler */
766 string_set(&Globals.szNetbiosName, myhostname_upper());
768 string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
769 string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
771 /* use the new 'hash2' method by default, with a prefix of 1 */
772 string_set(&Globals.szManglingMethod, "hash2");
773 Globals.mangle_prefix = 1;
775 string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
777 /* using UTF8 by default allows us to support all chars */
778 string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
780 /* Use codepage 850 as a default for the dos character set */
781 string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
784 * Allow the default PASSWD_CHAT to be overridden in local.h.
786 string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
788 string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
790 string_set(&Globals.szPasswdProgram, "");
791 string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
792 string_set(&Globals.szStateDir, get_dyn_STATEDIR());
793 string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
794 string_set(&Globals.szPidDir, get_dyn_PIDDIR());
795 string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
797 * By default support explicit binding to broadcast
798 * addresses.
800 Globals.bNmbdBindExplicitBroadcast = true;
802 if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
803 smb_panic("init_globals: ENOMEM");
805 string_set(&Globals.szServerString, s);
806 SAFE_FREE(s);
807 #ifdef DEVELOPER
808 string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
809 #endif
811 string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
813 string_set(&Globals.szLogonDrive, "");
814 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
815 string_set(&Globals.szLogonHome, "\\\\%N\\%U");
816 string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
818 Globals.szNameResolveOrder = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
819 string_set(&Globals.szPasswordServer, "*");
821 Globals.AlgorithmicRidBase = BASE_RID;
823 Globals.bLoadPrinters = true;
824 Globals.PrintcapCacheTime = 750; /* 12.5 minutes */
826 Globals.ConfigBackend = config_backend;
827 Globals.server_role = ROLE_AUTO;
829 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
830 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
831 Globals.max_xmit = 0x4104;
832 Globals.max_mux = 50; /* This is *needed* for profile support. */
833 Globals.lpqcachetime = 30; /* changed to handle large print servers better -- jerry */
834 Globals.bDisableSpoolss = false;
835 Globals.iMaxSmbdProcesses = 0;/* no limit specified */
836 Globals.pwordlevel = 0;
837 Globals.unamelevel = 0;
838 Globals.deadtime = 0;
839 Globals.getwd_cache = true;
840 Globals.bLargeReadwrite = true;
841 Globals.max_log_size = 5000;
842 Globals.max_open_files = max_open_files();
843 Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
844 Globals.srv_maxprotocol = PROTOCOL_SMB2_10;
845 Globals.srv_minprotocol = PROTOCOL_LANMAN1;
846 Globals.security = SEC_USER;
847 Globals.bEncryptPasswords = true;
848 Globals.clientSchannel = Auto;
849 Globals.serverSchannel = Auto;
850 Globals.bReadRaw = true;
851 Globals.bWriteRaw = true;
852 Globals.bNullPasswords = false;
853 Globals.bObeyPamRestrictions = false;
854 Globals.syslog = 1;
855 Globals.bSyslogOnly = false;
856 Globals.bTimestampLogs = true;
857 string_set(&Globals.loglevel, "0");
858 Globals.bDebugPrefixTimestamp = false;
859 Globals.bDebugHiresTimestamp = true;
860 Globals.bDebugPid = false;
861 Globals.bDebugUid = false;
862 Globals.bDebugClass = false;
863 Globals.bEnableCoreFiles = true;
864 Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
865 Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
866 Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
867 Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
868 Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
869 Globals.lm_interval = 60;
870 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
871 Globals.bNISHomeMap = false;
872 #ifdef WITH_NISPLUS_HOME
873 string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
874 #else
875 string_set(&Globals.szNISHomeMapName, "auto.home");
876 #endif
877 #endif
878 Globals.bTimeServer = false;
879 Globals.bBindInterfacesOnly = false;
880 Globals.bUnixPasswdSync = false;
881 Globals.bPamPasswordChange = false;
882 Globals.bPasswdChatDebug = false;
883 Globals.iPasswdChatTimeout = 2; /* 2 second default. */
884 Globals.bNTPipeSupport = true; /* Do NT pipes by default. */
885 Globals.bNTStatusSupport = true; /* Use NT status by default. */
886 Globals.bStatCache = true; /* use stat cache by default */
887 Globals.iMaxStatCacheSize = 256; /* 256k by default */
888 Globals.restrict_anonymous = 0;
889 Globals.bClientLanManAuth = false; /* Do NOT use the LanMan hash if it is available */
890 Globals.bClientPlaintextAuth = false; /* Do NOT use a plaintext password even if is requested by the server */
891 Globals.bLanmanAuth = false; /* Do NOT use the LanMan hash, even if it is supplied */
892 Globals.bNTLMAuth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
893 Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
894 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
896 Globals.map_to_guest = 0; /* By Default, "Never" */
897 Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
898 Globals.enhanced_browsing = true;
899 Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
900 #ifdef MMAP_BLACKLIST
901 Globals.bUseMmap = false;
902 #else
903 Globals.bUseMmap = true;
904 #endif
905 Globals.bUnicode = true;
906 Globals.bUnixExtensions = true;
907 Globals.bResetOnZeroVC = false;
908 Globals.bLogWriteableFilesOnExit = false;
909 Globals.bCreateKrb5Conf = true;
910 Globals.winbindMaxDomainConnections = 1;
912 /* hostname lookups can be very expensive and are broken on
913 a large number of sites (tridge) */
914 Globals.bHostnameLookups = false;
916 string_set(&Globals.passdb_backend, "tdbsam");
917 string_set(&Globals.szLdapSuffix, "");
918 string_set(&Globals.szLdapMachineSuffix, "");
919 string_set(&Globals.szLdapUserSuffix, "");
920 string_set(&Globals.szLdapGroupSuffix, "");
921 string_set(&Globals.szLdapIdmapSuffix, "");
923 string_set(&Globals.szLdapAdminDn, "");
924 Globals.ldap_ssl = LDAP_SSL_START_TLS;
925 Globals.ldap_ssl_ads = false;
926 Globals.ldap_deref = -1;
927 Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
928 Globals.ldap_delete_dn = false;
929 Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
930 Globals.ldap_follow_referral = Auto;
931 Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
932 Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
933 Globals.ldap_page_size = LDAP_PAGE_SIZE;
935 Globals.ldap_debug_level = 0;
936 Globals.ldap_debug_threshold = 10;
938 /* This is what we tell the afs client. in reality we set the token
939 * to never expire, though, when this runs out the afs client will
940 * forget the token. Set to 0 to get NEVERDATE.*/
941 Globals.iAfsTokenLifetime = 604800;
942 Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
944 /* these parameters are set to defaults that are more appropriate
945 for the increasing samba install base:
947 as a member of the workgroup, that will possibly become a
948 _local_ master browser (lm = true). this is opposed to a forced
949 local master browser startup (pm = true).
951 doesn't provide WINS server service by default (wsupp = false),
952 and doesn't provide domain master browser services by default, either.
956 Globals.bMsAddPrinterWizard = true;
957 Globals.os_level = 20;
958 Globals.bLocalMaster = true;
959 Globals.domain_master = Auto; /* depending on bDomainLogons */
960 Globals.bDomainLogons = false;
961 Globals.bBrowseList = true;
962 Globals.bWINSsupport = false;
963 Globals.bWINSproxy = false;
965 TALLOC_FREE(Globals.szInitLogonDelayedHosts);
966 Globals.InitLogonDelay = 100; /* 100 ms default delay */
968 Globals.bWINSdnsProxy = true;
970 Globals.bAllowTrustedDomains = true;
971 string_set(&Globals.szIdmapBackend, "tdb");
973 string_set(&Globals.szTemplateShell, "/bin/false");
974 string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
975 string_set(&Globals.szWinbindSeparator, "\\");
977 string_set(&Globals.szCupsServer, "");
978 string_set(&Globals.szIPrintServer, "");
980 #ifdef CLUSTER_SUPPORT
981 string_set(&Globals.ctdbdSocket, CTDB_PATH);
982 #else
983 string_set(&Globals.ctdbdSocket, "");
984 #endif
986 Globals.szClusterAddresses = NULL;
987 Globals.clustering = false;
988 Globals.ctdb_timeout = 0;
989 Globals.ctdb_locktime_warn_threshold = 0;
991 Globals.winbind_cache_time = 300; /* 5 minutes */
992 Globals.winbind_reconnect_delay = 30; /* 30 seconds */
993 Globals.winbind_max_clients = 200;
994 Globals.bWinbindEnumUsers = false;
995 Globals.bWinbindEnumGroups = false;
996 Globals.bWinbindUseDefaultDomain = false;
997 Globals.bWinbindTrustedDomainsOnly = false;
998 Globals.bWinbindNestedGroups = true;
999 Globals.winbind_expand_groups = 1;
1000 Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
1001 Globals.bWinbindRefreshTickets = false;
1002 Globals.bWinbindOfflineLogon = false;
1004 Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
1005 Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
1007 Globals.bPassdbExpandExplicit = false;
1009 Globals.name_cache_timeout = 660; /* In seconds */
1011 Globals.bUseSpnego = true;
1012 Globals.bClientUseSpnego = true;
1014 Globals.client_signing = SMB_SIGNING_DEFAULT;
1015 Globals.server_signing = SMB_SIGNING_DEFAULT;
1017 Globals.bDeferSharingViolations = true;
1018 Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
1020 Globals.bEnablePrivileges = true;
1021 Globals.bHostMSDfs = true;
1022 Globals.bASUSupport = false;
1024 /* User defined shares. */
1025 if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
1026 smb_panic("init_globals: ENOMEM");
1028 string_set(&Globals.szUsersharePath, s);
1029 SAFE_FREE(s);
1030 string_set(&Globals.szUsershareTemplateShare, "");
1031 Globals.iUsershareMaxShares = 0;
1032 /* By default disallow sharing of directories not owned by the sharer. */
1033 Globals.bUsershareOwnerOnly = true;
1034 /* By default disallow guest access to usershares. */
1035 Globals.bUsershareAllowGuests = false;
1037 Globals.iKeepalive = DEFAULT_KEEPALIVE;
1039 /* By default no shares out of the registry */
1040 Globals.bRegistryShares = false;
1042 Globals.iminreceivefile = 0;
1044 Globals.bMapUntrustedToDomain = false;
1045 Globals.bMulticastDnsRegister = true;
1047 Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
1048 Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
1049 Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
1050 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1052 string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1054 /* Now put back the settings that were set with lp_set_cmdline() */
1055 apply_lp_set_cmdline();
1058 /*******************************************************************
1059 Convenience routine to grab string parameters into talloced memory
1060 and run standard_sub_basic on them. The buffers can be written to by
1061 callers without affecting the source string.
1062 ********************************************************************/
1064 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1066 char *ret;
1068 /* The follow debug is useful for tracking down memory problems
1069 especially if you have an inner loop that is calling a lp_*()
1070 function that returns a string. Perhaps this debug should be
1071 present all the time? */
1073 #if 0
1074 DEBUG(10, ("lp_string(%s)\n", s));
1075 #endif
1076 if (!s) {
1077 return NULL;
1080 ret = talloc_sub_basic(ctx,
1081 get_current_username(),
1082 current_user_info.domain,
1084 if (trim_char(ret, '\"', '\"')) {
1085 if (strchr(ret,'\"') != NULL) {
1086 TALLOC_FREE(ret);
1087 ret = talloc_sub_basic(ctx,
1088 get_current_username(),
1089 current_user_info.domain,
1093 return ret;
1097 In this section all the functions that are used to access the
1098 parameters from the rest of the program are defined
1101 #define FN_GLOBAL_STRING(fn_name,ptr) \
1102 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1103 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1104 const char *lp_ ## fn_name(void) {return(*(const char **)(&Globals.ptr) ? *(const char **)(&Globals.ptr) : "");}
1105 #define FN_GLOBAL_LIST(fn_name,ptr) \
1106 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1107 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1108 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1109 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1110 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1111 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1112 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1114 #define FN_LOCAL_STRING(fn_name,val) \
1115 char *lp_ ## fn_name(TALLOC_CTX *ctx,int i) {return(lp_string((ctx), (LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1116 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1117 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1118 #define FN_LOCAL_LIST(fn_name,val) \
1119 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1120 #define FN_LOCAL_BOOL(fn_name,val) \
1121 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1122 #define FN_LOCAL_INTEGER(fn_name,val) \
1123 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1125 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1126 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1127 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1128 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1129 #define FN_LOCAL_CHAR(fn_name,val) \
1130 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1133 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1134 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1136 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1137 * build process or in smb.conf, we use that value. Otherwise they
1138 * default to the value of lp_lockdir(). */
1139 const char *lp_statedir(void) {
1140 if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1141 (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1142 return(*(char **)(&Globals.szStateDir) ?
1143 *(char **)(&Globals.szStateDir) : "");
1144 else
1145 return(*(char **)(&Globals.szLockDir) ?
1146 *(char **)(&Globals.szLockDir) : "");
1148 const char *lp_cachedir(void) {
1149 if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1150 (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1151 return(*(char **)(&Globals.szCacheDir) ?
1152 *(char **)(&Globals.szCacheDir) : "");
1153 else
1154 return(*(char **)(&Globals.szLockDir) ?
1155 *(char **)(&Globals.szLockDir) : "");
1157 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1158 winbindMaxDomainConnections)
1160 int lp_winbind_max_domain_connections(void)
1162 if (lp_winbind_offline_logon() &&
1163 lp_winbind_max_domain_connections_int() > 1) {
1164 DEBUG(1, ("offline logons active, restricting max domain "
1165 "connections to 1\n"));
1166 return 1;
1168 return MAX(1, lp_winbind_max_domain_connections_int());
1171 int lp_smb2_max_credits(void)
1173 if (Globals.ismb2_max_credits == 0) {
1174 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1176 return Globals.ismb2_max_credits;
1178 int lp_cups_encrypt(void)
1180 int result = 0;
1181 #ifdef HAVE_HTTPCONNECTENCRYPT
1182 switch (Globals.CupsEncrypt) {
1183 case Auto:
1184 result = HTTP_ENCRYPT_REQUIRED;
1185 break;
1186 case true:
1187 result = HTTP_ENCRYPT_ALWAYS;
1188 break;
1189 case false:
1190 result = HTTP_ENCRYPT_NEVER;
1191 break;
1193 #endif
1194 return result;
1197 /* These functions remain in source3/param for now */
1199 FN_GLOBAL_STRING(configfile, szConfigFile)
1201 #include "lib/param/param_functions.c"
1203 FN_LOCAL_STRING(servicename, szService)
1204 FN_LOCAL_CONST_STRING(const_servicename, szService)
1206 /* local prototypes */
1208 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1209 static const char *get_boolean(bool bool_value);
1210 static int getservicebyname(const char *pszServiceName,
1211 struct loadparm_service *pserviceDest);
1212 static void copy_service(struct loadparm_service *pserviceDest,
1213 struct loadparm_service *pserviceSource,
1214 struct bitmap *pcopymapDest);
1215 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1216 void *userdata);
1217 static bool do_section(const char *pszSectionName, void *userdata);
1218 static void init_copymap(struct loadparm_service *pservice);
1219 static bool hash_a_service(const char *name, int number);
1220 static void free_service_byindex(int iService);
1221 static void show_parameter(int parmIndex);
1222 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1225 * This is a helper function for parametrical options support. It returns a
1226 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1227 * parametrical functions are quite simple
1229 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1230 const char *option)
1232 bool global_section = false;
1233 char* param_key;
1234 struct parmlist_entry *data;
1236 if (service == NULL) {
1237 data = Globals.param_opt;
1238 global_section = true;
1239 } else {
1240 data = service->param_opt;
1243 if (asprintf(&param_key, "%s:%s", type, option) == -1) {
1244 DEBUG(0,("asprintf failed!\n"));
1245 return NULL;
1248 while (data) {
1249 if (strwicmp(data->key, param_key) == 0) {
1250 string_free(&param_key);
1251 return data;
1253 data = data->next;
1256 if (!global_section) {
1257 /* Try to fetch the same option but from globals */
1258 /* but only if we are not already working with Globals */
1259 data = Globals.param_opt;
1260 while (data) {
1261 if (strwicmp(data->key, param_key) == 0) {
1262 string_free(&param_key);
1263 return data;
1265 data = data->next;
1269 string_free(&param_key);
1271 return NULL;
1275 * This is a helper function for parametrical options support. It returns a
1276 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1277 * parametrical functions are quite simple
1279 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1280 const char *option)
1282 if (snum >= iNumServices) return NULL;
1284 if (snum < 0) {
1285 return get_parametrics_by_service(NULL, type, option);
1286 } else {
1287 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1292 #define MISSING_PARAMETER(name) \
1293 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1295 /*******************************************************************
1296 convenience routine to return int parameters.
1297 ********************************************************************/
1298 static int lp_int(const char *s)
1301 if (!s || !*s) {
1302 MISSING_PARAMETER(lp_int);
1303 return (-1);
1306 return (int)strtol(s, NULL, 0);
1309 /*******************************************************************
1310 convenience routine to return unsigned long parameters.
1311 ********************************************************************/
1312 static unsigned long lp_ulong(const char *s)
1315 if (!s || !*s) {
1316 MISSING_PARAMETER(lp_ulong);
1317 return (0);
1320 return strtoul(s, NULL, 0);
1323 /*******************************************************************
1324 convenience routine to return boolean parameters.
1325 ********************************************************************/
1326 static bool lp_bool(const char *s)
1328 bool ret = false;
1330 if (!s || !*s) {
1331 MISSING_PARAMETER(lp_bool);
1332 return false;
1335 if (!set_boolean(s, &ret)) {
1336 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1337 return false;
1340 return ret;
1343 /*******************************************************************
1344 convenience routine to return enum parameters.
1345 ********************************************************************/
1346 static int lp_enum(const char *s,const struct enum_list *_enum)
1348 int i;
1350 if (!s || !*s || !_enum) {
1351 MISSING_PARAMETER(lp_enum);
1352 return (-1);
1355 for (i=0; _enum[i].name; i++) {
1356 if (strequal(_enum[i].name,s))
1357 return _enum[i].value;
1360 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1361 return (-1);
1364 #undef MISSING_PARAMETER
1366 /* Return parametric option from a given service. Type is a part of option before ':' */
1367 /* Parametric option has following syntax: 'Type: option = value' */
1368 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1370 struct parmlist_entry *data = get_parametrics(snum, type, option);
1372 if (data == NULL||data->value==NULL) {
1373 if (def) {
1374 return lp_string(ctx, def);
1375 } else {
1376 return NULL;
1380 return lp_string(ctx, data->value);
1383 /* Return parametric option from a given service. Type is a part of option before ':' */
1384 /* Parametric option has following syntax: 'Type: option = value' */
1385 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1387 struct parmlist_entry *data = get_parametrics(snum, type, option);
1389 if (data == NULL||data->value==NULL)
1390 return def;
1392 return data->value;
1395 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1397 struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1399 if (data == NULL||data->value==NULL)
1400 return NULL;
1402 return data->value;
1406 /* Return parametric option from a given service. Type is a part of option before ':' */
1407 /* Parametric option has following syntax: 'Type: option = value' */
1409 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1411 struct parmlist_entry *data = get_parametrics(snum, type, option);
1413 if (data == NULL||data->value==NULL)
1414 return (const char **)def;
1416 if (data->list==NULL) {
1417 data->list = str_list_make_v3(NULL, data->value, NULL);
1420 return (const char **)data->list;
1423 /* Return parametric option from a given service. Type is a part of option before ':' */
1424 /* Parametric option has following syntax: 'Type: option = value' */
1426 int lp_parm_int(int snum, const char *type, const char *option, int def)
1428 struct parmlist_entry *data = get_parametrics(snum, type, option);
1430 if (data && data->value && *data->value)
1431 return lp_int(data->value);
1433 return def;
1436 /* Return parametric option from a given service. Type is a part of option before ':' */
1437 /* Parametric option has following syntax: 'Type: option = value' */
1439 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1441 struct parmlist_entry *data = get_parametrics(snum, type, option);
1443 if (data && data->value && *data->value)
1444 return lp_ulong(data->value);
1446 return def;
1449 /* Return parametric option from a given service. Type is a part of option before ':' */
1450 /* Parametric option has following syntax: 'Type: option = value' */
1452 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1454 struct parmlist_entry *data = get_parametrics(snum, type, option);
1456 if (data && data->value && *data->value)
1457 return lp_bool(data->value);
1459 return def;
1462 /* Return parametric option from a given service. Type is a part of option before ':' */
1463 /* Parametric option has following syntax: 'Type: option = value' */
1465 int lp_parm_enum(int snum, const char *type, const char *option,
1466 const struct enum_list *_enum, int def)
1468 struct parmlist_entry *data = get_parametrics(snum, type, option);
1470 if (data && data->value && *data->value && _enum)
1471 return lp_enum(data->value, _enum);
1473 return def;
1477 /***************************************************************************
1478 Initialise a service to the defaults.
1479 ***************************************************************************/
1481 static void init_service(struct loadparm_service *pservice)
1483 memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1484 copy_service(pservice, &sDefault, NULL);
1489 * free a param_opts structure.
1490 * param_opts handling should be moved to talloc;
1491 * then this whole functions reduces to a TALLOC_FREE().
1494 static void free_param_opts(struct parmlist_entry **popts)
1496 struct parmlist_entry *opt, *next_opt;
1498 if (*popts != NULL) {
1499 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 strlower_m(result);
1657 return result;
1660 /***************************************************************************
1661 Add a name/index pair for the services array to the hash table.
1662 ***************************************************************************/
1664 static bool hash_a_service(const char *name, int idx)
1666 char *canon_name;
1668 if ( !ServiceHash ) {
1669 DEBUG(10,("hash_a_service: creating servicehash\n"));
1670 ServiceHash = db_open_rbt(NULL);
1671 if ( !ServiceHash ) {
1672 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1673 return false;
1677 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1678 idx, name));
1680 canon_name = canonicalize_servicename(talloc_tos(), name );
1682 dbwrap_store_bystring(ServiceHash, canon_name,
1683 make_tdb_data((uint8 *)&idx, sizeof(idx)),
1684 TDB_REPLACE);
1686 TALLOC_FREE(canon_name);
1688 return true;
1691 /***************************************************************************
1692 Add a new home service, with the specified home directory, defaults coming
1693 from service ifrom.
1694 ***************************************************************************/
1696 bool lp_add_home(const char *pszHomename, int iDefaultService,
1697 const char *user, const char *pszHomedir)
1699 int i;
1701 if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1702 pszHomedir[0] == '\0') {
1703 return false;
1706 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1708 if (i < 0)
1709 return false;
1711 if (!(*(ServicePtrs[iDefaultService]->szPath))
1712 || strequal(ServicePtrs[iDefaultService]->szPath,
1713 lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1714 string_set(&ServicePtrs[i]->szPath, pszHomedir);
1717 if (!(*(ServicePtrs[i]->comment))) {
1718 char *comment = NULL;
1719 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1720 return false;
1722 string_set(&ServicePtrs[i]->comment, comment);
1723 SAFE_FREE(comment);
1726 /* set the browseable flag from the global default */
1728 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1729 ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
1731 ServicePtrs[i]->autoloaded = true;
1733 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1734 user, ServicePtrs[i]->szPath ));
1736 return true;
1739 /***************************************************************************
1740 Add a new service, based on an old one.
1741 ***************************************************************************/
1743 int lp_add_service(const char *pszService, int iDefaultService)
1745 if (iDefaultService < 0) {
1746 return add_a_service(&sDefault, pszService);
1749 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1752 /***************************************************************************
1753 Add the IPC service.
1754 ***************************************************************************/
1756 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1758 char *comment = NULL;
1759 int i = add_a_service(&sDefault, ipc_name);
1761 if (i < 0)
1762 return false;
1764 if (asprintf(&comment, "IPC Service (%s)",
1765 Globals.szServerString) < 0) {
1766 return false;
1769 string_set(&ServicePtrs[i]->szPath, tmpdir());
1770 string_set(&ServicePtrs[i]->szUsername, "");
1771 string_set(&ServicePtrs[i]->comment, comment);
1772 string_set(&ServicePtrs[i]->fstype, "IPC");
1773 ServicePtrs[i]->iMaxConnections = 0;
1774 ServicePtrs[i]->bAvailable = true;
1775 ServicePtrs[i]->bRead_only = true;
1776 ServicePtrs[i]->bGuest_only = false;
1777 ServicePtrs[i]->bAdministrative_share = true;
1778 ServicePtrs[i]->bGuest_ok = guest_ok;
1779 ServicePtrs[i]->bPrint_ok = false;
1780 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1782 DEBUG(3, ("adding IPC service\n"));
1784 SAFE_FREE(comment);
1785 return true;
1788 /***************************************************************************
1789 Add a new printer service, with defaults coming from service iFrom.
1790 ***************************************************************************/
1792 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1794 const char *comment = "From Printcap";
1795 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1797 if (i < 0)
1798 return false;
1800 /* note that we do NOT default the availability flag to true - */
1801 /* we take it from the default service passed. This allows all */
1802 /* dynamic printers to be disabled by disabling the [printers] */
1803 /* entry (if/when the 'available' keyword is implemented!). */
1805 /* the printer name is set to the service name. */
1806 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1807 string_set(&ServicePtrs[i]->comment, comment);
1809 /* set the browseable flag from the gloabl default */
1810 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1812 /* Printers cannot be read_only. */
1813 ServicePtrs[i]->bRead_only = false;
1814 /* No share modes on printer services. */
1815 ServicePtrs[i]->bShareModes = false;
1816 /* No oplocks on printer services. */
1817 ServicePtrs[i]->bOpLocks = false;
1818 /* Printer services must be printable. */
1819 ServicePtrs[i]->bPrint_ok = true;
1821 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1823 return true;
1827 /***************************************************************************
1828 Check whether the given parameter name is valid.
1829 Parametric options (names containing a colon) are considered valid.
1830 ***************************************************************************/
1832 bool lp_parameter_is_valid(const char *pszParmName)
1834 return ((map_parameter(pszParmName) != -1) ||
1835 (strchr(pszParmName, ':') != NULL));
1838 /***************************************************************************
1839 Check whether the given name is the name of a global parameter.
1840 Returns true for strings belonging to parameters of class
1841 P_GLOBAL, false for all other strings, also for parametric options
1842 and strings not belonging to any option.
1843 ***************************************************************************/
1845 bool lp_parameter_is_global(const char *pszParmName)
1847 int num = map_parameter(pszParmName);
1849 if (num >= 0) {
1850 return (parm_table[num].p_class == P_GLOBAL);
1853 return false;
1856 /**************************************************************************
1857 Check whether the given name is the canonical name of a parameter.
1858 Returns false if it is not a valid parameter Name.
1859 For parametric options, true is returned.
1860 **************************************************************************/
1862 bool lp_parameter_is_canonical(const char *parm_name)
1864 if (!lp_parameter_is_valid(parm_name)) {
1865 return false;
1868 return (map_parameter(parm_name) ==
1869 map_parameter_canonical(parm_name, NULL));
1872 /**************************************************************************
1873 Determine the canonical name for a parameter.
1874 Indicate when it is an inverse (boolean) synonym instead of a
1875 "usual" synonym.
1876 **************************************************************************/
1878 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1879 bool *inverse)
1881 int num;
1883 if (!lp_parameter_is_valid(parm_name)) {
1884 *canon_parm = NULL;
1885 return false;
1888 num = map_parameter_canonical(parm_name, inverse);
1889 if (num < 0) {
1890 /* parametric option */
1891 *canon_parm = parm_name;
1892 } else {
1893 *canon_parm = parm_table[num].label;
1896 return true;
1900 /**************************************************************************
1901 Determine the canonical name for a parameter.
1902 Turn the value given into the inverse boolean expression when
1903 the synonym is an invers boolean synonym.
1905 Return true if parm_name is a valid parameter name and
1906 in case it is an invers boolean synonym, if the val string could
1907 successfully be converted to the reverse bool.
1908 Return false in all other cases.
1909 **************************************************************************/
1911 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1912 const char *val,
1913 const char **canon_parm,
1914 const char **canon_val)
1916 int num;
1917 bool inverse;
1919 if (!lp_parameter_is_valid(parm_name)) {
1920 *canon_parm = NULL;
1921 *canon_val = NULL;
1922 return false;
1925 num = map_parameter_canonical(parm_name, &inverse);
1926 if (num < 0) {
1927 /* parametric option */
1928 *canon_parm = parm_name;
1929 *canon_val = val;
1930 } else {
1931 *canon_parm = parm_table[num].label;
1932 if (inverse) {
1933 if (!lp_invert_boolean(val, canon_val)) {
1934 *canon_val = NULL;
1935 return false;
1937 } else {
1938 *canon_val = val;
1942 return true;
1945 /***************************************************************************
1946 Map a parameter's string representation to something we can use.
1947 Returns false if the parameter string is not recognised, else TRUE.
1948 ***************************************************************************/
1950 static int map_parameter(const char *pszParmName)
1952 int iIndex;
1954 if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
1955 return (-1);
1957 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1958 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1959 return (iIndex);
1961 /* Warn only if it isn't parametric option */
1962 if (strchr(pszParmName, ':') == NULL)
1963 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1964 /* We do return 'fail' for parametric options as well because they are
1965 stored in different storage
1967 return (-1);
1970 /***************************************************************************
1971 Map a parameter's string representation to the index of the canonical
1972 form of the parameter (it might be a synonym).
1973 Returns -1 if the parameter string is not recognised.
1974 ***************************************************************************/
1976 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1978 int parm_num, canon_num;
1979 bool loc_inverse = false;
1981 parm_num = map_parameter(pszParmName);
1982 if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1983 /* invalid, parametric or no canidate for synonyms ... */
1984 goto done;
1987 for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1988 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1989 parm_num = canon_num;
1990 goto done;
1994 done:
1995 if (inverse != NULL) {
1996 *inverse = loc_inverse;
1998 return parm_num;
2001 /***************************************************************************
2002 return true if parameter number parm1 is a synonym of parameter
2003 number parm2 (parm2 being the principal name).
2004 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
2005 false otherwise.
2006 ***************************************************************************/
2008 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
2010 if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
2011 (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
2012 (parm_table[parm1].flags & FLAG_HIDE) &&
2013 !(parm_table[parm2].flags & FLAG_HIDE))
2015 if (inverse != NULL) {
2016 if ((parm_table[parm1].type == P_BOOLREV) &&
2017 (parm_table[parm2].type == P_BOOL))
2019 *inverse = true;
2020 } else {
2021 *inverse = false;
2024 return true;
2026 return false;
2029 /***************************************************************************
2030 Show one parameter's name, type, [values,] and flags.
2031 (helper functions for show_parameter_list)
2032 ***************************************************************************/
2034 static void show_parameter(int parmIndex)
2036 int enumIndex, flagIndex;
2037 int parmIndex2;
2038 bool hadFlag;
2039 bool hadSyn;
2040 bool inverse;
2041 const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2042 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2043 "P_ENUM", "P_SEP"};
2044 unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2045 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2046 FLAG_HIDE};
2047 const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2048 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2049 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2051 printf("%s=%s", parm_table[parmIndex].label,
2052 type[parm_table[parmIndex].type]);
2053 if (parm_table[parmIndex].type == P_ENUM) {
2054 printf(",");
2055 for (enumIndex=0;
2056 parm_table[parmIndex].enum_list[enumIndex].name;
2057 enumIndex++)
2059 printf("%s%s",
2060 enumIndex ? "|" : "",
2061 parm_table[parmIndex].enum_list[enumIndex].name);
2064 printf(",");
2065 hadFlag = false;
2066 for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2067 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2068 printf("%s%s",
2069 hadFlag ? "|" : "",
2070 flag_names[flagIndex]);
2071 hadFlag = true;
2075 /* output synonyms */
2076 hadSyn = false;
2077 for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2078 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2079 printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2080 parm_table[parmIndex2].label);
2081 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2082 if (!hadSyn) {
2083 printf(" (synonyms: ");
2084 hadSyn = true;
2085 } else {
2086 printf(", ");
2088 printf("%s%s", parm_table[parmIndex2].label,
2089 inverse ? "[i]" : "");
2092 if (hadSyn) {
2093 printf(")");
2096 printf("\n");
2099 /***************************************************************************
2100 Show all parameter's name, type, [values,] and flags.
2101 ***************************************************************************/
2103 void show_parameter_list(void)
2105 int classIndex, parmIndex;
2106 const char *section_names[] = { "local", "global", NULL};
2108 for (classIndex=0; section_names[classIndex]; classIndex++) {
2109 printf("[%s]\n", section_names[classIndex]);
2110 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2111 if (parm_table[parmIndex].p_class == classIndex) {
2112 show_parameter(parmIndex);
2118 /***************************************************************************
2119 Check if a given string correctly represents a boolean value.
2120 ***************************************************************************/
2122 bool lp_string_is_valid_boolean(const char *parm_value)
2124 return set_boolean(parm_value, NULL);
2127 /***************************************************************************
2128 Get the standard string representation of a boolean value ("yes" or "no")
2129 ***************************************************************************/
2131 static const char *get_boolean(bool bool_value)
2133 static const char *yes_str = "yes";
2134 static const char *no_str = "no";
2136 return (bool_value ? yes_str : no_str);
2139 /***************************************************************************
2140 Provide the string of the negated boolean value associated to the boolean
2141 given as a string. Returns false if the passed string does not correctly
2142 represent a boolean.
2143 ***************************************************************************/
2145 bool lp_invert_boolean(const char *str, const char **inverse_str)
2147 bool val;
2149 if (!set_boolean(str, &val)) {
2150 return false;
2153 *inverse_str = get_boolean(!val);
2154 return true;
2157 /***************************************************************************
2158 Provide the canonical string representation of a boolean value given
2159 as a string. Return true on success, false if the string given does
2160 not correctly represent a boolean.
2161 ***************************************************************************/
2163 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2165 bool val;
2167 if (!set_boolean(str, &val)) {
2168 return false;
2171 *canon_str = get_boolean(val);
2172 return true;
2175 /***************************************************************************
2176 Find a service by name. Otherwise works like get_service.
2177 ***************************************************************************/
2179 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2181 int iService = -1;
2182 char *canon_name;
2183 TDB_DATA data;
2184 NTSTATUS status;
2186 if (ServiceHash == NULL) {
2187 return -1;
2190 canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2192 status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2193 &data);
2195 if (NT_STATUS_IS_OK(status) &&
2196 (data.dptr != NULL) &&
2197 (data.dsize == sizeof(iService)))
2199 iService = *(int *)data.dptr;
2202 TALLOC_FREE(canon_name);
2204 if ((iService != -1) && (LP_SNUM_OK(iService))
2205 && (pserviceDest != NULL)) {
2206 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2209 return (iService);
2212 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2213 struct loadparm_service *lp_service(const char *pszServiceName)
2215 int iService = getservicebyname(pszServiceName, NULL);
2216 if (iService == -1 || !LP_SNUM_OK(iService)) {
2217 return NULL;
2219 return ServicePtrs[iService];
2222 struct loadparm_service *lp_servicebynum(int snum)
2224 if ((snum == -1) || !LP_SNUM_OK(snum)) {
2225 return NULL;
2227 return ServicePtrs[snum];
2230 struct loadparm_service *lp_default_loadparm_service()
2232 return &sDefault;
2236 /***************************************************************************
2237 Copy a service structure to another.
2238 If pcopymapDest is NULL then copy all fields
2239 ***************************************************************************/
2242 * Add a parametric option to a parmlist_entry,
2243 * replacing old value, if already present.
2245 static void set_param_opt(struct parmlist_entry **opt_list,
2246 const char *opt_name,
2247 const char *opt_value,
2248 unsigned priority)
2250 struct parmlist_entry *new_opt, *opt;
2251 bool not_added;
2253 opt = *opt_list;
2254 not_added = true;
2256 /* Traverse destination */
2257 while (opt) {
2258 /* If we already have same option, override it */
2259 if (strwicmp(opt->key, opt_name) == 0) {
2260 if ((opt->priority & FLAG_CMDLINE) &&
2261 !(priority & FLAG_CMDLINE)) {
2262 /* it's been marked as not to be
2263 overridden */
2264 return;
2266 string_free(&opt->value);
2267 TALLOC_FREE(opt->list);
2268 opt->value = SMB_STRDUP(opt_value);
2269 opt->priority = priority;
2270 not_added = false;
2271 break;
2273 opt = opt->next;
2275 if (not_added) {
2276 new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2277 new_opt->key = SMB_STRDUP(opt_name);
2278 new_opt->value = SMB_STRDUP(opt_value);
2279 new_opt->list = NULL;
2280 new_opt->priority = priority;
2281 DLIST_ADD(*opt_list, new_opt);
2285 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2286 struct bitmap *pcopymapDest)
2288 int i;
2289 bool bcopyall = (pcopymapDest == NULL);
2290 struct parmlist_entry *data;
2292 for (i = 0; parm_table[i].label; i++)
2293 if (parm_table[i].p_class == P_LOCAL &&
2294 (bcopyall || bitmap_query(pcopymapDest,i))) {
2295 void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2296 void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2298 switch (parm_table[i].type) {
2299 case P_BOOL:
2300 case P_BOOLREV:
2301 *(bool *)dest_ptr = *(bool *)src_ptr;
2302 break;
2304 case P_INTEGER:
2305 case P_ENUM:
2306 case P_OCTAL:
2307 case P_BYTES:
2308 *(int *)dest_ptr = *(int *)src_ptr;
2309 break;
2311 case P_CHAR:
2312 *(char *)dest_ptr = *(char *)src_ptr;
2313 break;
2315 case P_STRING:
2316 string_set((char **)dest_ptr,
2317 *(char **)src_ptr);
2318 break;
2320 case P_USTRING:
2322 char *upper_string = strupper_talloc(talloc_tos(),
2323 *(char **)src_ptr);
2324 string_set((char **)dest_ptr,
2325 upper_string);
2326 TALLOC_FREE(upper_string);
2327 break;
2329 case P_LIST:
2330 TALLOC_FREE(*((char ***)dest_ptr));
2331 *((char ***)dest_ptr) = str_list_copy(NULL,
2332 *(const char ***)src_ptr);
2333 break;
2334 default:
2335 break;
2339 if (bcopyall) {
2340 init_copymap(pserviceDest);
2341 if (pserviceSource->copymap)
2342 bitmap_copy(pserviceDest->copymap,
2343 pserviceSource->copymap);
2346 data = pserviceSource->param_opt;
2347 while (data) {
2348 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2349 data = data->next;
2353 /***************************************************************************
2354 Check a service for consistency. Return false if the service is in any way
2355 incomplete or faulty, else true.
2356 ***************************************************************************/
2358 bool service_ok(int iService)
2360 bool bRetval;
2362 bRetval = true;
2363 if (ServicePtrs[iService]->szService[0] == '\0') {
2364 DEBUG(0, ("The following message indicates an internal error:\n"));
2365 DEBUG(0, ("No service name in service entry.\n"));
2366 bRetval = false;
2369 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2370 /* I can't see why you'd want a non-printable printer service... */
2371 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2372 if (!ServicePtrs[iService]->bPrint_ok) {
2373 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2374 ServicePtrs[iService]->szService));
2375 ServicePtrs[iService]->bPrint_ok = true;
2377 /* [printers] service must also be non-browsable. */
2378 if (ServicePtrs[iService]->bBrowseable)
2379 ServicePtrs[iService]->bBrowseable = false;
2382 if (ServicePtrs[iService]->szPath[0] == '\0' &&
2383 strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2384 ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2386 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2387 ServicePtrs[iService]->szService));
2388 ServicePtrs[iService]->bAvailable = false;
2391 /* If a service is flagged unavailable, log the fact at level 1. */
2392 if (!ServicePtrs[iService]->bAvailable)
2393 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2394 ServicePtrs[iService]->szService));
2396 return (bRetval);
2399 static struct smbconf_ctx *lp_smbconf_ctx(void)
2401 sbcErr err;
2402 static struct smbconf_ctx *conf_ctx = NULL;
2404 if (conf_ctx == NULL) {
2405 err = smbconf_init(NULL, &conf_ctx, "registry:");
2406 if (!SBC_ERROR_IS_OK(err)) {
2407 DEBUG(1, ("error initializing registry configuration: "
2408 "%s\n", sbcErrorString(err)));
2409 conf_ctx = NULL;
2413 return conf_ctx;
2416 static bool process_smbconf_service(struct smbconf_service *service)
2418 uint32_t count;
2419 bool ret;
2421 if (service == NULL) {
2422 return false;
2425 ret = do_section(service->name, NULL);
2426 if (ret != true) {
2427 return false;
2429 for (count = 0; count < service->num_params; count++) {
2430 ret = do_parameter(service->param_names[count],
2431 service->param_values[count],
2432 NULL);
2433 if (ret != true) {
2434 return false;
2437 if (iServiceIndex >= 0) {
2438 return service_ok(iServiceIndex);
2440 return true;
2444 * load a service from registry and activate it
2446 bool process_registry_service(const char *service_name)
2448 sbcErr err;
2449 struct smbconf_service *service = NULL;
2450 TALLOC_CTX *mem_ctx = talloc_stackframe();
2451 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2452 bool ret = false;
2454 if (conf_ctx == NULL) {
2455 goto done;
2458 DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2460 if (!smbconf_share_exists(conf_ctx, service_name)) {
2462 * Registry does not contain data for this service (yet),
2463 * but make sure lp_load doesn't return false.
2465 ret = true;
2466 goto done;
2469 err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2470 if (!SBC_ERROR_IS_OK(err)) {
2471 goto done;
2474 ret = process_smbconf_service(service);
2475 if (!ret) {
2476 goto done;
2479 /* store the csn */
2480 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2482 done:
2483 TALLOC_FREE(mem_ctx);
2484 return ret;
2488 * process_registry_globals
2490 static bool process_registry_globals(void)
2492 bool ret;
2494 add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2496 ret = do_parameter("registry shares", "yes", NULL);
2497 if (!ret) {
2498 return ret;
2501 return process_registry_service(GLOBAL_NAME);
2504 bool process_registry_shares(void)
2506 sbcErr err;
2507 uint32_t count;
2508 struct smbconf_service **service = NULL;
2509 uint32_t num_shares = 0;
2510 TALLOC_CTX *mem_ctx = talloc_stackframe();
2511 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2512 bool ret = false;
2514 if (conf_ctx == NULL) {
2515 goto done;
2518 err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2519 if (!SBC_ERROR_IS_OK(err)) {
2520 goto done;
2523 ret = true;
2525 for (count = 0; count < num_shares; count++) {
2526 if (strequal(service[count]->name, GLOBAL_NAME)) {
2527 continue;
2529 ret = process_smbconf_service(service[count]);
2530 if (!ret) {
2531 goto done;
2535 /* store the csn */
2536 smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2538 done:
2539 TALLOC_FREE(mem_ctx);
2540 return ret;
2544 * reload those shares from registry that are already
2545 * activated in the services array.
2547 static bool reload_registry_shares(void)
2549 int i;
2550 bool ret = true;
2552 for (i = 0; i < iNumServices; i++) {
2553 if (!VALID(i)) {
2554 continue;
2557 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2558 continue;
2561 ret = process_registry_service(ServicePtrs[i]->szService);
2562 if (!ret) {
2563 goto done;
2567 done:
2568 return ret;
2572 #define MAX_INCLUDE_DEPTH 100
2574 static uint8_t include_depth;
2576 static struct file_lists {
2577 struct file_lists *next;
2578 char *name;
2579 char *subfname;
2580 time_t modtime;
2581 } *file_lists = NULL;
2583 /*******************************************************************
2584 Keep a linked list of all config files so we know when one has changed
2585 it's date and needs to be reloaded.
2586 ********************************************************************/
2588 static void add_to_file_list(const char *fname, const char *subfname)
2590 struct file_lists *f = file_lists;
2592 while (f) {
2593 if (f->name && !strcmp(f->name, fname))
2594 break;
2595 f = f->next;
2598 if (!f) {
2599 f = SMB_MALLOC_P(struct file_lists);
2600 if (!f)
2601 return;
2602 f->next = file_lists;
2603 f->name = SMB_STRDUP(fname);
2604 if (!f->name) {
2605 SAFE_FREE(f);
2606 return;
2608 f->subfname = SMB_STRDUP(subfname);
2609 if (!f->subfname) {
2610 SAFE_FREE(f->name);
2611 SAFE_FREE(f);
2612 return;
2614 file_lists = f;
2615 f->modtime = file_modtime(subfname);
2616 } else {
2617 time_t t = file_modtime(subfname);
2618 if (t)
2619 f->modtime = t;
2621 return;
2625 * Free the file lists
2627 static void free_file_list(void)
2629 struct file_lists *f;
2630 struct file_lists *next;
2632 f = file_lists;
2633 while( f ) {
2634 next = f->next;
2635 SAFE_FREE( f->name );
2636 SAFE_FREE( f->subfname );
2637 SAFE_FREE( f );
2638 f = next;
2640 file_lists = NULL;
2645 * Utility function for outsiders to check if we're running on registry.
2647 bool lp_config_backend_is_registry(void)
2649 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2653 * Utility function to check if the config backend is FILE.
2655 bool lp_config_backend_is_file(void)
2657 return (lp_config_backend() == CONFIG_BACKEND_FILE);
2660 /*******************************************************************
2661 Check if a config file has changed date.
2662 ********************************************************************/
2664 bool lp_file_list_changed(void)
2666 struct file_lists *f = file_lists;
2668 DEBUG(6, ("lp_file_list_changed()\n"));
2670 while (f) {
2671 time_t mod_time;
2673 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2674 struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2676 if (conf_ctx == NULL) {
2677 return false;
2679 if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2680 NULL))
2682 DEBUGADD(6, ("registry config changed\n"));
2683 return true;
2685 } else {
2686 char *n2 = NULL;
2687 n2 = talloc_sub_basic(talloc_tos(),
2688 get_current_username(),
2689 current_user_info.domain,
2690 f->name);
2691 if (!n2) {
2692 return false;
2694 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2695 f->name, n2, ctime(&f->modtime)));
2697 mod_time = file_modtime(n2);
2699 if (mod_time &&
2700 ((f->modtime != mod_time) ||
2701 (f->subfname == NULL) ||
2702 (strcmp(n2, f->subfname) != 0)))
2704 DEBUGADD(6,
2705 ("file %s modified: %s\n", n2,
2706 ctime(&mod_time)));
2707 f->modtime = mod_time;
2708 SAFE_FREE(f->subfname);
2709 f->subfname = SMB_STRDUP(n2);
2710 TALLOC_FREE(n2);
2711 return true;
2713 TALLOC_FREE(n2);
2715 f = f->next;
2717 return false;
2722 * Initialize iconv conversion descriptors.
2724 * This is called the first time it is needed, and also called again
2725 * every time the configuration is reloaded, because the charset or
2726 * codepage might have changed.
2728 static void init_iconv(void)
2730 global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2731 lp_unix_charset(),
2732 true, global_iconv_handle);
2735 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2737 if (strcmp(*ptr, pszParmValue) != 0) {
2738 string_set(ptr, pszParmValue);
2739 init_iconv();
2741 return true;
2744 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2746 bool is_utf8 = false;
2747 size_t len = strlen(pszParmValue);
2749 if (len == 4 || len == 5) {
2750 /* Don't use StrCaseCmp here as we don't want to
2751 initialize iconv. */
2752 if ((toupper_m(pszParmValue[0]) == 'U') &&
2753 (toupper_m(pszParmValue[1]) == 'T') &&
2754 (toupper_m(pszParmValue[2]) == 'F')) {
2755 if (len == 4) {
2756 if (pszParmValue[3] == '8') {
2757 is_utf8 = true;
2759 } else {
2760 if (pszParmValue[3] == '-' &&
2761 pszParmValue[4] == '8') {
2762 is_utf8 = true;
2768 if (strcmp(*ptr, pszParmValue) != 0) {
2769 if (is_utf8) {
2770 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2771 "be UTF8, using (default value) %s instead.\n",
2772 DEFAULT_DOS_CHARSET));
2773 pszParmValue = DEFAULT_DOS_CHARSET;
2775 string_set(ptr, pszParmValue);
2776 init_iconv();
2778 return true;
2781 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2783 bool ret = true;
2784 char *realm = strupper_talloc(talloc_tos(), pszParmValue);
2785 char *dnsdomain = strlower_talloc(realm, pszParmValue);
2787 ret &= string_set(&Globals.szRealm, pszParmValue);
2788 ret &= string_set(&Globals.szRealm_upper, realm);
2789 ret &= string_set(&Globals.szRealm_lower, dnsdomain);
2790 TALLOC_FREE(realm);
2792 return ret;
2795 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2797 TALLOC_FREE(Globals.szNetbiosAliases);
2798 Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2799 return set_netbios_aliases(Globals.szNetbiosAliases);
2802 /***************************************************************************
2803 Handle the include operation.
2804 ***************************************************************************/
2805 static bool bAllowIncludeRegistry = true;
2807 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2809 char *fname;
2811 if (include_depth >= MAX_INCLUDE_DEPTH) {
2812 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2813 include_depth));
2814 return false;
2817 if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2818 if (!bAllowIncludeRegistry) {
2819 return true;
2821 if (bInGlobalSection) {
2822 bool ret;
2823 include_depth++;
2824 ret = process_registry_globals();
2825 include_depth--;
2826 return ret;
2827 } else {
2828 DEBUG(1, ("\"include = registry\" only effective "
2829 "in %s section\n", GLOBAL_NAME));
2830 return false;
2834 fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2835 current_user_info.domain,
2836 pszParmValue);
2838 add_to_file_list(pszParmValue, fname);
2840 string_set(ptr, fname);
2842 if (file_exist(fname)) {
2843 bool ret;
2844 include_depth++;
2845 ret = pm_process(fname, do_section, do_parameter, NULL);
2846 include_depth--;
2847 TALLOC_FREE(fname);
2848 return ret;
2851 DEBUG(2, ("Can't find include file %s\n", fname));
2852 TALLOC_FREE(fname);
2853 return true;
2856 /***************************************************************************
2857 Handle the interpretation of the copy parameter.
2858 ***************************************************************************/
2860 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2862 bool bRetval;
2863 int iTemp;
2864 struct loadparm_service serviceTemp;
2866 string_set(ptr, pszParmValue);
2868 init_service(&serviceTemp);
2870 bRetval = false;
2872 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2874 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2875 if (iTemp == iServiceIndex) {
2876 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2877 } else {
2878 copy_service(ServicePtrs[iServiceIndex],
2879 &serviceTemp,
2880 ServicePtrs[iServiceIndex]->copymap);
2881 bRetval = true;
2883 } else {
2884 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2885 bRetval = false;
2888 free_service(&serviceTemp);
2889 return (bRetval);
2892 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2894 Globals.ldap_debug_level = lp_int(pszParmValue);
2895 init_ldap_debugging();
2896 return true;
2899 /***************************************************************************
2900 Handle idmap/non unix account uid and gid allocation parameters. The format of these
2901 parameters is:
2903 [global]
2905 idmap uid = 1000-1999
2906 idmap gid = 700-899
2908 We only do simple parsing checks here. The strings are parsed into useful
2909 structures in the idmap daemon code.
2911 ***************************************************************************/
2913 /* Some lp_ routines to return idmap [ug]id information */
2915 static uid_t idmap_uid_low, idmap_uid_high;
2916 static gid_t idmap_gid_low, idmap_gid_high;
2918 bool lp_idmap_uid(uid_t *low, uid_t *high)
2920 if (idmap_uid_low == 0 || idmap_uid_high == 0)
2921 return false;
2923 if (low)
2924 *low = idmap_uid_low;
2926 if (high)
2927 *high = idmap_uid_high;
2929 return true;
2932 bool lp_idmap_gid(gid_t *low, gid_t *high)
2934 if (idmap_gid_low == 0 || idmap_gid_high == 0)
2935 return false;
2937 if (low)
2938 *low = idmap_gid_low;
2940 if (high)
2941 *high = idmap_gid_high;
2943 return true;
2946 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2948 lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2950 return true;
2953 /* Do some simple checks on "idmap [ug]id" parameter values */
2955 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2957 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2959 return true;
2962 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2964 lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2966 return true;
2969 /***************************************************************************
2970 Handle the DEBUG level list.
2971 ***************************************************************************/
2973 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2975 string_set(ptr, pszParmValueIn);
2976 return debug_parse_levels(pszParmValueIn);
2979 /***************************************************************************
2980 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2981 ***************************************************************************/
2983 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2985 const char *suffix_string;
2987 suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2988 Globals.szLdapSuffix );
2989 if ( !suffix_string ) {
2990 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2991 return "";
2994 return suffix_string;
2997 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2999 if (Globals.szLdapMachineSuffix[0])
3000 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
3002 return lp_string(ctx, Globals.szLdapSuffix);
3005 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
3007 if (Globals.szLdapUserSuffix[0])
3008 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3010 return lp_string(ctx, Globals.szLdapSuffix);
3013 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3015 if (Globals.szLdapGroupSuffix[0])
3016 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3018 return lp_string(ctx, Globals.szLdapSuffix);
3021 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3023 if (Globals.szLdapIdmapSuffix[0])
3024 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3026 return lp_string(ctx, Globals.szLdapSuffix);
3029 /****************************************************************************
3030 set the value for a P_ENUM
3031 ***************************************************************************/
3033 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3034 int *ptr )
3036 int i;
3038 for (i = 0; parm->enum_list[i].name; i++) {
3039 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3040 *ptr = parm->enum_list[i].value;
3041 return;
3044 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3045 pszParmValue, parm->label));
3048 /***************************************************************************
3049 ***************************************************************************/
3051 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3053 static int parm_num = -1;
3054 struct loadparm_service *s;
3056 if ( parm_num == -1 )
3057 parm_num = map_parameter( "printing" );
3059 lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3061 if ( snum < 0 )
3062 s = &sDefault;
3063 else
3064 s = ServicePtrs[snum];
3066 init_printer_values( s );
3068 return true;
3072 /***************************************************************************
3073 Initialise a copymap.
3074 ***************************************************************************/
3076 static void init_copymap(struct loadparm_service *pservice)
3078 int i;
3080 TALLOC_FREE(pservice->copymap);
3082 pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3083 if (!pservice->copymap)
3084 DEBUG(0,
3085 ("Couldn't allocate copymap!! (size %d)\n",
3086 (int)NUMPARAMETERS));
3087 else
3088 for (i = 0; i < NUMPARAMETERS; i++)
3089 bitmap_set(pservice->copymap, i);
3093 return the parameter pointer for a parameter
3095 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3097 if (service == NULL) {
3098 if (parm->p_class == P_LOCAL)
3099 return (void *)(((char *)&sDefault)+parm->offset);
3100 else if (parm->p_class == P_GLOBAL)
3101 return (void *)(((char *)&Globals)+parm->offset);
3102 else return NULL;
3103 } else {
3104 return (void *)(((char *)service) + parm->offset);
3108 /***************************************************************************
3109 Return the local pointer to a parameter given the service number and parameter
3110 ***************************************************************************/
3112 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3114 return lp_parm_ptr(ServicePtrs[snum], parm);
3117 /***************************************************************************
3118 Process a parameter for a particular service number. If snum < 0
3119 then assume we are in the globals.
3120 ***************************************************************************/
3122 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3124 int parmnum, i;
3125 void *parm_ptr = NULL; /* where we are going to store the result */
3126 struct parmlist_entry **opt_list;
3128 parmnum = map_parameter(pszParmName);
3130 if (parmnum < 0) {
3131 if (strchr(pszParmName, ':') == NULL) {
3132 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3133 pszParmName));
3134 return true;
3138 * We've got a parametric option
3141 opt_list = (snum < 0)
3142 ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3143 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3145 return true;
3148 /* if it's already been set by the command line, then we don't
3149 override here */
3150 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3151 return true;
3154 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3155 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3156 pszParmName));
3159 /* we might point at a service, the default service or a global */
3160 if (snum < 0) {
3161 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3162 } else {
3163 if (parm_table[parmnum].p_class == P_GLOBAL) {
3164 DEBUG(0,
3165 ("Global parameter %s found in service section!\n",
3166 pszParmName));
3167 return true;
3169 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3172 if (snum >= 0) {
3173 if (!ServicePtrs[snum]->copymap)
3174 init_copymap(ServicePtrs[snum]);
3176 /* this handles the aliases - set the copymap for other entries with
3177 the same data pointer */
3178 for (i = 0; parm_table[i].label; i++) {
3179 if ((parm_table[i].offset == parm_table[parmnum].offset)
3180 && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3181 bitmap_clear(ServicePtrs[snum]->copymap, i);
3186 /* if it is a special case then go ahead */
3187 if (parm_table[parmnum].special) {
3188 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3189 (char **)parm_ptr);
3192 /* now switch on the type of variable it is */
3193 switch (parm_table[parmnum].type)
3195 case P_BOOL:
3196 *(bool *)parm_ptr = lp_bool(pszParmValue);
3197 break;
3199 case P_BOOLREV:
3200 *(bool *)parm_ptr = !lp_bool(pszParmValue);
3201 break;
3203 case P_INTEGER:
3204 *(int *)parm_ptr = lp_int(pszParmValue);
3205 break;
3207 case P_CHAR:
3208 *(char *)parm_ptr = *pszParmValue;
3209 break;
3211 case P_OCTAL:
3212 i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3213 if ( i != 1 ) {
3214 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3216 break;
3218 case P_BYTES:
3220 uint64_t val;
3221 if (conv_str_size_error(pszParmValue, &val)) {
3222 if (val <= INT_MAX) {
3223 *(int *)parm_ptr = (int)val;
3224 break;
3228 DEBUG(0,("lp_do_parameter(%s): value is not "
3229 "a valid size specifier!\n", pszParmValue));
3230 return false;
3233 case P_LIST:
3234 case P_CMDLIST:
3235 TALLOC_FREE(*((char ***)parm_ptr));
3236 *(char ***)parm_ptr = str_list_make_v3(
3237 NULL, pszParmValue, NULL);
3238 break;
3240 case P_STRING:
3241 string_set((char **)parm_ptr, pszParmValue);
3242 break;
3244 case P_USTRING:
3246 char *upper_string = strupper_talloc(talloc_tos(),
3247 pszParmValue);
3248 string_set((char **)parm_ptr, upper_string);
3249 TALLOC_FREE(upper_string);
3250 break;
3252 case P_ENUM:
3253 lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3254 break;
3255 case P_SEP:
3256 break;
3259 return true;
3262 /***************************************************************************
3263 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3264 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3265 ***************************************************************************/
3267 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3269 int parmnum, i;
3270 parmnum = map_parameter(pszParmName);
3271 if (parmnum >= 0) {
3272 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3273 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3274 return false;
3276 parm_table[parmnum].flags |= FLAG_CMDLINE;
3278 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3279 * be grouped in the table, so we don't have to search the
3280 * whole table */
3281 for (i=parmnum-1;
3282 i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3283 && parm_table[i].p_class == parm_table[parmnum].p_class;
3284 i--) {
3285 parm_table[i].flags |= FLAG_CMDLINE;
3287 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3288 && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3289 parm_table[i].flags |= FLAG_CMDLINE;
3292 if (store_values) {
3293 store_lp_set_cmdline(pszParmName, pszParmValue);
3295 return true;
3298 /* it might be parametric */
3299 if (strchr(pszParmName, ':') != NULL) {
3300 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3301 if (store_values) {
3302 store_lp_set_cmdline(pszParmName, pszParmValue);
3304 return true;
3307 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3308 return true;
3311 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3313 return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3316 /***************************************************************************
3317 Process a parameter.
3318 ***************************************************************************/
3320 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3321 void *userdata)
3323 if (!bInGlobalSection && bGlobalOnly)
3324 return true;
3326 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3328 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3329 pszParmName, pszParmValue));
3333 set a option from the commandline in 'a=b' format. Use to support --option
3335 bool lp_set_option(const char *option)
3337 char *p, *s;
3338 bool ret;
3340 s = talloc_strdup(NULL, option);
3341 if (!s) {
3342 return false;
3345 p = strchr(s, '=');
3346 if (!p) {
3347 talloc_free(s);
3348 return false;
3351 *p = 0;
3353 /* skip white spaces after the = sign */
3354 do {
3355 p++;
3356 } while (*p == ' ');
3358 ret = lp_set_cmdline(s, p);
3359 talloc_free(s);
3360 return ret;
3363 /**************************************************************************
3364 Print a parameter of the specified type.
3365 ***************************************************************************/
3367 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3369 /* For the seperation of lists values that we print below */
3370 const char *list_sep = ", ";
3371 int i;
3372 switch (p->type)
3374 case P_ENUM:
3375 for (i = 0; p->enum_list[i].name; i++) {
3376 if (*(int *)ptr == p->enum_list[i].value) {
3377 fprintf(f, "%s",
3378 p->enum_list[i].name);
3379 break;
3382 break;
3384 case P_BOOL:
3385 fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3386 break;
3388 case P_BOOLREV:
3389 fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3390 break;
3392 case P_INTEGER:
3393 case P_BYTES:
3394 fprintf(f, "%d", *(int *)ptr);
3395 break;
3397 case P_CHAR:
3398 fprintf(f, "%c", *(char *)ptr);
3399 break;
3401 case P_OCTAL: {
3402 int val = *(int *)ptr;
3403 if (val == -1) {
3404 fprintf(f, "-1");
3405 } else {
3406 fprintf(f, "0%o", val);
3408 break;
3411 case P_CMDLIST:
3412 list_sep = " ";
3413 /* fall through */
3414 case P_LIST:
3415 if ((char ***)ptr && *(char ***)ptr) {
3416 char **list = *(char ***)ptr;
3417 for (; *list; list++) {
3418 /* surround strings with whitespace in double quotes */
3419 if (*(list+1) == NULL) {
3420 /* last item, no extra separator */
3421 list_sep = "";
3423 if ( strchr_m( *list, ' ' ) ) {
3424 fprintf(f, "\"%s\"%s", *list, list_sep);
3425 } else {
3426 fprintf(f, "%s%s", *list, list_sep);
3430 break;
3432 case P_STRING:
3433 case P_USTRING:
3434 if (*(char **)ptr) {
3435 fprintf(f, "%s", *(char **)ptr);
3437 break;
3438 case P_SEP:
3439 break;
3443 /***************************************************************************
3444 Check if two parameters are equal.
3445 ***************************************************************************/
3447 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3449 switch (type) {
3450 case P_BOOL:
3451 case P_BOOLREV:
3452 return (*((bool *)ptr1) == *((bool *)ptr2));
3454 case P_INTEGER:
3455 case P_ENUM:
3456 case P_OCTAL:
3457 case P_BYTES:
3458 return (*((int *)ptr1) == *((int *)ptr2));
3460 case P_CHAR:
3461 return (*((char *)ptr1) == *((char *)ptr2));
3463 case P_LIST:
3464 case P_CMDLIST:
3465 return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3467 case P_STRING:
3468 case P_USTRING:
3470 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3471 if (p1 && !*p1)
3472 p1 = NULL;
3473 if (p2 && !*p2)
3474 p2 = NULL;
3475 return (p1 == p2 || strequal(p1, p2));
3477 case P_SEP:
3478 break;
3480 return false;
3483 /***************************************************************************
3484 Initialize any local varients in the sDefault table.
3485 ***************************************************************************/
3487 void init_locals(void)
3489 /* None as yet. */
3492 /***************************************************************************
3493 Process a new section (service). At this stage all sections are services.
3494 Later we'll have special sections that permit server parameters to be set.
3495 Returns true on success, false on failure.
3496 ***************************************************************************/
3498 static bool do_section(const char *pszSectionName, void *userdata)
3500 bool bRetval;
3501 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3502 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3503 bRetval = false;
3505 /* if we were in a global section then do the local inits */
3506 if (bInGlobalSection && !isglobal)
3507 init_locals();
3509 /* if we've just struck a global section, note the fact. */
3510 bInGlobalSection = isglobal;
3512 /* check for multiple global sections */
3513 if (bInGlobalSection) {
3514 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3515 return true;
3518 if (!bInGlobalSection && bGlobalOnly)
3519 return true;
3521 /* if we have a current service, tidy it up before moving on */
3522 bRetval = true;
3524 if (iServiceIndex >= 0)
3525 bRetval = service_ok(iServiceIndex);
3527 /* if all is still well, move to the next record in the services array */
3528 if (bRetval) {
3529 /* We put this here to avoid an odd message order if messages are */
3530 /* issued by the post-processing of a previous section. */
3531 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3533 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3534 if (iServiceIndex < 0) {
3535 DEBUG(0, ("Failed to add a new service\n"));
3536 return false;
3538 /* Clean all parametric options for service */
3539 /* They will be added during parsing again */
3540 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3543 return bRetval;
3547 /***************************************************************************
3548 Determine if a partcular base parameter is currentl set to the default value.
3549 ***************************************************************************/
3551 static bool is_default(int i)
3553 if (!defaults_saved)
3554 return false;
3555 switch (parm_table[i].type) {
3556 case P_LIST:
3557 case P_CMDLIST:
3558 return str_list_equal((const char **)parm_table[i].def.lvalue,
3559 *(const char ***)lp_parm_ptr(NULL,
3560 &parm_table[i]));
3561 case P_STRING:
3562 case P_USTRING:
3563 return strequal(parm_table[i].def.svalue,
3564 *(char **)lp_parm_ptr(NULL,
3565 &parm_table[i]));
3566 case P_BOOL:
3567 case P_BOOLREV:
3568 return parm_table[i].def.bvalue ==
3569 *(bool *)lp_parm_ptr(NULL,
3570 &parm_table[i]);
3571 case P_CHAR:
3572 return parm_table[i].def.cvalue ==
3573 *(char *)lp_parm_ptr(NULL,
3574 &parm_table[i]);
3575 case P_INTEGER:
3576 case P_OCTAL:
3577 case P_ENUM:
3578 case P_BYTES:
3579 return parm_table[i].def.ivalue ==
3580 *(int *)lp_parm_ptr(NULL,
3581 &parm_table[i]);
3582 case P_SEP:
3583 break;
3585 return false;
3588 /***************************************************************************
3589 Display the contents of the global structure.
3590 ***************************************************************************/
3592 static void dump_globals(FILE *f)
3594 int i;
3595 struct parmlist_entry *data;
3597 fprintf(f, "[global]\n");
3599 for (i = 0; parm_table[i].label; i++)
3600 if (parm_table[i].p_class == P_GLOBAL &&
3601 !(parm_table[i].flags & FLAG_META) &&
3602 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3603 if (defaults_saved && is_default(i))
3604 continue;
3605 fprintf(f, "\t%s = ", parm_table[i].label);
3606 print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3607 &parm_table[i]),
3609 fprintf(f, "\n");
3611 if (Globals.param_opt != NULL) {
3612 data = Globals.param_opt;
3613 while(data) {
3614 fprintf(f, "\t%s = %s\n", data->key, data->value);
3615 data = data->next;
3621 /***************************************************************************
3622 Return true if a local parameter is currently set to the global default.
3623 ***************************************************************************/
3625 bool lp_is_default(int snum, struct parm_struct *parm)
3627 return equal_parameter(parm->type,
3628 lp_parm_ptr(ServicePtrs[snum], parm),
3629 lp_parm_ptr(NULL, parm));
3632 /***************************************************************************
3633 Display the contents of a single services record.
3634 ***************************************************************************/
3636 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3638 int i;
3639 struct parmlist_entry *data;
3641 if (pService != &sDefault)
3642 fprintf(f, "[%s]\n", pService->szService);
3644 for (i = 0; parm_table[i].label; i++) {
3646 if (parm_table[i].p_class == P_LOCAL &&
3647 !(parm_table[i].flags & FLAG_META) &&
3648 (*parm_table[i].label != '-') &&
3649 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3651 if (pService == &sDefault) {
3652 if (defaults_saved && is_default(i))
3653 continue;
3654 } else {
3655 if (equal_parameter(parm_table[i].type,
3656 lp_parm_ptr(pService, &parm_table[i]),
3657 lp_parm_ptr(NULL, &parm_table[i])))
3658 continue;
3661 fprintf(f, "\t%s = ", parm_table[i].label);
3662 print_parameter(&parm_table[i],
3663 lp_parm_ptr(pService, &parm_table[i]),
3665 fprintf(f, "\n");
3669 if (pService->param_opt != NULL) {
3670 data = pService->param_opt;
3671 while(data) {
3672 fprintf(f, "\t%s = %s\n", data->key, data->value);
3673 data = data->next;
3678 /***************************************************************************
3679 Display the contents of a parameter of a single services record.
3680 ***************************************************************************/
3682 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3684 int i;
3685 bool result = false;
3686 parm_class p_class;
3687 unsigned flag = 0;
3688 fstring local_parm_name;
3689 char *parm_opt;
3690 const char *parm_opt_value;
3692 /* check for parametrical option */
3693 fstrcpy( local_parm_name, parm_name);
3694 parm_opt = strchr( local_parm_name, ':');
3696 if (parm_opt) {
3697 *parm_opt = '\0';
3698 parm_opt++;
3699 if (strlen(parm_opt)) {
3700 parm_opt_value = lp_parm_const_string( snum,
3701 local_parm_name, parm_opt, NULL);
3702 if (parm_opt_value) {
3703 printf( "%s\n", parm_opt_value);
3704 result = true;
3707 return result;
3710 /* check for a key and print the value */
3711 if (isGlobal) {
3712 p_class = P_GLOBAL;
3713 flag = FLAG_GLOBAL;
3714 } else
3715 p_class = P_LOCAL;
3717 for (i = 0; parm_table[i].label; i++) {
3718 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3719 !(parm_table[i].flags & FLAG_META) &&
3720 (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3721 (*parm_table[i].label != '-') &&
3722 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
3724 void *ptr;
3726 if (isGlobal) {
3727 ptr = lp_parm_ptr(NULL,
3728 &parm_table[i]);
3729 } else {
3730 ptr = lp_parm_ptr(ServicePtrs[snum],
3731 &parm_table[i]);
3734 print_parameter(&parm_table[i],
3735 ptr, f);
3736 fprintf(f, "\n");
3737 result = true;
3738 break;
3742 return result;
3745 /***************************************************************************
3746 Return info about the requested parameter (given as a string).
3747 Return NULL when the string is not a valid parameter name.
3748 ***************************************************************************/
3750 struct parm_struct *lp_get_parameter(const char *param_name)
3752 int num = map_parameter(param_name);
3754 if (num < 0) {
3755 return NULL;
3758 return &parm_table[num];
3761 /***************************************************************************
3762 Return info about the next parameter in a service.
3763 snum==GLOBAL_SECTION_SNUM gives the globals.
3764 Return NULL when out of parameters.
3765 ***************************************************************************/
3767 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3769 if (snum < 0) {
3770 /* do the globals */
3771 for (; parm_table[*i].label; (*i)++) {
3772 if (parm_table[*i].p_class == P_SEPARATOR)
3773 return &parm_table[(*i)++];
3775 if ((*parm_table[*i].label == '-'))
3776 continue;
3778 if ((*i) > 0
3779 && (parm_table[*i].offset ==
3780 parm_table[(*i) - 1].offset)
3781 && (parm_table[*i].p_class ==
3782 parm_table[(*i) - 1].p_class))
3783 continue;
3785 if (is_default(*i) && !allparameters)
3786 continue;
3788 return &parm_table[(*i)++];
3790 } else {
3791 struct loadparm_service *pService = ServicePtrs[snum];
3793 for (; parm_table[*i].label; (*i)++) {
3794 if (parm_table[*i].p_class == P_SEPARATOR)
3795 return &parm_table[(*i)++];
3797 if (parm_table[*i].p_class == P_LOCAL &&
3798 (*parm_table[*i].label != '-') &&
3799 ((*i) == 0 ||
3800 (parm_table[*i].offset !=
3801 parm_table[(*i) - 1].offset)))
3803 if (allparameters ||
3804 !equal_parameter(parm_table[*i].type,
3805 lp_parm_ptr(pService,
3806 &parm_table[*i]),
3807 lp_parm_ptr(NULL,
3808 &parm_table[*i])))
3810 return &parm_table[(*i)++];
3816 return NULL;
3820 #if 0
3821 /***************************************************************************
3822 Display the contents of a single copy structure.
3823 ***************************************************************************/
3824 static void dump_copy_map(bool *pcopymap)
3826 int i;
3827 if (!pcopymap)
3828 return;
3830 printf("\n\tNon-Copied parameters:\n");
3832 for (i = 0; parm_table[i].label; i++)
3833 if (parm_table[i].p_class == P_LOCAL &&
3834 parm_table[i].ptr && !pcopymap[i] &&
3835 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3837 printf("\t\t%s\n", parm_table[i].label);
3840 #endif
3842 /***************************************************************************
3843 Return TRUE if the passed service number is within range.
3844 ***************************************************************************/
3846 bool lp_snum_ok(int iService)
3848 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3851 /***************************************************************************
3852 Auto-load some home services.
3853 ***************************************************************************/
3855 static void lp_add_auto_services(char *str)
3857 char *s;
3858 char *p;
3859 int homes;
3860 char *saveptr;
3862 if (!str)
3863 return;
3865 s = SMB_STRDUP(str);
3866 if (!s)
3867 return;
3869 homes = lp_servicenumber(HOMES_NAME);
3871 for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3872 p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3873 char *home;
3875 if (lp_servicenumber(p) >= 0)
3876 continue;
3878 home = get_user_home_dir(talloc_tos(), p);
3880 if (home && home[0] && homes >= 0)
3881 lp_add_home(p, homes, p, home);
3883 TALLOC_FREE(home);
3885 SAFE_FREE(s);
3888 /***************************************************************************
3889 Auto-load one printer.
3890 ***************************************************************************/
3892 void lp_add_one_printer(const char *name, const char *comment,
3893 const char *location, void *pdata)
3895 int printers = lp_servicenumber(PRINTERS_NAME);
3896 int i;
3898 if (lp_servicenumber(name) < 0) {
3899 lp_add_printer(name, printers);
3900 if ((i = lp_servicenumber(name)) >= 0) {
3901 string_set(&ServicePtrs[i]->comment, comment);
3902 ServicePtrs[i]->autoloaded = true;
3907 /***************************************************************************
3908 Have we loaded a services file yet?
3909 ***************************************************************************/
3911 bool lp_loaded(void)
3913 return (bLoaded);
3916 /***************************************************************************
3917 Unload unused services.
3918 ***************************************************************************/
3920 void lp_killunused(struct smbd_server_connection *sconn,
3921 bool (*snumused) (struct smbd_server_connection *, int))
3923 int i;
3924 for (i = 0; i < iNumServices; i++) {
3925 if (!VALID(i))
3926 continue;
3928 /* don't kill autoloaded or usershare services */
3929 if ( ServicePtrs[i]->autoloaded ||
3930 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3931 continue;
3934 if (!snumused || !snumused(sconn, i)) {
3935 free_service_byindex(i);
3941 * Kill all except autoloaded and usershare services - convenience wrapper
3943 void lp_kill_all_services(void)
3945 lp_killunused(NULL, NULL);
3948 /***************************************************************************
3949 Unload a service.
3950 ***************************************************************************/
3952 void lp_killservice(int iServiceIn)
3954 if (VALID(iServiceIn)) {
3955 free_service_byindex(iServiceIn);
3959 /***************************************************************************
3960 Save the curent values of all global and sDefault parameters into the
3961 defaults union. This allows swat and testparm to show only the
3962 changed (ie. non-default) parameters.
3963 ***************************************************************************/
3965 static void lp_save_defaults(void)
3967 int i;
3968 for (i = 0; parm_table[i].label; i++) {
3969 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3970 && parm_table[i].p_class == parm_table[i - 1].p_class)
3971 continue;
3972 switch (parm_table[i].type) {
3973 case P_LIST:
3974 case P_CMDLIST:
3975 parm_table[i].def.lvalue = str_list_copy(
3976 NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3977 break;
3978 case P_STRING:
3979 case P_USTRING:
3980 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3981 break;
3982 case P_BOOL:
3983 case P_BOOLREV:
3984 parm_table[i].def.bvalue =
3985 *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
3986 break;
3987 case P_CHAR:
3988 parm_table[i].def.cvalue =
3989 *(char *)lp_parm_ptr(NULL, &parm_table[i]);
3990 break;
3991 case P_INTEGER:
3992 case P_OCTAL:
3993 case P_ENUM:
3994 case P_BYTES:
3995 parm_table[i].def.ivalue =
3996 *(int *)lp_parm_ptr(NULL, &parm_table[i]);
3997 break;
3998 case P_SEP:
3999 break;
4002 defaults_saved = true;
4005 /***********************************************************
4006 If we should send plaintext/LANMAN passwords in the clinet
4007 ************************************************************/
4009 static void set_allowed_client_auth(void)
4011 if (Globals.bClientNTLMv2Auth) {
4012 Globals.bClientLanManAuth = false;
4014 if (!Globals.bClientLanManAuth) {
4015 Globals.bClientPlaintextAuth = false;
4019 /***************************************************************************
4020 JRA.
4021 The following code allows smbd to read a user defined share file.
4022 Yes, this is my intent. Yes, I'm comfortable with that...
4024 THE FOLLOWING IS SECURITY CRITICAL CODE.
4026 It washes your clothes, it cleans your house, it guards you while you sleep...
4027 Do not f%^k with it....
4028 ***************************************************************************/
4030 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4032 /***************************************************************************
4033 Check allowed stat state of a usershare file.
4034 Ensure we print out who is dicking with us so the admin can
4035 get their sorry ass fired.
4036 ***************************************************************************/
4038 static bool check_usershare_stat(const char *fname,
4039 const SMB_STRUCT_STAT *psbuf)
4041 if (!S_ISREG(psbuf->st_ex_mode)) {
4042 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4043 "not a regular file\n",
4044 fname, (unsigned int)psbuf->st_ex_uid ));
4045 return false;
4048 /* Ensure this doesn't have the other write bit set. */
4049 if (psbuf->st_ex_mode & S_IWOTH) {
4050 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4051 "public write. Refusing to allow as a usershare file.\n",
4052 fname, (unsigned int)psbuf->st_ex_uid ));
4053 return false;
4056 /* Should be 10k or less. */
4057 if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4058 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4059 "too large (%u) to be a user share file.\n",
4060 fname, (unsigned int)psbuf->st_ex_uid,
4061 (unsigned int)psbuf->st_ex_size ));
4062 return false;
4065 return true;
4068 /***************************************************************************
4069 Parse the contents of a usershare file.
4070 ***************************************************************************/
4072 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4073 SMB_STRUCT_STAT *psbuf,
4074 const char *servicename,
4075 int snum,
4076 char **lines,
4077 int numlines,
4078 char **pp_sharepath,
4079 char **pp_comment,
4080 char **pp_cp_servicename,
4081 struct security_descriptor **ppsd,
4082 bool *pallow_guest)
4084 const char **prefixallowlist = lp_usershare_prefix_allow_list();
4085 const char **prefixdenylist = lp_usershare_prefix_deny_list();
4086 int us_vers;
4087 DIR *dp;
4088 SMB_STRUCT_STAT sbuf;
4089 char *sharepath = NULL;
4090 char *comment = NULL;
4092 *pp_sharepath = NULL;
4093 *pp_comment = NULL;
4095 *pallow_guest = false;
4097 if (numlines < 4) {
4098 return USERSHARE_MALFORMED_FILE;
4101 if (strcmp(lines[0], "#VERSION 1") == 0) {
4102 us_vers = 1;
4103 } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4104 us_vers = 2;
4105 if (numlines < 5) {
4106 return USERSHARE_MALFORMED_FILE;
4108 } else {
4109 return USERSHARE_BAD_VERSION;
4112 if (strncmp(lines[1], "path=", 5) != 0) {
4113 return USERSHARE_MALFORMED_PATH;
4116 sharepath = talloc_strdup(ctx, &lines[1][5]);
4117 if (!sharepath) {
4118 return USERSHARE_POSIX_ERR;
4120 trim_string(sharepath, " ", " ");
4122 if (strncmp(lines[2], "comment=", 8) != 0) {
4123 return USERSHARE_MALFORMED_COMMENT_DEF;
4126 comment = talloc_strdup(ctx, &lines[2][8]);
4127 if (!comment) {
4128 return USERSHARE_POSIX_ERR;
4130 trim_string(comment, " ", " ");
4131 trim_char(comment, '"', '"');
4133 if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4134 return USERSHARE_MALFORMED_ACL_DEF;
4137 if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4138 return USERSHARE_ACL_ERR;
4141 if (us_vers == 2) {
4142 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4143 return USERSHARE_MALFORMED_ACL_DEF;
4145 if (lines[4][9] == 'y') {
4146 *pallow_guest = true;
4149 /* Backwards compatible extension to file version #2. */
4150 if (numlines > 5) {
4151 if (strncmp(lines[5], "sharename=", 10) != 0) {
4152 return USERSHARE_MALFORMED_SHARENAME_DEF;
4154 if (!strequal(&lines[5][10], servicename)) {
4155 return USERSHARE_BAD_SHARENAME;
4157 *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4158 if (!*pp_cp_servicename) {
4159 return USERSHARE_POSIX_ERR;
4164 if (*pp_cp_servicename == NULL) {
4165 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4166 if (!*pp_cp_servicename) {
4167 return USERSHARE_POSIX_ERR;
4171 if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4172 /* Path didn't change, no checks needed. */
4173 *pp_sharepath = sharepath;
4174 *pp_comment = comment;
4175 return USERSHARE_OK;
4178 /* The path *must* be absolute. */
4179 if (sharepath[0] != '/') {
4180 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4181 servicename, sharepath));
4182 return USERSHARE_PATH_NOT_ABSOLUTE;
4185 /* If there is a usershare prefix deny list ensure one of these paths
4186 doesn't match the start of the user given path. */
4187 if (prefixdenylist) {
4188 int i;
4189 for ( i=0; prefixdenylist[i]; i++ ) {
4190 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4191 servicename, i, prefixdenylist[i], sharepath ));
4192 if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4193 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4194 "usershare prefix deny list entries.\n",
4195 servicename, sharepath));
4196 return USERSHARE_PATH_IS_DENIED;
4201 /* If there is a usershare prefix allow list ensure one of these paths
4202 does match the start of the user given path. */
4204 if (prefixallowlist) {
4205 int i;
4206 for ( i=0; prefixallowlist[i]; i++ ) {
4207 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4208 servicename, i, prefixallowlist[i], sharepath ));
4209 if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4210 break;
4213 if (prefixallowlist[i] == NULL) {
4214 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4215 "usershare prefix allow list entries.\n",
4216 servicename, sharepath));
4217 return USERSHARE_PATH_NOT_ALLOWED;
4221 /* Ensure this is pointing to a directory. */
4222 dp = opendir(sharepath);
4224 if (!dp) {
4225 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4226 servicename, sharepath));
4227 return USERSHARE_PATH_NOT_DIRECTORY;
4230 /* Ensure the owner of the usershare file has permission to share
4231 this directory. */
4233 if (sys_stat(sharepath, &sbuf, false) == -1) {
4234 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4235 servicename, sharepath, strerror(errno) ));
4236 closedir(dp);
4237 return USERSHARE_POSIX_ERR;
4240 closedir(dp);
4242 if (!S_ISDIR(sbuf.st_ex_mode)) {
4243 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4244 servicename, sharepath ));
4245 return USERSHARE_PATH_NOT_DIRECTORY;
4248 /* Check if sharing is restricted to owner-only. */
4249 /* psbuf is the stat of the usershare definition file,
4250 sbuf is the stat of the target directory to be shared. */
4252 if (lp_usershare_owner_only()) {
4253 /* root can share anything. */
4254 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4255 return USERSHARE_PATH_NOT_ALLOWED;
4259 *pp_sharepath = sharepath;
4260 *pp_comment = comment;
4261 return USERSHARE_OK;
4264 /***************************************************************************
4265 Deal with a usershare file.
4266 Returns:
4267 >= 0 - snum
4268 -1 - Bad name, invalid contents.
4269 - service name already existed and not a usershare, problem
4270 with permissions to share directory etc.
4271 ***************************************************************************/
4273 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4275 SMB_STRUCT_STAT sbuf;
4276 SMB_STRUCT_STAT lsbuf;
4277 char *fname = NULL;
4278 char *sharepath = NULL;
4279 char *comment = NULL;
4280 char *cp_service_name = NULL;
4281 char **lines = NULL;
4282 int numlines = 0;
4283 int fd = -1;
4284 int iService = -1;
4285 TALLOC_CTX *ctx = talloc_stackframe();
4286 struct security_descriptor *psd = NULL;
4287 bool guest_ok = false;
4288 char *canon_name = NULL;
4289 bool added_service = false;
4290 int ret = -1;
4292 /* Ensure share name doesn't contain invalid characters. */
4293 if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4294 DEBUG(0,("process_usershare_file: share name %s contains "
4295 "invalid characters (any of %s)\n",
4296 file_name, INVALID_SHARENAME_CHARS ));
4297 goto out;
4300 canon_name = canonicalize_servicename(ctx, file_name);
4301 if (!canon_name) {
4302 goto out;
4305 fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4306 if (!fname) {
4307 goto out;
4310 /* Minimize the race condition by doing an lstat before we
4311 open and fstat. Ensure this isn't a symlink link. */
4313 if (sys_lstat(fname, &lsbuf, false) != 0) {
4314 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4315 fname, strerror(errno) ));
4316 goto out;
4319 /* This must be a regular file, not a symlink, directory or
4320 other strange filetype. */
4321 if (!check_usershare_stat(fname, &lsbuf)) {
4322 goto out;
4326 TDB_DATA data;
4327 NTSTATUS status;
4329 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4330 canon_name, &data);
4332 iService = -1;
4334 if (NT_STATUS_IS_OK(status) &&
4335 (data.dptr != NULL) &&
4336 (data.dsize == sizeof(iService))) {
4337 memcpy(&iService, data.dptr, sizeof(iService));
4341 if (iService != -1 &&
4342 timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4343 &lsbuf.st_ex_mtime) == 0) {
4344 /* Nothing changed - Mark valid and return. */
4345 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4346 canon_name ));
4347 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4348 ret = iService;
4349 goto out;
4352 /* Try and open the file read only - no symlinks allowed. */
4353 #ifdef O_NOFOLLOW
4354 fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4355 #else
4356 fd = open(fname, O_RDONLY, 0);
4357 #endif
4359 if (fd == -1) {
4360 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4361 fname, strerror(errno) ));
4362 goto out;
4365 /* Now fstat to be *SURE* it's a regular file. */
4366 if (sys_fstat(fd, &sbuf, false) != 0) {
4367 close(fd);
4368 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4369 fname, strerror(errno) ));
4370 goto out;
4373 /* Is it the same dev/inode as was lstated ? */
4374 if (!check_same_stat(&lsbuf, &sbuf)) {
4375 close(fd);
4376 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4377 "Symlink spoofing going on ?\n", fname ));
4378 goto out;
4381 /* This must be a regular file, not a symlink, directory or
4382 other strange filetype. */
4383 if (!check_usershare_stat(fname, &sbuf)) {
4384 goto out;
4387 lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4389 close(fd);
4390 if (lines == NULL) {
4391 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4392 fname, (unsigned int)sbuf.st_ex_uid ));
4393 goto out;
4396 if (parse_usershare_file(ctx, &sbuf, file_name,
4397 iService, lines, numlines, &sharepath,
4398 &comment, &cp_service_name,
4399 &psd, &guest_ok) != USERSHARE_OK) {
4400 goto out;
4403 /* Everything ok - add the service possibly using a template. */
4404 if (iService < 0) {
4405 const struct loadparm_service *sp = &sDefault;
4406 if (snum_template != -1) {
4407 sp = ServicePtrs[snum_template];
4410 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4411 DEBUG(0, ("process_usershare_file: Failed to add "
4412 "new service %s\n", cp_service_name));
4413 goto out;
4416 added_service = true;
4418 /* Read only is controlled by usershare ACL below. */
4419 ServicePtrs[iService]->bRead_only = false;
4422 /* Write the ACL of the new/modified share. */
4423 if (!set_share_security(canon_name, psd)) {
4424 DEBUG(0, ("process_usershare_file: Failed to set share "
4425 "security for user share %s\n",
4426 canon_name ));
4427 goto out;
4430 /* If from a template it may be marked invalid. */
4431 ServicePtrs[iService]->valid = true;
4433 /* Set the service as a valid usershare. */
4434 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4436 /* Set guest access. */
4437 if (lp_usershare_allow_guests()) {
4438 ServicePtrs[iService]->bGuest_ok = guest_ok;
4441 /* And note when it was loaded. */
4442 ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4443 string_set(&ServicePtrs[iService]->szPath, sharepath);
4444 string_set(&ServicePtrs[iService]->comment, comment);
4446 ret = iService;
4448 out:
4450 if (ret == -1 && iService != -1 && added_service) {
4451 lp_remove_service(iService);
4454 TALLOC_FREE(lines);
4455 TALLOC_FREE(ctx);
4456 return ret;
4459 /***************************************************************************
4460 Checks if a usershare entry has been modified since last load.
4461 ***************************************************************************/
4463 static bool usershare_exists(int iService, struct timespec *last_mod)
4465 SMB_STRUCT_STAT lsbuf;
4466 const char *usersharepath = Globals.szUsersharePath;
4467 char *fname;
4469 if (asprintf(&fname, "%s/%s",
4470 usersharepath,
4471 ServicePtrs[iService]->szService) < 0) {
4472 return false;
4475 if (sys_lstat(fname, &lsbuf, false) != 0) {
4476 SAFE_FREE(fname);
4477 return false;
4480 if (!S_ISREG(lsbuf.st_ex_mode)) {
4481 SAFE_FREE(fname);
4482 return false;
4485 SAFE_FREE(fname);
4486 *last_mod = lsbuf.st_ex_mtime;
4487 return true;
4490 /***************************************************************************
4491 Load a usershare service by name. Returns a valid servicenumber or -1.
4492 ***************************************************************************/
4494 int load_usershare_service(const char *servicename)
4496 SMB_STRUCT_STAT sbuf;
4497 const char *usersharepath = Globals.szUsersharePath;
4498 int max_user_shares = Globals.iUsershareMaxShares;
4499 int snum_template = -1;
4501 if (*usersharepath == 0 || max_user_shares == 0) {
4502 return -1;
4505 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4506 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4507 usersharepath, strerror(errno) ));
4508 return -1;
4511 if (!S_ISDIR(sbuf.st_ex_mode)) {
4512 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4513 usersharepath ));
4514 return -1;
4518 * This directory must be owned by root, and have the 't' bit set.
4519 * It also must not be writable by "other".
4522 #ifdef S_ISVTX
4523 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4524 #else
4525 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4526 #endif
4527 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4528 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4529 usersharepath ));
4530 return -1;
4533 /* Ensure the template share exists if it's set. */
4534 if (Globals.szUsershareTemplateShare[0]) {
4535 /* We can't use lp_servicenumber here as we are recommending that
4536 template shares have -valid=false set. */
4537 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4538 if (ServicePtrs[snum_template]->szService &&
4539 strequal(ServicePtrs[snum_template]->szService,
4540 Globals.szUsershareTemplateShare)) {
4541 break;
4545 if (snum_template == -1) {
4546 DEBUG(0,("load_usershare_service: usershare template share %s "
4547 "does not exist.\n",
4548 Globals.szUsershareTemplateShare ));
4549 return -1;
4553 return process_usershare_file(usersharepath, servicename, snum_template);
4556 /***************************************************************************
4557 Load all user defined shares from the user share directory.
4558 We only do this if we're enumerating the share list.
4559 This is the function that can delete usershares that have
4560 been removed.
4561 ***************************************************************************/
4563 int load_usershare_shares(struct smbd_server_connection *sconn,
4564 bool (*snumused) (struct smbd_server_connection *, int))
4566 DIR *dp;
4567 SMB_STRUCT_STAT sbuf;
4568 struct dirent *de;
4569 int num_usershares = 0;
4570 int max_user_shares = Globals.iUsershareMaxShares;
4571 unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4572 unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4573 unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4574 int iService;
4575 int snum_template = -1;
4576 const char *usersharepath = Globals.szUsersharePath;
4577 int ret = lp_numservices();
4578 TALLOC_CTX *tmp_ctx;
4580 if (max_user_shares == 0 || *usersharepath == '\0') {
4581 return lp_numservices();
4584 if (sys_stat(usersharepath, &sbuf, false) != 0) {
4585 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4586 usersharepath, strerror(errno) ));
4587 return ret;
4591 * This directory must be owned by root, and have the 't' bit set.
4592 * It also must not be writable by "other".
4595 #ifdef S_ISVTX
4596 if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4597 #else
4598 if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4599 #endif
4600 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4601 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4602 usersharepath ));
4603 return ret;
4606 /* Ensure the template share exists if it's set. */
4607 if (Globals.szUsershareTemplateShare[0]) {
4608 /* We can't use lp_servicenumber here as we are recommending that
4609 template shares have -valid=false set. */
4610 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4611 if (ServicePtrs[snum_template]->szService &&
4612 strequal(ServicePtrs[snum_template]->szService,
4613 Globals.szUsershareTemplateShare)) {
4614 break;
4618 if (snum_template == -1) {
4619 DEBUG(0,("load_usershare_shares: usershare template share %s "
4620 "does not exist.\n",
4621 Globals.szUsershareTemplateShare ));
4622 return ret;
4626 /* Mark all existing usershares as pending delete. */
4627 for (iService = iNumServices - 1; iService >= 0; iService--) {
4628 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4629 ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4633 dp = opendir(usersharepath);
4634 if (!dp) {
4635 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4636 usersharepath, strerror(errno) ));
4637 return ret;
4640 for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4641 (de = readdir(dp));
4642 num_dir_entries++ ) {
4643 int r;
4644 const char *n = de->d_name;
4646 /* Ignore . and .. */
4647 if (*n == '.') {
4648 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4649 continue;
4653 if (n[0] == ':') {
4654 /* Temporary file used when creating a share. */
4655 num_tmp_dir_entries++;
4658 /* Allow 20% tmp entries. */
4659 if (num_tmp_dir_entries > allowed_tmp_entries) {
4660 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4661 "in directory %s\n",
4662 num_tmp_dir_entries, usersharepath));
4663 break;
4666 r = process_usershare_file(usersharepath, n, snum_template);
4667 if (r == 0) {
4668 /* Update the services count. */
4669 num_usershares++;
4670 if (num_usershares >= max_user_shares) {
4671 DEBUG(0,("load_usershare_shares: max user shares reached "
4672 "on file %s in directory %s\n",
4673 n, usersharepath ));
4674 break;
4676 } else if (r == -1) {
4677 num_bad_dir_entries++;
4680 /* Allow 20% bad entries. */
4681 if (num_bad_dir_entries > allowed_bad_entries) {
4682 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4683 "in directory %s\n",
4684 num_bad_dir_entries, usersharepath));
4685 break;
4688 /* Allow 20% bad entries. */
4689 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4690 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4691 "in directory %s\n",
4692 num_dir_entries, usersharepath));
4693 break;
4697 closedir(dp);
4699 /* Sweep through and delete any non-refreshed usershares that are
4700 not currently in use. */
4701 tmp_ctx = talloc_stackframe();
4702 for (iService = iNumServices - 1; iService >= 0; iService--) {
4703 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4704 char *servname;
4706 if (snumused && snumused(sconn, iService)) {
4707 continue;
4710 servname = lp_servicename(tmp_ctx, iService);
4712 /* Remove from the share ACL db. */
4713 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4714 servname ));
4715 delete_share_security(servname);
4716 free_service_byindex(iService);
4719 talloc_free(tmp_ctx);
4721 return lp_numservices();
4724 /********************************************************
4725 Destroy global resources allocated in this file
4726 ********************************************************/
4728 void gfree_loadparm(void)
4730 int i;
4732 free_file_list();
4734 /* Free resources allocated to services */
4736 for ( i = 0; i < iNumServices; i++ ) {
4737 if ( VALID(i) ) {
4738 free_service_byindex(i);
4742 SAFE_FREE( ServicePtrs );
4743 iNumServices = 0;
4745 /* Now release all resources allocated to global
4746 parameters and the default service */
4748 free_global_parameters();
4752 /***************************************************************************
4753 Allow client apps to specify that they are a client
4754 ***************************************************************************/
4755 static void lp_set_in_client(bool b)
4757 in_client = b;
4761 /***************************************************************************
4762 Determine if we're running in a client app
4763 ***************************************************************************/
4764 static bool lp_is_in_client(void)
4766 return in_client;
4769 /***************************************************************************
4770 Load the services array from the services file. Return true on success,
4771 false on failure.
4772 ***************************************************************************/
4774 static bool lp_load_ex(const char *pszFname,
4775 bool global_only,
4776 bool save_defaults,
4777 bool add_ipc,
4778 bool initialize_globals,
4779 bool allow_include_registry,
4780 bool load_all_shares)
4782 char *n2 = NULL;
4783 bool bRetval;
4785 bRetval = false;
4787 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4789 bInGlobalSection = true;
4790 bGlobalOnly = global_only;
4791 bAllowIncludeRegistry = allow_include_registry;
4793 init_globals(initialize_globals);
4795 free_file_list();
4797 if (save_defaults) {
4798 init_locals();
4799 lp_save_defaults();
4802 if (!initialize_globals) {
4803 free_param_opts(&Globals.param_opt);
4804 apply_lp_set_cmdline();
4807 lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4809 /* We get sections first, so have to start 'behind' to make up */
4810 iServiceIndex = -1;
4812 if (lp_config_backend_is_file()) {
4813 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4814 current_user_info.domain,
4815 pszFname);
4816 if (!n2) {
4817 smb_panic("lp_load_ex: out of memory");
4820 add_to_file_list(pszFname, n2);
4822 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4823 TALLOC_FREE(n2);
4825 /* finish up the last section */
4826 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4827 if (bRetval) {
4828 if (iServiceIndex >= 0) {
4829 bRetval = service_ok(iServiceIndex);
4833 if (lp_config_backend_is_registry()) {
4834 /* config backend changed to registry in config file */
4836 * We need to use this extra global variable here to
4837 * survive restart: init_globals uses this as a default
4838 * for ConfigBackend. Otherwise, init_globals would
4839 * send us into an endless loop here.
4841 config_backend = CONFIG_BACKEND_REGISTRY;
4842 /* start over */
4843 DEBUG(1, ("lp_load_ex: changing to config backend "
4844 "registry\n"));
4845 init_globals(true);
4846 lp_kill_all_services();
4847 return lp_load_ex(pszFname, global_only, save_defaults,
4848 add_ipc, initialize_globals,
4849 allow_include_registry,
4850 load_all_shares);
4852 } else if (lp_config_backend_is_registry()) {
4853 bRetval = process_registry_globals();
4854 } else {
4855 DEBUG(0, ("Illegal config backend given: %d\n",
4856 lp_config_backend()));
4857 bRetval = false;
4860 if (bRetval && lp_registry_shares()) {
4861 if (load_all_shares) {
4862 bRetval = process_registry_shares();
4863 } else {
4864 bRetval = reload_registry_shares();
4869 char *serv = lp_auto_services(talloc_tos());
4870 lp_add_auto_services(serv);
4871 TALLOC_FREE(serv);
4874 if (add_ipc) {
4875 /* When 'restrict anonymous = 2' guest connections to ipc$
4876 are denied */
4877 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4878 if ( lp_enable_asu_support() ) {
4879 lp_add_ipc("ADMIN$", false);
4883 set_allowed_client_auth();
4885 if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4886 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4887 lp_passwordserver()));
4890 bLoaded = true;
4892 /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4893 /* if bWINSsupport is true and we are in the client */
4894 if (lp_is_in_client() && Globals.bWINSsupport) {
4895 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4898 init_iconv();
4900 fault_configure(smb_panic_s3);
4902 bAllowIncludeRegistry = true;
4904 return (bRetval);
4907 bool lp_load(const char *pszFname,
4908 bool global_only,
4909 bool save_defaults,
4910 bool add_ipc,
4911 bool initialize_globals)
4913 return lp_load_ex(pszFname,
4914 global_only,
4915 save_defaults,
4916 add_ipc,
4917 initialize_globals,
4918 true, /* allow_include_registry */
4919 false); /* load_all_shares*/
4922 bool lp_load_initial_only(const char *pszFname)
4924 return lp_load_ex(pszFname,
4925 true, /* global only */
4926 false, /* save_defaults */
4927 false, /* add_ipc */
4928 true, /* initialize_globals */
4929 false, /* allow_include_registry */
4930 false); /* load_all_shares*/
4934 * most common lp_load wrapper, loading only the globals
4936 bool lp_load_global(const char *file_name)
4938 return lp_load_ex(file_name,
4939 true, /* global_only */
4940 false, /* save_defaults */
4941 false, /* add_ipc */
4942 true, /* initialize_globals */
4943 true, /* allow_include_registry */
4944 false); /* load_all_shares*/
4948 * lp_load wrapper, especially for clients
4950 bool lp_load_client(const char *file_name)
4952 lp_set_in_client(true);
4954 return lp_load_global(file_name);
4958 * lp_load wrapper, loading only globals, but intended
4959 * for subsequent calls, not reinitializing the globals
4960 * to default values
4962 bool lp_load_global_no_reinit(const char *file_name)
4964 return lp_load_ex(file_name,
4965 true, /* global_only */
4966 false, /* save_defaults */
4967 false, /* add_ipc */
4968 false, /* initialize_globals */
4969 true, /* allow_include_registry */
4970 false); /* load_all_shares*/
4974 * lp_load wrapper, especially for clients, no reinitialization
4976 bool lp_load_client_no_reinit(const char *file_name)
4978 lp_set_in_client(true);
4980 return lp_load_global_no_reinit(file_name);
4983 bool lp_load_with_registry_shares(const char *pszFname,
4984 bool global_only,
4985 bool save_defaults,
4986 bool add_ipc,
4987 bool initialize_globals)
4989 return lp_load_ex(pszFname,
4990 global_only,
4991 save_defaults,
4992 add_ipc,
4993 initialize_globals,
4994 true, /* allow_include_registry */
4995 true); /* load_all_shares*/
4998 /***************************************************************************
4999 Return the max number of services.
5000 ***************************************************************************/
5002 int lp_numservices(void)
5004 return (iNumServices);
5007 /***************************************************************************
5008 Display the contents of the services array in human-readable form.
5009 ***************************************************************************/
5011 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5013 int iService;
5015 if (show_defaults)
5016 defaults_saved = false;
5018 dump_globals(f);
5020 dump_a_service(&sDefault, f);
5022 for (iService = 0; iService < maxtoprint; iService++) {
5023 fprintf(f,"\n");
5024 lp_dump_one(f, show_defaults, iService);
5028 /***************************************************************************
5029 Display the contents of one service in human-readable form.
5030 ***************************************************************************/
5032 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5034 if (VALID(snum)) {
5035 if (ServicePtrs[snum]->szService[0] == '\0')
5036 return;
5037 dump_a_service(ServicePtrs[snum], f);
5041 /***************************************************************************
5042 Return the number of the service with the given name, or -1 if it doesn't
5043 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5044 getservicebyname()! This works ONLY if all services have been loaded, and
5045 does not copy the found service.
5046 ***************************************************************************/
5048 int lp_servicenumber(const char *pszServiceName)
5050 int iService;
5051 fstring serviceName;
5053 if (!pszServiceName) {
5054 return GLOBAL_SECTION_SNUM;
5057 for (iService = iNumServices - 1; iService >= 0; iService--) {
5058 if (VALID(iService) && ServicePtrs[iService]->szService) {
5060 * The substitution here is used to support %U is
5061 * service names
5063 fstrcpy(serviceName, ServicePtrs[iService]->szService);
5064 standard_sub_basic(get_current_username(),
5065 current_user_info.domain,
5066 serviceName,sizeof(serviceName));
5067 if (strequal(serviceName, pszServiceName)) {
5068 break;
5073 if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5074 struct timespec last_mod;
5076 if (!usershare_exists(iService, &last_mod)) {
5077 /* Remove the share security tdb entry for it. */
5078 delete_share_security(lp_servicename(talloc_tos(), iService));
5079 /* Remove it from the array. */
5080 free_service_byindex(iService);
5081 /* Doesn't exist anymore. */
5082 return GLOBAL_SECTION_SNUM;
5085 /* Has it been modified ? If so delete and reload. */
5086 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5087 &last_mod) < 0) {
5088 /* Remove it from the array. */
5089 free_service_byindex(iService);
5090 /* and now reload it. */
5091 iService = load_usershare_service(pszServiceName);
5095 if (iService < 0) {
5096 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5097 return GLOBAL_SECTION_SNUM;
5100 return (iService);
5103 /*******************************************************************
5104 A useful volume label function.
5105 ********************************************************************/
5107 const char *volume_label(TALLOC_CTX *ctx, int snum)
5109 char *ret;
5110 const char *label = lp_volume(ctx, snum);
5111 if (!*label) {
5112 label = lp_servicename(ctx, snum);
5115 /* This returns a 33 byte guarenteed null terminated string. */
5116 ret = talloc_strndup(ctx, label, 32);
5117 if (!ret) {
5118 return "";
5120 return ret;
5123 /*******************************************************************
5124 Get the default server type we will announce as via nmbd.
5125 ********************************************************************/
5127 int lp_default_server_announce(void)
5129 int default_server_announce = 0;
5130 default_server_announce |= SV_TYPE_WORKSTATION;
5131 default_server_announce |= SV_TYPE_SERVER;
5132 default_server_announce |= SV_TYPE_SERVER_UNIX;
5134 /* note that the flag should be set only if we have a
5135 printer service but nmbd doesn't actually load the
5136 services so we can't tell --jerry */
5138 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5140 default_server_announce |= SV_TYPE_SERVER_NT;
5141 default_server_announce |= SV_TYPE_NT;
5143 switch (lp_server_role()) {
5144 case ROLE_DOMAIN_MEMBER:
5145 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5146 break;
5147 case ROLE_DOMAIN_PDC:
5148 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5149 break;
5150 case ROLE_DOMAIN_BDC:
5151 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5152 break;
5153 case ROLE_STANDALONE:
5154 default:
5155 break;
5157 if (lp_time_server())
5158 default_server_announce |= SV_TYPE_TIME_SOURCE;
5160 if (lp_host_msdfs())
5161 default_server_announce |= SV_TYPE_DFS_SERVER;
5163 return default_server_announce;
5166 /***********************************************************
5167 If we are PDC then prefer us as DMB
5168 ************************************************************/
5170 bool lp_domain_master(void)
5172 if (Globals.domain_master == Auto)
5173 return (lp_server_role() == ROLE_DOMAIN_PDC);
5175 return (bool)Globals.domain_master;
5178 /***********************************************************
5179 If we are PDC then prefer us as DMB
5180 ************************************************************/
5182 static bool lp_domain_master_true_or_auto(void)
5184 if (Globals.domain_master) /* auto or yes */
5185 return true;
5187 return false;
5190 /***********************************************************
5191 If we are DMB then prefer us as LMB
5192 ************************************************************/
5194 bool lp_preferred_master(void)
5196 if (Globals.iPreferredMaster == Auto)
5197 return (lp_local_master() && lp_domain_master());
5199 return (bool)Globals.iPreferredMaster;
5202 /*******************************************************************
5203 Remove a service.
5204 ********************************************************************/
5206 void lp_remove_service(int snum)
5208 ServicePtrs[snum]->valid = false;
5209 invalid_services[num_invalid_services++] = snum;
5212 /*******************************************************************
5213 Copy a service.
5214 ********************************************************************/
5216 void lp_copy_service(int snum, const char *new_name)
5218 do_section(new_name, NULL);
5219 if (snum >= 0) {
5220 snum = lp_servicenumber(new_name);
5221 if (snum >= 0) {
5222 char *name = lp_servicename(talloc_tos(), snum);
5223 lp_do_parameter(snum, "copy", name);
5228 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5230 const char *ret = lp__printername(talloc_tos(), snum);
5231 if (ret == NULL || *ret == '\0') {
5232 ret = lp_const_servicename(snum);
5235 return ret;
5239 /***********************************************************
5240 Allow daemons such as winbindd to fix their logfile name.
5241 ************************************************************/
5243 void lp_set_logfile(const char *name)
5245 string_set(&Globals.logfile, name);
5246 debug_set_logfile(name);
5249 /*******************************************************************
5250 Return the max print jobs per queue.
5251 ********************************************************************/
5253 int lp_maxprintjobs(int snum)
5255 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5256 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5257 maxjobs = PRINT_MAX_JOBID - 1;
5259 return maxjobs;
5262 const char *lp_printcapname(void)
5264 if ((Globals.szPrintcapname != NULL) &&
5265 (Globals.szPrintcapname[0] != '\0'))
5266 return Globals.szPrintcapname;
5268 if (sDefault.iPrinting == PRINT_CUPS) {
5269 #ifdef HAVE_CUPS
5270 return "cups";
5271 #else
5272 return "lpstat";
5273 #endif
5276 if (sDefault.iPrinting == PRINT_BSD)
5277 return "/etc/printcap";
5279 return PRINTCAP_NAME;
5282 static uint32 spoolss_state;
5284 bool lp_disable_spoolss( void )
5286 if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5287 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5289 return spoolss_state == SVCCTL_STOPPED ? true : false;
5292 void lp_set_spoolss_state( uint32 state )
5294 SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5296 spoolss_state = state;
5299 uint32 lp_get_spoolss_state( void )
5301 return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5304 /*******************************************************************
5305 Ensure we don't use sendfile if server smb signing is active.
5306 ********************************************************************/
5308 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5310 bool sign_active = false;
5312 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5313 if (get_Protocol() < PROTOCOL_NT1) {
5314 return false;
5316 if (signing_state) {
5317 sign_active = smb_signing_is_active(signing_state);
5319 return (lp__use_sendfile(snum) &&
5320 (get_remote_arch() != RA_WIN95) &&
5321 !sign_active);
5324 /*******************************************************************
5325 Turn off sendfile if we find the underlying OS doesn't support it.
5326 ********************************************************************/
5328 void set_use_sendfile(int snum, bool val)
5330 if (LP_SNUM_OK(snum))
5331 ServicePtrs[snum]->bUseSendfile = val;
5332 else
5333 sDefault.bUseSendfile = val;
5336 /*******************************************************************
5337 Turn off storing DOS attributes if this share doesn't support it.
5338 ********************************************************************/
5340 void set_store_dos_attributes(int snum, bool val)
5342 if (!LP_SNUM_OK(snum))
5343 return;
5344 ServicePtrs[(snum)]->bStoreDosAttributes = val;
5347 void lp_set_mangling_method(const char *new_method)
5349 string_set(&Globals.szManglingMethod, new_method);
5352 /*******************************************************************
5353 Global state for POSIX pathname processing.
5354 ********************************************************************/
5356 static bool posix_pathnames;
5358 bool lp_posix_pathnames(void)
5360 return posix_pathnames;
5363 /*******************************************************************
5364 Change everything needed to ensure POSIX pathname processing (currently
5365 not much).
5366 ********************************************************************/
5368 void lp_set_posix_pathnames(void)
5370 posix_pathnames = true;
5373 /*******************************************************************
5374 Global state for POSIX lock processing - CIFS unix extensions.
5375 ********************************************************************/
5377 bool posix_default_lock_was_set;
5378 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5380 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5382 if (posix_default_lock_was_set) {
5383 return posix_cifsx_locktype;
5384 } else {
5385 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5389 /*******************************************************************
5390 ********************************************************************/
5392 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5394 posix_default_lock_was_set = true;
5395 posix_cifsx_locktype = val;
5398 int lp_min_receive_file_size(void)
5400 if (Globals.iminreceivefile < 0) {
5401 return 0;
5403 return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5406 /*******************************************************************
5407 Safe wide links checks.
5408 This helper function always verify the validity of wide links,
5409 even after a configuration file reload.
5410 ********************************************************************/
5412 static bool lp_widelinks_internal(int snum)
5414 return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5415 sDefault.bWidelinks);
5418 void widelinks_warning(int snum)
5420 if (lp_allow_insecure_widelinks()) {
5421 return;
5424 if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5425 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5426 "These parameters are incompatible. "
5427 "Wide links will be disabled for this share.\n",
5428 lp_servicename(talloc_tos(), snum) ));
5432 bool lp_widelinks(int snum)
5434 /* wide links is always incompatible with unix extensions */
5435 if (lp_unix_extensions()) {
5437 * Unless we have "allow insecure widelinks"
5438 * turned on.
5440 if (!lp_allow_insecure_widelinks()) {
5441 return false;
5445 return lp_widelinks_internal(snum);
5448 bool lp_writeraw(void)
5450 if (lp_async_smb_echo_handler()) {
5451 return false;
5453 return lp__writeraw();
5456 bool lp_readraw(void)
5458 if (lp_async_smb_echo_handler()) {
5459 return false;
5461 return lp__readraw();
5464 int lp_server_role(void)
5466 return lp_find_server_role(lp__server_role(),
5467 lp__security(),
5468 lp__domain_logons(),
5469 lp_domain_master_true_or_auto());
5472 int lp_security(void)
5474 return lp_find_security(lp__server_role(),
5475 lp__security());