0e1b019cfeec351338ba33791decd1737ae0ab28
[obnox/samba/samba-obnox.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 static 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, "map archive", "no");
3504                 lp_do_parameter(-1, "store dos attributes", "yes");
3505                 lp_do_parameter(-1, "create mask", "0777");
3506                 lp_do_parameter(-1, "directory mask", "0777");
3507         }
3508 }
3509
3510 /***************************************************************************
3511  Process a new section (service). At this stage all sections are services.
3512  Later we'll have special sections that permit server parameters to be set.
3513  Returns true on success, false on failure.
3514 ***************************************************************************/
3515
3516 static bool do_section(const char *pszSectionName, void *userdata)
3517 {
3518         bool bRetval;
3519         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3520                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3521         bRetval = false;
3522
3523         /* if we were in a global section then do the local inits */
3524         if (bInGlobalSection && !isglobal)
3525                 init_locals();
3526
3527         /* if we've just struck a global section, note the fact. */
3528         bInGlobalSection = isglobal;
3529
3530         /* check for multiple global sections */
3531         if (bInGlobalSection) {
3532                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3533                 return true;
3534         }
3535
3536         if (!bInGlobalSection && bGlobalOnly)
3537                 return true;
3538
3539         /* if we have a current service, tidy it up before moving on */
3540         bRetval = true;
3541
3542         if (iServiceIndex >= 0)
3543                 bRetval = service_ok(iServiceIndex);
3544
3545         /* if all is still well, move to the next record in the services array */
3546         if (bRetval) {
3547                 /* We put this here to avoid an odd message order if messages are */
3548                 /* issued by the post-processing of a previous section. */
3549                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3550
3551                 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3552                 if (iServiceIndex < 0) {
3553                         DEBUG(0, ("Failed to add a new service\n"));
3554                         return false;
3555                 }
3556                 /* Clean all parametric options for service */
3557                 /* They will be added during parsing again */
3558                 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3559         }
3560
3561         return bRetval;
3562 }
3563
3564
3565 /***************************************************************************
3566  Determine if a partcular base parameter is currentl set to the default value.
3567 ***************************************************************************/
3568
3569 static bool is_default(int i)
3570 {
3571         if (!defaults_saved)
3572                 return false;
3573         switch (parm_table[i].type) {
3574                 case P_LIST:
3575                 case P_CMDLIST:
3576                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
3577                                               *(const char ***)lp_parm_ptr(NULL, 
3578                                                                            &parm_table[i]));
3579                 case P_STRING:
3580                 case P_USTRING:
3581                         return strequal(parm_table[i].def.svalue,
3582                                         *(char **)lp_parm_ptr(NULL, 
3583                                                               &parm_table[i]));
3584                 case P_BOOL:
3585                 case P_BOOLREV:
3586                         return parm_table[i].def.bvalue ==
3587                                 *(bool *)lp_parm_ptr(NULL, 
3588                                                      &parm_table[i]);
3589                 case P_CHAR:
3590                         return parm_table[i].def.cvalue ==
3591                                 *(char *)lp_parm_ptr(NULL, 
3592                                                      &parm_table[i]);
3593                 case P_INTEGER:
3594                 case P_OCTAL:
3595                 case P_ENUM:
3596                 case P_BYTES:
3597                         return parm_table[i].def.ivalue ==
3598                                 *(int *)lp_parm_ptr(NULL, 
3599                                                     &parm_table[i]);
3600                 case P_SEP:
3601                         break;
3602         }
3603         return false;
3604 }
3605
3606 /***************************************************************************
3607 Display the contents of the global structure.
3608 ***************************************************************************/
3609
3610 static void dump_globals(FILE *f)
3611 {
3612         int i;
3613         struct parmlist_entry *data;
3614
3615         fprintf(f, "[global]\n");
3616
3617         for (i = 0; parm_table[i].label; i++)
3618                 if (parm_table[i].p_class == P_GLOBAL &&
3619                     !(parm_table[i].flags & FLAG_META) &&
3620                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3621                         if (defaults_saved && is_default(i))
3622                                 continue;
3623                         fprintf(f, "\t%s = ", parm_table[i].label);
3624                         print_parameter(&parm_table[i], lp_parm_ptr(NULL, 
3625                                                                     &parm_table[i]),
3626                                         f);
3627                         fprintf(f, "\n");
3628         }
3629         if (Globals.param_opt != NULL) {
3630                 data = Globals.param_opt;
3631                 while(data) {
3632                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3633                         data = data->next;
3634                 }
3635         }
3636
3637 }
3638
3639 /***************************************************************************
3640  Return true if a local parameter is currently set to the global default.
3641 ***************************************************************************/
3642
3643 bool lp_is_default(int snum, struct parm_struct *parm)
3644 {
3645         return equal_parameter(parm->type,
3646                                lp_parm_ptr(ServicePtrs[snum], parm),
3647                                lp_parm_ptr(NULL, parm));
3648 }
3649
3650 /***************************************************************************
3651  Display the contents of a single services record.
3652 ***************************************************************************/
3653
3654 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3655 {
3656         int i;
3657         struct parmlist_entry *data;
3658
3659         if (pService != &sDefault)
3660                 fprintf(f, "[%s]\n", pService->szService);
3661
3662         for (i = 0; parm_table[i].label; i++) {
3663
3664                 if (parm_table[i].p_class == P_LOCAL &&
3665                     !(parm_table[i].flags & FLAG_META) &&
3666                     (*parm_table[i].label != '-') &&
3667                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
3668                 {
3669                         if (pService == &sDefault) {
3670                                 if (defaults_saved && is_default(i))
3671                                         continue;
3672                         } else {
3673                                 if (equal_parameter(parm_table[i].type,
3674                                                     lp_parm_ptr(pService, &parm_table[i]),
3675                                                     lp_parm_ptr(NULL, &parm_table[i])))
3676                                         continue;
3677                         }
3678
3679                         fprintf(f, "\t%s = ", parm_table[i].label);
3680                         print_parameter(&parm_table[i],
3681                                         lp_parm_ptr(pService, &parm_table[i]),
3682                                         f);
3683                         fprintf(f, "\n");
3684                 }
3685         }
3686
3687                 if (pService->param_opt != NULL) {
3688                         data = pService->param_opt;
3689                         while(data) {
3690                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
3691                                 data = data->next;
3692                         }
3693                 }
3694 }
3695
3696 /***************************************************************************
3697  Display the contents of a parameter of a single services record.
3698 ***************************************************************************/
3699
3700 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3701 {
3702         int i;
3703         bool result = false;
3704         parm_class p_class;
3705         unsigned flag = 0;
3706         fstring local_parm_name;
3707         char *parm_opt;
3708         const char *parm_opt_value;
3709
3710         /* check for parametrical option */
3711         fstrcpy( local_parm_name, parm_name);
3712         parm_opt = strchr( local_parm_name, ':');
3713
3714         if (parm_opt) {
3715                 *parm_opt = '\0';
3716                 parm_opt++;
3717                 if (strlen(parm_opt)) {
3718                         parm_opt_value = lp_parm_const_string( snum,
3719                                 local_parm_name, parm_opt, NULL);
3720                         if (parm_opt_value) {
3721                                 printf( "%s\n", parm_opt_value);
3722                                 result = true;
3723                         }
3724                 }
3725                 return result;
3726         }
3727
3728         /* check for a key and print the value */
3729         if (isGlobal) {
3730                 p_class = P_GLOBAL;
3731                 flag = FLAG_GLOBAL;
3732         } else
3733                 p_class = P_LOCAL;
3734
3735         for (i = 0; parm_table[i].label; i++) {
3736                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3737                     !(parm_table[i].flags & FLAG_META) &&
3738                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3739                     (*parm_table[i].label != '-') &&
3740                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
3741                 {
3742                         void *ptr;
3743
3744                         if (isGlobal) {
3745                                 ptr = lp_parm_ptr(NULL, 
3746                                                   &parm_table[i]);
3747                         } else {
3748                                 ptr = lp_parm_ptr(ServicePtrs[snum], 
3749                                                   &parm_table[i]);
3750                         }
3751
3752                         print_parameter(&parm_table[i],
3753                                         ptr, f);
3754                         fprintf(f, "\n");
3755                         result = true;
3756                         break;
3757                 }
3758         }
3759
3760         return result;
3761 }
3762
3763 /***************************************************************************
3764  Return info about the requested parameter (given as a string).
3765  Return NULL when the string is not a valid parameter name.
3766 ***************************************************************************/
3767
3768 struct parm_struct *lp_get_parameter(const char *param_name)
3769 {
3770         int num = map_parameter(param_name);
3771
3772         if (num < 0) {
3773                 return NULL;
3774         }
3775
3776         return &parm_table[num];
3777 }
3778
3779 /***************************************************************************
3780  Return info about the next parameter in a service.
3781  snum==GLOBAL_SECTION_SNUM gives the globals.
3782  Return NULL when out of parameters.
3783 ***************************************************************************/
3784
3785 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3786 {
3787         if (snum < 0) {
3788                 /* do the globals */
3789                 for (; parm_table[*i].label; (*i)++) {
3790                         if (parm_table[*i].p_class == P_SEPARATOR)
3791                                 return &parm_table[(*i)++];
3792
3793                         if ((*parm_table[*i].label == '-'))
3794                                 continue;
3795
3796                         if ((*i) > 0
3797                             && (parm_table[*i].offset ==
3798                                 parm_table[(*i) - 1].offset)
3799                             && (parm_table[*i].p_class ==
3800                                 parm_table[(*i) - 1].p_class))
3801                                 continue;
3802
3803                         if (is_default(*i) && !allparameters)
3804                                 continue;
3805
3806                         return &parm_table[(*i)++];
3807                 }
3808         } else {
3809                 struct loadparm_service *pService = ServicePtrs[snum];
3810
3811                 for (; parm_table[*i].label; (*i)++) {
3812                         if (parm_table[*i].p_class == P_SEPARATOR)
3813                                 return &parm_table[(*i)++];
3814
3815                         if (parm_table[*i].p_class == P_LOCAL &&
3816                             (*parm_table[*i].label != '-') &&
3817                             ((*i) == 0 ||
3818                              (parm_table[*i].offset !=
3819                               parm_table[(*i) - 1].offset)))
3820                         {
3821                                 if (allparameters ||
3822                                     !equal_parameter(parm_table[*i].type,
3823                                                      lp_parm_ptr(pService, 
3824                                                                  &parm_table[*i]),
3825                                                      lp_parm_ptr(NULL, 
3826                                                                  &parm_table[*i])))
3827                                 {
3828                                         return &parm_table[(*i)++];
3829                                 }
3830                         }
3831                 }
3832         }
3833
3834         return NULL;
3835 }
3836
3837
3838 #if 0
3839 /***************************************************************************
3840  Display the contents of a single copy structure.
3841 ***************************************************************************/
3842 static void dump_copy_map(bool *pcopymap)
3843 {
3844         int i;
3845         if (!pcopymap)
3846                 return;
3847
3848         printf("\n\tNon-Copied parameters:\n");
3849
3850         for (i = 0; parm_table[i].label; i++)
3851                 if (parm_table[i].p_class == P_LOCAL &&
3852                     parm_table[i].ptr && !pcopymap[i] &&
3853                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3854                 {
3855                         printf("\t\t%s\n", parm_table[i].label);
3856                 }
3857 }
3858 #endif
3859
3860 /***************************************************************************
3861  Return TRUE if the passed service number is within range.
3862 ***************************************************************************/
3863
3864 bool lp_snum_ok(int iService)
3865 {
3866         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3867 }
3868
3869 /***************************************************************************
3870  Auto-load some home services.
3871 ***************************************************************************/
3872
3873 static void lp_add_auto_services(char *str)
3874 {
3875         char *s;
3876         char *p;
3877         int homes;
3878         char *saveptr;
3879
3880         if (!str)
3881                 return;
3882
3883         s = SMB_STRDUP(str);
3884         if (!s)
3885                 return;
3886
3887         homes = lp_servicenumber(HOMES_NAME);
3888
3889         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3890              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3891                 char *home;
3892
3893                 if (lp_servicenumber(p) >= 0)
3894                         continue;
3895
3896                 home = get_user_home_dir(talloc_tos(), p);
3897
3898                 if (home && home[0] && homes >= 0)
3899                         lp_add_home(p, homes, p, home);
3900
3901                 TALLOC_FREE(home);
3902         }
3903         SAFE_FREE(s);
3904 }
3905
3906 /***************************************************************************
3907  Auto-load one printer.
3908 ***************************************************************************/
3909
3910 void lp_add_one_printer(const char *name, const char *comment,
3911                         const char *location, void *pdata)
3912 {
3913         int printers = lp_servicenumber(PRINTERS_NAME);
3914         int i;
3915
3916         if (lp_servicenumber(name) < 0) {
3917                 lp_add_printer(name, printers);
3918                 if ((i = lp_servicenumber(name)) >= 0) {
3919                         string_set(&ServicePtrs[i]->comment, comment);
3920                         ServicePtrs[i]->autoloaded = true;
3921                 }
3922         }
3923 }
3924
3925 /***************************************************************************
3926  Have we loaded a services file yet?
3927 ***************************************************************************/
3928
3929 bool lp_loaded(void)
3930 {
3931         return (bLoaded);
3932 }
3933
3934 /***************************************************************************
3935  Unload unused services.
3936 ***************************************************************************/
3937
3938 void lp_killunused(struct smbd_server_connection *sconn,
3939                    bool (*snumused) (struct smbd_server_connection *, int))
3940 {
3941         int i;
3942         for (i = 0; i < iNumServices; i++) {
3943                 if (!VALID(i))
3944                         continue;
3945
3946                 /* don't kill autoloaded or usershare services */
3947                 if ( ServicePtrs[i]->autoloaded ||
3948                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3949                         continue;
3950                 }
3951
3952                 if (!snumused || !snumused(sconn, i)) {
3953                         free_service_byindex(i);
3954                 }
3955         }
3956 }
3957
3958 /**
3959  * Kill all except autoloaded and usershare services - convenience wrapper
3960  */
3961 void lp_kill_all_services(void)
3962 {
3963         lp_killunused(NULL, NULL);
3964 }
3965
3966 /***************************************************************************
3967  Unload a service.
3968 ***************************************************************************/
3969
3970 void lp_killservice(int iServiceIn)
3971 {
3972         if (VALID(iServiceIn)) {
3973                 free_service_byindex(iServiceIn);
3974         }
3975 }
3976
3977 /***************************************************************************
3978  Save the curent values of all global and sDefault parameters into the 
3979  defaults union. This allows swat and testparm to show only the
3980  changed (ie. non-default) parameters.
3981 ***************************************************************************/
3982
3983 static void lp_save_defaults(void)
3984 {
3985         int i;
3986         for (i = 0; parm_table[i].label; i++) {
3987                 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
3988                     && parm_table[i].p_class == parm_table[i - 1].p_class)
3989                         continue;
3990                 switch (parm_table[i].type) {
3991                         case P_LIST:
3992                         case P_CMDLIST:
3993                                 parm_table[i].def.lvalue = str_list_copy(
3994                                         NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
3995                                 break;
3996                         case P_STRING:
3997                         case P_USTRING:
3998                                 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
3999                                 break;
4000                         case P_BOOL:
4001                         case P_BOOLREV:
4002                                 parm_table[i].def.bvalue =
4003                                         *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
4004                                 break;
4005                         case P_CHAR:
4006                                 parm_table[i].def.cvalue =
4007                                         *(char *)lp_parm_ptr(NULL, &parm_table[i]);
4008                                 break;
4009                         case P_INTEGER:
4010                         case P_OCTAL:
4011                         case P_ENUM:
4012                         case P_BYTES:
4013                                 parm_table[i].def.ivalue =
4014                                         *(int *)lp_parm_ptr(NULL, &parm_table[i]);
4015                                 break;
4016                         case P_SEP:
4017                                 break;
4018                 }
4019         }
4020         defaults_saved = true;
4021 }
4022
4023 /***********************************************************
4024  If we should send plaintext/LANMAN passwords in the clinet
4025 ************************************************************/
4026
4027 static void set_allowed_client_auth(void)
4028 {
4029         if (Globals.bClientNTLMv2Auth) {
4030                 Globals.bClientLanManAuth = false;
4031         }
4032         if (!Globals.bClientLanManAuth) {
4033                 Globals.bClientPlaintextAuth = false;
4034         }
4035 }
4036
4037 /***************************************************************************
4038  JRA.
4039  The following code allows smbd to read a user defined share file.
4040  Yes, this is my intent. Yes, I'm comfortable with that...
4041
4042  THE FOLLOWING IS SECURITY CRITICAL CODE.
4043
4044  It washes your clothes, it cleans your house, it guards you while you sleep...
4045  Do not f%^k with it....
4046 ***************************************************************************/
4047
4048 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4049
4050 /***************************************************************************
4051  Check allowed stat state of a usershare file.
4052  Ensure we print out who is dicking with us so the admin can
4053  get their sorry ass fired.
4054 ***************************************************************************/
4055
4056 static bool check_usershare_stat(const char *fname,
4057                                  const SMB_STRUCT_STAT *psbuf)
4058 {
4059         if (!S_ISREG(psbuf->st_ex_mode)) {
4060                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4061                         "not a regular file\n",
4062                         fname, (unsigned int)psbuf->st_ex_uid ));
4063                 return false;
4064         }
4065
4066         /* Ensure this doesn't have the other write bit set. */
4067         if (psbuf->st_ex_mode & S_IWOTH) {
4068                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4069                         "public write. Refusing to allow as a usershare file.\n",
4070                         fname, (unsigned int)psbuf->st_ex_uid ));
4071                 return false;
4072         }
4073
4074         /* Should be 10k or less. */
4075         if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4076                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4077                         "too large (%u) to be a user share file.\n",
4078                         fname, (unsigned int)psbuf->st_ex_uid,
4079                         (unsigned int)psbuf->st_ex_size ));
4080                 return false;
4081         }
4082
4083         return true;
4084 }
4085
4086 /***************************************************************************
4087  Parse the contents of a usershare file.
4088 ***************************************************************************/
4089
4090 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4091                         SMB_STRUCT_STAT *psbuf,
4092                         const char *servicename,
4093                         int snum,
4094                         char **lines,
4095                         int numlines,
4096                         char **pp_sharepath,
4097                         char **pp_comment,
4098                         char **pp_cp_servicename,
4099                         struct security_descriptor **ppsd,
4100                         bool *pallow_guest)
4101 {
4102         const char **prefixallowlist = lp_usershare_prefix_allow_list();
4103         const char **prefixdenylist = lp_usershare_prefix_deny_list();
4104         int us_vers;
4105         DIR *dp;
4106         SMB_STRUCT_STAT sbuf;
4107         char *sharepath = NULL;
4108         char *comment = NULL;
4109
4110         *pp_sharepath = NULL;
4111         *pp_comment = NULL;
4112
4113         *pallow_guest = false;
4114
4115         if (numlines < 4) {
4116                 return USERSHARE_MALFORMED_FILE;
4117         }
4118
4119         if (strcmp(lines[0], "#VERSION 1") == 0) {
4120                 us_vers = 1;
4121         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4122                 us_vers = 2;
4123                 if (numlines < 5) {
4124                         return USERSHARE_MALFORMED_FILE;
4125                 }
4126         } else {
4127                 return USERSHARE_BAD_VERSION;
4128         }
4129
4130         if (strncmp(lines[1], "path=", 5) != 0) {
4131                 return USERSHARE_MALFORMED_PATH;
4132         }
4133
4134         sharepath = talloc_strdup(ctx, &lines[1][5]);
4135         if (!sharepath) {
4136                 return USERSHARE_POSIX_ERR;
4137         }
4138         trim_string(sharepath, " ", " ");
4139
4140         if (strncmp(lines[2], "comment=", 8) != 0) {
4141                 return USERSHARE_MALFORMED_COMMENT_DEF;
4142         }
4143
4144         comment = talloc_strdup(ctx, &lines[2][8]);
4145         if (!comment) {
4146                 return USERSHARE_POSIX_ERR;
4147         }
4148         trim_string(comment, " ", " ");
4149         trim_char(comment, '"', '"');
4150
4151         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4152                 return USERSHARE_MALFORMED_ACL_DEF;
4153         }
4154
4155         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4156                 return USERSHARE_ACL_ERR;
4157         }
4158
4159         if (us_vers == 2) {
4160                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4161                         return USERSHARE_MALFORMED_ACL_DEF;
4162                 }
4163                 if (lines[4][9] == 'y') {
4164                         *pallow_guest = true;
4165                 }
4166
4167                 /* Backwards compatible extension to file version #2. */
4168                 if (numlines > 5) {
4169                         if (strncmp(lines[5], "sharename=", 10) != 0) {
4170                                 return USERSHARE_MALFORMED_SHARENAME_DEF;
4171                         }
4172                         if (!strequal(&lines[5][10], servicename)) {
4173                                 return USERSHARE_BAD_SHARENAME;
4174                         }
4175                         *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4176                         if (!*pp_cp_servicename) {
4177                                 return USERSHARE_POSIX_ERR;
4178                         }
4179                 }
4180         }
4181
4182         if (*pp_cp_servicename == NULL) {
4183                 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4184                 if (!*pp_cp_servicename) {
4185                         return USERSHARE_POSIX_ERR;
4186                 }
4187         }
4188
4189         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4190                 /* Path didn't change, no checks needed. */
4191                 *pp_sharepath = sharepath;
4192                 *pp_comment = comment;
4193                 return USERSHARE_OK;
4194         }
4195
4196         /* The path *must* be absolute. */
4197         if (sharepath[0] != '/') {
4198                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4199                         servicename, sharepath));
4200                 return USERSHARE_PATH_NOT_ABSOLUTE;
4201         }
4202
4203         /* If there is a usershare prefix deny list ensure one of these paths
4204            doesn't match the start of the user given path. */
4205         if (prefixdenylist) {
4206                 int i;
4207                 for ( i=0; prefixdenylist[i]; i++ ) {
4208                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4209                                 servicename, i, prefixdenylist[i], sharepath ));
4210                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4211                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4212                                         "usershare prefix deny list entries.\n",
4213                                         servicename, sharepath));
4214                                 return USERSHARE_PATH_IS_DENIED;
4215                         }
4216                 }
4217         }
4218
4219         /* If there is a usershare prefix allow list ensure one of these paths
4220            does match the start of the user given path. */
4221
4222         if (prefixallowlist) {
4223                 int i;
4224                 for ( i=0; prefixallowlist[i]; i++ ) {
4225                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4226                                 servicename, i, prefixallowlist[i], sharepath ));
4227                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4228                                 break;
4229                         }
4230                 }
4231                 if (prefixallowlist[i] == NULL) {
4232                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4233                                 "usershare prefix allow list entries.\n",
4234                                 servicename, sharepath));
4235                         return USERSHARE_PATH_NOT_ALLOWED;
4236                 }
4237         }
4238
4239         /* Ensure this is pointing to a directory. */
4240         dp = opendir(sharepath);
4241
4242         if (!dp) {
4243                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4244                         servicename, sharepath));
4245                 return USERSHARE_PATH_NOT_DIRECTORY;
4246         }
4247
4248         /* Ensure the owner of the usershare file has permission to share
4249            this directory. */
4250
4251         if (sys_stat(sharepath, &sbuf, false) == -1) {
4252                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4253                         servicename, sharepath, strerror(errno) ));
4254                 closedir(dp);
4255                 return USERSHARE_POSIX_ERR;
4256         }
4257
4258         closedir(dp);
4259
4260         if (!S_ISDIR(sbuf.st_ex_mode)) {
4261                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4262                         servicename, sharepath ));
4263                 return USERSHARE_PATH_NOT_DIRECTORY;
4264         }
4265
4266         /* Check if sharing is restricted to owner-only. */
4267         /* psbuf is the stat of the usershare definition file,
4268            sbuf is the stat of the target directory to be shared. */
4269
4270         if (lp_usershare_owner_only()) {
4271                 /* root can share anything. */
4272                 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4273                         return USERSHARE_PATH_NOT_ALLOWED;
4274                 }
4275         }
4276
4277         *pp_sharepath = sharepath;
4278         *pp_comment = comment;
4279         return USERSHARE_OK;
4280 }
4281
4282 /***************************************************************************
4283  Deal with a usershare file.
4284  Returns:
4285         >= 0 - snum
4286         -1 - Bad name, invalid contents.
4287            - service name already existed and not a usershare, problem
4288             with permissions to share directory etc.
4289 ***************************************************************************/
4290
4291 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4292 {
4293         SMB_STRUCT_STAT sbuf;
4294         SMB_STRUCT_STAT lsbuf;
4295         char *fname = NULL;
4296         char *sharepath = NULL;
4297         char *comment = NULL;
4298         char *cp_service_name = NULL;
4299         char **lines = NULL;
4300         int numlines = 0;
4301         int fd = -1;
4302         int iService = -1;
4303         TALLOC_CTX *ctx = talloc_stackframe();
4304         struct security_descriptor *psd = NULL;
4305         bool guest_ok = false;
4306         char *canon_name = NULL;
4307         bool added_service = false;
4308         int ret = -1;
4309
4310         /* Ensure share name doesn't contain invalid characters. */
4311         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4312                 DEBUG(0,("process_usershare_file: share name %s contains "
4313                         "invalid characters (any of %s)\n",
4314                         file_name, INVALID_SHARENAME_CHARS ));
4315                 goto out;
4316         }
4317
4318         canon_name = canonicalize_servicename(ctx, file_name);
4319         if (!canon_name) {
4320                 goto out;
4321         }
4322
4323         fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4324         if (!fname) {
4325                 goto out;
4326         }
4327
4328         /* Minimize the race condition by doing an lstat before we
4329            open and fstat. Ensure this isn't a symlink link. */
4330
4331         if (sys_lstat(fname, &lsbuf, false) != 0) {
4332                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4333                         fname, strerror(errno) ));
4334                 goto out;
4335         }
4336
4337         /* This must be a regular file, not a symlink, directory or
4338            other strange filetype. */
4339         if (!check_usershare_stat(fname, &lsbuf)) {
4340                 goto out;
4341         }
4342
4343         {
4344                 TDB_DATA data;
4345                 NTSTATUS status;
4346
4347                 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4348                                                canon_name, &data);
4349
4350                 iService = -1;
4351
4352                 if (NT_STATUS_IS_OK(status) &&
4353                     (data.dptr != NULL) &&
4354                     (data.dsize == sizeof(iService))) {
4355                         memcpy(&iService, data.dptr, sizeof(iService));
4356                 }
4357         }
4358
4359         if (iService != -1 &&
4360             timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4361                              &lsbuf.st_ex_mtime) == 0) {
4362                 /* Nothing changed - Mark valid and return. */
4363                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4364                         canon_name ));
4365                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4366                 ret = iService;
4367                 goto out;
4368         }
4369
4370         /* Try and open the file read only - no symlinks allowed. */
4371 #ifdef O_NOFOLLOW
4372         fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4373 #else
4374         fd = open(fname, O_RDONLY, 0);
4375 #endif
4376
4377         if (fd == -1) {
4378                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4379                         fname, strerror(errno) ));
4380                 goto out;
4381         }
4382
4383         /* Now fstat to be *SURE* it's a regular file. */
4384         if (sys_fstat(fd, &sbuf, false) != 0) {
4385                 close(fd);
4386                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4387                         fname, strerror(errno) ));
4388                 goto out;
4389         }
4390
4391         /* Is it the same dev/inode as was lstated ? */
4392         if (!check_same_stat(&lsbuf, &sbuf)) {
4393                 close(fd);
4394                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4395                         "Symlink spoofing going on ?\n", fname ));
4396                 goto out;
4397         }
4398
4399         /* This must be a regular file, not a symlink, directory or
4400            other strange filetype. */
4401         if (!check_usershare_stat(fname, &sbuf)) {
4402                 goto out;
4403         }
4404
4405         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4406
4407         close(fd);
4408         if (lines == NULL) {
4409                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4410                         fname, (unsigned int)sbuf.st_ex_uid ));
4411                 goto out;
4412         }
4413
4414         if (parse_usershare_file(ctx, &sbuf, file_name,
4415                         iService, lines, numlines, &sharepath,
4416                         &comment, &cp_service_name,
4417                         &psd, &guest_ok) != USERSHARE_OK) {
4418                 goto out;
4419         }
4420
4421         /* Everything ok - add the service possibly using a template. */
4422         if (iService < 0) {
4423                 const struct loadparm_service *sp = &sDefault;
4424                 if (snum_template != -1) {
4425                         sp = ServicePtrs[snum_template];
4426                 }
4427
4428                 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4429                         DEBUG(0, ("process_usershare_file: Failed to add "
4430                                 "new service %s\n", cp_service_name));
4431                         goto out;
4432                 }
4433
4434                 added_service = true;
4435
4436                 /* Read only is controlled by usershare ACL below. */
4437                 ServicePtrs[iService]->bRead_only = false;
4438         }
4439
4440         /* Write the ACL of the new/modified share. */
4441         if (!set_share_security(canon_name, psd)) {
4442                  DEBUG(0, ("process_usershare_file: Failed to set share "
4443                         "security for user share %s\n",
4444                         canon_name ));
4445                 goto out;
4446         }
4447
4448         /* If from a template it may be marked invalid. */
4449         ServicePtrs[iService]->valid = true;
4450
4451         /* Set the service as a valid usershare. */
4452         ServicePtrs[iService]->usershare = USERSHARE_VALID;
4453
4454         /* Set guest access. */
4455         if (lp_usershare_allow_guests()) {
4456                 ServicePtrs[iService]->bGuest_ok = guest_ok;
4457         }
4458
4459         /* And note when it was loaded. */
4460         ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4461         string_set(&ServicePtrs[iService]->szPath, sharepath);
4462         string_set(&ServicePtrs[iService]->comment, comment);
4463
4464         ret = iService;
4465
4466   out:
4467
4468         if (ret == -1 && iService != -1 && added_service) {
4469                 lp_remove_service(iService);
4470         }
4471
4472         TALLOC_FREE(lines);
4473         TALLOC_FREE(ctx);
4474         return ret;
4475 }
4476
4477 /***************************************************************************
4478  Checks if a usershare entry has been modified since last load.
4479 ***************************************************************************/
4480
4481 static bool usershare_exists(int iService, struct timespec *last_mod)
4482 {
4483         SMB_STRUCT_STAT lsbuf;
4484         const char *usersharepath = Globals.szUsersharePath;
4485         char *fname;
4486
4487         if (asprintf(&fname, "%s/%s",
4488                                 usersharepath,
4489                                 ServicePtrs[iService]->szService) < 0) {
4490                 return false;
4491         }
4492
4493         if (sys_lstat(fname, &lsbuf, false) != 0) {
4494                 SAFE_FREE(fname);
4495                 return false;
4496         }
4497
4498         if (!S_ISREG(lsbuf.st_ex_mode)) {
4499                 SAFE_FREE(fname);
4500                 return false;
4501         }
4502
4503         SAFE_FREE(fname);
4504         *last_mod = lsbuf.st_ex_mtime;
4505         return true;
4506 }
4507
4508 /***************************************************************************
4509  Load a usershare service by name. Returns a valid servicenumber or -1.
4510 ***************************************************************************/
4511
4512 int load_usershare_service(const char *servicename)
4513 {
4514         SMB_STRUCT_STAT sbuf;
4515         const char *usersharepath = Globals.szUsersharePath;
4516         int max_user_shares = Globals.iUsershareMaxShares;
4517         int snum_template = -1;
4518
4519         if (*usersharepath == 0 ||  max_user_shares == 0) {
4520                 return -1;
4521         }
4522
4523         if (sys_stat(usersharepath, &sbuf, false) != 0) {
4524                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4525                         usersharepath, strerror(errno) ));
4526                 return -1;
4527         }
4528
4529         if (!S_ISDIR(sbuf.st_ex_mode)) {
4530                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4531                         usersharepath ));
4532                 return -1;
4533         }
4534
4535         /*
4536          * This directory must be owned by root, and have the 't' bit set.
4537          * It also must not be writable by "other".
4538          */
4539
4540 #ifdef S_ISVTX
4541         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4542 #else
4543         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4544 #endif
4545                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4546                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4547                         usersharepath ));
4548                 return -1;
4549         }
4550
4551         /* Ensure the template share exists if it's set. */
4552         if (Globals.szUsershareTemplateShare[0]) {
4553                 /* We can't use lp_servicenumber here as we are recommending that
4554                    template shares have -valid=false set. */
4555                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4556                         if (ServicePtrs[snum_template]->szService &&
4557                                         strequal(ServicePtrs[snum_template]->szService,
4558                                                 Globals.szUsershareTemplateShare)) {
4559                                 break;
4560                         }
4561                 }
4562
4563                 if (snum_template == -1) {
4564                         DEBUG(0,("load_usershare_service: usershare template share %s "
4565                                 "does not exist.\n",
4566                                 Globals.szUsershareTemplateShare ));
4567                         return -1;
4568                 }
4569         }
4570
4571         return process_usershare_file(usersharepath, servicename, snum_template);
4572 }
4573
4574 /***************************************************************************
4575  Load all user defined shares from the user share directory.
4576  We only do this if we're enumerating the share list.
4577  This is the function that can delete usershares that have
4578  been removed.
4579 ***************************************************************************/
4580
4581 int load_usershare_shares(struct smbd_server_connection *sconn,
4582                           bool (*snumused) (struct smbd_server_connection *, int))
4583 {
4584         DIR *dp;
4585         SMB_STRUCT_STAT sbuf;
4586         struct dirent *de;
4587         int num_usershares = 0;
4588         int max_user_shares = Globals.iUsershareMaxShares;
4589         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4590         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4591         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4592         int iService;
4593         int snum_template = -1;
4594         const char *usersharepath = Globals.szUsersharePath;
4595         int ret = lp_numservices();
4596         TALLOC_CTX *tmp_ctx;
4597
4598         if (max_user_shares == 0 || *usersharepath == '\0') {
4599                 return lp_numservices();
4600         }
4601
4602         if (sys_stat(usersharepath, &sbuf, false) != 0) {
4603                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4604                         usersharepath, strerror(errno) ));
4605                 return ret;
4606         }
4607
4608         /*
4609          * This directory must be owned by root, and have the 't' bit set.
4610          * It also must not be writable by "other".
4611          */
4612
4613 #ifdef S_ISVTX
4614         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4615 #else
4616         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4617 #endif
4618                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4619                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4620                         usersharepath ));
4621                 return ret;
4622         }
4623
4624         /* Ensure the template share exists if it's set. */
4625         if (Globals.szUsershareTemplateShare[0]) {
4626                 /* We can't use lp_servicenumber here as we are recommending that
4627                    template shares have -valid=false set. */
4628                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4629                         if (ServicePtrs[snum_template]->szService &&
4630                                         strequal(ServicePtrs[snum_template]->szService,
4631                                                 Globals.szUsershareTemplateShare)) {
4632                                 break;
4633                         }
4634                 }
4635
4636                 if (snum_template == -1) {
4637                         DEBUG(0,("load_usershare_shares: usershare template share %s "
4638                                 "does not exist.\n",
4639                                 Globals.szUsershareTemplateShare ));
4640                         return ret;
4641                 }
4642         }
4643
4644         /* Mark all existing usershares as pending delete. */
4645         for (iService = iNumServices - 1; iService >= 0; iService--) {
4646                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4647                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4648                 }
4649         }
4650
4651         dp = opendir(usersharepath);
4652         if (!dp) {
4653                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4654                         usersharepath, strerror(errno) ));
4655                 return ret;
4656         }
4657
4658         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4659                         (de = readdir(dp));
4660                         num_dir_entries++ ) {
4661                 int r;
4662                 const char *n = de->d_name;
4663
4664                 /* Ignore . and .. */
4665                 if (*n == '.') {
4666                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4667                                 continue;
4668                         }
4669                 }
4670
4671                 if (n[0] == ':') {
4672                         /* Temporary file used when creating a share. */
4673                         num_tmp_dir_entries++;
4674                 }
4675
4676                 /* Allow 20% tmp entries. */
4677                 if (num_tmp_dir_entries > allowed_tmp_entries) {
4678                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4679                                 "in directory %s\n",
4680                                 num_tmp_dir_entries, usersharepath));
4681                         break;
4682                 }
4683
4684                 r = process_usershare_file(usersharepath, n, snum_template);
4685                 if (r == 0) {
4686                         /* Update the services count. */
4687                         num_usershares++;
4688                         if (num_usershares >= max_user_shares) {
4689                                 DEBUG(0,("load_usershare_shares: max user shares reached "
4690                                         "on file %s in directory %s\n",
4691                                         n, usersharepath ));
4692                                 break;
4693                         }
4694                 } else if (r == -1) {
4695                         num_bad_dir_entries++;
4696                 }
4697
4698                 /* Allow 20% bad entries. */
4699                 if (num_bad_dir_entries > allowed_bad_entries) {
4700                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4701                                 "in directory %s\n",
4702                                 num_bad_dir_entries, usersharepath));
4703                         break;
4704                 }
4705
4706                 /* Allow 20% bad entries. */
4707                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4708                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4709                         "in directory %s\n",
4710                         num_dir_entries, usersharepath));
4711                         break;
4712                 }
4713         }
4714
4715         closedir(dp);
4716
4717         /* Sweep through and delete any non-refreshed usershares that are
4718            not currently in use. */
4719         tmp_ctx = talloc_stackframe();
4720         for (iService = iNumServices - 1; iService >= 0; iService--) {
4721                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4722                         char *servname;
4723
4724                         if (snumused && snumused(sconn, iService)) {
4725                                 continue;
4726                         }
4727
4728                         servname = lp_servicename(tmp_ctx, iService);
4729
4730                         /* Remove from the share ACL db. */
4731                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4732                                   servname ));
4733                         delete_share_security(servname);
4734                         free_service_byindex(iService);
4735                 }
4736         }
4737         talloc_free(tmp_ctx);
4738
4739         return lp_numservices();
4740 }
4741
4742 /********************************************************
4743  Destroy global resources allocated in this file
4744 ********************************************************/
4745
4746 void gfree_loadparm(void)
4747 {
4748         int i;
4749
4750         free_file_list();
4751
4752         /* Free resources allocated to services */
4753
4754         for ( i = 0; i < iNumServices; i++ ) {
4755                 if ( VALID(i) ) {
4756                         free_service_byindex(i);
4757                 }
4758         }
4759
4760         SAFE_FREE( ServicePtrs );
4761         iNumServices = 0;
4762
4763         /* Now release all resources allocated to global
4764            parameters and the default service */
4765
4766         free_global_parameters();
4767 }
4768
4769
4770 /***************************************************************************
4771  Allow client apps to specify that they are a client
4772 ***************************************************************************/
4773 static void lp_set_in_client(bool b)
4774 {
4775     in_client = b;
4776 }
4777
4778
4779 /***************************************************************************
4780  Determine if we're running in a client app
4781 ***************************************************************************/
4782 static bool lp_is_in_client(void)
4783 {
4784     return in_client;
4785 }
4786
4787 /***************************************************************************
4788  Load the services array from the services file. Return true on success,
4789  false on failure.
4790 ***************************************************************************/
4791
4792 static bool lp_load_ex(const char *pszFname,
4793                        bool global_only,
4794                        bool save_defaults,
4795                        bool add_ipc,
4796                        bool initialize_globals,
4797                        bool allow_include_registry,
4798                        bool load_all_shares)
4799 {
4800         char *n2 = NULL;
4801         bool bRetval;
4802
4803         bRetval = false;
4804
4805         DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4806
4807         bInGlobalSection = true;
4808         bGlobalOnly = global_only;
4809         bAllowIncludeRegistry = allow_include_registry;
4810
4811         init_globals(initialize_globals);
4812
4813         free_file_list();
4814
4815         if (save_defaults) {
4816                 init_locals();
4817                 lp_save_defaults();
4818         }
4819
4820         if (!initialize_globals) {
4821                 free_param_opts(&Globals.param_opt);
4822                 apply_lp_set_cmdline();
4823         }
4824
4825         lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4826
4827         /* We get sections first, so have to start 'behind' to make up */
4828         iServiceIndex = -1;
4829
4830         if (lp_config_backend_is_file()) {
4831                 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4832                                         current_user_info.domain,
4833                                         pszFname);
4834                 if (!n2) {
4835                         smb_panic("lp_load_ex: out of memory");
4836                 }
4837
4838                 add_to_file_list(pszFname, n2);
4839
4840                 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4841                 TALLOC_FREE(n2);
4842
4843                 /* finish up the last section */
4844                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4845                 if (bRetval) {
4846                         if (iServiceIndex >= 0) {
4847                                 bRetval = service_ok(iServiceIndex);
4848                         }
4849                 }
4850
4851                 if (lp_config_backend_is_registry()) {
4852                         /* config backend changed to registry in config file */
4853                         /*
4854                          * We need to use this extra global variable here to
4855                          * survive restart: init_globals uses this as a default
4856                          * for ConfigBackend. Otherwise, init_globals would
4857                          *  send us into an endless loop here.
4858                          */
4859                         config_backend = CONFIG_BACKEND_REGISTRY;
4860                         /* start over */
4861                         DEBUG(1, ("lp_load_ex: changing to config backend "
4862                                   "registry\n"));
4863                         init_globals(true);
4864                         lp_kill_all_services();
4865                         return lp_load_ex(pszFname, global_only, save_defaults,
4866                                           add_ipc, initialize_globals,
4867                                           allow_include_registry,
4868                                           load_all_shares);
4869                 }
4870         } else if (lp_config_backend_is_registry()) {
4871                 bRetval = process_registry_globals();
4872         } else {
4873                 DEBUG(0, ("Illegal config  backend given: %d\n",
4874                           lp_config_backend()));
4875                 bRetval = false;
4876         }
4877
4878         if (bRetval && lp_registry_shares()) {
4879                 if (load_all_shares) {
4880                         bRetval = process_registry_shares();
4881                 } else {
4882                         bRetval = reload_registry_shares();
4883                 }
4884         }
4885
4886         {
4887                 char *serv = lp_auto_services(talloc_tos());
4888                 lp_add_auto_services(serv);
4889                 TALLOC_FREE(serv);
4890         }
4891
4892         if (add_ipc) {
4893                 /* When 'restrict anonymous = 2' guest connections to ipc$
4894                    are denied */
4895                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4896                 if ( lp_enable_asu_support() ) {
4897                         lp_add_ipc("ADMIN$", false);
4898                 }
4899         }
4900
4901         set_allowed_client_auth();
4902
4903         if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4904                 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4905                           lp_passwordserver()));
4906         }
4907
4908         bLoaded = true;
4909
4910         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4911         /* if bWINSsupport is true and we are in the client            */
4912         if (lp_is_in_client() && Globals.bWINSsupport) {
4913                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4914         }
4915
4916         init_iconv();
4917
4918         fault_configure(smb_panic_s3);
4919
4920         /*
4921          * We run this check once the whole smb.conf is parsed, to
4922          * force some settings for the standard way a AD DC is
4923          * operated.  We may changed these as our code evolves, which
4924          * is why we force these settings.
4925          */
4926         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4927                 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4928
4929                 lp_do_parameter(-1, "rpc_server:default", "external");
4930                 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4931                 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4932                 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4933                 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4934                 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4935                 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4936                 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4937                 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4938         }
4939
4940         bAllowIncludeRegistry = true;
4941
4942         return (bRetval);
4943 }
4944
4945 bool lp_load(const char *pszFname,
4946              bool global_only,
4947              bool save_defaults,
4948              bool add_ipc,
4949              bool initialize_globals)
4950 {
4951         return lp_load_ex(pszFname,
4952                           global_only,
4953                           save_defaults,
4954                           add_ipc,
4955                           initialize_globals,
4956                           true,   /* allow_include_registry */
4957                           false); /* load_all_shares*/
4958 }
4959
4960 bool lp_load_initial_only(const char *pszFname)
4961 {
4962         return lp_load_ex(pszFname,
4963                           true,   /* global only */
4964                           false,  /* save_defaults */
4965                           false,  /* add_ipc */
4966                           true,   /* initialize_globals */
4967                           false,  /* allow_include_registry */
4968                           false); /* load_all_shares*/
4969 }
4970
4971 /**
4972  * most common lp_load wrapper, loading only the globals
4973  */
4974 bool lp_load_global(const char *file_name)
4975 {
4976         return lp_load_ex(file_name,
4977                           true,   /* global_only */
4978                           false,  /* save_defaults */
4979                           false,  /* add_ipc */
4980                           true,   /* initialize_globals */
4981                           true,   /* allow_include_registry */
4982                           false); /* load_all_shares*/
4983 }
4984
4985 /**
4986  * lp_load wrapper, especially for clients
4987  */
4988 bool lp_load_client(const char *file_name)
4989 {
4990         lp_set_in_client(true);
4991
4992         return lp_load_global(file_name);
4993 }
4994
4995 /**
4996  * lp_load wrapper, loading only globals, but intended
4997  * for subsequent calls, not reinitializing the globals
4998  * to default values
4999  */
5000 bool lp_load_global_no_reinit(const char *file_name)
5001 {
5002         return lp_load_ex(file_name,
5003                           true,   /* global_only */
5004                           false,  /* save_defaults */
5005                           false,  /* add_ipc */
5006                           false,  /* initialize_globals */
5007                           true,   /* allow_include_registry */
5008                           false); /* load_all_shares*/
5009 }
5010
5011 /**
5012  * lp_load wrapper, especially for clients, no reinitialization
5013  */
5014 bool lp_load_client_no_reinit(const char *file_name)
5015 {
5016         lp_set_in_client(true);
5017
5018         return lp_load_global_no_reinit(file_name);
5019 }
5020
5021 bool lp_load_with_registry_shares(const char *pszFname,
5022                                   bool global_only,
5023                                   bool save_defaults,
5024                                   bool add_ipc,
5025                                   bool initialize_globals)
5026 {
5027         return lp_load_ex(pszFname,
5028                           global_only,
5029                           save_defaults,
5030                           add_ipc,
5031                           initialize_globals,
5032                           true,  /* allow_include_registry */
5033                           true); /* load_all_shares*/
5034 }
5035
5036 /***************************************************************************
5037  Return the max number of services.
5038 ***************************************************************************/
5039
5040 int lp_numservices(void)
5041 {
5042         return (iNumServices);
5043 }
5044
5045 /***************************************************************************
5046 Display the contents of the services array in human-readable form.
5047 ***************************************************************************/
5048
5049 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5050 {
5051         int iService;
5052
5053         if (show_defaults)
5054                 defaults_saved = false;
5055
5056         dump_globals(f);
5057
5058         dump_a_service(&sDefault, f);
5059
5060         for (iService = 0; iService < maxtoprint; iService++) {
5061                 fprintf(f,"\n");
5062                 lp_dump_one(f, show_defaults, iService);
5063         }
5064 }
5065
5066 /***************************************************************************
5067 Display the contents of one service in human-readable form.
5068 ***************************************************************************/
5069
5070 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5071 {
5072         if (VALID(snum)) {
5073                 if (ServicePtrs[snum]->szService[0] == '\0')
5074                         return;
5075                 dump_a_service(ServicePtrs[snum], f);
5076         }
5077 }
5078
5079 /***************************************************************************
5080 Return the number of the service with the given name, or -1 if it doesn't
5081 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5082 getservicebyname()! This works ONLY if all services have been loaded, and
5083 does not copy the found service.
5084 ***************************************************************************/
5085
5086 int lp_servicenumber(const char *pszServiceName)
5087 {
5088         int iService;
5089         fstring serviceName;
5090
5091         if (!pszServiceName) {
5092                 return GLOBAL_SECTION_SNUM;
5093         }
5094
5095         for (iService = iNumServices - 1; iService >= 0; iService--) {
5096                 if (VALID(iService) && ServicePtrs[iService]->szService) {
5097                         /*
5098                          * The substitution here is used to support %U is
5099                          * service names
5100                          */
5101                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
5102                         standard_sub_basic(get_current_username(),
5103                                            current_user_info.domain,
5104                                            serviceName,sizeof(serviceName));
5105                         if (strequal(serviceName, pszServiceName)) {
5106                                 break;
5107                         }
5108                 }
5109         }
5110
5111         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5112                 struct timespec last_mod;
5113
5114                 if (!usershare_exists(iService, &last_mod)) {
5115                         /* Remove the share security tdb entry for it. */
5116                         delete_share_security(lp_servicename(talloc_tos(), iService));
5117                         /* Remove it from the array. */
5118                         free_service_byindex(iService);
5119                         /* Doesn't exist anymore. */
5120                         return GLOBAL_SECTION_SNUM;
5121                 }
5122
5123                 /* Has it been modified ? If so delete and reload. */
5124                 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5125                                      &last_mod) < 0) {
5126                         /* Remove it from the array. */
5127                         free_service_byindex(iService);
5128                         /* and now reload it. */
5129                         iService = load_usershare_service(pszServiceName);
5130                 }
5131         }
5132
5133         if (iService < 0) {
5134                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5135                 return GLOBAL_SECTION_SNUM;
5136         }
5137
5138         return (iService);
5139 }
5140
5141 /*******************************************************************
5142  A useful volume label function. 
5143 ********************************************************************/
5144
5145 const char *volume_label(TALLOC_CTX *ctx, int snum)
5146 {
5147         char *ret;
5148         const char *label = lp_volume(ctx, snum);
5149         if (!*label) {
5150                 label = lp_servicename(ctx, snum);
5151         }
5152
5153         /* This returns a 33 byte guarenteed null terminated string. */
5154         ret = talloc_strndup(ctx, label, 32);
5155         if (!ret) {
5156                 return "";
5157         }               
5158         return ret;
5159 }
5160
5161 /*******************************************************************
5162  Get the default server type we will announce as via nmbd.
5163 ********************************************************************/
5164
5165 int lp_default_server_announce(void)
5166 {
5167         int default_server_announce = 0;
5168         default_server_announce |= SV_TYPE_WORKSTATION;
5169         default_server_announce |= SV_TYPE_SERVER;
5170         default_server_announce |= SV_TYPE_SERVER_UNIX;
5171
5172         /* note that the flag should be set only if we have a 
5173            printer service but nmbd doesn't actually load the 
5174            services so we can't tell   --jerry */
5175
5176         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5177
5178         default_server_announce |= SV_TYPE_SERVER_NT;
5179         default_server_announce |= SV_TYPE_NT;
5180
5181         switch (lp_server_role()) {
5182                 case ROLE_DOMAIN_MEMBER:
5183                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5184                         break;
5185                 case ROLE_DOMAIN_PDC:
5186                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5187                         break;
5188                 case ROLE_DOMAIN_BDC:
5189                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5190                         break;
5191                 case ROLE_STANDALONE:
5192                 default:
5193                         break;
5194         }
5195         if (lp_time_server())
5196                 default_server_announce |= SV_TYPE_TIME_SOURCE;
5197
5198         if (lp_host_msdfs())
5199                 default_server_announce |= SV_TYPE_DFS_SERVER;
5200
5201         return default_server_announce;
5202 }
5203
5204 /***********************************************************
5205  If we are PDC then prefer us as DMB
5206 ************************************************************/
5207
5208 bool lp_domain_master(void)
5209 {
5210         if (Globals.domain_master == Auto)
5211                 return (lp_server_role() == ROLE_DOMAIN_PDC);
5212
5213         return (bool)Globals.domain_master;
5214 }
5215
5216 /***********************************************************
5217  If we are PDC then prefer us as DMB
5218 ************************************************************/
5219
5220 static bool lp_domain_master_true_or_auto(void)
5221 {
5222         if (Globals.domain_master) /* auto or yes */
5223                 return true;
5224
5225         return false;
5226 }
5227
5228 /***********************************************************
5229  If we are DMB then prefer us as LMB
5230 ************************************************************/
5231
5232 bool lp_preferred_master(void)
5233 {
5234         if (Globals.iPreferredMaster == Auto)
5235                 return (lp_local_master() && lp_domain_master());
5236
5237         return (bool)Globals.iPreferredMaster;
5238 }
5239
5240 /*******************************************************************
5241  Remove a service.
5242 ********************************************************************/
5243
5244 void lp_remove_service(int snum)
5245 {
5246         ServicePtrs[snum]->valid = false;
5247         invalid_services[num_invalid_services++] = snum;
5248 }
5249
5250 /*******************************************************************
5251  Copy a service.
5252 ********************************************************************/
5253
5254 void lp_copy_service(int snum, const char *new_name)
5255 {
5256         do_section(new_name, NULL);
5257         if (snum >= 0) {
5258                 snum = lp_servicenumber(new_name);
5259                 if (snum >= 0) {
5260                         char *name = lp_servicename(talloc_tos(), snum);
5261                         lp_do_parameter(snum, "copy", name);
5262                 }
5263         }
5264 }
5265
5266 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5267 {
5268         const char *ret = lp__printername(talloc_tos(), snum);
5269         if (ret == NULL || *ret == '\0') {
5270                 ret = lp_const_servicename(snum);
5271         }
5272
5273         return ret;
5274 }
5275
5276
5277 /***********************************************************
5278  Allow daemons such as winbindd to fix their logfile name.
5279 ************************************************************/
5280
5281 void lp_set_logfile(const char *name)
5282 {
5283         string_set(&Globals.logfile, name);
5284         debug_set_logfile(name);
5285 }
5286
5287 /*******************************************************************
5288  Return the max print jobs per queue.
5289 ********************************************************************/
5290
5291 int lp_maxprintjobs(int snum)
5292 {
5293         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5294         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5295                 maxjobs = PRINT_MAX_JOBID - 1;
5296
5297         return maxjobs;
5298 }
5299
5300 const char *lp_printcapname(void)
5301 {
5302         if ((Globals.szPrintcapname != NULL) &&
5303             (Globals.szPrintcapname[0] != '\0'))
5304                 return Globals.szPrintcapname;
5305
5306         if (sDefault.iPrinting == PRINT_CUPS) {
5307                 return "cups";
5308         }
5309
5310         if (sDefault.iPrinting == PRINT_BSD)
5311                 return "/etc/printcap";
5312
5313         return PRINTCAP_NAME;
5314 }
5315
5316 static uint32 spoolss_state;
5317
5318 bool lp_disable_spoolss( void )
5319 {
5320         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5321                 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5322
5323         return spoolss_state == SVCCTL_STOPPED ? true : false;
5324 }
5325
5326 void lp_set_spoolss_state( uint32 state )
5327 {
5328         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5329
5330         spoolss_state = state;
5331 }
5332
5333 uint32 lp_get_spoolss_state( void )
5334 {
5335         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5336 }
5337
5338 /*******************************************************************
5339  Ensure we don't use sendfile if server smb signing is active.
5340 ********************************************************************/
5341
5342 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5343 {
5344         bool sign_active = false;
5345
5346         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5347         if (get_Protocol() < PROTOCOL_NT1) {
5348                 return false;
5349         }
5350         if (signing_state) {
5351                 sign_active = smb_signing_is_active(signing_state);
5352         }
5353         return (lp__use_sendfile(snum) &&
5354                         (get_remote_arch() != RA_WIN95) &&
5355                         !sign_active);
5356 }
5357
5358 /*******************************************************************
5359  Turn off sendfile if we find the underlying OS doesn't support it.
5360 ********************************************************************/
5361
5362 void set_use_sendfile(int snum, bool val)
5363 {
5364         if (LP_SNUM_OK(snum))
5365                 ServicePtrs[snum]->bUseSendfile = val;
5366         else
5367                 sDefault.bUseSendfile = val;
5368 }
5369
5370 /*******************************************************************
5371  Turn off storing DOS attributes if this share doesn't support it.
5372 ********************************************************************/
5373
5374 void set_store_dos_attributes(int snum, bool val)
5375 {
5376         if (!LP_SNUM_OK(snum))
5377                 return;
5378         ServicePtrs[(snum)]->bStoreDosAttributes = val;
5379 }
5380
5381 void lp_set_mangling_method(const char *new_method)
5382 {
5383         string_set(&Globals.szManglingMethod, new_method);
5384 }
5385
5386 /*******************************************************************
5387  Global state for POSIX pathname processing.
5388 ********************************************************************/
5389
5390 static bool posix_pathnames;
5391
5392 bool lp_posix_pathnames(void)
5393 {
5394         return posix_pathnames;
5395 }
5396
5397 /*******************************************************************
5398  Change everything needed to ensure POSIX pathname processing (currently
5399  not much).
5400 ********************************************************************/
5401
5402 void lp_set_posix_pathnames(void)
5403 {
5404         posix_pathnames = true;
5405 }
5406
5407 /*******************************************************************
5408  Global state for POSIX lock processing - CIFS unix extensions.
5409 ********************************************************************/
5410
5411 bool posix_default_lock_was_set;
5412 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5413
5414 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5415 {
5416         if (posix_default_lock_was_set) {
5417                 return posix_cifsx_locktype;
5418         } else {
5419                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5420         }
5421 }
5422
5423 /*******************************************************************
5424 ********************************************************************/
5425
5426 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5427 {
5428         posix_default_lock_was_set = true;
5429         posix_cifsx_locktype = val;
5430 }
5431
5432 int lp_min_receive_file_size(void)
5433 {
5434         if (Globals.iminreceivefile < 0) {
5435                 return 0;
5436         }
5437         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5438 }
5439
5440 /*******************************************************************
5441  Safe wide links checks.
5442  This helper function always verify the validity of wide links,
5443  even after a configuration file reload.
5444 ********************************************************************/
5445
5446 static bool lp_widelinks_internal(int snum)
5447 {
5448         return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5449                         sDefault.bWidelinks);
5450 }
5451
5452 void widelinks_warning(int snum)
5453 {
5454         if (lp_allow_insecure_widelinks()) {
5455                 return;
5456         }
5457
5458         if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5459                 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5460                         "These parameters are incompatible. "
5461                         "Wide links will be disabled for this share.\n",
5462                          lp_servicename(talloc_tos(), snum) ));
5463         }
5464 }
5465
5466 bool lp_widelinks(int snum)
5467 {
5468         /* wide links is always incompatible with unix extensions */
5469         if (lp_unix_extensions()) {
5470                 /*
5471                  * Unless we have "allow insecure widelinks"
5472                  * turned on.
5473                  */
5474                 if (!lp_allow_insecure_widelinks()) {
5475                         return false;
5476                 }
5477         }
5478
5479         return lp_widelinks_internal(snum);
5480 }
5481
5482 bool lp_writeraw(void)
5483 {
5484         if (lp_async_smb_echo_handler()) {
5485                 return false;
5486         }
5487         return lp__writeraw();
5488 }
5489
5490 bool lp_readraw(void)
5491 {
5492         if (lp_async_smb_echo_handler()) {
5493                 return false;
5494         }
5495         return lp__readraw();
5496 }
5497
5498 int lp_server_role(void)
5499 {
5500         return lp_find_server_role(lp__server_role(),
5501                                    lp__security(),
5502                                    lp__domain_logons(),
5503                                    lp_domain_master_true_or_auto());
5504 }
5505
5506 int lp_security(void)
5507 {
5508         return lp_find_security(lp__server_role(),
5509                                 lp__security());
5510 }