e702420124666662b0a4e8d7e4be3e6cf1848fc3
[mat/samba.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
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
15
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.
20
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.
25
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/>.
28 */
29
30 /*
31  *  Load parameters.
32  *
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.
36  *
37  * To add a parameter:
38  *
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
44  *  
45  *
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!
53  *
54  */
55
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"
63
64 #include "ads.h"
65 #include "../librpc/gen_ndr/svcctl.h"
66 #include "intl.h"
67 #include "../libcli/smb/smb_signing.h"
68 #include "dbwrap/dbwrap.h"
69 #include "dbwrap/dbwrap_rbt.h"
70 #include "../lib/util/bitmap.h"
71
72 #ifdef HAVE_SYS_SYSCTL_H
73 #include <sys/sysctl.h>
74 #endif
75
76 #ifdef HAVE_HTTPCONNECTENCRYPT
77 #include <cups/http.h>
78 #endif
79
80 #ifdef CLUSTER_SUPPORT
81 #include "ctdb_private.h"
82 #endif
83
84 bool bLoaded = false;
85
86 extern userdom_struct current_user_info;
87
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
95
96 static bool in_client = false;          /* Not in the client by default */
97 static struct smbconf_csn conf_last_csn;
98
99 static int config_backend = CONFIG_BACKEND_FILE;
100
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)
104
105 #define USERSHARE_VALID 1
106 #define USERSHARE_PENDING_DELETE 2
107
108 static bool defaults_saved = false;
109
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;
136
137 #include "param/param_global.h"
138
139 static struct loadparm_global Globals;
140
141 /* This is a default service used to prime a services structure */
142 static struct loadparm_service sDefault =
143 {
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 = ""
284 };
285
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 bool bInGlobalSection = true;
292 static bool bGlobalOnly = false;
293
294 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
295
296 /* prototypes for the special type handlers */
297 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
298 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
299 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
300 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
301 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
302 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
303 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
304 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
305 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
306 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
307 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
308 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
309
310 /* these are parameter handlers which are not needed in the
311  * source3 code
312  */
313
314 #define handle_logfile NULL
315
316 static void set_allowed_client_auth(void);
317
318 static void add_to_file_list(const char *fname, const char *subfname);
319 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
320 static void free_param_opts(struct parmlist_entry **popts);
321
322 #include "lib/param/param_table.c"
323
324 /* this is used to prevent lots of mallocs of size 1 */
325 static const char null_string[] = "";
326
327 /**
328  Set a string value, allocing the space for the string
329 **/
330
331 static bool string_init(char **dest,const char *src)
332 {
333         size_t l;
334
335         if (!src)
336                 src = "";
337
338         l = strlen(src);
339
340         if (l == 0) {
341                 *dest = discard_const_p(char, null_string);
342         } else {
343                 (*dest) = SMB_STRDUP(src);
344                 if ((*dest) == NULL) {
345                         DEBUG(0,("Out of memory in string_init\n"));
346                         return false;
347                 }
348         }
349         return(true);
350 }
351
352 /**
353  Free a string value.
354 **/
355
356 static void string_free(char **s)
357 {
358         if (!s || !(*s))
359                 return;
360         if (*s == null_string)
361                 *s = NULL;
362         SAFE_FREE(*s);
363 }
364
365 /**
366  Set a string value, deallocating any existing space, and allocing the space
367  for the string
368 **/
369
370 static bool string_set(char **dest,const char *src)
371 {
372         string_free(dest);
373         return(string_init(dest,src));
374 }
375
376 /***************************************************************************
377  Initialise the sDefault parameter structure for the printer values.
378 ***************************************************************************/
379
380 static void init_printer_values(struct loadparm_service *pService)
381 {
382         /* choose defaults depending on the type of printing */
383         switch (pService->iPrinting) {
384                 case PRINT_BSD:
385                 case PRINT_AIX:
386                 case PRINT_LPRNT:
387                 case PRINT_LPROS2:
388                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
389                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
390                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
391                         break;
392
393                 case PRINT_LPRNG:
394                 case PRINT_PLP:
395                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
396                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
397                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
398                         string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
399                         string_set(&pService->szQueueresumecommand, "lpc start '%p'");
400                         string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
401                         string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
402                         break;
403
404                 case PRINT_CUPS:
405                 case PRINT_IPRINT:
406                         /* set the lpq command to contain the destination printer
407                            name only.  This is used by cups_queue_get() */
408                         string_set(&pService->szLpqcommand, "%p");
409                         string_set(&pService->szLprmcommand, "");
410                         string_set(&pService->szPrintcommand, "");
411                         string_set(&pService->szLppausecommand, "");
412                         string_set(&pService->szLpresumecommand, "");
413                         string_set(&pService->szQueuepausecommand, "");
414                         string_set(&pService->szQueueresumecommand, "");
415                         break;
416
417                 case PRINT_SYSV:
418                 case PRINT_HPUX:
419                         string_set(&pService->szLpqcommand, "lpstat -o%p");
420                         string_set(&pService->szLprmcommand, "cancel %p-%j");
421                         string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
422                         string_set(&pService->szQueuepausecommand, "disable %p");
423                         string_set(&pService->szQueueresumecommand, "enable %p");
424 #ifndef HPUX
425                         string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
426                         string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
427 #endif /* HPUX */
428                         break;
429
430                 case PRINT_QNX:
431                         string_set(&pService->szLpqcommand, "lpq -P%p");
432                         string_set(&pService->szLprmcommand, "lprm -P%p %j");
433                         string_set(&pService->szPrintcommand, "lp -r -P%p %s");
434                         break;
435
436 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
437
438         case PRINT_TEST:
439         case PRINT_VLP: {
440                 const char *tdbfile;
441                 TALLOC_CTX *tmp_ctx = talloc_stackframe();
442                 char *tmp;
443
444                 tdbfile = talloc_asprintf(
445                         tmp_ctx, "tdbfile=%s",
446                         lp_parm_const_string(-1, "vlp", "tdbfile",
447                                              "/tmp/vlp.tdb"));
448                 if (tdbfile == NULL) {
449                         tdbfile="tdbfile=/tmp/vlp.tdb";
450                 }
451
452                 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
453                                       tdbfile);
454                 string_set(&pService->szPrintcommand,
455                            tmp ? tmp : "vlp print %p %s");
456
457                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
458                                       tdbfile);
459                 string_set(&pService->szLpqcommand,
460                            tmp ? tmp : "vlp lpq %p");
461
462                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
463                                       tdbfile);
464                 string_set(&pService->szLprmcommand,
465                            tmp ? tmp : "vlp lprm %p %j");
466
467                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
468                                       tdbfile);
469                 string_set(&pService->szLppausecommand,
470                            tmp ? tmp : "vlp lppause %p %j");
471
472                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
473                                       tdbfile);
474                 string_set(&pService->szLpresumecommand,
475                            tmp ? tmp : "vlp lpresume %p %j");
476
477                 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
478                                       tdbfile);
479                 string_set(&pService->szQueuepausecommand,
480                            tmp ? tmp : "vlp queuepause %p");
481
482                 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
483                                       tdbfile);
484                 string_set(&pService->szQueueresumecommand,
485                            tmp ? tmp : "vlp queueresume %p");
486                 TALLOC_FREE(tmp_ctx);
487
488                 break;
489         }
490 #endif /* DEVELOPER */
491
492         }
493 }
494 /**
495  *  Function to return the default value for the maximum number of open
496  *  file descriptors permitted.  This function tries to consult the
497  *  kernel-level (sysctl) and ulimit (getrlimit()) values and goes
498  *  the smaller of those.
499  */
500 static int max_open_files(void)
501 {
502         int sysctl_max = MAX_OPEN_FILES;
503         int rlimit_max = MAX_OPEN_FILES;
504
505 #ifdef HAVE_SYSCTLBYNAME
506         {
507                 size_t size = sizeof(sysctl_max);
508                 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
509                              0);
510         }
511 #endif
512
513 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
514         {
515                 struct rlimit rl;
516
517                 ZERO_STRUCT(rl);
518
519                 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
520                         rlimit_max = rl.rlim_cur;
521
522 #if defined(RLIM_INFINITY)
523                 if(rl.rlim_cur == RLIM_INFINITY)
524                         rlimit_max = MAX_OPEN_FILES;
525 #endif
526         }
527 #endif
528
529         if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
530                 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
531                         "minimum Windows limit (%d)\n",
532                         sysctl_max,
533                         MIN_OPEN_FILES_WINDOWS));
534                 sysctl_max = MIN_OPEN_FILES_WINDOWS;
535         }
536
537         if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
538                 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
539                         "minimum Windows limit (%d)\n",
540                         rlimit_max,
541                         MIN_OPEN_FILES_WINDOWS));
542                 rlimit_max = MIN_OPEN_FILES_WINDOWS;
543         }
544
545         return MIN(sysctl_max, rlimit_max);
546 }
547
548 /**
549  * Common part of freeing allocated data for one parameter.
550  */
551 static void free_one_parameter_common(void *parm_ptr,
552                                       struct parm_struct parm)
553 {
554         if ((parm.type == P_STRING) ||
555             (parm.type == P_USTRING))
556         {
557                 string_free((char**)parm_ptr);
558         } else if (parm.type == P_LIST) {
559                 TALLOC_FREE(*((char***)parm_ptr));
560         }
561 }
562
563 /**
564  * Free the allocated data for one parameter for a share
565  * given as a service struct.
566  */
567 static void free_one_parameter(struct loadparm_service *service,
568                                struct parm_struct parm)
569 {
570         void *parm_ptr;
571
572         if (parm.p_class != P_LOCAL) {
573                 return;
574         }
575
576         parm_ptr = lp_parm_ptr(service, &parm);
577
578         free_one_parameter_common(parm_ptr, parm);
579 }
580
581 /**
582  * Free the allocated parameter data of a share given
583  * as a service struct.
584  */
585 static void free_parameters(struct loadparm_service *service)
586 {
587         uint32_t i;
588
589         for (i=0; parm_table[i].label; i++) {
590                 free_one_parameter(service, parm_table[i]);
591         }
592 }
593
594 /**
595  * Free the allocated data for one parameter for a given share
596  * specified by an snum.
597  */
598 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
599 {
600         void *parm_ptr;
601
602         if (snum < 0) {
603                 parm_ptr = lp_parm_ptr(NULL, &parm);
604         } else if (parm.p_class != P_LOCAL) {
605                 return;
606         } else {
607                 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
608         }
609
610         free_one_parameter_common(parm_ptr, parm);
611 }
612
613 /**
614  * Free the allocated parameter data for a share specified
615  * by an snum.
616  */
617 static void free_parameters_by_snum(int snum)
618 {
619         uint32_t i;
620
621         for (i=0; parm_table[i].label; i++) {
622                 free_one_parameter_by_snum(snum, parm_table[i]);
623         }
624 }
625
626 /**
627  * Free the allocated global parameters.
628  */
629 static void free_global_parameters(void)
630 {
631         free_param_opts(&Globals.param_opt);
632         free_parameters_by_snum(GLOBAL_SECTION_SNUM);
633         TALLOC_FREE(Globals.ctx);
634 }
635
636 static int map_parameter(const char *pszParmName);
637
638 struct lp_stored_option {
639         struct lp_stored_option *prev, *next;
640         const char *label;
641         const char *value;
642 };
643
644 static struct lp_stored_option *stored_options;
645
646 /*
647   save options set by lp_set_cmdline() into a list. This list is
648   re-applied when we do a globals reset, so that cmdline set options
649   are sticky across reloads of smb.conf
650  */
651 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
652 {
653         struct lp_stored_option *entry, *entry_next;
654         for (entry = stored_options; entry != NULL; entry = entry_next) {
655                 entry_next = entry->next;
656                 if (strcmp(pszParmName, entry->label) == 0) {
657                         DLIST_REMOVE(stored_options, entry);
658                         talloc_free(entry);
659                         break;
660                 }
661         }
662
663         entry = talloc(NULL, struct lp_stored_option);
664         if (!entry) {
665                 return false;
666         }
667
668         entry->label = talloc_strdup(entry, pszParmName);
669         if (!entry->label) {
670                 talloc_free(entry);
671                 return false;
672         }
673
674         entry->value = talloc_strdup(entry, pszParmValue);
675         if (!entry->value) {
676                 talloc_free(entry);
677                 return false;
678         }
679
680         DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
681
682         return true;
683 }
684
685 static bool apply_lp_set_cmdline(void)
686 {
687         struct lp_stored_option *entry = NULL;
688         for (entry = stored_options; entry != NULL; entry = entry->next) {
689                 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
690                         DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
691                                   entry->label, entry->value));
692                         return false;
693                 }
694         }
695         return true;
696 }
697
698 /***************************************************************************
699  Initialise the global parameter structure.
700 ***************************************************************************/
701
702 static void init_globals(bool reinit_globals)
703 {
704         static bool done_init = false;
705         char *s = NULL;
706         int i;
707
708         /* If requested to initialize only once and we've already done it... */
709         if (!reinit_globals && done_init) {
710                 /* ... then we have nothing more to do */
711                 return;
712         }
713
714         if (!done_init) {
715                 /* The logfile can be set before this is invoked. Free it if so. */
716                 if (Globals.logfile != NULL) {
717                         string_free(&Globals.logfile);
718                         Globals.logfile = NULL;
719                 }
720                 done_init = true;
721         } else {
722                 free_global_parameters();
723         }
724
725         /* This memset and the free_global_parameters() above will
726          * wipe out smb.conf options set with lp_set_cmdline().  The
727          * apply_lp_set_cmdline() call puts these values back in the
728          * table once the defaults are set */
729         ZERO_STRUCT(Globals);
730
731         Globals.ctx = talloc_new(NULL);
732
733         for (i = 0; parm_table[i].label; i++) {
734                 if ((parm_table[i].type == P_STRING ||
735                      parm_table[i].type == P_USTRING))
736                 {
737                         string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
738                 }
739         }
740
741
742         string_set(&sDefault.fstype, FSTYPE_STRING);
743         string_set(&sDefault.szPrintjobUsername, "%U");
744
745         init_printer_values(&sDefault);
746
747
748         DEBUG(3, ("Initialising global parameters\n"));
749
750         /* Must manually force to upper case here, as this does not go via the handler */
751         string_set(&Globals.szNetbiosName, myhostname_upper());
752
753         string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
754         string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
755
756         /* use the new 'hash2' method by default, with a prefix of 1 */
757         string_set(&Globals.szManglingMethod, "hash2");
758         Globals.mangle_prefix = 1;
759
760         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
761
762         /* using UTF8 by default allows us to support all chars */
763         string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
764
765         /* Use codepage 850 as a default for the dos character set */
766         string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
767
768         /*
769          * Allow the default PASSWD_CHAT to be overridden in local.h.
770          */
771         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
772
773         string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
774
775         string_set(&Globals.szPasswdProgram, "");
776         string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
777         string_set(&Globals.szStateDir, get_dyn_STATEDIR());
778         string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
779         string_set(&Globals.szPidDir, get_dyn_PIDDIR());
780         string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
781         /*
782          * By default support explicit binding to broadcast
783          * addresses.
784          */
785         Globals.bNmbdBindExplicitBroadcast = true;
786
787         if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
788                 smb_panic("init_globals: ENOMEM");
789         }
790         string_set(&Globals.szServerString, s);
791         SAFE_FREE(s);
792 #ifdef DEVELOPER
793         string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
794 #endif
795
796         string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
797
798         string_set(&Globals.szLogonDrive, "");
799         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
800         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
801         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
802
803         Globals.szNameResolveOrder = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
804         string_set(&Globals.szPasswordServer, "*");
805
806         Globals.AlgorithmicRidBase = BASE_RID;
807
808         Globals.bLoadPrinters = true;
809         Globals.PrintcapCacheTime = 750;        /* 12.5 minutes */
810
811         Globals.ConfigBackend = config_backend;
812         Globals.server_role = ROLE_AUTO;
813
814         /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
815         /* Discovered by 2 days of pain by Don McCall @ HP :-). */
816         Globals.max_xmit = 0x4104;
817         Globals.max_mux = 50;   /* This is *needed* for profile support. */
818         Globals.lpqcachetime = 30;      /* changed to handle large print servers better -- jerry */
819         Globals.bDisableSpoolss = false;
820         Globals.iMaxSmbdProcesses = 0;/* no limit specified */
821         Globals.unamelevel = 0;
822         Globals.deadtime = 0;
823         Globals.getwd_cache = true;
824         Globals.bLargeReadwrite = true;
825         Globals.max_log_size = 5000;
826         Globals.max_open_files = max_open_files();
827         Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
828         Globals.srv_maxprotocol = PROTOCOL_SMB3_00;
829         Globals.srv_minprotocol = PROTOCOL_LANMAN1;
830         Globals.cli_maxprotocol = PROTOCOL_NT1;
831         Globals.cli_minprotocol = PROTOCOL_CORE;
832         Globals.security = SEC_USER;
833         Globals.bEncryptPasswords = true;
834         Globals.clientSchannel = Auto;
835         Globals.serverSchannel = Auto;
836         Globals.bReadRaw = true;
837         Globals.bWriteRaw = true;
838         Globals.bNullPasswords = false;
839         Globals.bObeyPamRestrictions = false;
840         Globals.syslog = 1;
841         Globals.bSyslogOnly = false;
842         Globals.bTimestampLogs = true;
843         string_set(&Globals.loglevel, "0");
844         Globals.bDebugPrefixTimestamp = false;
845         Globals.bDebugHiresTimestamp = true;
846         Globals.bDebugPid = false;
847         Globals.bDebugUid = false;
848         Globals.bDebugClass = false;
849         Globals.bEnableCoreFiles = true;
850         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
851         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
852         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
853         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
854         Globals.lm_announce = Auto;     /* = Auto: send only if LM clients found */
855         Globals.lm_interval = 60;
856 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
857         Globals.bNISHomeMap = false;
858 #ifdef WITH_NISPLUS_HOME
859         string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
860 #else
861         string_set(&Globals.szNISHomeMapName, "auto.home");
862 #endif
863 #endif
864         Globals.bTimeServer = false;
865         Globals.bBindInterfacesOnly = false;
866         Globals.bUnixPasswdSync = false;
867         Globals.bPamPasswordChange = false;
868         Globals.bPasswdChatDebug = false;
869         Globals.iPasswdChatTimeout = 2; /* 2 second default. */
870         Globals.bNTPipeSupport = true;  /* Do NT pipes by default. */
871         Globals.bNTStatusSupport = true; /* Use NT status by default. */
872         Globals.bStatCache = true;      /* use stat cache by default */
873         Globals.iMaxStatCacheSize = 256; /* 256k by default */
874         Globals.restrict_anonymous = 0;
875         Globals.bClientLanManAuth = false;      /* Do NOT use the LanMan hash if it is available */
876         Globals.bClientPlaintextAuth = false;   /* Do NOT use a plaintext password even if is requested by the server */
877         Globals.bLanmanAuth = false;    /* Do NOT use the LanMan hash, even if it is supplied */
878         Globals.bNTLMAuth = true;       /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
879         Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
880         /* Note, that we will also use NTLM2 session security (which is different), if it is available */
881
882         Globals.map_to_guest = 0;       /* By Default, "Never" */
883         Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
884         Globals.enhanced_browsing = true;
885         Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
886 #ifdef MMAP_BLACKLIST
887         Globals.bUseMmap = false;
888 #else
889         Globals.bUseMmap = true;
890 #endif
891         Globals.bUnicode = true;
892         Globals.bUnixExtensions = true;
893         Globals.bResetOnZeroVC = false;
894         Globals.bLogWriteableFilesOnExit = false;
895         Globals.bCreateKrb5Conf = true;
896         Globals.winbindMaxDomainConnections = 1;
897
898         /* hostname lookups can be very expensive and are broken on
899            a large number of sites (tridge) */
900         Globals.bHostnameLookups = false;
901
902         string_set(&Globals.passdb_backend, "tdbsam");
903         string_set(&Globals.szLdapSuffix, "");
904         string_set(&Globals.szLdapMachineSuffix, "");
905         string_set(&Globals.szLdapUserSuffix, "");
906         string_set(&Globals.szLdapGroupSuffix, "");
907         string_set(&Globals.szLdapIdmapSuffix, "");
908
909         string_set(&Globals.szLdapAdminDn, "");
910         Globals.ldap_ssl = LDAP_SSL_START_TLS;
911         Globals.ldap_ssl_ads = false;
912         Globals.ldap_deref = -1;
913         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
914         Globals.ldap_delete_dn = false;
915         Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
916         Globals.ldap_follow_referral = Auto;
917         Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
918         Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
919         Globals.ldap_page_size = LDAP_PAGE_SIZE;
920
921         Globals.ldap_debug_level = 0;
922         Globals.ldap_debug_threshold = 10;
923
924         /* This is what we tell the afs client. in reality we set the token 
925          * to never expire, though, when this runs out the afs client will 
926          * forget the token. Set to 0 to get NEVERDATE.*/
927         Globals.iAfsTokenLifetime = 604800;
928         Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
929
930 /* these parameters are set to defaults that are more appropriate
931    for the increasing samba install base:
932
933    as a member of the workgroup, that will possibly become a
934    _local_ master browser (lm = true).  this is opposed to a forced
935    local master browser startup (pm = true).
936
937    doesn't provide WINS server service by default (wsupp = false),
938    and doesn't provide domain master browser services by default, either.
939
940 */
941
942         Globals.bMsAddPrinterWizard = true;
943         Globals.os_level = 20;
944         Globals.bLocalMaster = true;
945         Globals.domain_master = Auto;   /* depending on bDomainLogons */
946         Globals.bDomainLogons = false;
947         Globals.bBrowseList = true;
948         Globals.bWINSsupport = false;
949         Globals.bWINSproxy = false;
950
951         TALLOC_FREE(Globals.szInitLogonDelayedHosts);
952         Globals.InitLogonDelay = 100; /* 100 ms default delay */
953
954         Globals.bWINSdnsProxy = true;
955
956         Globals.bAllowTrustedDomains = true;
957         string_set(&Globals.szIdmapBackend, "tdb");
958
959         string_set(&Globals.szTemplateShell, "/bin/false");
960         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
961         string_set(&Globals.szWinbindSeparator, "\\");
962
963         string_set(&Globals.szCupsServer, "");
964         string_set(&Globals.szIPrintServer, "");
965
966 #ifdef CLUSTER_SUPPORT
967         string_set(&Globals.ctdbdSocket, CTDB_PATH);
968 #else
969         string_set(&Globals.ctdbdSocket, "");
970 #endif
971
972         Globals.szClusterAddresses = NULL;
973         Globals.clustering = false;
974         Globals.ctdb_timeout = 0;
975         Globals.ctdb_locktime_warn_threshold = 0;
976
977         Globals.winbind_cache_time = 300;       /* 5 minutes */
978         Globals.winbind_reconnect_delay = 30;   /* 30 seconds */
979         Globals.winbind_max_clients = 200;
980         Globals.bWinbindEnumUsers = false;
981         Globals.bWinbindEnumGroups = false;
982         Globals.bWinbindUseDefaultDomain = false;
983         Globals.bWinbindTrustedDomainsOnly = false;
984         Globals.bWinbindNestedGroups = true;
985         Globals.winbind_expand_groups = 1;
986         Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
987         Globals.bWinbindRefreshTickets = false;
988         Globals.bWinbindOfflineLogon = false;
989
990         Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
991         Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
992
993         Globals.bPassdbExpandExplicit = false;
994
995         Globals.name_cache_timeout = 660; /* In seconds */
996
997         Globals.bUseSpnego = true;
998         Globals.bClientUseSpnego = true;
999
1000         Globals.client_signing = SMB_SIGNING_DEFAULT;
1001         Globals.server_signing = SMB_SIGNING_DEFAULT;
1002
1003         Globals.bDeferSharingViolations = true;
1004         Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
1005
1006         Globals.bEnablePrivileges = true;
1007         Globals.bHostMSDfs        = true;
1008         Globals.bASUSupport       = false;
1009
1010         /* User defined shares. */
1011         if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
1012                 smb_panic("init_globals: ENOMEM");
1013         }
1014         string_set(&Globals.szUsersharePath, s);
1015         SAFE_FREE(s);
1016         string_set(&Globals.szUsershareTemplateShare, "");
1017         Globals.iUsershareMaxShares = 0;
1018         /* By default disallow sharing of directories not owned by the sharer. */
1019         Globals.bUsershareOwnerOnly = true;
1020         /* By default disallow guest access to usershares. */
1021         Globals.bUsershareAllowGuests = false;
1022
1023         Globals.iKeepalive = DEFAULT_KEEPALIVE;
1024
1025         /* By default no shares out of the registry */
1026         Globals.bRegistryShares = false;
1027
1028         Globals.iminreceivefile = 0;
1029
1030         Globals.bMapUntrustedToDomain = false;
1031         Globals.bMulticastDnsRegister = true;
1032
1033         Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
1034         Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
1035         Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
1036         Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1037
1038         string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1039
1040         /* Now put back the settings that were set with lp_set_cmdline() */
1041         apply_lp_set_cmdline();
1042 }
1043
1044 /*******************************************************************
1045  Convenience routine to grab string parameters into talloced memory
1046  and run standard_sub_basic on them. The buffers can be written to by
1047  callers without affecting the source string.
1048 ********************************************************************/
1049
1050 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1051 {
1052         char *ret;
1053
1054         /* The follow debug is useful for tracking down memory problems
1055            especially if you have an inner loop that is calling a lp_*()
1056            function that returns a string.  Perhaps this debug should be
1057            present all the time? */
1058
1059 #if 0
1060         DEBUG(10, ("lp_string(%s)\n", s));
1061 #endif
1062         if (!s) {
1063                 return NULL;
1064         }
1065
1066         ret = talloc_sub_basic(ctx,
1067                         get_current_username(),
1068                         current_user_info.domain,
1069                         s);
1070         if (trim_char(ret, '\"', '\"')) {
1071                 if (strchr(ret,'\"') != NULL) {
1072                         TALLOC_FREE(ret);
1073                         ret = talloc_sub_basic(ctx,
1074                                         get_current_username(),
1075                                         current_user_info.domain,
1076                                         s);
1077                 }
1078         }
1079         return ret;
1080 }
1081
1082 /*
1083    In this section all the functions that are used to access the
1084    parameters from the rest of the program are defined
1085 */
1086
1087 #define FN_GLOBAL_STRING(fn_name,ptr) \
1088 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1089 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1090  const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1091 #define FN_GLOBAL_LIST(fn_name,ptr) \
1092  const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1093 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1094  bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1095 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1096  char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1097 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1098  int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1099
1100 #define FN_LOCAL_STRING(fn_name,val) \
1101 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));}
1102 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1103  const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1104 #define FN_LOCAL_LIST(fn_name,val) \
1105  const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1106 #define FN_LOCAL_BOOL(fn_name,val) \
1107  bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1108 #define FN_LOCAL_INTEGER(fn_name,val) \
1109  int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1110
1111 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1112  bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1113 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1114  int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1115 #define FN_LOCAL_CHAR(fn_name,val) \
1116  char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1117
1118
1119 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1120 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1121
1122 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1123  * build process or in smb.conf, we use that value.  Otherwise they
1124  * default to the value of lp_lockdir(). */
1125 const char *lp_statedir(void) {
1126         if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1127             (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1128                 return(*(char **)(&Globals.szStateDir) ?
1129                        *(char **)(&Globals.szStateDir) : "");
1130         else
1131                 return(*(char **)(&Globals.szLockDir) ?
1132                        *(char **)(&Globals.szLockDir) : "");
1133 }
1134 const char *lp_cachedir(void) {
1135         if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1136             (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1137                 return(*(char **)(&Globals.szCacheDir) ?
1138                        *(char **)(&Globals.szCacheDir) : "");
1139         else
1140                 return(*(char **)(&Globals.szLockDir) ?
1141                        *(char **)(&Globals.szLockDir) : "");
1142 }
1143 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1144                   winbindMaxDomainConnections)
1145
1146 int lp_winbind_max_domain_connections(void)
1147 {
1148         if (lp_winbind_offline_logon() &&
1149             lp_winbind_max_domain_connections_int() > 1) {
1150                 DEBUG(1, ("offline logons active, restricting max domain "
1151                           "connections to 1\n"));
1152                 return 1;
1153         }
1154         return MAX(1, lp_winbind_max_domain_connections_int());
1155 }
1156
1157 int lp_smb2_max_credits(void)
1158 {
1159         if (Globals.ismb2_max_credits == 0) {
1160                 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1161         }
1162         return Globals.ismb2_max_credits;
1163 }
1164 int lp_cups_encrypt(void)
1165 {
1166         int result = 0;
1167 #ifdef HAVE_HTTPCONNECTENCRYPT
1168         switch (Globals.CupsEncrypt) {
1169                 case Auto:
1170                         result = HTTP_ENCRYPT_REQUIRED;
1171                         break;
1172                 case true:
1173                         result = HTTP_ENCRYPT_ALWAYS;
1174                         break;
1175                 case false:
1176                         result = HTTP_ENCRYPT_NEVER;
1177                         break;
1178         }
1179 #endif
1180         return result;
1181 }
1182
1183 /* These functions remain in source3/param for now */
1184
1185 FN_GLOBAL_STRING(configfile, szConfigFile)
1186
1187 #include "lib/param/param_functions.c"
1188
1189 FN_LOCAL_STRING(servicename, szService)
1190 FN_LOCAL_CONST_STRING(const_servicename, szService)
1191
1192 /* local prototypes */
1193
1194 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1195 static const char *get_boolean(bool bool_value);
1196 static int getservicebyname(const char *pszServiceName,
1197                             struct loadparm_service *pserviceDest);
1198 static void copy_service(struct loadparm_service *pserviceDest,
1199                          struct loadparm_service *pserviceSource,
1200                          struct bitmap *pcopymapDest);
1201 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1202                          void *userdata);
1203 static bool do_section(const char *pszSectionName, void *userdata);
1204 static void init_copymap(struct loadparm_service *pservice);
1205 static bool hash_a_service(const char *name, int number);
1206 static void free_service_byindex(int iService);
1207 static void show_parameter(int parmIndex);
1208 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1209
1210 /*
1211  * This is a helper function for parametrical options support.  It returns a
1212  * pointer to parametrical option value if it exists or NULL otherwise. Actual
1213  * parametrical functions are quite simple
1214  */
1215 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1216                                                            const char *option)
1217 {
1218         bool global_section = false;
1219         char* param_key;
1220         struct parmlist_entry *data;
1221
1222         if (service == NULL) {
1223                 data = Globals.param_opt;
1224                 global_section = true;
1225         } else {
1226                 data = service->param_opt;
1227         }
1228
1229         if (asprintf(&param_key, "%s:%s", type, option) == -1) {
1230                 DEBUG(0,("asprintf failed!\n"));
1231                 return NULL;
1232         }
1233
1234         while (data) {
1235                 if (strwicmp(data->key, param_key) == 0) {
1236                         string_free(&param_key);
1237                         return data;
1238                 }
1239                 data = data->next;
1240         }
1241
1242         if (!global_section) {
1243                 /* Try to fetch the same option but from globals */
1244                 /* but only if we are not already working with Globals */
1245                 data = Globals.param_opt;
1246                 while (data) {
1247                         if (strwicmp(data->key, param_key) == 0) {
1248                                 string_free(&param_key);
1249                                 return data;
1250                         }
1251                         data = data->next;
1252                 }
1253         }
1254
1255         string_free(&param_key);
1256
1257         return NULL;
1258 }
1259
1260 /*
1261  * This is a helper function for parametrical options support.  It returns a
1262  * pointer to parametrical option value if it exists or NULL otherwise. Actual
1263  * parametrical functions are quite simple
1264  */
1265 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1266                                                 const char *option)
1267 {
1268         if (snum >= iNumServices) return NULL;
1269
1270         if (snum < 0) {
1271                 return get_parametrics_by_service(NULL, type, option);
1272         } else {
1273                 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1274         }
1275 }
1276
1277
1278 #define MISSING_PARAMETER(name) \
1279     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1280
1281 /*******************************************************************
1282 convenience routine to return int parameters.
1283 ********************************************************************/
1284 static int lp_int(const char *s)
1285 {
1286
1287         if (!s || !*s) {
1288                 MISSING_PARAMETER(lp_int);
1289                 return (-1);
1290         }
1291
1292         return (int)strtol(s, NULL, 0);
1293 }
1294
1295 /*******************************************************************
1296 convenience routine to return unsigned long parameters.
1297 ********************************************************************/
1298 static unsigned long lp_ulong(const char *s)
1299 {
1300
1301         if (!s || !*s) {
1302                 MISSING_PARAMETER(lp_ulong);
1303                 return (0);
1304         }
1305
1306         return strtoul(s, NULL, 0);
1307 }
1308
1309 /*******************************************************************
1310 convenience routine to return boolean parameters.
1311 ********************************************************************/
1312 static bool lp_bool(const char *s)
1313 {
1314         bool ret = false;
1315
1316         if (!s || !*s) {
1317                 MISSING_PARAMETER(lp_bool);
1318                 return false;
1319         }
1320
1321         if (!set_boolean(s, &ret)) {
1322                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1323                 return false;
1324         }
1325
1326         return ret;
1327 }
1328
1329 /*******************************************************************
1330 convenience routine to return enum parameters.
1331 ********************************************************************/
1332 static int lp_enum(const char *s,const struct enum_list *_enum)
1333 {
1334         int i;
1335
1336         if (!s || !*s || !_enum) {
1337                 MISSING_PARAMETER(lp_enum);
1338                 return (-1);
1339         }
1340
1341         for (i=0; _enum[i].name; i++) {
1342                 if (strequal(_enum[i].name,s))
1343                         return _enum[i].value;
1344         }
1345
1346         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1347         return (-1);
1348 }
1349
1350 #undef MISSING_PARAMETER
1351
1352 /* Return parametric option from a given service. Type is a part of option before ':' */
1353 /* Parametric option has following syntax: 'Type: option = value' */
1354 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1355 {
1356         struct parmlist_entry *data = get_parametrics(snum, type, option);
1357
1358         if (data == NULL||data->value==NULL) {
1359                 if (def) {
1360                         return lp_string(ctx, def);
1361                 } else {
1362                         return NULL;
1363                 }
1364         }
1365
1366         return lp_string(ctx, data->value);
1367 }
1368
1369 /* Return parametric option from a given service. Type is a part of option before ':' */
1370 /* Parametric option has following syntax: 'Type: option = value' */
1371 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1372 {
1373         struct parmlist_entry *data = get_parametrics(snum, type, option);
1374
1375         if (data == NULL||data->value==NULL)
1376                 return def;
1377
1378         return data->value;
1379 }
1380
1381 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1382 {
1383         struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1384
1385         if (data == NULL||data->value==NULL)
1386                 return NULL;
1387
1388         return data->value;
1389 }
1390
1391
1392 /* Return parametric option from a given service. Type is a part of option before ':' */
1393 /* Parametric option has following syntax: 'Type: option = value' */
1394
1395 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1396 {
1397         struct parmlist_entry *data = get_parametrics(snum, type, option);
1398
1399         if (data == NULL||data->value==NULL)
1400                 return (const char **)def;
1401
1402         if (data->list==NULL) {
1403                 data->list = str_list_make_v3(NULL, data->value, NULL);
1404         }
1405
1406         return (const char **)data->list;
1407 }
1408
1409 /* Return parametric option from a given service. Type is a part of option before ':' */
1410 /* Parametric option has following syntax: 'Type: option = value' */
1411
1412 int lp_parm_int(int snum, const char *type, const char *option, int def)
1413 {
1414         struct parmlist_entry *data = get_parametrics(snum, type, option);
1415
1416         if (data && data->value && *data->value)
1417                 return lp_int(data->value);
1418
1419         return def;
1420 }
1421
1422 /* Return parametric option from a given service. Type is a part of option before ':' */
1423 /* Parametric option has following syntax: 'Type: option = value' */
1424
1425 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1426 {
1427         struct parmlist_entry *data = get_parametrics(snum, type, option);
1428
1429         if (data && data->value && *data->value)
1430                 return lp_ulong(data->value);
1431
1432         return def;
1433 }
1434
1435 /* Return parametric option from a given service. Type is a part of option before ':' */
1436 /* Parametric option has following syntax: 'Type: option = value' */
1437
1438 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1439 {
1440         struct parmlist_entry *data = get_parametrics(snum, type, option);
1441
1442         if (data && data->value && *data->value)
1443                 return lp_bool(data->value);
1444
1445         return def;
1446 }
1447
1448 /* Return parametric option from a given service. Type is a part of option before ':' */
1449 /* Parametric option has following syntax: 'Type: option = value' */
1450
1451 int lp_parm_enum(int snum, const char *type, const char *option,
1452                  const struct enum_list *_enum, int def)
1453 {
1454         struct parmlist_entry *data = get_parametrics(snum, type, option);
1455
1456         if (data && data->value && *data->value && _enum)
1457                 return lp_enum(data->value, _enum);
1458
1459         return def;
1460 }
1461
1462
1463 /***************************************************************************
1464  Initialise a service to the defaults.
1465 ***************************************************************************/
1466
1467 static void init_service(struct loadparm_service *pservice)
1468 {
1469         memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1470         copy_service(pservice, &sDefault, NULL);
1471 }
1472
1473
1474 /**
1475  * free a param_opts structure.
1476  * param_opts handling should be moved to talloc;
1477  * then this whole functions reduces to a TALLOC_FREE().
1478  */
1479
1480 static void free_param_opts(struct parmlist_entry **popts)
1481 {
1482         struct parmlist_entry *opt, *next_opt;
1483
1484         if (*popts != NULL) {
1485                 DEBUG(5, ("Freeing parametrics:\n"));
1486         }
1487         opt = *popts;
1488         while (opt != NULL) {
1489                 string_free(&opt->key);
1490                 string_free(&opt->value);
1491                 TALLOC_FREE(opt->list);
1492                 next_opt = opt->next;
1493                 SAFE_FREE(opt);
1494                 opt = next_opt;
1495         }
1496         *popts = NULL;
1497 }
1498
1499 /***************************************************************************
1500  Free the dynamically allocated parts of a service struct.
1501 ***************************************************************************/
1502
1503 static void free_service(struct loadparm_service *pservice)
1504 {
1505         if (!pservice)
1506                 return;
1507
1508         if (pservice->szService)
1509                 DEBUG(5, ("free_service: Freeing service %s\n",
1510                        pservice->szService));
1511
1512         free_parameters(pservice);
1513
1514         string_free(&pservice->szService);
1515         TALLOC_FREE(pservice->copymap);
1516
1517         free_param_opts(&pservice->param_opt);
1518
1519         ZERO_STRUCTP(pservice);
1520 }
1521
1522
1523 /***************************************************************************
1524  remove a service indexed in the ServicePtrs array from the ServiceHash
1525  and free the dynamically allocated parts
1526 ***************************************************************************/
1527
1528 static void free_service_byindex(int idx)
1529 {
1530         if ( !LP_SNUM_OK(idx) ) 
1531                 return;
1532
1533         ServicePtrs[idx]->valid = false;
1534
1535         /* we have to cleanup the hash record */
1536
1537         if (ServicePtrs[idx]->szService) {
1538                 char *canon_name = canonicalize_servicename(
1539                         talloc_tos(),
1540                         ServicePtrs[idx]->szService );
1541
1542                 dbwrap_delete_bystring(ServiceHash, canon_name );
1543                 TALLOC_FREE(canon_name);
1544         }
1545
1546         free_service(ServicePtrs[idx]);
1547         talloc_free_children(ServicePtrs[idx]);
1548 }
1549
1550 /***************************************************************************
1551  Add a new service to the services array initialising it with the given 
1552  service. 
1553 ***************************************************************************/
1554
1555 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1556 {
1557         int i;
1558         struct loadparm_service tservice;
1559         int num_to_alloc = iNumServices + 1;
1560         struct loadparm_service **tsp = NULL;
1561
1562         tservice = *pservice;
1563
1564         /* it might already exist */
1565         if (name) {
1566                 i = getservicebyname(name, NULL);
1567                 if (i >= 0) {
1568                         return (i);
1569                 }
1570         }
1571
1572         /* if not, then create one */
1573         i = iNumServices;
1574         tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1575         if (tsp == NULL) {
1576                 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1577                 return (-1);
1578         }
1579         ServicePtrs = tsp;
1580         ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1581         if (!ServicePtrs[iNumServices]) {
1582                 DEBUG(0,("add_a_service: out of memory!\n"));
1583                 return (-1);
1584         }
1585         iNumServices++;
1586
1587         ServicePtrs[i]->valid = true;
1588
1589         init_service(ServicePtrs[i]);
1590         copy_service(ServicePtrs[i], &tservice, NULL);
1591         if (name)
1592                 string_set(&ServicePtrs[i]->szService, name);
1593
1594         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
1595                 i, ServicePtrs[i]->szService));
1596
1597         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1598                 return (-1);
1599         }
1600
1601         return (i);
1602 }
1603
1604 /***************************************************************************
1605   Convert a string to uppercase and remove whitespaces.
1606 ***************************************************************************/
1607
1608 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1609 {
1610         char *result;
1611
1612         if ( !src ) {
1613                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1614                 return NULL;
1615         }
1616
1617         result = talloc_strdup(ctx, src);
1618         SMB_ASSERT(result != NULL);
1619
1620         if (!strlower_m(result)) {
1621                 TALLOC_FREE(result);
1622                 return NULL;
1623         }
1624         return result;
1625 }
1626
1627 /***************************************************************************
1628   Add a name/index pair for the services array to the hash table.
1629 ***************************************************************************/
1630
1631 static bool hash_a_service(const char *name, int idx)
1632 {
1633         char *canon_name;
1634
1635         if ( !ServiceHash ) {
1636                 DEBUG(10,("hash_a_service: creating servicehash\n"));
1637                 ServiceHash = db_open_rbt(NULL);
1638                 if ( !ServiceHash ) {
1639                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1640                         return false;
1641                 }
1642         }
1643
1644         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1645                 idx, name));
1646
1647         canon_name = canonicalize_servicename(talloc_tos(), name );
1648
1649         dbwrap_store_bystring(ServiceHash, canon_name,
1650                               make_tdb_data((uint8 *)&idx, sizeof(idx)),
1651                               TDB_REPLACE);
1652
1653         TALLOC_FREE(canon_name);
1654
1655         return true;
1656 }
1657
1658 /***************************************************************************
1659  Add a new home service, with the specified home directory, defaults coming
1660  from service ifrom.
1661 ***************************************************************************/
1662
1663 bool lp_add_home(const char *pszHomename, int iDefaultService,
1664                  const char *user, const char *pszHomedir)
1665 {
1666         int i;
1667
1668         if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1669                         pszHomedir[0] == '\0') {
1670                 return false;
1671         }
1672
1673         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1674
1675         if (i < 0)
1676                 return false;
1677
1678         if (!(*(ServicePtrs[iDefaultService]->szPath))
1679             || strequal(ServicePtrs[iDefaultService]->szPath,
1680                         lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1681                 string_set(&ServicePtrs[i]->szPath, pszHomedir);
1682         }
1683
1684         if (!(*(ServicePtrs[i]->comment))) {
1685                 char *comment = NULL;
1686                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1687                         return false;
1688                 }
1689                 string_set(&ServicePtrs[i]->comment, comment);
1690                 SAFE_FREE(comment);
1691         }
1692
1693         /* set the browseable flag from the global default */
1694
1695         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1696         ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
1697
1698         ServicePtrs[i]->autoloaded = true;
1699
1700         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
1701                user, ServicePtrs[i]->szPath ));
1702
1703         return true;
1704 }
1705
1706 /***************************************************************************
1707  Add a new service, based on an old one.
1708 ***************************************************************************/
1709
1710 int lp_add_service(const char *pszService, int iDefaultService)
1711 {
1712         if (iDefaultService < 0) {
1713                 return add_a_service(&sDefault, pszService);
1714         }
1715
1716         return (add_a_service(ServicePtrs[iDefaultService], pszService));
1717 }
1718
1719 /***************************************************************************
1720  Add the IPC service.
1721 ***************************************************************************/
1722
1723 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1724 {
1725         char *comment = NULL;
1726         int i = add_a_service(&sDefault, ipc_name);
1727
1728         if (i < 0)
1729                 return false;
1730
1731         if (asprintf(&comment, "IPC Service (%s)",
1732                                 Globals.szServerString) < 0) {
1733                 return false;
1734         }
1735
1736         string_set(&ServicePtrs[i]->szPath, tmpdir());
1737         string_set(&ServicePtrs[i]->szUsername, "");
1738         string_set(&ServicePtrs[i]->comment, comment);
1739         string_set(&ServicePtrs[i]->fstype, "IPC");
1740         ServicePtrs[i]->iMaxConnections = 0;
1741         ServicePtrs[i]->bAvailable = true;
1742         ServicePtrs[i]->bRead_only = true;
1743         ServicePtrs[i]->bGuest_only = false;
1744         ServicePtrs[i]->bAdministrative_share = true;
1745         ServicePtrs[i]->bGuest_ok = guest_ok;
1746         ServicePtrs[i]->bPrint_ok = false;
1747         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1748
1749         DEBUG(3, ("adding IPC service\n"));
1750
1751         SAFE_FREE(comment);
1752         return true;
1753 }
1754
1755 /***************************************************************************
1756  Add a new printer service, with defaults coming from service iFrom.
1757 ***************************************************************************/
1758
1759 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1760 {
1761         const char *comment = "From Printcap";
1762         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1763
1764         if (i < 0)
1765                 return false;
1766
1767         /* note that we do NOT default the availability flag to true - */
1768         /* we take it from the default service passed. This allows all */
1769         /* dynamic printers to be disabled by disabling the [printers] */
1770         /* entry (if/when the 'available' keyword is implemented!).    */
1771
1772         /* the printer name is set to the service name. */
1773         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1774         string_set(&ServicePtrs[i]->comment, comment);
1775
1776         /* set the browseable flag from the gloabl default */
1777         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1778
1779         /* Printers cannot be read_only. */
1780         ServicePtrs[i]->bRead_only = false;
1781         /* No oplocks on printer services. */
1782         ServicePtrs[i]->bOpLocks = false;
1783         /* Printer services must be printable. */
1784         ServicePtrs[i]->bPrint_ok = true;
1785
1786         DEBUG(3, ("adding printer service %s\n", pszPrintername));
1787
1788         return true;
1789 }
1790
1791
1792 /***************************************************************************
1793  Check whether the given parameter name is valid.
1794  Parametric options (names containing a colon) are considered valid.
1795 ***************************************************************************/
1796
1797 bool lp_parameter_is_valid(const char *pszParmName)
1798 {
1799         return ((map_parameter(pszParmName) != -1) ||
1800                 (strchr(pszParmName, ':') != NULL));
1801 }
1802
1803 /***************************************************************************
1804  Check whether the given name is the name of a global parameter.
1805  Returns true for strings belonging to parameters of class
1806  P_GLOBAL, false for all other strings, also for parametric options
1807  and strings not belonging to any option.
1808 ***************************************************************************/
1809
1810 bool lp_parameter_is_global(const char *pszParmName)
1811 {
1812         int num = map_parameter(pszParmName);
1813
1814         if (num >= 0) {
1815                 return (parm_table[num].p_class == P_GLOBAL);
1816         }
1817
1818         return false;
1819 }
1820
1821 /**************************************************************************
1822  Check whether the given name is the canonical name of a parameter.
1823  Returns false if it is not a valid parameter Name.
1824  For parametric options, true is returned.
1825 **************************************************************************/
1826
1827 bool lp_parameter_is_canonical(const char *parm_name)
1828 {
1829         if (!lp_parameter_is_valid(parm_name)) {
1830                 return false;
1831         }
1832
1833         return (map_parameter(parm_name) ==
1834                 map_parameter_canonical(parm_name, NULL));
1835 }
1836
1837 /**************************************************************************
1838  Determine the canonical name for a parameter.
1839  Indicate when it is an inverse (boolean) synonym instead of a
1840  "usual" synonym.
1841 **************************************************************************/
1842
1843 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1844                                bool *inverse)
1845 {
1846         int num;
1847
1848         if (!lp_parameter_is_valid(parm_name)) {
1849                 *canon_parm = NULL;
1850                 return false;
1851         }
1852
1853         num = map_parameter_canonical(parm_name, inverse);
1854         if (num < 0) {
1855                 /* parametric option */
1856                 *canon_parm = parm_name;
1857         } else {
1858                 *canon_parm = parm_table[num].label;
1859         }
1860
1861         return true;
1862
1863 }
1864
1865 /**************************************************************************
1866  Determine the canonical name for a parameter.
1867  Turn the value given into the inverse boolean expression when
1868  the synonym is an invers boolean synonym.
1869
1870  Return true if parm_name is a valid parameter name and
1871  in case it is an invers boolean synonym, if the val string could
1872  successfully be converted to the reverse bool.
1873  Return false in all other cases.
1874 **************************************************************************/
1875
1876 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1877                                           const char *val,
1878                                           const char **canon_parm,
1879                                           const char **canon_val)
1880 {
1881         int num;
1882         bool inverse;
1883
1884         if (!lp_parameter_is_valid(parm_name)) {
1885                 *canon_parm = NULL;
1886                 *canon_val = NULL;
1887                 return false;
1888         }
1889
1890         num = map_parameter_canonical(parm_name, &inverse);
1891         if (num < 0) {
1892                 /* parametric option */
1893                 *canon_parm = parm_name;
1894                 *canon_val = val;
1895         } else {
1896                 *canon_parm = parm_table[num].label;
1897                 if (inverse) {
1898                         if (!lp_invert_boolean(val, canon_val)) {
1899                                 *canon_val = NULL;
1900                                 return false;
1901                         }
1902                 } else {
1903                         *canon_val = val;
1904                 }
1905         }
1906
1907         return true;
1908 }
1909
1910 /***************************************************************************
1911  Map a parameter's string representation to something we can use. 
1912  Returns false if the parameter string is not recognised, else TRUE.
1913 ***************************************************************************/
1914
1915 static int map_parameter(const char *pszParmName)
1916 {
1917         int iIndex;
1918
1919         if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
1920                 return (-1);
1921
1922         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1923                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1924                         return (iIndex);
1925
1926         /* Warn only if it isn't parametric option */
1927         if (strchr(pszParmName, ':') == NULL)
1928                 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1929         /* We do return 'fail' for parametric options as well because they are
1930            stored in different storage
1931          */
1932         return (-1);
1933 }
1934
1935 /***************************************************************************
1936  Map a parameter's string representation to the index of the canonical
1937  form of the parameter (it might be a synonym).
1938  Returns -1 if the parameter string is not recognised.
1939 ***************************************************************************/
1940
1941 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1942 {
1943         int parm_num, canon_num;
1944         bool loc_inverse = false;
1945
1946         parm_num = map_parameter(pszParmName);
1947         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1948                 /* invalid, parametric or no canidate for synonyms ... */
1949                 goto done;
1950         }
1951
1952         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1953                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1954                         parm_num = canon_num;
1955                         goto done;
1956                 }
1957         }
1958
1959 done:
1960         if (inverse != NULL) {
1961                 *inverse = loc_inverse;
1962         }
1963         return parm_num;
1964 }
1965
1966 /***************************************************************************
1967  return true if parameter number parm1 is a synonym of parameter
1968  number parm2 (parm2 being the principal name).
1969  set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1970  false otherwise.
1971 ***************************************************************************/
1972
1973 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
1974 {
1975         if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
1976             (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
1977             (parm_table[parm1].flags & FLAG_HIDE) &&
1978             !(parm_table[parm2].flags & FLAG_HIDE))
1979         {
1980                 if (inverse != NULL) {
1981                         if ((parm_table[parm1].type == P_BOOLREV) &&
1982                             (parm_table[parm2].type == P_BOOL))
1983                         {
1984                                 *inverse = true;
1985                         } else {
1986                                 *inverse = false;
1987                         }
1988                 }
1989                 return true;
1990         }
1991         return false;
1992 }
1993
1994 /***************************************************************************
1995  Show one parameter's name, type, [values,] and flags.
1996  (helper functions for show_parameter_list)
1997 ***************************************************************************/
1998
1999 static void show_parameter(int parmIndex)
2000 {
2001         int enumIndex, flagIndex;
2002         int parmIndex2;
2003         bool hadFlag;
2004         bool hadSyn;
2005         bool inverse;
2006         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2007                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2008                 "P_ENUM", "P_SEP"};
2009         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2010                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2011                 FLAG_HIDE};
2012         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2013                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2014                 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2015
2016         printf("%s=%s", parm_table[parmIndex].label,
2017                type[parm_table[parmIndex].type]);
2018         if (parm_table[parmIndex].type == P_ENUM) {
2019                 printf(",");
2020                 for (enumIndex=0;
2021                      parm_table[parmIndex].enum_list[enumIndex].name;
2022                      enumIndex++)
2023                 {
2024                         printf("%s%s",
2025                                enumIndex ? "|" : "",
2026                                parm_table[parmIndex].enum_list[enumIndex].name);
2027                 }
2028         }
2029         printf(",");
2030         hadFlag = false;
2031         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2032                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2033                         printf("%s%s",
2034                                 hadFlag ? "|" : "",
2035                                 flag_names[flagIndex]);
2036                         hadFlag = true;
2037                 }
2038         }
2039
2040         /* output synonyms */
2041         hadSyn = false;
2042         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2043                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2044                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2045                                parm_table[parmIndex2].label);
2046                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2047                         if (!hadSyn) {
2048                                 printf(" (synonyms: ");
2049                                 hadSyn = true;
2050                         } else {
2051                                 printf(", ");
2052                         }
2053                         printf("%s%s", parm_table[parmIndex2].label,
2054                                inverse ? "[i]" : "");
2055                 }
2056         }
2057         if (hadSyn) {
2058                 printf(")");
2059         }
2060
2061         printf("\n");
2062 }
2063
2064 /***************************************************************************
2065  Show all parameter's name, type, [values,] and flags.
2066 ***************************************************************************/
2067
2068 void show_parameter_list(void)
2069 {
2070         int classIndex, parmIndex;
2071         const char *section_names[] = { "local", "global", NULL};
2072
2073         for (classIndex=0; section_names[classIndex]; classIndex++) {
2074                 printf("[%s]\n", section_names[classIndex]);
2075                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2076                         if (parm_table[parmIndex].p_class == classIndex) {
2077                                 show_parameter(parmIndex);
2078                         }
2079                 }
2080         }
2081 }
2082
2083 /***************************************************************************
2084  Check if a given string correctly represents a boolean value.
2085 ***************************************************************************/
2086
2087 bool lp_string_is_valid_boolean(const char *parm_value)
2088 {
2089         return set_boolean(parm_value, NULL);
2090 }
2091
2092 /***************************************************************************
2093  Get the standard string representation of a boolean value ("yes" or "no")
2094 ***************************************************************************/
2095
2096 static const char *get_boolean(bool bool_value)
2097 {
2098         static const char *yes_str = "yes";
2099         static const char *no_str = "no";
2100
2101         return (bool_value ? yes_str : no_str);
2102 }
2103
2104 /***************************************************************************
2105  Provide the string of the negated boolean value associated to the boolean
2106  given as a string. Returns false if the passed string does not correctly
2107  represent a boolean.
2108 ***************************************************************************/
2109
2110 bool lp_invert_boolean(const char *str, const char **inverse_str)
2111 {
2112         bool val;
2113
2114         if (!set_boolean(str, &val)) {
2115                 return false;
2116         }
2117
2118         *inverse_str = get_boolean(!val);
2119         return true;
2120 }
2121
2122 /***************************************************************************
2123  Provide the canonical string representation of a boolean value given
2124  as a string. Return true on success, false if the string given does
2125  not correctly represent a boolean.
2126 ***************************************************************************/
2127
2128 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2129 {
2130         bool val;
2131
2132         if (!set_boolean(str, &val)) {
2133                 return false;
2134         }
2135
2136         *canon_str = get_boolean(val);
2137         return true;
2138 }
2139
2140 /***************************************************************************
2141 Find a service by name. Otherwise works like get_service.
2142 ***************************************************************************/
2143
2144 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2145 {
2146         int iService = -1;
2147         char *canon_name;
2148         TDB_DATA data;
2149         NTSTATUS status;
2150
2151         if (ServiceHash == NULL) {
2152                 return -1;
2153         }
2154
2155         canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2156
2157         status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2158                                        &data);
2159
2160         if (NT_STATUS_IS_OK(status) &&
2161             (data.dptr != NULL) &&
2162             (data.dsize == sizeof(iService)))
2163         {
2164                 iService = *(int *)data.dptr;
2165         }
2166
2167         TALLOC_FREE(canon_name);
2168
2169         if ((iService != -1) && (LP_SNUM_OK(iService))
2170             && (pserviceDest != NULL)) {
2171                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2172         }
2173
2174         return (iService);
2175 }
2176
2177 /* Return a pointer to a service by name.  Unlike getservicebyname, it does not copy the service */
2178 struct loadparm_service *lp_service(const char *pszServiceName)
2179 {
2180         int iService = getservicebyname(pszServiceName, NULL);
2181         if (iService == -1 || !LP_SNUM_OK(iService)) {
2182                 return NULL;
2183         }
2184         return ServicePtrs[iService];
2185 }
2186
2187 struct loadparm_service *lp_servicebynum(int snum)
2188 {
2189         if ((snum == -1) || !LP_SNUM_OK(snum)) {
2190                 return NULL;
2191         }
2192         return ServicePtrs[snum];
2193 }
2194
2195 struct loadparm_service *lp_default_loadparm_service()
2196 {
2197         return &sDefault;
2198 }
2199
2200
2201 /***************************************************************************
2202  Copy a service structure to another.
2203  If pcopymapDest is NULL then copy all fields
2204 ***************************************************************************/
2205
2206 /**
2207  * Add a parametric option to a parmlist_entry,
2208  * replacing old value, if already present.
2209  */
2210 static void set_param_opt(struct parmlist_entry **opt_list,
2211                           const char *opt_name,
2212                           const char *opt_value,
2213                           unsigned priority)
2214 {
2215         struct parmlist_entry *new_opt, *opt;
2216         bool not_added;
2217
2218         opt = *opt_list;
2219         not_added = true;
2220
2221         /* Traverse destination */
2222         while (opt) {
2223                 /* If we already have same option, override it */
2224                 if (strwicmp(opt->key, opt_name) == 0) {
2225                         if ((opt->priority & FLAG_CMDLINE) &&
2226                             !(priority & FLAG_CMDLINE)) {
2227                                 /* it's been marked as not to be
2228                                    overridden */
2229                                 return;
2230                         }
2231                         string_free(&opt->value);
2232                         TALLOC_FREE(opt->list);
2233                         opt->value = SMB_STRDUP(opt_value);
2234                         opt->priority = priority;
2235                         not_added = false;
2236                         break;
2237                 }
2238                 opt = opt->next;
2239         }
2240         if (not_added) {
2241             new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2242             new_opt->key = SMB_STRDUP(opt_name);
2243             new_opt->value = SMB_STRDUP(opt_value);
2244             new_opt->list = NULL;
2245             new_opt->priority = priority;
2246             DLIST_ADD(*opt_list, new_opt);
2247         }
2248 }
2249
2250 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2251                          struct bitmap *pcopymapDest)
2252 {
2253         int i;
2254         bool bcopyall = (pcopymapDest == NULL);
2255         struct parmlist_entry *data;
2256
2257         for (i = 0; parm_table[i].label; i++)
2258                 if (parm_table[i].p_class == P_LOCAL &&
2259                     (bcopyall || bitmap_query(pcopymapDest,i))) {
2260                         void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2261                         void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2262
2263                         switch (parm_table[i].type) {
2264                                 case P_BOOL:
2265                                 case P_BOOLREV:
2266                                         *(bool *)dest_ptr = *(bool *)src_ptr;
2267                                         break;
2268
2269                                 case P_INTEGER:
2270                                 case P_ENUM:
2271                                 case P_OCTAL:
2272                                 case P_BYTES:
2273                                         *(int *)dest_ptr = *(int *)src_ptr;
2274                                         break;
2275
2276                                 case P_CHAR:
2277                                         *(char *)dest_ptr = *(char *)src_ptr;
2278                                         break;
2279
2280                                 case P_STRING:
2281                                         string_set((char **)dest_ptr,
2282                                                    *(char **)src_ptr);
2283                                         break;
2284
2285                                 case P_USTRING:
2286                                 {
2287                                         char *upper_string = strupper_talloc(talloc_tos(), 
2288                                                                              *(char **)src_ptr);
2289                                         string_set((char **)dest_ptr,
2290                                                    upper_string);
2291                                         TALLOC_FREE(upper_string);
2292                                         break;
2293                                 }
2294                                 case P_LIST:
2295                                         TALLOC_FREE(*((char ***)dest_ptr));
2296                                         *((char ***)dest_ptr) = str_list_copy(NULL, 
2297                                                       *(const char ***)src_ptr);
2298                                         break;
2299                                 default:
2300                                         break;
2301                         }
2302                 }
2303
2304         if (bcopyall) {
2305                 init_copymap(pserviceDest);
2306                 if (pserviceSource->copymap)
2307                         bitmap_copy(pserviceDest->copymap,
2308                                     pserviceSource->copymap);
2309         }
2310
2311         data = pserviceSource->param_opt;
2312         while (data) {
2313                 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2314                 data = data->next;
2315         }
2316 }
2317
2318 /***************************************************************************
2319 Check a service for consistency. Return false if the service is in any way
2320 incomplete or faulty, else true.
2321 ***************************************************************************/
2322
2323 bool service_ok(int iService)
2324 {
2325         bool bRetval;
2326
2327         bRetval = true;
2328         if (ServicePtrs[iService]->szService[0] == '\0') {
2329                 DEBUG(0, ("The following message indicates an internal error:\n"));
2330                 DEBUG(0, ("No service name in service entry.\n"));
2331                 bRetval = false;
2332         }
2333
2334         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2335         /* I can't see why you'd want a non-printable printer service...        */
2336         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2337                 if (!ServicePtrs[iService]->bPrint_ok) {
2338                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2339                                ServicePtrs[iService]->szService));
2340                         ServicePtrs[iService]->bPrint_ok = true;
2341                 }
2342                 /* [printers] service must also be non-browsable. */
2343                 if (ServicePtrs[iService]->bBrowseable)
2344                         ServicePtrs[iService]->bBrowseable = false;
2345         }
2346
2347         if (ServicePtrs[iService]->szPath[0] == '\0' &&
2348             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2349             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2350             ) {
2351                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2352                         ServicePtrs[iService]->szService));
2353                 ServicePtrs[iService]->bAvailable = false;
2354         }
2355
2356         /* If a service is flagged unavailable, log the fact at level 1. */
2357         if (!ServicePtrs[iService]->bAvailable)
2358                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2359                           ServicePtrs[iService]->szService));
2360
2361         return (bRetval);
2362 }
2363
2364 static struct smbconf_ctx *lp_smbconf_ctx(void)
2365 {
2366         sbcErr err;
2367         static struct smbconf_ctx *conf_ctx = NULL;
2368
2369         if (conf_ctx == NULL) {
2370                 err = smbconf_init(NULL, &conf_ctx, "registry:");
2371                 if (!SBC_ERROR_IS_OK(err)) {
2372                         DEBUG(1, ("error initializing registry configuration: "
2373                                   "%s\n", sbcErrorString(err)));
2374                         conf_ctx = NULL;
2375                 }
2376         }
2377
2378         return conf_ctx;
2379 }
2380
2381 static bool process_smbconf_service(struct smbconf_service *service)
2382 {
2383         uint32_t count;
2384         bool ret;
2385
2386         if (service == NULL) {
2387                 return false;
2388         }
2389
2390         ret = do_section(service->name, NULL);
2391         if (ret != true) {
2392                 return false;
2393         }
2394         for (count = 0; count < service->num_params; count++) {
2395                 ret = do_parameter(service->param_names[count],
2396                                    service->param_values[count],
2397                                    NULL);
2398                 if (ret != true) {
2399                         return false;
2400                 }
2401         }
2402         if (iServiceIndex >= 0) {
2403                 return service_ok(iServiceIndex);
2404         }
2405         return true;
2406 }
2407
2408 /**
2409  * load a service from registry and activate it
2410  */
2411 bool process_registry_service(const char *service_name)
2412 {
2413         sbcErr err;
2414         struct smbconf_service *service = NULL;
2415         TALLOC_CTX *mem_ctx = talloc_stackframe();
2416         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2417         bool ret = false;
2418
2419         if (conf_ctx == NULL) {
2420                 goto done;
2421         }
2422
2423         DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2424
2425         if (!smbconf_share_exists(conf_ctx, service_name)) {
2426                 /*
2427                  * Registry does not contain data for this service (yet),
2428                  * but make sure lp_load doesn't return false.
2429                  */
2430                 ret = true;
2431                 goto done;
2432         }
2433
2434         err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2435         if (!SBC_ERROR_IS_OK(err)) {
2436                 goto done;
2437         }
2438
2439         ret = process_smbconf_service(service);
2440         if (!ret) {
2441                 goto done;
2442         }
2443
2444         /* store the csn */
2445         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2446
2447 done:
2448         TALLOC_FREE(mem_ctx);
2449         return ret;
2450 }
2451
2452 /*
2453  * process_registry_globals
2454  */
2455 static bool process_registry_globals(void)
2456 {
2457         bool ret;
2458
2459         add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2460
2461         ret = do_parameter("registry shares", "yes", NULL);
2462         if (!ret) {
2463                 return ret;
2464         }
2465
2466         return process_registry_service(GLOBAL_NAME);
2467 }
2468
2469 bool process_registry_shares(void)
2470 {
2471         sbcErr err;
2472         uint32_t count;
2473         struct smbconf_service **service = NULL;
2474         uint32_t num_shares = 0;
2475         TALLOC_CTX *mem_ctx = talloc_stackframe();
2476         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2477         bool ret = false;
2478
2479         if (conf_ctx == NULL) {
2480                 goto done;
2481         }
2482
2483         err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2484         if (!SBC_ERROR_IS_OK(err)) {
2485                 goto done;
2486         }
2487
2488         ret = true;
2489
2490         for (count = 0; count < num_shares; count++) {
2491                 if (strequal(service[count]->name, GLOBAL_NAME)) {
2492                         continue;
2493                 }
2494                 ret = process_smbconf_service(service[count]);
2495                 if (!ret) {
2496                         goto done;
2497                 }
2498         }
2499
2500         /* store the csn */
2501         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2502
2503 done:
2504         TALLOC_FREE(mem_ctx);
2505         return ret;
2506 }
2507
2508 /**
2509  * reload those shares from registry that are already
2510  * activated in the services array.
2511  */
2512 static bool reload_registry_shares(void)
2513 {
2514         int i;
2515         bool ret = true;
2516
2517         for (i = 0; i < iNumServices; i++) {
2518                 if (!VALID(i)) {
2519                         continue;
2520                 }
2521
2522                 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2523                         continue;
2524                 }
2525
2526                 ret = process_registry_service(ServicePtrs[i]->szService);
2527                 if (!ret) {
2528                         goto done;
2529                 }
2530         }
2531
2532 done:
2533         return ret;
2534 }
2535
2536
2537 #define MAX_INCLUDE_DEPTH 100
2538
2539 static uint8_t include_depth;
2540
2541 static struct file_lists {
2542         struct file_lists *next;
2543         char *name;
2544         char *subfname;
2545         time_t modtime;
2546 } *file_lists = NULL;
2547
2548 /*******************************************************************
2549  Keep a linked list of all config files so we know when one has changed 
2550  it's date and needs to be reloaded.
2551 ********************************************************************/
2552
2553 static void add_to_file_list(const char *fname, const char *subfname)
2554 {
2555         struct file_lists *f = file_lists;
2556
2557         while (f) {
2558                 if (f->name && !strcmp(f->name, fname))
2559                         break;
2560                 f = f->next;
2561         }
2562
2563         if (!f) {
2564                 f = SMB_MALLOC_P(struct file_lists);
2565                 if (!f)
2566                         return;
2567                 f->next = file_lists;
2568                 f->name = SMB_STRDUP(fname);
2569                 if (!f->name) {
2570                         SAFE_FREE(f);
2571                         return;
2572                 }
2573                 f->subfname = SMB_STRDUP(subfname);
2574                 if (!f->subfname) {
2575                         SAFE_FREE(f->name);
2576                         SAFE_FREE(f);
2577                         return;
2578                 }
2579                 file_lists = f;
2580                 f->modtime = file_modtime(subfname);
2581         } else {
2582                 time_t t = file_modtime(subfname);
2583                 if (t)
2584                         f->modtime = t;
2585         }
2586         return;
2587 }
2588
2589 /**
2590  * Free the file lists
2591  */
2592 static void free_file_list(void)
2593 {
2594         struct file_lists *f;
2595         struct file_lists *next;
2596
2597         f = file_lists;
2598         while( f ) {
2599                 next = f->next;
2600                 SAFE_FREE( f->name );
2601                 SAFE_FREE( f->subfname );
2602                 SAFE_FREE( f );
2603                 f = next;
2604         }
2605         file_lists = NULL;
2606 }
2607
2608
2609 /**
2610  * Utility function for outsiders to check if we're running on registry.
2611  */
2612 bool lp_config_backend_is_registry(void)
2613 {
2614         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2615 }
2616
2617 /**
2618  * Utility function to check if the config backend is FILE.
2619  */
2620 bool lp_config_backend_is_file(void)
2621 {
2622         return (lp_config_backend() == CONFIG_BACKEND_FILE);
2623 }
2624
2625 /*******************************************************************
2626  Check if a config file has changed date.
2627 ********************************************************************/
2628
2629 bool lp_file_list_changed(void)
2630 {
2631         struct file_lists *f = file_lists;
2632
2633         DEBUG(6, ("lp_file_list_changed()\n"));
2634
2635         while (f) {
2636                 time_t mod_time;
2637
2638                 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2639                         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2640
2641                         if (conf_ctx == NULL) {
2642                                 return false;
2643                         }
2644                         if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2645                                             NULL))
2646                         {
2647                                 DEBUGADD(6, ("registry config changed\n"));
2648                                 return true;
2649                         }
2650                 } else {
2651                         char *n2 = NULL;
2652                         n2 = talloc_sub_basic(talloc_tos(),
2653                                               get_current_username(),
2654                                               current_user_info.domain,
2655                                               f->name);
2656                         if (!n2) {
2657                                 return false;
2658                         }
2659                         DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2660                                      f->name, n2, ctime(&f->modtime)));
2661
2662                         mod_time = file_modtime(n2);
2663
2664                         if (mod_time &&
2665                             ((f->modtime != mod_time) ||
2666                              (f->subfname == NULL) ||
2667                              (strcmp(n2, f->subfname) != 0)))
2668                         {
2669                                 DEBUGADD(6,
2670                                          ("file %s modified: %s\n", n2,
2671                                           ctime(&mod_time)));
2672                                 f->modtime = mod_time;
2673                                 SAFE_FREE(f->subfname);
2674                                 f->subfname = SMB_STRDUP(n2);
2675                                 TALLOC_FREE(n2);
2676                                 return true;
2677                         }
2678                         TALLOC_FREE(n2);
2679                 }
2680                 f = f->next;
2681         }
2682         return false;
2683 }
2684
2685
2686 /**
2687  * Initialize iconv conversion descriptors.
2688  *
2689  * This is called the first time it is needed, and also called again
2690  * every time the configuration is reloaded, because the charset or
2691  * codepage might have changed.
2692  **/
2693 static void init_iconv(void)
2694 {
2695         global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2696                                                       lp_unix_charset(),
2697                                                       true, global_iconv_handle);
2698 }
2699
2700 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2701 {
2702         if (strcmp(*ptr, pszParmValue) != 0) {
2703                 string_set(ptr, pszParmValue);
2704                 init_iconv();
2705         }
2706         return true;
2707 }
2708
2709 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2710 {
2711         bool is_utf8 = false;
2712         size_t len = strlen(pszParmValue);
2713
2714         if (len == 4 || len == 5) {
2715                 /* Don't use StrCaseCmp here as we don't want to
2716                    initialize iconv. */
2717                 if ((toupper_m(pszParmValue[0]) == 'U') &&
2718                     (toupper_m(pszParmValue[1]) == 'T') &&
2719                     (toupper_m(pszParmValue[2]) == 'F')) {
2720                         if (len == 4) {
2721                                 if (pszParmValue[3] == '8') {
2722                                         is_utf8 = true;
2723                                 }
2724                         } else {
2725                                 if (pszParmValue[3] == '-' &&
2726                                     pszParmValue[4] == '8') {
2727                                         is_utf8 = true;
2728                                 }
2729                         }
2730                 }
2731         }
2732
2733         if (strcmp(*ptr, pszParmValue) != 0) {
2734                 if (is_utf8) {
2735                         DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2736                                 "be UTF8, using (default value) %s instead.\n",
2737                                 DEFAULT_DOS_CHARSET));
2738                         pszParmValue = DEFAULT_DOS_CHARSET;
2739                 }
2740                 string_set(ptr, pszParmValue);
2741                 init_iconv();
2742         }
2743         return true;
2744 }
2745
2746 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2747 {
2748         bool ret = true;
2749         TALLOC_CTX *frame = talloc_stackframe();
2750         char *realm = strupper_talloc(frame, pszParmValue);
2751         char *dnsdomain = strlower_talloc(realm, pszParmValue);
2752
2753         ret &= string_set(&Globals.szRealm, pszParmValue);
2754         ret &= string_set(&Globals.szRealm_upper, realm);
2755         ret &= string_set(&Globals.szRealm_lower, dnsdomain);
2756         TALLOC_FREE(frame);
2757
2758         return ret;
2759 }
2760
2761 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2762 {
2763         TALLOC_FREE(Globals.szNetbiosAliases);
2764         Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2765         return set_netbios_aliases(Globals.szNetbiosAliases);
2766 }
2767
2768 /***************************************************************************
2769  Handle the include operation.
2770 ***************************************************************************/
2771 static bool bAllowIncludeRegistry = true;
2772
2773 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2774 {
2775         char *fname;
2776
2777         if (include_depth >= MAX_INCLUDE_DEPTH) {
2778                 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2779                           include_depth));
2780                 return false;
2781         }
2782
2783         if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2784                 if (!bAllowIncludeRegistry) {
2785                         return true;
2786                 }
2787                 if (bInGlobalSection) {
2788                         bool ret;
2789                         include_depth++;
2790                         ret = process_registry_globals();
2791                         include_depth--;
2792                         return ret;
2793                 } else {
2794                         DEBUG(1, ("\"include = registry\" only effective "
2795                                   "in %s section\n", GLOBAL_NAME));
2796                         return false;
2797                 }
2798         }
2799
2800         fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2801                                  current_user_info.domain,
2802                                  pszParmValue);
2803
2804         add_to_file_list(pszParmValue, fname);
2805
2806         string_set(ptr, fname);
2807
2808         if (file_exist(fname)) {
2809                 bool ret;
2810                 include_depth++;
2811                 ret = pm_process(fname, do_section, do_parameter, NULL);
2812                 include_depth--;
2813                 TALLOC_FREE(fname);
2814                 return ret;
2815         }
2816
2817         DEBUG(2, ("Can't find include file %s\n", fname));
2818         TALLOC_FREE(fname);
2819         return true;
2820 }
2821
2822 /***************************************************************************
2823  Handle the interpretation of the copy parameter.
2824 ***************************************************************************/
2825
2826 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2827 {
2828         bool bRetval;
2829         int iTemp;
2830         struct loadparm_service serviceTemp;
2831
2832         string_set(ptr, pszParmValue);
2833
2834         init_service(&serviceTemp);
2835
2836         bRetval = false;
2837
2838         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2839
2840         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2841                 if (iTemp == iServiceIndex) {
2842                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2843                 } else {
2844                         copy_service(ServicePtrs[iServiceIndex],
2845                                      &serviceTemp,
2846                                      ServicePtrs[iServiceIndex]->copymap);
2847                         bRetval = true;
2848                 }
2849         } else {
2850                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2851                 bRetval = false;
2852         }
2853
2854         free_service(&serviceTemp);
2855         return (bRetval);
2856 }
2857
2858 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2859 {
2860         Globals.ldap_debug_level = lp_int(pszParmValue);
2861         init_ldap_debugging();
2862         return true;
2863 }
2864
2865 /*
2866  * idmap related parameters
2867  */
2868
2869 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2870 {
2871         lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2872
2873         return true;
2874 }
2875
2876 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2877 {
2878         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2879
2880         return true;
2881 }
2882
2883 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2884 {
2885         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2886
2887         return true;
2888 }
2889
2890 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2891 {
2892         char *config_option = NULL;
2893         const char *range = NULL;
2894         bool ret = false;
2895
2896         SMB_ASSERT(low != NULL);
2897         SMB_ASSERT(high != NULL);
2898
2899         if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2900                 domain_name = "*";
2901         }
2902
2903         config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2904                                         domain_name);
2905         if (config_option == NULL) {
2906                 DEBUG(0, ("out of memory\n"));
2907                 return false;
2908         }
2909
2910         range = lp_parm_const_string(-1, config_option, "range", NULL);
2911         if (range == NULL) {
2912                 DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2913                 goto done;
2914         }
2915
2916         if (sscanf(range, "%u - %u", low, high) != 2) {
2917                 DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2918                           range, domain_name));
2919                 goto done;
2920         }
2921
2922         ret = true;
2923
2924 done:
2925         talloc_free(config_option);
2926         return ret;
2927
2928 }
2929
2930 bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2931 {
2932         return lp_idmap_range("*", low, high);
2933 }
2934
2935 const char *lp_idmap_backend(const char *domain_name)
2936 {
2937         char *config_option = NULL;
2938         const char *backend = NULL;
2939
2940         if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2941                 domain_name = "*";
2942         }
2943
2944         config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2945                                         domain_name);
2946         if (config_option == NULL) {
2947                 DEBUG(0, ("out of memory\n"));
2948                 return false;
2949         }
2950
2951         backend = lp_parm_const_string(-1, config_option, "backend", NULL);
2952         if (backend == NULL) {
2953                 DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
2954                 goto done;
2955         }
2956
2957 done:
2958         talloc_free(config_option);
2959         return backend;
2960 }
2961
2962 const char *lp_idmap_default_backend(void)
2963 {
2964         return lp_idmap_backend("*");
2965 }
2966
2967 /***************************************************************************
2968  Handle the DEBUG level list.
2969 ***************************************************************************/
2970
2971 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2972 {
2973         string_set(ptr, pszParmValueIn);
2974         return debug_parse_levels(pszParmValueIn);
2975 }
2976
2977 /***************************************************************************
2978  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2979 ***************************************************************************/
2980
2981 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2982 {
2983         const char *suffix_string;
2984
2985         suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2986                                         Globals.szLdapSuffix );
2987         if ( !suffix_string ) {
2988                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2989                 return "";
2990         }
2991
2992         return suffix_string;
2993 }
2994
2995 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
2996 {
2997         if (Globals.szLdapMachineSuffix[0])
2998                 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
2999
3000         return lp_string(ctx, Globals.szLdapSuffix);
3001 }
3002
3003 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
3004 {
3005         if (Globals.szLdapUserSuffix[0])
3006                 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3007
3008         return lp_string(ctx, Globals.szLdapSuffix);
3009 }
3010
3011 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3012 {
3013         if (Globals.szLdapGroupSuffix[0])
3014                 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3015
3016         return lp_string(ctx, Globals.szLdapSuffix);
3017 }
3018
3019 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3020 {
3021         if (Globals.szLdapIdmapSuffix[0])
3022                 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3023
3024         return lp_string(ctx, Globals.szLdapSuffix);
3025 }
3026
3027 /****************************************************************************
3028  set the value for a P_ENUM
3029  ***************************************************************************/
3030
3031 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3032                               int *ptr )
3033 {
3034         int i;
3035
3036         for (i = 0; parm->enum_list[i].name; i++) {
3037                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3038                         *ptr = parm->enum_list[i].value;
3039                         return;
3040                 }
3041         }
3042         DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3043                   pszParmValue, parm->label));
3044 }
3045
3046 /***************************************************************************
3047 ***************************************************************************/
3048
3049 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3050 {
3051         static int parm_num = -1;
3052         struct loadparm_service *s;
3053
3054         if ( parm_num == -1 )
3055                 parm_num = map_parameter( "printing" );
3056
3057         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3058
3059         if ( snum < 0 )
3060                 s = &sDefault;
3061         else
3062                 s = ServicePtrs[snum];
3063
3064         init_printer_values( s );
3065
3066         return true;
3067 }
3068
3069
3070 /***************************************************************************
3071  Initialise a copymap.
3072 ***************************************************************************/
3073
3074 static void init_copymap(struct loadparm_service *pservice)
3075 {
3076         int i;
3077
3078         TALLOC_FREE(pservice->copymap);
3079
3080         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3081         if (!pservice->copymap)
3082                 DEBUG(0,
3083                       ("Couldn't allocate copymap!! (size %d)\n",
3084                        (int)NUMPARAMETERS));
3085         else
3086                 for (i = 0; i < NUMPARAMETERS; i++)
3087                         bitmap_set(pservice->copymap, i);
3088 }
3089
3090 /**
3091   return the parameter pointer for a parameter
3092 */
3093 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3094 {
3095         if (service == NULL) {
3096                 if (parm->p_class == P_LOCAL)
3097                         return (void *)(((char *)&sDefault)+parm->offset);
3098                 else if (parm->p_class == P_GLOBAL)
3099                         return (void *)(((char *)&Globals)+parm->offset);
3100                 else return NULL;
3101         } else {
3102                 return (void *)(((char *)service) + parm->offset);
3103         }
3104 }
3105
3106 /***************************************************************************
3107  Return the local pointer to a parameter given the service number and parameter
3108 ***************************************************************************/
3109
3110 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3111 {
3112         return lp_parm_ptr(ServicePtrs[snum], parm);
3113 }
3114
3115 /***************************************************************************
3116  Process a parameter for a particular service number. If snum < 0
3117  then assume we are in the globals.
3118 ***************************************************************************/
3119
3120 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3121 {
3122         int parmnum, i;
3123         void *parm_ptr = NULL;  /* where we are going to store the result */
3124         struct parmlist_entry **opt_list;
3125
3126         parmnum = map_parameter(pszParmName);
3127
3128         if (parmnum < 0) {
3129                 if (strchr(pszParmName, ':') == NULL) {
3130                         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3131                                   pszParmName));
3132                         return true;
3133                 }
3134
3135                 /*
3136                  * We've got a parametric option
3137                  */
3138
3139                 opt_list = (snum < 0)
3140                         ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3141                 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3142
3143                 return true;
3144         }
3145
3146         /* if it's already been set by the command line, then we don't
3147            override here */
3148         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3149                 return true;
3150         }
3151
3152         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3153                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3154                           pszParmName));
3155         }
3156
3157         /* we might point at a service, the default service or a global */
3158         if (snum < 0) {
3159                 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3160         } else {
3161                 if (parm_table[parmnum].p_class == P_GLOBAL) {
3162                         DEBUG(0,
3163                               ("Global parameter %s found in service section!\n",
3164                                pszParmName));
3165                         return true;
3166                 }
3167                 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3168         }
3169
3170         if (snum >= 0) {
3171                 if (!ServicePtrs[snum]->copymap)
3172                         init_copymap(ServicePtrs[snum]);
3173
3174                 /* this handles the aliases - set the copymap for other entries with
3175                    the same data pointer */
3176                 for (i = 0; parm_table[i].label; i++) {
3177                         if ((parm_table[i].offset == parm_table[parmnum].offset)
3178                             && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3179                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
3180                         }
3181                 }
3182         }
3183
3184         /* if it is a special case then go ahead */
3185         if (parm_table[parmnum].special) {
3186                 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3187                                                    (char **)parm_ptr);
3188         }
3189
3190         /* now switch on the type of variable it is */
3191         switch (parm_table[parmnum].type)
3192         {
3193                 case P_BOOL:
3194                         *(bool *)parm_ptr = lp_bool(pszParmValue);
3195                         break;
3196
3197                 case P_BOOLREV:
3198                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
3199                         break;
3200
3201                 case P_INTEGER:
3202                         *(int *)parm_ptr = lp_int(pszParmValue);
3203                         break;
3204
3205                 case P_CHAR:
3206                         *(char *)parm_ptr = *pszParmValue;
3207                         break;
3208
3209                 case P_OCTAL:
3210                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3211                         if ( i != 1 ) {
3212                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3213                         }
3214                         break;
3215
3216                 case P_BYTES:
3217                 {
3218                         uint64_t val;
3219                         if (conv_str_size_error(pszParmValue, &val)) {
3220                                 if (val <= INT_MAX) {
3221                                         *(int *)parm_ptr = (int)val;
3222                                         break;
3223                                 }
3224                         }
3225
3226                         DEBUG(0,("lp_do_parameter(%s): value is not "
3227                             "a valid size specifier!\n", pszParmValue));
3228                         return false;
3229                 }
3230
3231                 case P_LIST:
3232                 case P_CMDLIST:
3233                         TALLOC_FREE(*((char ***)parm_ptr));
3234                         *(char ***)parm_ptr = str_list_make_v3(
3235                                 NULL, pszParmValue, NULL);
3236                         break;
3237
3238                 case P_STRING:
3239                         string_set((char **)parm_ptr, pszParmValue);
3240                         break;
3241
3242                 case P_USTRING:
3243                 {
3244                         char *upper_string = strupper_talloc(talloc_tos(), 
3245                                                              pszParmValue);
3246                         string_set((char **)parm_ptr, upper_string);
3247                         TALLOC_FREE(upper_string);
3248                         break;
3249                 }
3250                 case P_ENUM:
3251                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3252                         break;
3253                 case P_SEP:
3254                         break;
3255         }
3256
3257         return true;
3258 }
3259
3260 /***************************************************************************
3261 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3262 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3263 ***************************************************************************/
3264
3265 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3266 {
3267         int parmnum, i;
3268         parmnum = map_parameter(pszParmName);
3269         if (parmnum >= 0) {
3270                 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3271                 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3272                         return false;
3273                 }
3274                 parm_table[parmnum].flags |= FLAG_CMDLINE;
3275
3276                 /* we have to also set FLAG_CMDLINE on aliases.  Aliases must
3277                  * be grouped in the table, so we don't have to search the
3278                  * whole table */
3279                 for (i=parmnum-1;
3280                      i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3281                              && parm_table[i].p_class == parm_table[parmnum].p_class;
3282                      i--) {
3283                         parm_table[i].flags |= FLAG_CMDLINE;
3284                 }
3285                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3286                              && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3287                         parm_table[i].flags |= FLAG_CMDLINE;
3288                 }
3289
3290                 if (store_values) {
3291                         store_lp_set_cmdline(pszParmName, pszParmValue);
3292                 }
3293                 return true;
3294         }
3295
3296         /* it might be parametric */
3297         if (strchr(pszParmName, ':') != NULL) {
3298                 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3299                 if (store_values) {
3300                         store_lp_set_cmdline(pszParmName, pszParmValue);
3301                 }
3302                 return true;
3303         }
3304
3305         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
3306         return true;
3307 }
3308
3309 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3310 {
3311         return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3312 }
3313
3314 /***************************************************************************
3315  Process a parameter.
3316 ***************************************************************************/
3317
3318 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3319                          void *userdata)
3320 {
3321         if (!bInGlobalSection && bGlobalOnly)
3322                 return true;
3323
3324         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3325
3326         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3327                                 pszParmName, pszParmValue));
3328 }
3329
3330 /*
3331   set a option from the commandline in 'a=b' format. Use to support --option
3332 */
3333 bool lp_set_option(const char *option)
3334 {
3335         char *p, *s;
3336         bool ret;
3337
3338         s = talloc_strdup(NULL, option);
3339         if (!s) {
3340                 return false;
3341         }
3342
3343         p = strchr(s, '=');
3344         if (!p) {
3345                 talloc_free(s);
3346                 return false;
3347         }
3348
3349         *p = 0;
3350
3351         /* skip white spaces after the = sign */
3352         do {
3353                 p++;
3354         } while (*p == ' ');
3355
3356         ret = lp_set_cmdline(s, p);
3357         talloc_free(s);
3358         return ret;
3359 }
3360
3361 /**************************************************************************
3362  Print a parameter of the specified type.
3363 ***************************************************************************/
3364
3365 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3366 {
3367         /* For the seperation of lists values that we print below */
3368         const char *list_sep = ", ";
3369         int i;
3370         switch (p->type)
3371         {
3372                 case P_ENUM:
3373                         for (i = 0; p->enum_list[i].name; i++) {
3374                                 if (*(int *)ptr == p->enum_list[i].value) {
3375                                         fprintf(f, "%s",
3376                                                 p->enum_list[i].name);
3377                                         break;
3378                                 }
3379                         }
3380                         break;
3381
3382                 case P_BOOL:
3383                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3384                         break;
3385
3386                 case P_BOOLREV:
3387                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3388                         break;
3389
3390                 case P_INTEGER:
3391                 case P_BYTES:
3392                         fprintf(f, "%d", *(int *)ptr);
3393                         break;
3394
3395                 case P_CHAR:
3396                         fprintf(f, "%c", *(char *)ptr);
3397                         break;
3398
3399                 case P_OCTAL: {
3400                         int val = *(int *)ptr; 
3401                         if (val == -1) {
3402                                 fprintf(f, "-1");
3403                         } else {
3404                                 fprintf(f, "0%o", val);
3405                         }
3406                         break;
3407                 }
3408
3409                 case P_CMDLIST:
3410                         list_sep = " ";
3411                         /* fall through */
3412                 case P_LIST:
3413                         if ((char ***)ptr && *(char ***)ptr) {
3414                                 char **list = *(char ***)ptr;
3415                                 for (; *list; list++) {
3416                                         /* surround strings with whitespace in double quotes */
3417                                         if (*(list+1) == NULL) {
3418                                                 /* last item, no extra separator */
3419                                                 list_sep = "";
3420                                         }
3421                                         if ( strchr_m( *list, ' ' ) ) {
3422                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
3423                                         } else {
3424                                                 fprintf(f, "%s%s", *list, list_sep);
3425                                         }
3426                                 }
3427                         }
3428                         break;
3429
3430                 case P_STRING:
3431                 case P_USTRING:
3432                         if (*(char **)ptr) {
3433                                 fprintf(f, "%s", *(char **)ptr);
3434                         }
3435                         break;
3436                 case P_SEP:
3437                         break;
3438         }
3439 }
3440
3441 /***************************************************************************
3442  Check if two parameters are equal.
3443 ***************************************************************************/
3444
3445 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3446 {
3447         switch (type) {
3448                 case P_BOOL:
3449                 case P_BOOLREV:
3450                         return (*((bool *)ptr1) == *((bool *)ptr2));
3451
3452                 case P_INTEGER:
3453                 case P_ENUM:
3454                 case P_OCTAL:
3455                 case P_BYTES:
3456                         return (*((int *)ptr1) == *((int *)ptr2));
3457
3458                 case P_CHAR:
3459                         return (*((char *)ptr1) == *((char *)ptr2));
3460
3461                 case P_LIST:
3462                 case P_CMDLIST:
3463                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3464
3465                 case P_STRING:
3466                 case P_USTRING:
3467                 {
3468                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3469                         if (p1 && !*p1)
3470                                 p1 = NULL;
3471                         if (p2 && !*p2)
3472                                 p2 = NULL;
3473                         return (p1 == p2 || strequal(p1, p2));
3474                 }
3475                 case P_SEP:
3476                         break;
3477         }
3478         return false;
3479 }
3480
3481 /***************************************************************************
3482  Initialize any local variables in the sDefault table, after parsing a
3483  [globals] section.
3484 ***************************************************************************/
3485
3486 static void init_locals(void)
3487 {
3488         /*
3489          * We run this check once the [globals] is parsed, to force
3490          * the VFS objects and other per-share settings we need for
3491          * the standard way a AD DC is operated.  We may change these
3492          * as our code evolves, which is why we force these settings.
3493          *
3494          * We can't do this at the end of lp_load_ex(), as by that
3495          * point the services have been loaded and they will already
3496          * have "" as their vfs objects.
3497          */
3498         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
3499                 const char **vfs_objects = lp_vfs_objects(-1);
3500                 if (!vfs_objects || !vfs_objects[0]) {
3501                         if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
3502                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
3503                         } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
3504                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
3505                         } else {
3506                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
3507                         }
3508                 }
3509
3510                 lp_do_parameter(-1, "map hidden", "no");
3511                 lp_do_parameter(-1, "map system", "no");
3512                 lp_do_parameter(-1, "map readonly", "no");
3513                 lp_do_parameter(-1, "map archive", "no");
3514                 lp_do_parameter(-1, "store dos attributes", "yes");
3515         }
3516 }
3517
3518 /***************************************************************************
3519  Process a new section (service). At this stage all sections are services.
3520  Later we'll have special sections that permit server parameters to be set.
3521  Returns true on success, false on failure.
3522 ***************************************************************************/
3523
3524 static bool do_section(const char *pszSectionName, void *userdata)
3525 {
3526         bool bRetval;
3527         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3528                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3529         bRetval = false;
3530
3531         /* if we were in a global section then do the local inits */
3532         if (bInGlobalSection && !isglobal)
3533                 init_locals();
3534
3535         /* if we've just struck a global section, note the fact. */
3536         bInGlobalSection = isglobal;
3537
3538         /* check for multiple global sections */
3539         if (bInGlobalSection) {
3540                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3541                 return true;
3542         }
3543
3544         if (!bInGlobalSection && bGlobalOnly)
3545                 return true;
3546
3547         /* if we have a current service, tidy it up before moving on */
3548         bRetval = true;
3549
3550         if (iServiceIndex >= 0)
3551                 bRetval = service_ok(iServiceIndex);
3552
3553         /* if all is still well, move to the next record in the services array */
3554         if (bRetval) {
3555                 /* We put this here to avoid an odd message order if messages are */
3556                 /* issued by the post-processing of a previous section. */
3557                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3558
3559                 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3560                 if (iServiceIndex < 0) {
3561                         DEBUG(0, ("Failed to add a new service\n"));
3562                         return false;
3563                 }
3564                 /* Clean all parametric options for service */
3565                 /* They will be added during parsing again */
3566                 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3567         }
3568
3569         return bRetval;
3570 }
3571
3572
3573 /***************************************************************************
3574  Determine if a partcular base parameter is currentl set to the default value.
3575 ***************************************************************************/
3576
3577 static bool is_default(int i)
3578 {
3579         if (!defaults_saved)
3580                 return false;
3581         switch (parm_table[i].type) {
3582                 case P_LIST:
3583                 case P_CMDLIST:
3584                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
3585                                               *(const char ***)lp_parm_ptr(NULL, 
3586                                                                            &parm_table[i]));
3587                 case P_STRING:
3588                 case P_USTRING:
3589                         return strequal(parm_table[i].def.svalue,
3590                                         *(char **)lp_parm_ptr(NULL, 
3591                                                               &parm_table[i]));
3592                 case P_BOOL:
3593                 case P_BOOLREV:
3594                         return parm_table[i].def.bvalue ==
3595                                 *(bool *)lp_parm_ptr(NULL, 
3596                                                      &parm_table[i]);
3597                 case P_CHAR:
3598                         return parm_table[i].def.cvalue ==
3599                                 *(char *)lp_parm_ptr(NULL, 
3600                                                      &parm_table[i]);
3601                 case P_INTEGER:
3602                 case P_OCTAL:
3603                 case P_ENUM:
3604                 case P_BYTES:
3605                         return parm_table[i].def.ivalue ==
3606                                 *(int *)lp_parm_ptr(NULL, 
3607                                                     &parm_table[i]);
3608                 case P_SEP:
3609                         break;
3610         }
3611         return false;
3612 }
3613
3614 /***************************************************************************
3615 Display the contents of the global structure.
3616 ***************************************************************************/
3617
3618 static void dump_globals(FILE *f)
3619 {
3620         int i;
3621         struct parmlist_entry *data;
3622
3623         fprintf(f, "[global]\n");
3624
3625         for (i = 0; parm_table[i].label; i++)
3626                 if (parm_table[i].p_class == P_GLOBAL &&
3627                     !(parm_table[i].flags & FLAG_META) &&
3628                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3629                         if (defaults_saved && is_default(i))
3630                                 continue;
3631                         fprintf(f, "\t%s = ", parm_table[i].label);
3632                         print_parameter(&parm_table[i], lp_parm_ptr(NULL, 
3633                                                                     &parm_table[i]),
3634                                         f);
3635                         fprintf(f, "\n");
3636         }
3637         if (Globals.param_opt != NULL) {
3638                 data = Globals.param_opt;
3639                 while(data) {
3640                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3641                         data = data->next;
3642                 }
3643         }
3644
3645 }
3646
3647 /***************************************************************************
3648  Return true if a local parameter is currently set to the global default.
3649 ***************************************************************************/
3650
3651 bool lp_is_default(int snum, struct parm_struct *parm)
3652 {
3653         return equal_parameter(parm->type,
3654                                lp_parm_ptr(ServicePtrs[snum], parm),
3655                                lp_parm_ptr(NULL, parm));
3656 }
3657
3658 /***************************************************************************
3659  Display the contents of a single services record.
3660 ***************************************************************************/
3661
3662 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3663 {
3664         int i;
3665         struct parmlist_entry *data;
3666
3667         if (pService != &sDefault)
3668                 fprintf(f, "[%s]\n", pService->szService);
3669
3670         for (i = 0; parm_table[i].label; i++) {
3671
3672                 if (parm_table[i].p_class == P_LOCAL &&
3673                     !(parm_table[i].flags & FLAG_META) &&
3674                     (*parm_table[i].label != '-') &&
3675                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
3676                 {
3677                         if (pService == &sDefault) {
3678                                 if (defaults_saved && is_default(i))
3679                                         continue;
3680                         } else {
3681                                 if (equal_parameter(parm_table[i].type,
3682                                                     lp_parm_ptr(pService, &parm_table[i]),
3683                                                     lp_parm_ptr(NULL, &parm_table[i])))
3684                                         continue;
3685                         }
3686
3687                         fprintf(f, "\t%s = ", parm_table[i].label);
3688                         print_parameter(&parm_table[i],
3689                                         lp_parm_ptr(pService, &parm_table[i]),
3690                                         f);
3691                         fprintf(f, "\n");
3692                 }
3693         }
3694
3695                 if (pService->param_opt != NULL) {
3696                         data = pService->param_opt;
3697                         while(data) {
3698                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
3699                                 data = data->next;
3700                         }
3701                 }
3702 }
3703
3704 /***************************************************************************
3705  Display the contents of a parameter of a single services record.
3706 ***************************************************************************/
3707
3708 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3709 {
3710         int i;
3711         bool result = false;
3712         parm_class p_class;
3713         unsigned flag = 0;
3714         fstring local_parm_name;
3715         char *parm_opt;
3716         const char *parm_opt_value;
3717
3718         /* check for parametrical option */
3719         fstrcpy( local_parm_name, parm_name);
3720         parm_opt = strchr( local_parm_name, ':');
3721
3722         if (parm_opt) {
3723                 *parm_opt = '\0';
3724                 parm_opt++;
3725                 if (strlen(parm_opt)) {
3726                         parm_opt_value = lp_parm_const_string( snum,
3727                                 local_parm_name, parm_opt, NULL);
3728                         if (parm_opt_value) {
3729                                 printf( "%s\n", parm_opt_value);
3730                                 result = true;
3731                         }
3732                 }
3733                 return result;
3734         }
3735
3736         /* check for a key and print the value */
3737         if (isGlobal) {
3738                 p_class = P_GLOBAL;
3739                 flag = FLAG_GLOBAL;
3740         } else
3741                 p_class = P_LOCAL;
3742
3743         for (i = 0; parm_table[i].label; i++) {
3744                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3745                     !(parm_table[i].flags & FLAG_META) &&
3746                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3747                     (*parm_table[i].label != '-') &&
3748                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
3749                 {
3750                         void *ptr;
3751
3752                         if (isGlobal) {
3753                                 ptr = lp_parm_ptr(NULL, 
3754                                                   &parm_table[i]);
3755                         } else {
3756                                 ptr = lp_parm_ptr(ServicePtrs[snum], 
3757                                                   &parm_table[i]);
3758                         }
3759
3760                         print_parameter(&parm_table[i],
3761                                         ptr, f);
3762                         fprintf(f, "\n");
3763                         result = true;
3764                         break;
3765                 }
3766         }
3767
3768         return result;
3769 }
3770
3771 /***************************************************************************
3772  Return info about the requested parameter (given as a string).
3773  Return NULL when the string is not a valid parameter name.
3774 ***************************************************************************/
3775
3776 struct parm_struct *lp_get_parameter(const char *param_name)
3777 {
3778         int num = map_parameter(param_name);
3779
3780         if (num < 0) {
3781                 return NULL;
3782         }
3783
3784         return &parm_table[num];
3785 }
3786
3787 /***************************************************************************
3788  Return info about the next parameter in a service.
3789  snum==GLOBAL_SECTION_SNUM gives the globals.
3790  Return NULL when out of parameters.
3791 ***************************************************************************/
3792
3793 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3794 {
3795         if (snum < 0) {
3796                 /* do the globals */
3797                 for (; parm_table[*i].label; (*i)++) {
3798                         if (parm_table[*i].p_class == P_SEPARATOR)
3799                                 return &parm_table[(*i)++];
3800
3801                         if ((*parm_table[*i].label == '-'))
3802                                 continue;
3803
3804                         if ((*i) > 0
3805                             && (parm_table[*i].offset ==
3806                                 parm_table[(*i) - 1].offset)
3807                             && (parm_table[*i].p_class ==
3808                                 parm_table[(*i) - 1].p_class))
3809                                 continue;
3810
3811                         if (is_default(*i) && !allparameters)
3812                                 continue;
3813
3814                         return &parm_table[(*i)++];
3815                 }
3816         } else {
3817                 struct loadparm_service *pService = ServicePtrs[snum];
3818
3819                 for (; parm_table[*i].label; (*i)++) {
3820                         if (parm_table[*i].p_class == P_SEPARATOR)
3821                                 return &parm_table[(*i)++];
3822
3823                         if (parm_table[*i].p_class == P_LOCAL &&
3824                             (*parm_table[*i].label != '-') &&
3825                             ((*i) == 0 ||
3826                              (parm_table[*i].offset !=
3827                               parm_table[(*i) - 1].offset)))
3828                         {
3829                                 if (allparameters ||
3830                                     !equal_parameter(parm_table[*i].type,
3831                                                      lp_parm_ptr(pService, 
3832                                                                  &parm_table[*i]),
3833                                                      lp_parm_ptr(NULL, 
3834                                                                  &parm_table[*i])))
3835                                 {
3836                                         return &parm_table[(*i)++];
3837                                 }
3838                         }
3839                 }
3840         }
3841
3842         return NULL;
3843 }
3844
3845
3846 #if 0
3847 /***************************************************************************
3848  Display the contents of a single copy structure.
3849 ***************************************************************************/
3850 static void dump_copy_map(bool *pcopymap)
3851 {
3852         int i;
3853         if (!pcopymap)
3854                 return;
3855
3856         printf("\n\tNon-Copied parameters:\n");
3857
3858         for (i = 0; parm_table[i].label; i++)
3859                 if (parm_table[i].p_class == P_LOCAL &&
3860                     parm_table[i].ptr && !pcopymap[i] &&
3861                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3862                 {
3863                         printf("\t\t%s\n", parm_table[i].label);
3864                 }
3865 }
3866 #endif
3867
3868 /***************************************************************************
3869  Return TRUE if the passed service number is within range.
3870 ***************************************************************************/
3871
3872 bool lp_snum_ok(int iService)
3873 {
3874         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3875 }
3876
3877 /***************************************************************************
3878  Auto-load some home services.
3879 ***************************************************************************/
3880
3881 static void lp_add_auto_services(char *str)
3882 {
3883         char *s;
3884         char *p;
3885         int homes;
3886         char *saveptr;
3887
3888         if (!str)
3889                 return;
3890
3891         s = SMB_STRDUP(str);
3892         if (!s)
3893                 return;
3894
3895         homes = lp_servicenumber(HOMES_NAME);
3896
3897         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3898              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3899                 char *home;
3900
3901                 if (lp_servicenumber(p) >= 0)
3902                         continue;
3903
3904                 home = get_user_home_dir(talloc_tos(), p);
3905
3906                 if (home && home[0] && homes >= 0)
3907                         lp_add_home(p, homes, p, home);
3908
3909                 TALLOC_FREE(home);
3910         }
3911         SAFE_FREE(s);
3912 }
3913
3914 /***************************************************************************
3915  Auto-load one printer.
3916 ***************************************************************************/
3917
3918 void lp_add_one_printer(const char *name, const char *comment,
3919                         const char *location, void *pdata)
3920 {
3921         int printers = lp_servicenumber(PRINTERS_NAME);
3922         int i;
3923
3924         if (lp_servicenumber(name) < 0) {
3925                 lp_add_printer(name, printers);
3926                 if ((i = lp_servicenumber(name)) >= 0) {
3927                         string_set(&ServicePtrs[i]->comment, comment);
3928                         ServicePtrs[i]->autoloaded = true;
3929                 }
3930         }
3931 }
3932
3933 /***************************************************************************
3934  Have we loaded a services file yet?
3935 ***************************************************************************/
3936
3937 bool lp_loaded(void)
3938 {
3939         return (bLoaded);
3940 }
3941
3942 /***************************************************************************
3943  Unload unused services.
3944 ***************************************************************************/
3945
3946 void lp_killunused(struct smbd_server_connection *sconn,
3947                    bool (*snumused) (struct smbd_server_connection *, int))
3948 {
3949         int i;
3950         for (i = 0; i < iNumServices; i++) {
3951                 if (!VALID(i))
3952                         continue;
3953
3954                 /* don't kill autoloaded or usershare services */
3955                 if ( ServicePtrs[i]->autoloaded ||
3956                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3957                         continue;
3958                 }
3959
3960                 if (!snumused || !snumused(sconn, i)) {
3961                         free_service_byindex(i);
3962                 }
3963         }
3964 }
3965
3966 /**
3967  * Kill all except autoloaded and usershare services - convenience wrapper
3968  */
3969 void lp_kill_all_services(void)
3970 {
3971         lp_killunused(NULL, NULL);
3972 }
3973
3974 /***************************************************************************
3975  Unload a service.
3976 ***************************************************************************/
3977
3978 void lp_killservice(int iServiceIn)
3979 {
3980         if (VALID(iServiceIn)) {
3981                 free_service_byindex(iServiceIn);
3982         }
3983 }
3984
3985 /***************************************************************************
3986  Save the curent values of all global and sDefault parameters into the 
3987  defaults union. This allows testparm to show only the
3988  changed (ie. non-default) parameters.
3989 ***************************************************************************/
3990
3991 static void lp_save_defaults(void)
3992 {
3993         int i;
3994         for (i = 0; parm_table[i].label; i++) {
3995                 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3996                     && parm_table[i].p_class == parm_table[i - 1].p_class)
3997                         continue;
3998                 switch (parm_table[i].type) {
3999                         case P_LIST:
4000                         case P_CMDLIST:
4001                                 parm_table[i].def.lvalue = str_list_copy(
4002                                         NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
4003                                 break;
4004                         case P_STRING:
4005                         case P_USTRING:
4006                                 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
4007                                 break;
4008                         case P_BOOL:
4009                         case P_BOOLREV:
4010                                 parm_table[i].def.bvalue =
4011                                         *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
4012                                 break;
4013                         case P_CHAR:
4014                                 parm_table[i].def.cvalue =
4015                                         *(char *)lp_parm_ptr(NULL, &parm_table[i]);
4016                                 break;
4017                         case P_INTEGER:
4018                         case P_OCTAL:
4019                         case P_ENUM:
4020                         case P_BYTES:
4021                                 parm_table[i].def.ivalue =
4022                                         *(int *)lp_parm_ptr(NULL, &parm_table[i]);
4023                                 break;
4024                         case P_SEP:
4025                                 break;
4026                 }
4027         }
4028         defaults_saved = true;
4029 }
4030
4031 /***********************************************************
4032  If we should send plaintext/LANMAN passwords in the clinet
4033 ************************************************************/
4034
4035 static void set_allowed_client_auth(void)
4036 {
4037         if (Globals.bClientNTLMv2Auth) {
4038                 Globals.bClientLanManAuth = false;
4039         }
4040         if (!Globals.bClientLanManAuth) {
4041                 Globals.bClientPlaintextAuth = false;
4042         }
4043 }
4044
4045 /***************************************************************************
4046  JRA.
4047  The following code allows smbd to read a user defined share file.
4048  Yes, this is my intent. Yes, I'm comfortable with that...
4049
4050  THE FOLLOWING IS SECURITY CRITICAL CODE.
4051
4052  It washes your clothes, it cleans your house, it guards you while you sleep...
4053  Do not f%^k with it....
4054 ***************************************************************************/
4055
4056 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4057
4058 /***************************************************************************
4059  Check allowed stat state of a usershare file.
4060  Ensure we print out who is dicking with us so the admin can
4061  get their sorry ass fired.
4062 ***************************************************************************/
4063
4064 static bool check_usershare_stat(const char *fname,
4065                                  const SMB_STRUCT_STAT *psbuf)
4066 {
4067         if (!S_ISREG(psbuf->st_ex_mode)) {
4068                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4069                         "not a regular file\n",
4070                         fname, (unsigned int)psbuf->st_ex_uid ));
4071                 return false;
4072         }
4073
4074         /* Ensure this doesn't have the other write bit set. */
4075         if (psbuf->st_ex_mode & S_IWOTH) {
4076                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4077                         "public write. Refusing to allow as a usershare file.\n",
4078                         fname, (unsigned int)psbuf->st_ex_uid ));
4079                 return false;
4080         }
4081
4082         /* Should be 10k or less. */
4083         if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4084                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4085                         "too large (%u) to be a user share file.\n",
4086                         fname, (unsigned int)psbuf->st_ex_uid,
4087                         (unsigned int)psbuf->st_ex_size ));
4088                 return false;
4089         }
4090
4091         return true;
4092 }
4093
4094 /***************************************************************************
4095  Parse the contents of a usershare file.
4096 ***************************************************************************/
4097
4098 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4099                         SMB_STRUCT_STAT *psbuf,
4100                         const char *servicename,
4101                         int snum,
4102                         char **lines,
4103                         int numlines,
4104                         char **pp_sharepath,
4105                         char **pp_comment,
4106                         char **pp_cp_servicename,
4107                         struct security_descriptor **ppsd,
4108                         bool *pallow_guest)
4109 {
4110         const char **prefixallowlist = lp_usershare_prefix_allow_list();
4111         const char **prefixdenylist = lp_usershare_prefix_deny_list();
4112         int us_vers;
4113         DIR *dp;
4114         SMB_STRUCT_STAT sbuf;
4115         char *sharepath = NULL;
4116         char *comment = NULL;
4117
4118         *pp_sharepath = NULL;
4119         *pp_comment = NULL;
4120
4121         *pallow_guest = false;
4122
4123         if (numlines < 4) {
4124                 return USERSHARE_MALFORMED_FILE;
4125         }
4126
4127         if (strcmp(lines[0], "#VERSION 1") == 0) {
4128                 us_vers = 1;
4129         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4130                 us_vers = 2;
4131                 if (numlines < 5) {
4132                         return USERSHARE_MALFORMED_FILE;
4133                 }
4134         } else {
4135                 return USERSHARE_BAD_VERSION;
4136         }
4137
4138         if (strncmp(lines[1], "path=", 5) != 0) {
4139                 return USERSHARE_MALFORMED_PATH;
4140         }
4141
4142         sharepath = talloc_strdup(ctx, &lines[1][5]);
4143         if (!sharepath) {
4144                 return USERSHARE_POSIX_ERR;
4145         }
4146         trim_string(sharepath, " ", " ");
4147
4148         if (strncmp(lines[2], "comment=", 8) != 0) {
4149                 return USERSHARE_MALFORMED_COMMENT_DEF;
4150         }
4151
4152         comment = talloc_strdup(ctx, &lines[2][8]);
4153         if (!comment) {
4154                 return USERSHARE_POSIX_ERR;
4155         }
4156         trim_string(comment, " ", " ");
4157         trim_char(comment, '"', '"');
4158
4159         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4160                 return USERSHARE_MALFORMED_ACL_DEF;
4161         }
4162
4163         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4164                 return USERSHARE_ACL_ERR;
4165         }
4166
4167         if (us_vers == 2) {
4168                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4169                         return USERSHARE_MALFORMED_ACL_DEF;
4170                 }
4171                 if (lines[4][9] == 'y') {
4172                         *pallow_guest = true;
4173                 }
4174
4175                 /* Backwards compatible extension to file version #2. */
4176                 if (numlines > 5) {
4177                         if (strncmp(lines[5], "sharename=", 10) != 0) {
4178                                 return USERSHARE_MALFORMED_SHARENAME_DEF;
4179                         }
4180                         if (!strequal(&lines[5][10], servicename)) {
4181                                 return USERSHARE_BAD_SHARENAME;
4182                         }
4183                         *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4184                         if (!*pp_cp_servicename) {
4185                                 return USERSHARE_POSIX_ERR;
4186                         }
4187                 }
4188         }
4189
4190         if (*pp_cp_servicename == NULL) {
4191                 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4192                 if (!*pp_cp_servicename) {
4193                         return USERSHARE_POSIX_ERR;
4194                 }
4195         }
4196
4197         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4198                 /* Path didn't change, no checks needed. */
4199                 *pp_sharepath = sharepath;
4200                 *pp_comment = comment;
4201                 return USERSHARE_OK;
4202         }
4203
4204         /* The path *must* be absolute. */
4205         if (sharepath[0] != '/') {
4206                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4207                         servicename, sharepath));
4208                 return USERSHARE_PATH_NOT_ABSOLUTE;
4209         }
4210
4211         /* If there is a usershare prefix deny list ensure one of these paths
4212            doesn't match the start of the user given path. */
4213         if (prefixdenylist) {
4214                 int i;
4215                 for ( i=0; prefixdenylist[i]; i++ ) {
4216                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4217                                 servicename, i, prefixdenylist[i], sharepath ));
4218                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4219                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4220                                         "usershare prefix deny list entries.\n",
4221                                         servicename, sharepath));
4222                                 return USERSHARE_PATH_IS_DENIED;
4223                         }
4224                 }
4225         }
4226
4227         /* If there is a usershare prefix allow list ensure one of these paths
4228            does match the start of the user given path. */
4229
4230         if (prefixallowlist) {
4231                 int i;
4232                 for ( i=0; prefixallowlist[i]; i++ ) {
4233                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4234                                 servicename, i, prefixallowlist[i], sharepath ));
4235                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4236                                 break;
4237                         }
4238                 }
4239                 if (prefixallowlist[i] == NULL) {
4240                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4241                                 "usershare prefix allow list entries.\n",
4242                                 servicename, sharepath));
4243                         return USERSHARE_PATH_NOT_ALLOWED;
4244                 }
4245         }
4246
4247         /* Ensure this is pointing to a directory. */
4248         dp = opendir(sharepath);
4249
4250         if (!dp) {
4251                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4252                         servicename, sharepath));
4253                 return USERSHARE_PATH_NOT_DIRECTORY;
4254         }
4255
4256         /* Ensure the owner of the usershare file has permission to share
4257            this directory. */
4258
4259         if (sys_stat(sharepath, &sbuf, false) == -1) {
4260                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4261                         servicename, sharepath, strerror(errno) ));
4262                 closedir(dp);
4263                 return USERSHARE_POSIX_ERR;
4264         }
4265
4266         closedir(dp);
4267
4268         if (!S_ISDIR(sbuf.st_ex_mode)) {
4269                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4270                         servicename, sharepath ));
4271                 return USERSHARE_PATH_NOT_DIRECTORY;
4272         }
4273
4274         /* Check if sharing is restricted to owner-only. */
4275         /* psbuf is the stat of the usershare definition file,
4276            sbuf is the stat of the target directory to be shared. */
4277
4278         if (lp_usershare_owner_only()) {
4279                 /* root can share anything. */
4280                 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4281                         return USERSHARE_PATH_NOT_ALLOWED;
4282                 }
4283         }
4284
4285         *pp_sharepath = sharepath;
4286         *pp_comment = comment;
4287         return USERSHARE_OK;
4288 }
4289
4290 /***************************************************************************
4291  Deal with a usershare file.
4292  Returns:
4293         >= 0 - snum
4294         -1 - Bad name, invalid contents.
4295            - service name already existed and not a usershare, problem
4296             with permissions to share directory etc.
4297 ***************************************************************************/
4298
4299 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4300 {
4301         SMB_STRUCT_STAT sbuf;
4302         SMB_STRUCT_STAT lsbuf;
4303         char *fname = NULL;
4304         char *sharepath = NULL;
4305         char *comment = NULL;
4306         char *cp_service_name = NULL;
4307         char **lines = NULL;
4308         int numlines = 0;
4309         int fd = -1;
4310         int iService = -1;
4311         TALLOC_CTX *ctx = talloc_stackframe();
4312         struct security_descriptor *psd = NULL;
4313         bool guest_ok = false;
4314         char *canon_name = NULL;
4315         bool added_service = false;
4316         int ret = -1;
4317
4318         /* Ensure share name doesn't contain invalid characters. */
4319         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4320                 DEBUG(0,("process_usershare_file: share name %s contains "
4321                         "invalid characters (any of %s)\n",
4322                         file_name, INVALID_SHARENAME_CHARS ));
4323                 goto out;
4324         }
4325
4326         canon_name = canonicalize_servicename(ctx, file_name);
4327         if (!canon_name) {
4328                 goto out;
4329         }
4330
4331         fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4332         if (!fname) {
4333                 goto out;
4334         }
4335
4336         /* Minimize the race condition by doing an lstat before we
4337            open and fstat. Ensure this isn't a symlink link. */
4338
4339         if (sys_lstat(fname, &lsbuf, false) != 0) {
4340                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4341                         fname, strerror(errno) ));
4342                 goto out;
4343         }
4344
4345         /* This must be a regular file, not a symlink, directory or
4346            other strange filetype. */
4347         if (!check_usershare_stat(fname, &lsbuf)) {
4348                 goto out;
4349         }
4350
4351         {
4352                 TDB_DATA data;
4353                 NTSTATUS status;
4354
4355                 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4356                                                canon_name, &data);
4357
4358                 iService = -1;
4359
4360                 if (NT_STATUS_IS_OK(status) &&
4361                     (data.dptr != NULL) &&
4362                     (data.dsize == sizeof(iService))) {
4363                         memcpy(&iService, data.dptr, sizeof(iService));
4364                 }
4365         }
4366
4367         if (iService != -1 &&
4368             timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4369                              &lsbuf.st_ex_mtime) == 0) {
4370                 /* Nothing changed - Mark valid and return. */
4371                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4372                         canon_name ));
4373                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4374                 ret = iService;
4375                 goto out;
4376         }
4377
4378         /* Try and open the file read only - no symlinks allowed. */
4379 #ifdef O_NOFOLLOW
4380         fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4381 #else
4382         fd = open(fname, O_RDONLY, 0);
4383 #endif
4384
4385         if (fd == -1) {
4386                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4387                         fname, strerror(errno) ));
4388                 goto out;
4389         }
4390
4391         /* Now fstat to be *SURE* it's a regular file. */
4392         if (sys_fstat(fd, &sbuf, false) != 0) {
4393                 close(fd);
4394                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4395                         fname, strerror(errno) ));
4396                 goto out;
4397         }
4398
4399         /* Is it the same dev/inode as was lstated ? */
4400         if (!check_same_stat(&lsbuf, &sbuf)) {
4401                 close(fd);
4402                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4403                         "Symlink spoofing going on ?\n", fname ));
4404                 goto out;
4405         }
4406
4407         /* This must be a regular file, not a symlink, directory or
4408            other strange filetype. */
4409         if (!check_usershare_stat(fname, &sbuf)) {
4410                 close(fd);
4411                 goto out;
4412         }
4413
4414         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4415
4416         close(fd);
4417         if (lines == NULL) {
4418                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4419                         fname, (unsigned int)sbuf.st_ex_uid ));
4420                 goto out;
4421         }
4422
4423         if (parse_usershare_file(ctx, &sbuf, file_name,
4424                         iService, lines, numlines, &sharepath,
4425                         &comment, &cp_service_name,
4426                         &psd, &guest_ok) != USERSHARE_OK) {
4427                 goto out;
4428         }
4429
4430         /* Everything ok - add the service possibly using a template. */
4431         if (iService < 0) {
4432                 const struct loadparm_service *sp = &sDefault;
4433                 if (snum_template != -1) {
4434                         sp = ServicePtrs[snum_template];
4435                 }
4436
4437                 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4438                         DEBUG(0, ("process_usershare_file: Failed to add "
4439                                 "new service %s\n", cp_service_name));
4440                         goto out;
4441                 }
4442
4443                 added_service = true;
4444
4445                 /* Read only is controlled by usershare ACL below. */
4446                 ServicePtrs[iService]->bRead_only = false;
4447         }
4448
4449         /* Write the ACL of the new/modified share. */
4450         if (!set_share_security(canon_name, psd)) {
4451                  DEBUG(0, ("process_usershare_file: Failed to set share "
4452                         "security for user share %s\n",
4453                         canon_name ));
4454                 goto out;
4455         }
4456
4457         /* If from a template it may be marked invalid. */
4458         ServicePtrs[iService]->valid = true;
4459
4460         /* Set the service as a valid usershare. */
4461         ServicePtrs[iService]->usershare = USERSHARE_VALID;
4462
4463         /* Set guest access. */
4464         if (lp_usershare_allow_guests()) {
4465                 ServicePtrs[iService]->bGuest_ok = guest_ok;
4466         }
4467
4468         /* And note when it was loaded. */
4469         ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4470         string_set(&ServicePtrs[iService]->szPath, sharepath);
4471         string_set(&ServicePtrs[iService]->comment, comment);
4472
4473         ret = iService;
4474
4475   out:
4476
4477         if (ret == -1 && iService != -1 && added_service) {
4478                 lp_remove_service(iService);
4479         }
4480
4481         TALLOC_FREE(lines);
4482         TALLOC_FREE(ctx);
4483         return ret;
4484 }
4485
4486 /***************************************************************************
4487  Checks if a usershare entry has been modified since last load.
4488 ***************************************************************************/
4489
4490 static bool usershare_exists(int iService, struct timespec *last_mod)
4491 {
4492         SMB_STRUCT_STAT lsbuf;
4493         const char *usersharepath = Globals.szUsersharePath;
4494         char *fname;
4495
4496         if (asprintf(&fname, "%s/%s",
4497                                 usersharepath,
4498                                 ServicePtrs[iService]->szService) < 0) {
4499                 return false;
4500         }
4501
4502         if (sys_lstat(fname, &lsbuf, false) != 0) {
4503                 SAFE_FREE(fname);
4504                 return false;
4505         }
4506
4507         if (!S_ISREG(lsbuf.st_ex_mode)) {
4508                 SAFE_FREE(fname);
4509                 return false;
4510         }
4511
4512         SAFE_FREE(fname);
4513         *last_mod = lsbuf.st_ex_mtime;
4514         return true;
4515 }
4516
4517 /***************************************************************************
4518  Load a usershare service by name. Returns a valid servicenumber or -1.
4519 ***************************************************************************/
4520
4521 int load_usershare_service(const char *servicename)
4522 {
4523         SMB_STRUCT_STAT sbuf;
4524         const char *usersharepath = Globals.szUsersharePath;
4525         int max_user_shares = Globals.iUsershareMaxShares;
4526         int snum_template = -1;
4527
4528         if (*usersharepath == 0 ||  max_user_shares == 0) {
4529                 return -1;
4530         }
4531
4532         if (sys_stat(usersharepath, &sbuf, false) != 0) {
4533                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4534                         usersharepath, strerror(errno) ));
4535                 return -1;
4536         }
4537
4538         if (!S_ISDIR(sbuf.st_ex_mode)) {
4539                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4540                         usersharepath ));
4541                 return -1;
4542         }
4543
4544         /*
4545          * This directory must be owned by root, and have the 't' bit set.
4546          * It also must not be writable by "other".
4547          */
4548
4549 #ifdef S_ISVTX
4550         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4551 #else
4552         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4553 #endif
4554                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4555                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4556                         usersharepath ));
4557                 return -1;
4558         }
4559
4560         /* Ensure the template share exists if it's set. */
4561         if (Globals.szUsershareTemplateShare[0]) {
4562                 /* We can't use lp_servicenumber here as we are recommending that
4563                    template shares have -valid=false set. */
4564                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4565                         if (ServicePtrs[snum_template]->szService &&
4566                                         strequal(ServicePtrs[snum_template]->szService,
4567                                                 Globals.szUsershareTemplateShare)) {
4568                                 break;
4569                         }
4570                 }
4571
4572                 if (snum_template == -1) {
4573                         DEBUG(0,("load_usershare_service: usershare template share %s "
4574                                 "does not exist.\n",
4575                                 Globals.szUsershareTemplateShare ));
4576                         return -1;
4577                 }
4578         }
4579
4580         return process_usershare_file(usersharepath, servicename, snum_template);
4581 }
4582
4583 /***************************************************************************
4584  Load all user defined shares from the user share directory.
4585  We only do this if we're enumerating the share list.
4586  This is the function that can delete usershares that have
4587  been removed.
4588 ***************************************************************************/
4589
4590 int load_usershare_shares(struct smbd_server_connection *sconn,
4591                           bool (*snumused) (struct smbd_server_connection *, int))
4592 {
4593         DIR *dp;
4594         SMB_STRUCT_STAT sbuf;
4595         struct dirent *de;
4596         int num_usershares = 0;
4597         int max_user_shares = Globals.iUsershareMaxShares;
4598         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4599         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4600         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4601         int iService;
4602         int snum_template = -1;
4603         const char *usersharepath = Globals.szUsersharePath;
4604         int ret = lp_numservices();
4605         TALLOC_CTX *tmp_ctx;
4606
4607         if (max_user_shares == 0 || *usersharepath == '\0') {
4608                 return lp_numservices();
4609         }
4610
4611         if (sys_stat(usersharepath, &sbuf, false) != 0) {
4612                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4613                         usersharepath, strerror(errno) ));
4614                 return ret;
4615         }
4616
4617         /*
4618          * This directory must be owned by root, and have the 't' bit set.
4619          * It also must not be writable by "other".
4620          */
4621
4622 #ifdef S_ISVTX
4623         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4624 #else
4625         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4626 #endif
4627                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4628                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4629                         usersharepath ));
4630                 return ret;
4631         }
4632
4633         /* Ensure the template share exists if it's set. */
4634         if (Globals.szUsershareTemplateShare[0]) {
4635                 /* We can't use lp_servicenumber here as we are recommending that
4636                    template shares have -valid=false set. */
4637                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4638                         if (ServicePtrs[snum_template]->szService &&
4639                                         strequal(ServicePtrs[snum_template]->szService,
4640                                                 Globals.szUsershareTemplateShare)) {
4641                                 break;
4642                         }
4643                 }
4644
4645                 if (snum_template == -1) {
4646                         DEBUG(0,("load_usershare_shares: usershare template share %s "
4647                                 "does not exist.\n",
4648                                 Globals.szUsershareTemplateShare ));
4649                         return ret;
4650                 }
4651         }
4652
4653         /* Mark all existing usershares as pending delete. */
4654         for (iService = iNumServices - 1; iService >= 0; iService--) {
4655                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4656                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4657                 }
4658         }
4659
4660         dp = opendir(usersharepath);
4661         if (!dp) {
4662                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4663                         usersharepath, strerror(errno) ));
4664                 return ret;
4665         }
4666
4667         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4668                         (de = readdir(dp));
4669                         num_dir_entries++ ) {
4670                 int r;
4671                 const char *n = de->d_name;
4672
4673                 /* Ignore . and .. */
4674                 if (*n == '.') {
4675                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4676                                 continue;
4677                         }
4678                 }
4679
4680                 if (n[0] == ':') {
4681                         /* Temporary file used when creating a share. */
4682                         num_tmp_dir_entries++;
4683                 }
4684
4685                 /* Allow 20% tmp entries. */
4686                 if (num_tmp_dir_entries > allowed_tmp_entries) {
4687                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4688                                 "in directory %s\n",
4689                                 num_tmp_dir_entries, usersharepath));
4690                         break;
4691                 }
4692
4693                 r = process_usershare_file(usersharepath, n, snum_template);
4694                 if (r == 0) {
4695                         /* Update the services count. */
4696                         num_usershares++;
4697                         if (num_usershares >= max_user_shares) {
4698                                 DEBUG(0,("load_usershare_shares: max user shares reached "
4699                                         "on file %s in directory %s\n",
4700                                         n, usersharepath ));
4701                                 break;
4702                         }
4703                 } else if (r == -1) {
4704                         num_bad_dir_entries++;
4705                 }
4706
4707                 /* Allow 20% bad entries. */
4708                 if (num_bad_dir_entries > allowed_bad_entries) {
4709                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4710                                 "in directory %s\n",
4711                                 num_bad_dir_entries, usersharepath));
4712                         break;
4713                 }
4714
4715                 /* Allow 20% bad entries. */
4716                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4717                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4718                         "in directory %s\n",
4719                         num_dir_entries, usersharepath));
4720                         break;
4721                 }
4722         }
4723
4724         closedir(dp);
4725
4726         /* Sweep through and delete any non-refreshed usershares that are
4727            not currently in use. */
4728         tmp_ctx = talloc_stackframe();
4729         for (iService = iNumServices - 1; iService >= 0; iService--) {
4730                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4731                         char *servname;
4732
4733                         if (snumused && snumused(sconn, iService)) {
4734                                 continue;
4735                         }
4736
4737                         servname = lp_servicename(tmp_ctx, iService);
4738
4739                         /* Remove from the share ACL db. */
4740                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4741                                   servname ));
4742                         delete_share_security(servname);
4743                         free_service_byindex(iService);
4744                 }
4745         }
4746         talloc_free(tmp_ctx);
4747
4748         return lp_numservices();
4749 }
4750
4751 /********************************************************
4752  Destroy global resources allocated in this file
4753 ********************************************************/
4754
4755 void gfree_loadparm(void)
4756 {
4757         int i;
4758
4759         free_file_list();
4760
4761         /* Free resources allocated to services */
4762
4763         for ( i = 0; i < iNumServices; i++ ) {
4764                 if ( VALID(i) ) {
4765                         free_service_byindex(i);
4766                 }
4767         }
4768
4769         SAFE_FREE( ServicePtrs );
4770         iNumServices = 0;
4771
4772         /* Now release all resources allocated to global
4773            parameters and the default service */
4774
4775         free_global_parameters();
4776 }
4777
4778
4779 /***************************************************************************
4780  Allow client apps to specify that they are a client
4781 ***************************************************************************/
4782 static void lp_set_in_client(bool b)
4783 {
4784     in_client = b;
4785 }
4786
4787
4788 /***************************************************************************
4789  Determine if we're running in a client app
4790 ***************************************************************************/
4791 static bool lp_is_in_client(void)
4792 {
4793     return in_client;
4794 }
4795
4796 /***************************************************************************
4797  Load the services array from the services file. Return true on success,
4798  false on failure.
4799 ***************************************************************************/
4800
4801 static bool lp_load_ex(const char *pszFname,
4802                        bool global_only,
4803                        bool save_defaults,
4804                        bool add_ipc,
4805                        bool initialize_globals,
4806                        bool allow_include_registry,
4807                        bool load_all_shares)
4808 {
4809         char *n2 = NULL;
4810         bool bRetval;
4811
4812         bRetval = false;
4813
4814         DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4815
4816         bInGlobalSection = true;
4817         bGlobalOnly = global_only;
4818         bAllowIncludeRegistry = allow_include_registry;
4819
4820         init_globals(initialize_globals);
4821
4822         free_file_list();
4823
4824         if (save_defaults) {
4825                 init_locals();
4826                 lp_save_defaults();
4827         }
4828
4829         if (!initialize_globals) {
4830                 free_param_opts(&Globals.param_opt);
4831                 apply_lp_set_cmdline();
4832         }
4833
4834         lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4835
4836         /* We get sections first, so have to start 'behind' to make up */
4837         iServiceIndex = -1;
4838
4839         if (lp_config_backend_is_file()) {
4840                 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4841                                         current_user_info.domain,
4842                                         pszFname);
4843                 if (!n2) {
4844                         smb_panic("lp_load_ex: out of memory");
4845                 }
4846
4847                 add_to_file_list(pszFname, n2);
4848
4849                 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4850                 TALLOC_FREE(n2);
4851
4852                 /* finish up the last section */
4853                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4854                 if (bRetval) {
4855                         if (iServiceIndex >= 0) {
4856                                 bRetval = service_ok(iServiceIndex);
4857                         }
4858                 }
4859
4860                 if (lp_config_backend_is_registry()) {
4861                         /* config backend changed to registry in config file */
4862                         /*
4863                          * We need to use this extra global variable here to
4864                          * survive restart: init_globals uses this as a default
4865                          * for ConfigBackend. Otherwise, init_globals would
4866                          *  send us into an endless loop here.
4867                          */
4868                         config_backend = CONFIG_BACKEND_REGISTRY;
4869                         /* start over */
4870                         DEBUG(1, ("lp_load_ex: changing to config backend "
4871                                   "registry\n"));
4872                         init_globals(true);
4873                         lp_kill_all_services();
4874                         return lp_load_ex(pszFname, global_only, save_defaults,
4875                                           add_ipc, initialize_globals,
4876                                           allow_include_registry,
4877                                           load_all_shares);
4878                 }
4879         } else if (lp_config_backend_is_registry()) {
4880                 bRetval = process_registry_globals();
4881         } else {
4882                 DEBUG(0, ("Illegal config  backend given: %d\n",
4883                           lp_config_backend()));
4884                 bRetval = false;
4885         }
4886
4887         if (bRetval && lp_registry_shares()) {
4888                 if (load_all_shares) {
4889                         bRetval = process_registry_shares();
4890                 } else {
4891                         bRetval = reload_registry_shares();
4892                 }
4893         }
4894
4895         {
4896                 char *serv = lp_auto_services(talloc_tos());
4897                 lp_add_auto_services(serv);
4898                 TALLOC_FREE(serv);
4899         }
4900
4901         if (add_ipc) {
4902                 /* When 'restrict anonymous = 2' guest connections to ipc$
4903                    are denied */
4904                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4905                 if ( lp_enable_asu_support() ) {
4906                         lp_add_ipc("ADMIN$", false);
4907                 }
4908         }
4909
4910         set_allowed_client_auth();
4911
4912         if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4913                 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4914                           lp_passwordserver()));
4915         }
4916
4917         bLoaded = true;
4918
4919         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4920         /* if bWINSsupport is true and we are in the client            */
4921         if (lp_is_in_client() && Globals.bWINSsupport) {
4922                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4923         }
4924
4925         init_iconv();
4926
4927         fault_configure(smb_panic_s3);
4928
4929         /*
4930          * We run this check once the whole smb.conf is parsed, to
4931          * force some settings for the standard way a AD DC is
4932          * operated.  We may changed these as our code evolves, which
4933          * is why we force these settings.
4934          */
4935         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4936                 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4937
4938                 lp_do_parameter(-1, "rpc_server:default", "external");
4939                 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4940                 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4941                 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4942                 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4943                 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4944                 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4945                 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4946                 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4947         }
4948
4949         bAllowIncludeRegistry = true;
4950
4951         return (bRetval);
4952 }
4953
4954 bool lp_load(const char *pszFname,
4955              bool global_only,
4956              bool save_defaults,
4957              bool add_ipc,
4958              bool initialize_globals)
4959 {
4960         return lp_load_ex(pszFname,
4961                           global_only,
4962                           save_defaults,
4963                           add_ipc,
4964                           initialize_globals,
4965                           true,   /* allow_include_registry */
4966                           false); /* load_all_shares*/
4967 }
4968
4969 bool lp_load_initial_only(const char *pszFname)
4970 {
4971         return lp_load_ex(pszFname,
4972                           true,   /* global only */
4973                           false,  /* save_defaults */
4974                           false,  /* add_ipc */
4975                           true,   /* initialize_globals */
4976                           false,  /* allow_include_registry */
4977                           false); /* load_all_shares*/
4978 }
4979
4980 /**
4981  * most common lp_load wrapper, loading only the globals
4982  */
4983 bool lp_load_global(const char *file_name)
4984 {
4985         return lp_load_ex(file_name,
4986                           true,   /* global_only */
4987                           false,  /* save_defaults */
4988                           false,  /* add_ipc */
4989                           true,   /* initialize_globals */
4990                           true,   /* allow_include_registry */
4991                           false); /* load_all_shares*/
4992 }
4993
4994 /**
4995  * lp_load wrapper, especially for clients
4996  */
4997 bool lp_load_client(const char *file_name)
4998 {
4999         lp_set_in_client(true);
5000
5001         return lp_load_global(file_name);
5002 }
5003
5004 /**
5005  * lp_load wrapper, loading only globals, but intended
5006  * for subsequent calls, not reinitializing the globals
5007  * to default values
5008  */
5009 bool lp_load_global_no_reinit(const char *file_name)
5010 {
5011         return lp_load_ex(file_name,
5012                           true,   /* global_only */
5013                           false,  /* save_defaults */
5014                           false,  /* add_ipc */
5015                           false,  /* initialize_globals */
5016                           true,   /* allow_include_registry */
5017                           false); /* load_all_shares*/
5018 }
5019
5020 /**
5021  * lp_load wrapper, especially for clients, no reinitialization
5022  */
5023 bool lp_load_client_no_reinit(const char *file_name)
5024 {
5025         lp_set_in_client(true);
5026
5027         return lp_load_global_no_reinit(file_name);
5028 }
5029
5030 bool lp_load_with_registry_shares(const char *pszFname,
5031                                   bool global_only,
5032                                   bool save_defaults,
5033                                   bool add_ipc,
5034                                   bool initialize_globals)
5035 {
5036         return lp_load_ex(pszFname,
5037                           global_only,
5038                           save_defaults,
5039                           add_ipc,
5040                           initialize_globals,
5041                           true,  /* allow_include_registry */
5042                           true); /* load_all_shares*/
5043 }
5044
5045 /***************************************************************************
5046  Return the max number of services.
5047 ***************************************************************************/
5048
5049 int lp_numservices(void)
5050 {
5051         return (iNumServices);
5052 }
5053
5054 /***************************************************************************
5055 Display the contents of the services array in human-readable form.
5056 ***************************************************************************/
5057
5058 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5059 {
5060         int iService;
5061
5062         if (show_defaults)
5063                 defaults_saved = false;
5064
5065         dump_globals(f);
5066
5067         dump_a_service(&sDefault, f);
5068
5069         for (iService = 0; iService < maxtoprint; iService++) {
5070                 fprintf(f,"\n");
5071                 lp_dump_one(f, show_defaults, iService);
5072         }
5073 }
5074
5075 /***************************************************************************
5076 Display the contents of one service in human-readable form.
5077 ***************************************************************************/
5078
5079 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5080 {
5081         if (VALID(snum)) {
5082                 if (ServicePtrs[snum]->szService[0] == '\0')
5083                         return;
5084                 dump_a_service(ServicePtrs[snum], f);
5085         }
5086 }
5087
5088 /***************************************************************************
5089 Return the number of the service with the given name, or -1 if it doesn't
5090 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5091 getservicebyname()! This works ONLY if all services have been loaded, and
5092 does not copy the found service.
5093 ***************************************************************************/
5094
5095 int lp_servicenumber(const char *pszServiceName)
5096 {
5097         int iService;
5098         fstring serviceName;
5099
5100         if (!pszServiceName) {
5101                 return GLOBAL_SECTION_SNUM;
5102         }
5103
5104         for (iService = iNumServices - 1; iService >= 0; iService--) {
5105                 if (VALID(iService) && ServicePtrs[iService]->szService) {
5106                         /*
5107                          * The substitution here is used to support %U is
5108                          * service names
5109                          */
5110                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
5111                         standard_sub_basic(get_current_username(),
5112                                            current_user_info.domain,
5113                                            serviceName,sizeof(serviceName));
5114                         if (strequal(serviceName, pszServiceName)) {
5115                                 break;
5116                         }
5117                 }
5118         }
5119
5120         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5121                 struct timespec last_mod;
5122
5123                 if (!usershare_exists(iService, &last_mod)) {
5124                         /* Remove the share security tdb entry for it. */
5125                         delete_share_security(lp_servicename(talloc_tos(), iService));
5126                         /* Remove it from the array. */
5127                         free_service_byindex(iService);
5128                         /* Doesn't exist anymore. */
5129                         return GLOBAL_SECTION_SNUM;
5130                 }
5131
5132                 /* Has it been modified ? If so delete and reload. */
5133                 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5134                                      &last_mod) < 0) {
5135                         /* Remove it from the array. */
5136                         free_service_byindex(iService);
5137                         /* and now reload it. */
5138                         iService = load_usershare_service(pszServiceName);
5139                 }
5140         }
5141
5142         if (iService < 0) {
5143                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5144                 return GLOBAL_SECTION_SNUM;
5145         }
5146
5147         return (iService);
5148 }
5149
5150 /*******************************************************************
5151  A useful volume label function. 
5152 ********************************************************************/
5153
5154 const char *volume_label(TALLOC_CTX *ctx, int snum)
5155 {
5156         char *ret;
5157         const char *label = lp_volume(ctx, snum);
5158         if (!*label) {
5159                 label = lp_servicename(ctx, snum);
5160         }
5161
5162         /* This returns a 33 byte guarenteed null terminated string. */
5163         ret = talloc_strndup(ctx, label, 32);
5164         if (!ret) {
5165                 return "";
5166         }               
5167         return ret;
5168 }
5169
5170 /*******************************************************************
5171  Get the default server type we will announce as via nmbd.
5172 ********************************************************************/
5173
5174 int lp_default_server_announce(void)
5175 {
5176         int default_server_announce = 0;
5177         default_server_announce |= SV_TYPE_WORKSTATION;
5178         default_server_announce |= SV_TYPE_SERVER;
5179         default_server_announce |= SV_TYPE_SERVER_UNIX;
5180
5181         /* note that the flag should be set only if we have a 
5182            printer service but nmbd doesn't actually load the 
5183            services so we can't tell   --jerry */
5184
5185         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5186
5187         default_server_announce |= SV_TYPE_SERVER_NT;
5188         default_server_announce |= SV_TYPE_NT;
5189
5190         switch (lp_server_role()) {
5191                 case ROLE_DOMAIN_MEMBER:
5192                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5193                         break;
5194                 case ROLE_DOMAIN_PDC:
5195                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5196                         break;
5197                 case ROLE_DOMAIN_BDC:
5198                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5199                         break;
5200                 case ROLE_STANDALONE:
5201                 default:
5202                         break;
5203         }
5204         if (lp_time_server())
5205                 default_server_announce |= SV_TYPE_TIME_SOURCE;
5206
5207         if (lp_host_msdfs())
5208                 default_server_announce |= SV_TYPE_DFS_SERVER;
5209
5210         return default_server_announce;
5211 }
5212
5213 /***********************************************************
5214  If we are PDC then prefer us as DMB
5215 ************************************************************/
5216
5217 bool lp_domain_master(void)
5218 {
5219         if (Globals.domain_master == Auto)
5220                 return (lp_server_role() == ROLE_DOMAIN_PDC);
5221
5222         return (bool)Globals.domain_master;
5223 }
5224
5225 /***********************************************************
5226  If we are PDC then prefer us as DMB
5227 ************************************************************/
5228
5229 static bool lp_domain_master_true_or_auto(void)
5230 {
5231         if (Globals.domain_master) /* auto or yes */
5232                 return true;
5233
5234         return false;
5235 }
5236
5237 /***********************************************************
5238  If we are DMB then prefer us as LMB
5239 ************************************************************/
5240
5241 bool lp_preferred_master(void)
5242 {
5243         if (Globals.iPreferredMaster == Auto)
5244                 return (lp_local_master() && lp_domain_master());
5245
5246         return (bool)Globals.iPreferredMaster;
5247 }
5248
5249 /*******************************************************************
5250  Remove a service.
5251 ********************************************************************/
5252
5253 void lp_remove_service(int snum)
5254 {
5255         ServicePtrs[snum]->valid = false;
5256 }
5257
5258 /*******************************************************************
5259  Copy a service.
5260 ********************************************************************/
5261
5262 void lp_copy_service(int snum, const char *new_name)
5263 {
5264         do_section(new_name, NULL);
5265         if (snum >= 0) {
5266                 snum = lp_servicenumber(new_name);
5267                 if (snum >= 0) {
5268                         char *name = lp_servicename(talloc_tos(), snum);
5269                         lp_do_parameter(snum, "copy", name);
5270                 }
5271         }
5272 }
5273
5274 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5275 {
5276         const char *ret = lp__printername(talloc_tos(), snum);
5277         if (ret == NULL || *ret == '\0') {
5278                 ret = lp_const_servicename(snum);
5279         }
5280
5281         return ret;
5282 }
5283
5284
5285 /***********************************************************
5286  Allow daemons such as winbindd to fix their logfile name.
5287 ************************************************************/
5288
5289 void lp_set_logfile(const char *name)
5290 {
5291         string_set(&Globals.logfile, name);
5292         debug_set_logfile(name);
5293 }
5294
5295 /*******************************************************************
5296  Return the max print jobs per queue.
5297 ********************************************************************/
5298
5299 int lp_maxprintjobs(int snum)
5300 {
5301         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5302         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5303                 maxjobs = PRINT_MAX_JOBID - 1;
5304
5305         return maxjobs;
5306 }
5307
5308 const char *lp_printcapname(void)
5309 {
5310         if ((Globals.szPrintcapname != NULL) &&
5311             (Globals.szPrintcapname[0] != '\0'))
5312                 return Globals.szPrintcapname;
5313
5314         if (sDefault.iPrinting == PRINT_CUPS) {
5315                 return "cups";
5316         }
5317
5318         if (sDefault.iPrinting == PRINT_BSD)
5319                 return "/etc/printcap";
5320
5321         return PRINTCAP_NAME;
5322 }
5323
5324 static uint32 spoolss_state;
5325
5326 bool lp_disable_spoolss( void )
5327 {
5328         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5329                 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5330
5331         return spoolss_state == SVCCTL_STOPPED ? true : false;
5332 }
5333
5334 void lp_set_spoolss_state( uint32 state )
5335 {
5336         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5337
5338         spoolss_state = state;
5339 }
5340
5341 uint32 lp_get_spoolss_state( void )
5342 {
5343         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5344 }
5345
5346 /*******************************************************************
5347  Ensure we don't use sendfile if server smb signing is active.
5348 ********************************************************************/
5349
5350 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5351 {
5352         bool sign_active = false;
5353
5354         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5355         if (get_Protocol() < PROTOCOL_NT1) {
5356                 return false;
5357         }
5358         if (signing_state) {
5359                 sign_active = smb_signing_is_active(signing_state);
5360         }
5361         return (lp__use_sendfile(snum) &&
5362                         (get_remote_arch() != RA_WIN95) &&
5363                         !sign_active);
5364 }
5365
5366 /*******************************************************************
5367  Turn off sendfile if we find the underlying OS doesn't support it.
5368 ********************************************************************/
5369
5370 void set_use_sendfile(int snum, bool val)
5371 {
5372         if (LP_SNUM_OK(snum))
5373                 ServicePtrs[snum]->bUseSendfile = val;
5374         else
5375                 sDefault.bUseSendfile = val;
5376 }
5377
5378 /*******************************************************************
5379  Turn off storing DOS attributes if this share doesn't support it.
5380 ********************************************************************/
5381
5382 void set_store_dos_attributes(int snum, bool val)
5383 {
5384         if (!LP_SNUM_OK(snum))
5385                 return;
5386         ServicePtrs[(snum)]->bStoreDosAttributes = val;
5387 }
5388
5389 void lp_set_mangling_method(const char *new_method)
5390 {
5391         string_set(&Globals.szManglingMethod, new_method);
5392 }
5393
5394 /*******************************************************************
5395  Global state for POSIX pathname processing.
5396 ********************************************************************/
5397
5398 static bool posix_pathnames;
5399
5400 bool lp_posix_pathnames(void)
5401 {
5402         return posix_pathnames;
5403 }
5404
5405 /*******************************************************************
5406  Change everything needed to ensure POSIX pathname processing (currently
5407  not much).
5408 ********************************************************************/
5409
5410 void lp_set_posix_pathnames(void)
5411 {
5412         posix_pathnames = true;
5413 }
5414
5415 /*******************************************************************
5416  Global state for POSIX lock processing - CIFS unix extensions.
5417 ********************************************************************/
5418
5419 bool posix_default_lock_was_set;
5420 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5421
5422 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5423 {
5424         if (posix_default_lock_was_set) {
5425                 return posix_cifsx_locktype;
5426         } else {
5427                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5428         }
5429 }
5430
5431 /*******************************************************************
5432 ********************************************************************/
5433
5434 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5435 {
5436         posix_default_lock_was_set = true;
5437         posix_cifsx_locktype = val;
5438 }
5439
5440 int lp_min_receive_file_size(void)
5441 {
5442         if (Globals.iminreceivefile < 0) {
5443                 return 0;
5444         }
5445         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5446 }
5447
5448 /*******************************************************************
5449  Safe wide links checks.
5450  This helper function always verify the validity of wide links,
5451  even after a configuration file reload.
5452 ********************************************************************/
5453
5454 static bool lp_widelinks_internal(int snum)
5455 {
5456         return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5457                         sDefault.bWidelinks);
5458 }
5459
5460 void widelinks_warning(int snum)
5461 {
5462         if (lp_allow_insecure_widelinks()) {
5463                 return;
5464         }
5465
5466         if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5467                 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5468                         "These parameters are incompatible. "
5469                         "Wide links will be disabled for this share.\n",
5470                          lp_servicename(talloc_tos(), snum) ));
5471         }
5472 }
5473
5474 bool lp_widelinks(int snum)
5475 {
5476         /* wide links is always incompatible with unix extensions */
5477         if (lp_unix_extensions()) {
5478                 /*
5479                  * Unless we have "allow insecure widelinks"
5480                  * turned on.
5481                  */
5482                 if (!lp_allow_insecure_widelinks()) {
5483                         return false;
5484                 }
5485         }
5486
5487         return lp_widelinks_internal(snum);
5488 }
5489
5490 bool lp_writeraw(void)
5491 {
5492         if (lp_async_smb_echo_handler()) {
5493                 return false;
5494         }
5495         return lp__writeraw();
5496 }
5497
5498 bool lp_readraw(void)
5499 {
5500         if (lp_async_smb_echo_handler()) {
5501                 return false;
5502         }
5503         return lp__readraw();
5504 }
5505
5506 int lp_server_role(void)
5507 {
5508         return lp_find_server_role(lp__server_role(),
5509                                    lp__security(),
5510                                    lp__domain_logons(),
5511                                    lp_domain_master_true_or_auto());
5512 }
5513
5514 int lp_security(void)
5515 {
5516         return lp_find_security(lp__server_role(),
5517                                 lp__security());
5518 }