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