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