swat: Remove swat.
[kamenim/samba-autobuild/.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12    Copyright (C) Michael Adam 2008
13    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14    Copyright (C) Andrew Bartlett 2011
15
16    This program is free software; you can redistribute it and/or modify
17    it under the terms of the GNU General Public License as published by
18    the Free Software Foundation; either version 3 of the License, or
19    (at your option) any later version.
20
21    This program is distributed in the hope that it will be useful,
22    but WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24    GNU General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 */
29
30 /*
31  *  Load parameters.
32  *
33  *  This module provides suitable callback functions for the params
34  *  module. It builds the internal table of service details which is
35  *  then used by the rest of the server.
36  *
37  * To add a parameter:
38  *
39  * 1) add it to the global or service structure definition
40  * 2) add it to the parm_table
41  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42  * 4) If it's a global then initialise it in init_globals. If a local
43  *    (ie. service) parameter then initialise it in the sDefault structure
44  *  
45  *
46  * Notes:
47  *   The configuration file is processed sequentially for speed. It is NOT
48  *   accessed randomly as happens in 'real' Windows. For this reason, there
49  *   is a fair bit of sequence-dependent code here - ie., code which assumes
50  *   that certain things happen before others. In particular, the code which
51  *   happens at the boundary between sections is delicately poised, so be
52  *   careful!
53  *
54  */
55
56 #include "includes.h"
57 #include "system/filesys.h"
58 #include "util_tdb.h"
59 #include "lib/param/loadparm.h"
60 #include "printing.h"
61 #include "lib/smbconf/smbconf.h"
62 #include "lib/smbconf/smbconf_init.h"
63
64 #include "ads.h"
65 #include "../librpc/gen_ndr/svcctl.h"
66 #include "intl.h"
67 #include "../libcli/smb/smb_signing.h"
68 #include "dbwrap/dbwrap.h"
69 #include "dbwrap/dbwrap_rbt.h"
70 #include "../lib/util/bitmap.h"
71
72 #ifdef HAVE_SYS_SYSCTL_H
73 #include <sys/sysctl.h>
74 #endif
75
76 #ifdef HAVE_HTTPCONNECTENCRYPT
77 #include <cups/http.h>
78 #endif
79
80 #ifdef CLUSTER_SUPPORT
81 #include "ctdb_private.h"
82 #endif
83
84 bool bLoaded = false;
85
86 extern userdom_struct current_user_info;
87
88 /* the special value for the include parameter
89  * to be interpreted not as a file name but to
90  * trigger loading of the global smb.conf options
91  * from registry. */
92 #ifndef INCLUDE_REGISTRY_NAME
93 #define INCLUDE_REGISTRY_NAME "registry"
94 #endif
95
96 static bool in_client = false;          /* Not in the client by default */
97 static struct smbconf_csn conf_last_csn;
98
99 static int config_backend = CONFIG_BACKEND_FILE;
100
101 /* some helpful bits */
102 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
103 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
104
105 #define USERSHARE_VALID 1
106 #define USERSHARE_PENDING_DELETE 2
107
108 static bool defaults_saved = false;
109
110 #define LOADPARM_EXTRA_GLOBALS \
111         struct parmlist_entry *param_opt;                               \
112         char *szRealm;                                                  \
113         char *loglevel;                                                 \
114         int iminreceivefile;                                            \
115         char *szPrintcapname;                                           \
116         int CupsEncrypt;                                                \
117         int  iPreferredMaster;                                          \
118         char *szLdapMachineSuffix;                                      \
119         char *szLdapUserSuffix;                                         \
120         char *szLdapIdmapSuffix;                                        \
121         char *szLdapGroupSuffix;                                        \
122         char *szStateDir;                                               \
123         char *szCacheDir;                                               \
124         char *szUsershareTemplateShare;                                 \
125         char *szIdmapUID;                                               \
126         char *szIdmapGID;                                               \
127         char *szIdmapBackend;                                           \
128         int winbindMaxDomainConnections;                                \
129         int ismb2_max_credits;                                          \
130         char *tls_keyfile;                                              \
131         char *tls_certfile;                                             \
132         char *tls_cafile;                                               \
133         char *tls_crlfile;                                              \
134         char *tls_dhpfile;                                              \
135         int bPreferredMaster;
136
137 #include "param/param_global.h"
138
139 static struct loadparm_global Globals;
140
141 /* This is a default service used to prime a services structure */
142 static struct loadparm_service sDefault =
143 {
144         .valid = true,
145         .autoloaded = false,
146         .usershare = 0,
147         .usershare_last_mod = {0, 0},
148         .szService = NULL,
149         .szPath = NULL,
150         .szUsername = NULL,
151         .szInvalidUsers = NULL,
152         .szValidUsers = NULL,
153         .szAdminUsers = NULL,
154         .szCopy = NULL,
155         .szInclude = NULL,
156         .szPreExec = NULL,
157         .szPostExec = NULL,
158         .szRootPreExec = NULL,
159         .szRootPostExec = NULL,
160         .szCupsOptions = NULL,
161         .szPrintcommand = NULL,
162         .szLpqcommand = NULL,
163         .szLprmcommand = NULL,
164         .szLppausecommand = NULL,
165         .szLpresumecommand = NULL,
166         .szQueuepausecommand = NULL,
167         .szQueueresumecommand = NULL,
168         .szPrintername = NULL,
169         .szPrintjobUsername = NULL,
170         .szDontdescend = NULL,
171         .szHostsallow = NULL,
172         .szHostsdeny = NULL,
173         .szMagicScript = NULL,
174         .szMagicOutput = NULL,
175         .szVetoFiles = NULL,
176         .szHideFiles = NULL,
177         .szVetoOplockFiles = NULL,
178         .comment = NULL,
179         .force_user = NULL,
180         .force_group = NULL,
181         .readlist = NULL,
182         .writelist = NULL,
183         .volume = NULL,
184         .fstype = NULL,
185         .szVfsObjects = NULL,
186         .szMSDfsProxy = NULL,
187         .szAioWriteBehind = NULL,
188         .szDfree = NULL,
189         .iMinPrintSpace = 0,
190         .iMaxPrintJobs = 1000,
191         .iMaxReportedPrintJobs = 0,
192         .iWriteCacheSize = 0,
193         .iCreate_mask = 0744,
194         .iCreate_force_mode = 0,
195         .iDir_mask = 0755,
196         .iDir_force_mode = 0,
197         .iMaxConnections = 0,
198         .iDefaultCase = CASE_LOWER,
199         .iPrinting = DEFAULT_PRINTING,
200         .iOplockContentionLimit = 2,
201         .iCSCPolicy = 0,
202         .iBlock_size = 1024,
203         .iDfreeCacheTime = 0,
204         .bPreexecClose = false,
205         .bRootpreexecClose = false,
206         .iCaseSensitive = Auto,
207         .bCasePreserve = true,
208         .bShortCasePreserve = true,
209         .bHideDotFiles = true,
210         .bHideSpecialFiles = false,
211         .bHideUnReadable = false,
212         .bHideUnWriteableFiles = false,
213         .bBrowseable = true,
214         .bAccessBasedShareEnum = false,
215         .bAvailable = true,
216         .bRead_only = true,
217         .bGuest_only = false,
218         .bAdministrative_share = false,
219         .bGuest_ok = false,
220         .bPrint_ok = false,
221         .bPrintNotifyBackchannel = true,
222         .bMap_system = false,
223         .bMap_hidden = false,
224         .bMap_archive = true,
225         .bStoreDosAttributes = false,
226         .bDmapiSupport = false,
227         .bLocking = true,
228         .iStrictLocking = Auto,
229         .bPosixLocking = true,
230         .bOpLocks = true,
231         .bKernelOplocks = false,
232         .bLevel2OpLocks = true,
233         .bOnlyUser = false,
234         .bMangledNames = true,
235         .bWidelinks = false,
236         .bSymlinks = true,
237         .bSyncAlways = false,
238         .bStrictAllocate = false,
239         .bStrictSync = false,
240         .magic_char = '~',
241         .copymap = NULL,
242         .bDeleteReadonly = false,
243         .bFakeOplocks = false,
244         .bDeleteVetoFiles = false,
245         .bDosFilemode = false,
246         .bDosFiletimes = true,
247         .bDosFiletimeResolution = false,
248         .bFakeDirCreateTimes = false,
249         .bBlockingLocks = true,
250         .bInheritPerms = false,
251         .bInheritACLS = false,
252         .bInheritOwner = false,
253         .bMSDfsRoot = false,
254         .bUseClientDriver = false,
255         .bDefaultDevmode = true,
256         .bForcePrintername = false,
257         .bNTAclSupport = true,
258         .bForceUnknownAclUser = false,
259         .bUseSendfile = false,
260         .bProfileAcls = false,
261         .bMap_acl_inherit = false,
262         .bAfs_Share = false,
263         .bEASupport = false,
264         .bAclCheckPermissions = true,
265         .bAclMapFullControl = true,
266         .bAclGroupControl = false,
267         .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  * idmap related parameters
2889  */
2890
2891 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2892 {
2893         lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2894
2895         return true;
2896 }
2897
2898 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2899 {
2900         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2901
2902         return true;
2903 }
2904
2905 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2906 {
2907         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2908
2909         return true;
2910 }
2911
2912 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2913 {
2914         char *config_option = NULL;
2915         const char *range = NULL;
2916         bool ret = false;
2917
2918         SMB_ASSERT(low != NULL);
2919         SMB_ASSERT(high != NULL);
2920
2921         if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2922                 domain_name = "*";
2923         }
2924
2925         config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2926                                         domain_name);
2927         if (config_option == NULL) {
2928                 DEBUG(0, ("out of memory\n"));
2929                 return false;
2930         }
2931
2932         range = lp_parm_const_string(-1, config_option, "range", NULL);
2933         if (range == NULL) {
2934                 DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2935                 goto done;
2936         }
2937
2938         if (sscanf(range, "%u - %u", low, high) != 2) {
2939                 DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2940                           range, domain_name));
2941                 goto done;
2942         }
2943
2944         ret = true;
2945
2946 done:
2947         talloc_free(config_option);
2948         return ret;
2949
2950 }
2951
2952 bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2953 {
2954         return lp_idmap_range("*", low, high);
2955 }
2956
2957 const char *lp_idmap_backend(const char *domain_name)
2958 {
2959         char *config_option = NULL;
2960         const char *backend = NULL;
2961
2962         if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2963                 domain_name = "*";
2964         }
2965
2966         config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2967                                         domain_name);
2968         if (config_option == NULL) {
2969                 DEBUG(0, ("out of memory\n"));
2970                 return false;
2971         }
2972
2973         backend = lp_parm_const_string(-1, config_option, "backend", NULL);
2974         if (backend == NULL) {
2975                 DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
2976                 goto done;
2977         }
2978
2979 done:
2980         talloc_free(config_option);
2981         return backend;
2982 }
2983
2984 const char *lp_idmap_default_backend(void)
2985 {
2986         return lp_idmap_backend("*");
2987 }
2988
2989 /***************************************************************************
2990  Handle the DEBUG level list.
2991 ***************************************************************************/
2992
2993 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2994 {
2995         string_set(ptr, pszParmValueIn);
2996         return debug_parse_levels(pszParmValueIn);
2997 }
2998
2999 /***************************************************************************
3000  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3001 ***************************************************************************/
3002
3003 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
3004 {
3005         const char *suffix_string;
3006
3007         suffix_string = talloc_asprintf(ctx, "%s,%s", str,
3008                                         Globals.szLdapSuffix );
3009         if ( !suffix_string ) {
3010                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3011                 return "";
3012         }
3013
3014         return suffix_string;
3015 }
3016
3017 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
3018 {
3019         if (Globals.szLdapMachineSuffix[0])
3020                 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
3021
3022         return lp_string(ctx, Globals.szLdapSuffix);
3023 }
3024
3025 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
3026 {
3027         if (Globals.szLdapUserSuffix[0])
3028                 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3029
3030         return lp_string(ctx, Globals.szLdapSuffix);
3031 }
3032
3033 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3034 {
3035         if (Globals.szLdapGroupSuffix[0])
3036                 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3037
3038         return lp_string(ctx, Globals.szLdapSuffix);
3039 }
3040
3041 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3042 {
3043         if (Globals.szLdapIdmapSuffix[0])
3044                 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3045
3046         return lp_string(ctx, Globals.szLdapSuffix);
3047 }
3048
3049 /****************************************************************************
3050  set the value for a P_ENUM
3051  ***************************************************************************/
3052
3053 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3054                               int *ptr )
3055 {
3056         int i;
3057
3058         for (i = 0; parm->enum_list[i].name; i++) {
3059                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3060                         *ptr = parm->enum_list[i].value;
3061                         return;
3062                 }
3063         }
3064         DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3065                   pszParmValue, parm->label));
3066 }
3067
3068 /***************************************************************************
3069 ***************************************************************************/
3070
3071 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3072 {
3073         static int parm_num = -1;
3074         struct loadparm_service *s;
3075
3076         if ( parm_num == -1 )
3077                 parm_num = map_parameter( "printing" );
3078
3079         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3080
3081         if ( snum < 0 )
3082                 s = &sDefault;
3083         else
3084                 s = ServicePtrs[snum];
3085
3086         init_printer_values( s );
3087
3088         return true;
3089 }
3090
3091
3092 /***************************************************************************
3093  Initialise a copymap.
3094 ***************************************************************************/
3095
3096 static void init_copymap(struct loadparm_service *pservice)
3097 {
3098         int i;
3099
3100         TALLOC_FREE(pservice->copymap);
3101
3102         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3103         if (!pservice->copymap)
3104                 DEBUG(0,
3105                       ("Couldn't allocate copymap!! (size %d)\n",
3106                        (int)NUMPARAMETERS));
3107         else
3108                 for (i = 0; i < NUMPARAMETERS; i++)
3109                         bitmap_set(pservice->copymap, i);
3110 }
3111
3112 /**
3113   return the parameter pointer for a parameter
3114 */
3115 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3116 {
3117         if (service == NULL) {
3118                 if (parm->p_class == P_LOCAL)
3119                         return (void *)(((char *)&sDefault)+parm->offset);
3120                 else if (parm->p_class == P_GLOBAL)
3121                         return (void *)(((char *)&Globals)+parm->offset);
3122                 else return NULL;
3123         } else {
3124                 return (void *)(((char *)service) + parm->offset);
3125         }
3126 }
3127
3128 /***************************************************************************
3129  Return the local pointer to a parameter given the service number and parameter
3130 ***************************************************************************/
3131
3132 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3133 {
3134         return lp_parm_ptr(ServicePtrs[snum], parm);
3135 }
3136
3137 /***************************************************************************
3138  Process a parameter for a particular service number. If snum < 0
3139  then assume we are in the globals.
3140 ***************************************************************************/
3141
3142 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3143 {
3144         int parmnum, i;
3145         void *parm_ptr = NULL;  /* where we are going to store the result */
3146         struct parmlist_entry **opt_list;
3147
3148         parmnum = map_parameter(pszParmName);
3149
3150         if (parmnum < 0) {
3151                 if (strchr(pszParmName, ':') == NULL) {
3152                         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3153                                   pszParmName));
3154                         return true;
3155                 }
3156
3157                 /*
3158                  * We've got a parametric option
3159                  */
3160
3161                 opt_list = (snum < 0)
3162                         ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3163                 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3164
3165                 return true;
3166         }
3167
3168         /* if it's already been set by the command line, then we don't
3169            override here */
3170         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3171                 return true;
3172         }
3173
3174         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3175                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3176                           pszParmName));
3177         }
3178
3179         /* we might point at a service, the default service or a global */
3180         if (snum < 0) {
3181                 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3182         } else {
3183                 if (parm_table[parmnum].p_class == P_GLOBAL) {
3184                         DEBUG(0,
3185                               ("Global parameter %s found in service section!\n",
3186                                pszParmName));
3187                         return true;
3188                 }
3189                 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3190         }
3191
3192         if (snum >= 0) {
3193                 if (!ServicePtrs[snum]->copymap)
3194                         init_copymap(ServicePtrs[snum]);
3195
3196                 /* this handles the aliases - set the copymap for other entries with
3197                    the same data pointer */
3198                 for (i = 0; parm_table[i].label; i++) {
3199                         if ((parm_table[i].offset == parm_table[parmnum].offset)
3200                             && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3201                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
3202                         }
3203                 }
3204         }
3205
3206         /* if it is a special case then go ahead */
3207         if (parm_table[parmnum].special) {
3208                 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3209                                                    (char **)parm_ptr);
3210         }
3211
3212         /* now switch on the type of variable it is */
3213         switch (parm_table[parmnum].type)
3214         {
3215                 case P_BOOL:
3216                         *(bool *)parm_ptr = lp_bool(pszParmValue);
3217                         break;
3218
3219                 case P_BOOLREV:
3220                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
3221                         break;
3222
3223                 case P_INTEGER:
3224                         *(int *)parm_ptr = lp_int(pszParmValue);
3225                         break;
3226
3227                 case P_CHAR:
3228                         *(char *)parm_ptr = *pszParmValue;
3229                         break;
3230
3231                 case P_OCTAL:
3232                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3233                         if ( i != 1 ) {
3234                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3235                         }
3236                         break;
3237
3238                 case P_BYTES:
3239                 {
3240                         uint64_t val;
3241                         if (conv_str_size_error(pszParmValue, &val)) {
3242                                 if (val <= INT_MAX) {
3243                                         *(int *)parm_ptr = (int)val;
3244                                         break;
3245                                 }
3246                         }
3247
3248                         DEBUG(0,("lp_do_parameter(%s): value is not "
3249                             "a valid size specifier!\n", pszParmValue));
3250                         return false;
3251                 }
3252
3253                 case P_LIST:
3254                 case P_CMDLIST:
3255                         TALLOC_FREE(*((char ***)parm_ptr));
3256                         *(char ***)parm_ptr = str_list_make_v3(
3257                                 NULL, pszParmValue, NULL);
3258                         break;
3259
3260                 case P_STRING:
3261                         string_set((char **)parm_ptr, pszParmValue);
3262                         break;
3263
3264                 case P_USTRING:
3265                 {
3266                         char *upper_string = strupper_talloc(talloc_tos(), 
3267                                                              pszParmValue);
3268                         string_set((char **)parm_ptr, upper_string);
3269                         TALLOC_FREE(upper_string);
3270                         break;
3271                 }
3272                 case P_ENUM:
3273                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3274                         break;
3275                 case P_SEP:
3276                         break;
3277         }
3278
3279         return true;
3280 }
3281
3282 /***************************************************************************
3283 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3284 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3285 ***************************************************************************/
3286
3287 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3288 {
3289         int parmnum, i;
3290         parmnum = map_parameter(pszParmName);
3291         if (parmnum >= 0) {
3292                 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3293                 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3294                         return false;
3295                 }
3296                 parm_table[parmnum].flags |= FLAG_CMDLINE;
3297
3298                 /* we have to also set FLAG_CMDLINE on aliases.  Aliases must
3299                  * be grouped in the table, so we don't have to search the
3300                  * whole table */
3301                 for (i=parmnum-1;
3302                      i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3303                              && parm_table[i].p_class == parm_table[parmnum].p_class;
3304                      i--) {
3305                         parm_table[i].flags |= FLAG_CMDLINE;
3306                 }
3307                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3308                              && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3309                         parm_table[i].flags |= FLAG_CMDLINE;
3310                 }
3311
3312                 if (store_values) {
3313                         store_lp_set_cmdline(pszParmName, pszParmValue);
3314                 }
3315                 return true;
3316         }
3317
3318         /* it might be parametric */
3319         if (strchr(pszParmName, ':') != NULL) {
3320                 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3321                 if (store_values) {
3322                         store_lp_set_cmdline(pszParmName, pszParmValue);
3323                 }
3324                 return true;
3325         }
3326
3327         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
3328         return true;
3329 }
3330
3331 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3332 {
3333         return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3334 }
3335
3336 /***************************************************************************
3337  Process a parameter.
3338 ***************************************************************************/
3339
3340 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3341                          void *userdata)
3342 {
3343         if (!bInGlobalSection && bGlobalOnly)
3344                 return true;
3345
3346         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3347
3348         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3349                                 pszParmName, pszParmValue));
3350 }
3351
3352 /*
3353   set a option from the commandline in 'a=b' format. Use to support --option
3354 */
3355 bool lp_set_option(const char *option)
3356 {
3357         char *p, *s;
3358         bool ret;
3359
3360         s = talloc_strdup(NULL, option);
3361         if (!s) {
3362                 return false;
3363         }
3364
3365         p = strchr(s, '=');
3366         if (!p) {
3367                 talloc_free(s);
3368                 return false;
3369         }
3370
3371         *p = 0;
3372
3373         /* skip white spaces after the = sign */
3374         do {
3375                 p++;
3376         } while (*p == ' ');
3377
3378         ret = lp_set_cmdline(s, p);
3379         talloc_free(s);
3380         return ret;
3381 }
3382
3383 /**************************************************************************
3384  Print a parameter of the specified type.
3385 ***************************************************************************/
3386
3387 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3388 {
3389         /* For the seperation of lists values that we print below */
3390         const char *list_sep = ", ";
3391         int i;
3392         switch (p->type)
3393         {
3394                 case P_ENUM:
3395                         for (i = 0; p->enum_list[i].name; i++) {
3396                                 if (*(int *)ptr == p->enum_list[i].value) {
3397                                         fprintf(f, "%s",
3398                                                 p->enum_list[i].name);
3399                                         break;
3400                                 }
3401                         }
3402                         break;
3403
3404                 case P_BOOL:
3405                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3406                         break;
3407
3408                 case P_BOOLREV:
3409                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3410                         break;
3411
3412                 case P_INTEGER:
3413                 case P_BYTES:
3414                         fprintf(f, "%d", *(int *)ptr);
3415                         break;
3416
3417                 case P_CHAR:
3418                         fprintf(f, "%c", *(char *)ptr);
3419                         break;
3420
3421                 case P_OCTAL: {
3422                         int val = *(int *)ptr; 
3423                         if (val == -1) {
3424                                 fprintf(f, "-1");
3425                         } else {
3426                                 fprintf(f, "0%o", val);
3427                         }
3428                         break;
3429                 }
3430
3431                 case P_CMDLIST:
3432                         list_sep = " ";
3433                         /* fall through */
3434                 case P_LIST:
3435                         if ((char ***)ptr && *(char ***)ptr) {
3436                                 char **list = *(char ***)ptr;
3437                                 for (; *list; list++) {
3438                                         /* surround strings with whitespace in double quotes */
3439                                         if (*(list+1) == NULL) {
3440                                                 /* last item, no extra separator */
3441                                                 list_sep = "";
3442                                         }
3443                                         if ( strchr_m( *list, ' ' ) ) {
3444                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
3445                                         } else {
3446                                                 fprintf(f, "%s%s", *list, list_sep);
3447                                         }
3448                                 }
3449                         }
3450                         break;
3451
3452                 case P_STRING:
3453                 case P_USTRING:
3454                         if (*(char **)ptr) {
3455                                 fprintf(f, "%s", *(char **)ptr);
3456                         }
3457                         break;
3458                 case P_SEP:
3459                         break;
3460         }
3461 }
3462
3463 /***************************************************************************
3464  Check if two parameters are equal.
3465 ***************************************************************************/
3466
3467 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3468 {
3469         switch (type) {
3470                 case P_BOOL:
3471                 case P_BOOLREV:
3472                         return (*((bool *)ptr1) == *((bool *)ptr2));
3473
3474                 case P_INTEGER:
3475                 case P_ENUM:
3476                 case P_OCTAL:
3477                 case P_BYTES:
3478                         return (*((int *)ptr1) == *((int *)ptr2));
3479
3480                 case P_CHAR:
3481                         return (*((char *)ptr1) == *((char *)ptr2));
3482
3483                 case P_LIST:
3484                 case P_CMDLIST:
3485                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3486
3487                 case P_STRING:
3488                 case P_USTRING:
3489                 {
3490                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3491                         if (p1 && !*p1)
3492                                 p1 = NULL;
3493                         if (p2 && !*p2)
3494                                 p2 = NULL;
3495                         return (p1 == p2 || strequal(p1, p2));
3496                 }
3497                 case P_SEP:
3498                         break;
3499         }
3500         return false;
3501 }
3502
3503 /***************************************************************************
3504  Initialize any local variables in the sDefault table, after parsing a
3505  [globals] section.
3506 ***************************************************************************/
3507
3508 static void init_locals(void)
3509 {
3510         /*
3511          * We run this check once the [globals] is parsed, to force
3512          * the VFS objects and other per-share settings we need for
3513          * the standard way a AD DC is operated.  We may change these
3514          * as our code evolves, which is why we force these settings.
3515          *
3516          * We can't do this at the end of lp_load_ex(), as by that
3517          * point the services have been loaded and they will already
3518          * have "" as their vfs objects.
3519          */
3520         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
3521                 const char **vfs_objects = lp_vfs_objects(-1);
3522                 if (!vfs_objects || !vfs_objects[0]) {
3523                         if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
3524                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
3525                         } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
3526                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
3527                         } else {
3528                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
3529                         }
3530                 }
3531
3532                 lp_do_parameter(-1, "map hidden", "no");
3533                 lp_do_parameter(-1, "map system", "no");
3534                 lp_do_parameter(-1, "map readonly", "no");
3535                 lp_do_parameter(-1, "map archive", "no");
3536                 lp_do_parameter(-1, "store dos attributes", "yes");
3537         }
3538 }
3539
3540 /***************************************************************************
3541  Process a new section (service). At this stage all sections are services.
3542  Later we'll have special sections that permit server parameters to be set.
3543  Returns true on success, false on failure.
3544 ***************************************************************************/
3545
3546 static bool do_section(const char *pszSectionName, void *userdata)
3547 {
3548         bool bRetval;
3549         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3550                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3551         bRetval = false;
3552
3553         /* if we were in a global section then do the local inits */
3554         if (bInGlobalSection && !isglobal)
3555                 init_locals();
3556
3557         /* if we've just struck a global section, note the fact. */
3558         bInGlobalSection = isglobal;
3559
3560         /* check for multiple global sections */
3561         if (bInGlobalSection) {
3562                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3563                 return true;
3564         }
3565
3566         if (!bInGlobalSection && bGlobalOnly)
3567                 return true;
3568
3569         /* if we have a current service, tidy it up before moving on */
3570         bRetval = true;
3571
3572         if (iServiceIndex >= 0)
3573                 bRetval = service_ok(iServiceIndex);
3574
3575         /* if all is still well, move to the next record in the services array */
3576         if (bRetval) {
3577                 /* We put this here to avoid an odd message order if messages are */
3578                 /* issued by the post-processing of a previous section. */
3579                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3580
3581                 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3582                 if (iServiceIndex < 0) {
3583                         DEBUG(0, ("Failed to add a new service\n"));
3584                         return false;
3585                 }
3586                 /* Clean all parametric options for service */
3587                 /* They will be added during parsing again */
3588                 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3589         }
3590
3591         return bRetval;
3592 }
3593
3594
3595 /***************************************************************************
3596  Determine if a partcular base parameter is currentl set to the default value.
3597 ***************************************************************************/
3598
3599 static bool is_default(int i)
3600 {
3601         if (!defaults_saved)
3602                 return false;
3603         switch (parm_table[i].type) {
3604                 case P_LIST:
3605                 case P_CMDLIST:
3606                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
3607                                               *(const char ***)lp_parm_ptr(NULL, 
3608                                                                            &parm_table[i]));
3609                 case P_STRING:
3610                 case P_USTRING:
3611                         return strequal(parm_table[i].def.svalue,
3612                                         *(char **)lp_parm_ptr(NULL, 
3613                                                               &parm_table[i]));
3614                 case P_BOOL:
3615                 case P_BOOLREV:
3616                         return parm_table[i].def.bvalue ==
3617                                 *(bool *)lp_parm_ptr(NULL, 
3618                                                      &parm_table[i]);
3619                 case P_CHAR:
3620                         return parm_table[i].def.cvalue ==
3621                                 *(char *)lp_parm_ptr(NULL, 
3622                                                      &parm_table[i]);
3623                 case P_INTEGER:
3624                 case P_OCTAL:
3625                 case P_ENUM:
3626                 case P_BYTES:
3627                         return parm_table[i].def.ivalue ==
3628                                 *(int *)lp_parm_ptr(NULL, 
3629                                                     &parm_table[i]);
3630                 case P_SEP:
3631                         break;
3632         }
3633         return false;
3634 }
3635
3636 /***************************************************************************
3637 Display the contents of the global structure.
3638 ***************************************************************************/
3639
3640 static void dump_globals(FILE *f)
3641 {
3642         int i;
3643         struct parmlist_entry *data;
3644
3645         fprintf(f, "[global]\n");
3646
3647         for (i = 0; parm_table[i].label; i++)
3648                 if (parm_table[i].p_class == P_GLOBAL &&
3649                     !(parm_table[i].flags & FLAG_META) &&
3650                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3651                         if (defaults_saved && is_default(i))
3652                                 continue;
3653                         fprintf(f, "\t%s = ", parm_table[i].label);
3654                         print_parameter(&parm_table[i], lp_parm_ptr(NULL, 
3655                                                                     &parm_table[i]),
3656                                         f);
3657                         fprintf(f, "\n");
3658         }
3659         if (Globals.param_opt != NULL) {
3660                 data = Globals.param_opt;
3661                 while(data) {
3662                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3663                         data = data->next;
3664                 }
3665         }
3666
3667 }
3668
3669 /***************************************************************************
3670  Return true if a local parameter is currently set to the global default.
3671 ***************************************************************************/
3672
3673 bool lp_is_default(int snum, struct parm_struct *parm)
3674 {
3675         return equal_parameter(parm->type,
3676                                lp_parm_ptr(ServicePtrs[snum], parm),
3677                                lp_parm_ptr(NULL, parm));
3678 }
3679
3680 /***************************************************************************
3681  Display the contents of a single services record.
3682 ***************************************************************************/
3683
3684 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3685 {
3686         int i;
3687         struct parmlist_entry *data;
3688
3689         if (pService != &sDefault)
3690                 fprintf(f, "[%s]\n", pService->szService);
3691
3692         for (i = 0; parm_table[i].label; i++) {
3693
3694                 if (parm_table[i].p_class == P_LOCAL &&
3695                     !(parm_table[i].flags & FLAG_META) &&
3696                     (*parm_table[i].label != '-') &&
3697                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
3698                 {
3699                         if (pService == &sDefault) {
3700                                 if (defaults_saved && is_default(i))
3701                                         continue;
3702                         } else {
3703                                 if (equal_parameter(parm_table[i].type,
3704                                                     lp_parm_ptr(pService, &parm_table[i]),
3705                                                     lp_parm_ptr(NULL, &parm_table[i])))
3706                                         continue;
3707                         }
3708
3709                         fprintf(f, "\t%s = ", parm_table[i].label);
3710                         print_parameter(&parm_table[i],
3711                                         lp_parm_ptr(pService, &parm_table[i]),
3712                                         f);
3713                         fprintf(f, "\n");
3714                 }
3715         }
3716
3717                 if (pService->param_opt != NULL) {
3718                         data = pService->param_opt;
3719                         while(data) {
3720                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
3721                                 data = data->next;
3722                         }
3723                 }
3724 }
3725
3726 /***************************************************************************
3727  Display the contents of a parameter of a single services record.
3728 ***************************************************************************/
3729
3730 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3731 {
3732         int i;
3733         bool result = false;
3734         parm_class p_class;
3735         unsigned flag = 0;
3736         fstring local_parm_name;
3737         char *parm_opt;
3738         const char *parm_opt_value;
3739
3740         /* check for parametrical option */
3741         fstrcpy( local_parm_name, parm_name);
3742         parm_opt = strchr( local_parm_name, ':');
3743
3744         if (parm_opt) {
3745                 *parm_opt = '\0';
3746                 parm_opt++;
3747                 if (strlen(parm_opt)) {
3748                         parm_opt_value = lp_parm_const_string( snum,
3749                                 local_parm_name, parm_opt, NULL);
3750                         if (parm_opt_value) {
3751                                 printf( "%s\n", parm_opt_value);
3752                                 result = true;
3753                         }
3754                 }
3755                 return result;
3756         }
3757
3758         /* check for a key and print the value */
3759         if (isGlobal) {
3760                 p_class = P_GLOBAL;
3761                 flag = FLAG_GLOBAL;
3762         } else
3763                 p_class = P_LOCAL;
3764
3765         for (i = 0; parm_table[i].label; i++) {
3766                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3767                     !(parm_table[i].flags & FLAG_META) &&
3768                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3769                     (*parm_table[i].label != '-') &&
3770                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
3771                 {
3772                         void *ptr;
3773
3774                         if (isGlobal) {
3775                                 ptr = lp_parm_ptr(NULL, 
3776                                                   &parm_table[i]);
3777                         } else {
3778                                 ptr = lp_parm_ptr(ServicePtrs[snum], 
3779                                                   &parm_table[i]);
3780                         }
3781
3782                         print_parameter(&parm_table[i],
3783                                         ptr, f);
3784                         fprintf(f, "\n");
3785                         result = true;
3786                         break;
3787                 }
3788         }
3789
3790         return result;
3791 }
3792
3793 /***************************************************************************
3794  Return info about the requested parameter (given as a string).
3795  Return NULL when the string is not a valid parameter name.
3796 ***************************************************************************/
3797
3798 struct parm_struct *lp_get_parameter(const char *param_name)
3799 {
3800         int num = map_parameter(param_name);
3801
3802         if (num < 0) {
3803                 return NULL;
3804         }
3805
3806         return &parm_table[num];
3807 }
3808
3809 /***************************************************************************
3810  Return info about the next parameter in a service.
3811  snum==GLOBAL_SECTION_SNUM gives the globals.
3812  Return NULL when out of parameters.
3813 ***************************************************************************/
3814
3815 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3816 {
3817         if (snum < 0) {
3818                 /* do the globals */
3819                 for (; parm_table[*i].label; (*i)++) {
3820                         if (parm_table[*i].p_class == P_SEPARATOR)
3821                                 return &parm_table[(*i)++];
3822
3823                         if ((*parm_table[*i].label == '-'))
3824                                 continue;
3825
3826                         if ((*i) > 0
3827                             && (parm_table[*i].offset ==
3828                                 parm_table[(*i) - 1].offset)
3829                             && (parm_table[*i].p_class ==
3830                                 parm_table[(*i) - 1].p_class))
3831                                 continue;
3832
3833                         if (is_default(*i) && !allparameters)
3834                                 continue;
3835
3836                         return &parm_table[(*i)++];
3837                 }
3838         } else {
3839                 struct loadparm_service *pService = ServicePtrs[snum];
3840
3841                 for (; parm_table[*i].label; (*i)++) {
3842                         if (parm_table[*i].p_class == P_SEPARATOR)
3843                                 return &parm_table[(*i)++];
3844
3845                         if (parm_table[*i].p_class == P_LOCAL &&
3846                             (*parm_table[*i].label != '-') &&
3847                             ((*i) == 0 ||
3848                              (parm_table[*i].offset !=
3849                               parm_table[(*i) - 1].offset)))
3850                         {
3851                                 if (allparameters ||
3852                                     !equal_parameter(parm_table[*i].type,
3853                                                      lp_parm_ptr(pService, 
3854                                                                  &parm_table[*i]),
3855                                                      lp_parm_ptr(NULL, 
3856                                                                  &parm_table[*i])))
3857                                 {
3858                                         return &parm_table[(*i)++];
3859                                 }
3860                         }
3861                 }
3862         }
3863
3864         return NULL;
3865 }
3866
3867
3868 #if 0
3869 /***************************************************************************
3870  Display the contents of a single copy structure.
3871 ***************************************************************************/
3872 static void dump_copy_map(bool *pcopymap)
3873 {
3874         int i;
3875         if (!pcopymap)
3876                 return;
3877
3878         printf("\n\tNon-Copied parameters:\n");
3879
3880         for (i = 0; parm_table[i].label; i++)
3881                 if (parm_table[i].p_class == P_LOCAL &&
3882                     parm_table[i].ptr && !pcopymap[i] &&
3883                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3884                 {
3885                         printf("\t\t%s\n", parm_table[i].label);
3886                 }
3887 }
3888 #endif
3889
3890 /***************************************************************************
3891  Return TRUE if the passed service number is within range.
3892 ***************************************************************************/
3893
3894 bool lp_snum_ok(int iService)
3895 {
3896         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3897 }
3898
3899 /***************************************************************************
3900  Auto-load some home services.
3901 ***************************************************************************/
3902
3903 static void lp_add_auto_services(char *str)
3904 {
3905         char *s;
3906         char *p;
3907         int homes;
3908         char *saveptr;
3909
3910         if (!str)
3911                 return;
3912
3913         s = SMB_STRDUP(str);
3914         if (!s)
3915                 return;
3916
3917         homes = lp_servicenumber(HOMES_NAME);
3918
3919         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3920              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3921                 char *home;
3922
3923                 if (lp_servicenumber(p) >= 0)
3924                         continue;
3925
3926                 home = get_user_home_dir(talloc_tos(), p);
3927
3928                 if (home && home[0] && homes >= 0)
3929                         lp_add_home(p, homes, p, home);
3930
3931                 TALLOC_FREE(home);
3932         }
3933         SAFE_FREE(s);
3934 }
3935
3936 /***************************************************************************
3937  Auto-load one printer.
3938 ***************************************************************************/
3939
3940 void lp_add_one_printer(const char *name, const char *comment,
3941                         const char *location, void *pdata)
3942 {
3943         int printers = lp_servicenumber(PRINTERS_NAME);
3944         int i;
3945
3946         if (lp_servicenumber(name) < 0) {
3947                 lp_add_printer(name, printers);
3948                 if ((i = lp_servicenumber(name)) >= 0) {
3949                         string_set(&ServicePtrs[i]->comment, comment);
3950                         ServicePtrs[i]->autoloaded = true;
3951                 }
3952         }
3953 }
3954
3955 /***************************************************************************
3956  Have we loaded a services file yet?
3957 ***************************************************************************/
3958
3959 bool lp_loaded(void)
3960 {
3961         return (bLoaded);
3962 }
3963
3964 /***************************************************************************
3965  Unload unused services.
3966 ***************************************************************************/
3967
3968 void lp_killunused(struct smbd_server_connection *sconn,
3969                    bool (*snumused) (struct smbd_server_connection *, int))
3970 {
3971         int i;
3972         for (i = 0; i < iNumServices; i++) {
3973                 if (!VALID(i))
3974                         continue;
3975
3976                 /* don't kill autoloaded or usershare services */
3977                 if ( ServicePtrs[i]->autoloaded ||
3978                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
3979                         continue;
3980                 }
3981
3982                 if (!snumused || !snumused(sconn, i)) {
3983                         free_service_byindex(i);
3984                 }
3985         }
3986 }
3987
3988 /**
3989  * Kill all except autoloaded and usershare services - convenience wrapper
3990  */
3991 void lp_kill_all_services(void)
3992 {
3993         lp_killunused(NULL, NULL);
3994 }
3995
3996 /***************************************************************************
3997  Unload a service.
3998 ***************************************************************************/
3999
4000 void lp_killservice(int iServiceIn)
4001 {
4002         if (VALID(iServiceIn)) {
4003                 free_service_byindex(iServiceIn);
4004         }
4005 }
4006
4007 /***************************************************************************
4008  Save the curent values of all global and sDefault parameters into the 
4009  defaults union. This allows testparm to show only the
4010  changed (ie. non-default) parameters.
4011 ***************************************************************************/
4012
4013 static void lp_save_defaults(void)
4014 {
4015         int i;
4016         for (i = 0; parm_table[i].label; i++) {
4017                 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
4018                     && parm_table[i].p_class == parm_table[i - 1].p_class)
4019                         continue;
4020                 switch (parm_table[i].type) {
4021                         case P_LIST:
4022                         case P_CMDLIST:
4023                                 parm_table[i].def.lvalue = str_list_copy(
4024                                         NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
4025                                 break;
4026                         case P_STRING:
4027                         case P_USTRING:
4028                                 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
4029                                 break;
4030                         case P_BOOL:
4031                         case P_BOOLREV:
4032                                 parm_table[i].def.bvalue =
4033                                         *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
4034                                 break;
4035                         case P_CHAR:
4036                                 parm_table[i].def.cvalue =
4037                                         *(char *)lp_parm_ptr(NULL, &parm_table[i]);
4038                                 break;
4039                         case P_INTEGER:
4040                         case P_OCTAL:
4041                         case P_ENUM:
4042                         case P_BYTES:
4043                                 parm_table[i].def.ivalue =
4044                                         *(int *)lp_parm_ptr(NULL, &parm_table[i]);
4045                                 break;
4046                         case P_SEP:
4047                                 break;
4048                 }
4049         }
4050         defaults_saved = true;
4051 }
4052
4053 /***********************************************************
4054  If we should send plaintext/LANMAN passwords in the clinet
4055 ************************************************************/
4056
4057 static void set_allowed_client_auth(void)
4058 {
4059         if (Globals.bClientNTLMv2Auth) {
4060                 Globals.bClientLanManAuth = false;
4061         }
4062         if (!Globals.bClientLanManAuth) {
4063                 Globals.bClientPlaintextAuth = false;
4064         }
4065 }
4066
4067 /***************************************************************************
4068  JRA.
4069  The following code allows smbd to read a user defined share file.
4070  Yes, this is my intent. Yes, I'm comfortable with that...
4071
4072  THE FOLLOWING IS SECURITY CRITICAL CODE.
4073
4074  It washes your clothes, it cleans your house, it guards you while you sleep...
4075  Do not f%^k with it....
4076 ***************************************************************************/
4077
4078 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4079
4080 /***************************************************************************
4081  Check allowed stat state of a usershare file.
4082  Ensure we print out who is dicking with us so the admin can
4083  get their sorry ass fired.
4084 ***************************************************************************/
4085
4086 static bool check_usershare_stat(const char *fname,
4087                                  const SMB_STRUCT_STAT *psbuf)
4088 {
4089         if (!S_ISREG(psbuf->st_ex_mode)) {
4090                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4091                         "not a regular file\n",
4092                         fname, (unsigned int)psbuf->st_ex_uid ));
4093                 return false;
4094         }
4095
4096         /* Ensure this doesn't have the other write bit set. */
4097         if (psbuf->st_ex_mode & S_IWOTH) {
4098                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4099                         "public write. Refusing to allow as a usershare file.\n",
4100                         fname, (unsigned int)psbuf->st_ex_uid ));
4101                 return false;
4102         }
4103
4104         /* Should be 10k or less. */
4105         if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4106                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4107                         "too large (%u) to be a user share file.\n",
4108                         fname, (unsigned int)psbuf->st_ex_uid,
4109                         (unsigned int)psbuf->st_ex_size ));
4110                 return false;
4111         }
4112
4113         return true;
4114 }
4115
4116 /***************************************************************************
4117  Parse the contents of a usershare file.
4118 ***************************************************************************/
4119
4120 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4121                         SMB_STRUCT_STAT *psbuf,
4122                         const char *servicename,
4123                         int snum,
4124                         char **lines,
4125                         int numlines,
4126                         char **pp_sharepath,
4127                         char **pp_comment,
4128                         char **pp_cp_servicename,
4129                         struct security_descriptor **ppsd,
4130                         bool *pallow_guest)
4131 {
4132         const char **prefixallowlist = lp_usershare_prefix_allow_list();
4133         const char **prefixdenylist = lp_usershare_prefix_deny_list();
4134         int us_vers;
4135         DIR *dp;
4136         SMB_STRUCT_STAT sbuf;
4137         char *sharepath = NULL;
4138         char *comment = NULL;
4139
4140         *pp_sharepath = NULL;
4141         *pp_comment = NULL;
4142
4143         *pallow_guest = false;
4144
4145         if (numlines < 4) {
4146                 return USERSHARE_MALFORMED_FILE;
4147         }
4148
4149         if (strcmp(lines[0], "#VERSION 1") == 0) {
4150                 us_vers = 1;
4151         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4152                 us_vers = 2;
4153                 if (numlines < 5) {
4154                         return USERSHARE_MALFORMED_FILE;
4155                 }
4156         } else {
4157                 return USERSHARE_BAD_VERSION;
4158         }
4159
4160         if (strncmp(lines[1], "path=", 5) != 0) {
4161                 return USERSHARE_MALFORMED_PATH;
4162         }
4163
4164         sharepath = talloc_strdup(ctx, &lines[1][5]);
4165         if (!sharepath) {
4166                 return USERSHARE_POSIX_ERR;
4167         }
4168         trim_string(sharepath, " ", " ");
4169
4170         if (strncmp(lines[2], "comment=", 8) != 0) {
4171                 return USERSHARE_MALFORMED_COMMENT_DEF;
4172         }
4173
4174         comment = talloc_strdup(ctx, &lines[2][8]);
4175         if (!comment) {
4176                 return USERSHARE_POSIX_ERR;
4177         }
4178         trim_string(comment, " ", " ");
4179         trim_char(comment, '"', '"');
4180
4181         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4182                 return USERSHARE_MALFORMED_ACL_DEF;
4183         }
4184
4185         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4186                 return USERSHARE_ACL_ERR;
4187         }
4188
4189         if (us_vers == 2) {
4190                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4191                         return USERSHARE_MALFORMED_ACL_DEF;
4192                 }
4193                 if (lines[4][9] == 'y') {
4194                         *pallow_guest = true;
4195                 }
4196
4197                 /* Backwards compatible extension to file version #2. */
4198                 if (numlines > 5) {
4199                         if (strncmp(lines[5], "sharename=", 10) != 0) {
4200                                 return USERSHARE_MALFORMED_SHARENAME_DEF;
4201                         }
4202                         if (!strequal(&lines[5][10], servicename)) {
4203                                 return USERSHARE_BAD_SHARENAME;
4204                         }
4205                         *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4206                         if (!*pp_cp_servicename) {
4207                                 return USERSHARE_POSIX_ERR;
4208                         }
4209                 }
4210         }
4211
4212         if (*pp_cp_servicename == NULL) {
4213                 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4214                 if (!*pp_cp_servicename) {
4215                         return USERSHARE_POSIX_ERR;
4216                 }
4217         }
4218
4219         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4220                 /* Path didn't change, no checks needed. */
4221                 *pp_sharepath = sharepath;
4222                 *pp_comment = comment;
4223                 return USERSHARE_OK;
4224         }
4225
4226         /* The path *must* be absolute. */
4227         if (sharepath[0] != '/') {
4228                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4229                         servicename, sharepath));
4230                 return USERSHARE_PATH_NOT_ABSOLUTE;
4231         }
4232
4233         /* If there is a usershare prefix deny list ensure one of these paths
4234            doesn't match the start of the user given path. */
4235         if (prefixdenylist) {
4236                 int i;
4237                 for ( i=0; prefixdenylist[i]; i++ ) {
4238                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4239                                 servicename, i, prefixdenylist[i], sharepath ));
4240                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4241                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4242                                         "usershare prefix deny list entries.\n",
4243                                         servicename, sharepath));
4244                                 return USERSHARE_PATH_IS_DENIED;
4245                         }
4246                 }
4247         }
4248
4249         /* If there is a usershare prefix allow list ensure one of these paths
4250            does match the start of the user given path. */
4251
4252         if (prefixallowlist) {
4253                 int i;
4254                 for ( i=0; prefixallowlist[i]; i++ ) {
4255                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4256                                 servicename, i, prefixallowlist[i], sharepath ));
4257                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4258                                 break;
4259                         }
4260                 }
4261                 if (prefixallowlist[i] == NULL) {
4262                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4263                                 "usershare prefix allow list entries.\n",
4264                                 servicename, sharepath));
4265                         return USERSHARE_PATH_NOT_ALLOWED;
4266                 }
4267         }
4268
4269         /* Ensure this is pointing to a directory. */
4270         dp = opendir(sharepath);
4271
4272         if (!dp) {
4273                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4274                         servicename, sharepath));
4275                 return USERSHARE_PATH_NOT_DIRECTORY;
4276         }
4277
4278         /* Ensure the owner of the usershare file has permission to share
4279            this directory. */
4280
4281         if (sys_stat(sharepath, &sbuf, false) == -1) {
4282                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4283                         servicename, sharepath, strerror(errno) ));
4284                 closedir(dp);
4285                 return USERSHARE_POSIX_ERR;
4286         }
4287
4288         closedir(dp);
4289
4290         if (!S_ISDIR(sbuf.st_ex_mode)) {
4291                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4292                         servicename, sharepath ));
4293                 return USERSHARE_PATH_NOT_DIRECTORY;
4294         }
4295
4296         /* Check if sharing is restricted to owner-only. */
4297         /* psbuf is the stat of the usershare definition file,
4298            sbuf is the stat of the target directory to be shared. */
4299
4300         if (lp_usershare_owner_only()) {
4301                 /* root can share anything. */
4302                 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4303                         return USERSHARE_PATH_NOT_ALLOWED;
4304                 }
4305         }
4306
4307         *pp_sharepath = sharepath;
4308         *pp_comment = comment;
4309         return USERSHARE_OK;
4310 }
4311
4312 /***************************************************************************
4313  Deal with a usershare file.
4314  Returns:
4315         >= 0 - snum
4316         -1 - Bad name, invalid contents.
4317            - service name already existed and not a usershare, problem
4318             with permissions to share directory etc.
4319 ***************************************************************************/
4320
4321 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4322 {
4323         SMB_STRUCT_STAT sbuf;
4324         SMB_STRUCT_STAT lsbuf;
4325         char *fname = NULL;
4326         char *sharepath = NULL;
4327         char *comment = NULL;
4328         char *cp_service_name = NULL;
4329         char **lines = NULL;
4330         int numlines = 0;
4331         int fd = -1;
4332         int iService = -1;
4333         TALLOC_CTX *ctx = talloc_stackframe();
4334         struct security_descriptor *psd = NULL;
4335         bool guest_ok = false;
4336         char *canon_name = NULL;
4337         bool added_service = false;
4338         int ret = -1;
4339
4340         /* Ensure share name doesn't contain invalid characters. */
4341         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4342                 DEBUG(0,("process_usershare_file: share name %s contains "
4343                         "invalid characters (any of %s)\n",
4344                         file_name, INVALID_SHARENAME_CHARS ));
4345                 goto out;
4346         }
4347
4348         canon_name = canonicalize_servicename(ctx, file_name);
4349         if (!canon_name) {
4350                 goto out;
4351         }
4352
4353         fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4354         if (!fname) {
4355                 goto out;
4356         }
4357
4358         /* Minimize the race condition by doing an lstat before we
4359            open and fstat. Ensure this isn't a symlink link. */
4360
4361         if (sys_lstat(fname, &lsbuf, false) != 0) {
4362                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4363                         fname, strerror(errno) ));
4364                 goto out;
4365         }
4366
4367         /* This must be a regular file, not a symlink, directory or
4368            other strange filetype. */
4369         if (!check_usershare_stat(fname, &lsbuf)) {
4370                 goto out;
4371         }
4372
4373         {
4374                 TDB_DATA data;
4375                 NTSTATUS status;
4376
4377                 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4378                                                canon_name, &data);
4379
4380                 iService = -1;
4381
4382                 if (NT_STATUS_IS_OK(status) &&
4383                     (data.dptr != NULL) &&
4384                     (data.dsize == sizeof(iService))) {
4385                         memcpy(&iService, data.dptr, sizeof(iService));
4386                 }
4387         }
4388
4389         if (iService != -1 &&
4390             timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4391                              &lsbuf.st_ex_mtime) == 0) {
4392                 /* Nothing changed - Mark valid and return. */
4393                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4394                         canon_name ));
4395                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4396                 ret = iService;
4397                 goto out;
4398         }
4399
4400         /* Try and open the file read only - no symlinks allowed. */
4401 #ifdef O_NOFOLLOW
4402         fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4403 #else
4404         fd = open(fname, O_RDONLY, 0);
4405 #endif
4406
4407         if (fd == -1) {
4408                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4409                         fname, strerror(errno) ));
4410                 goto out;
4411         }
4412
4413         /* Now fstat to be *SURE* it's a regular file. */
4414         if (sys_fstat(fd, &sbuf, false) != 0) {
4415                 close(fd);
4416                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4417                         fname, strerror(errno) ));
4418                 goto out;
4419         }
4420
4421         /* Is it the same dev/inode as was lstated ? */
4422         if (!check_same_stat(&lsbuf, &sbuf)) {
4423                 close(fd);
4424                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4425                         "Symlink spoofing going on ?\n", fname ));
4426                 goto out;
4427         }
4428
4429         /* This must be a regular file, not a symlink, directory or
4430            other strange filetype. */
4431         if (!check_usershare_stat(fname, &sbuf)) {
4432                 close(fd);
4433                 goto out;
4434         }
4435
4436         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4437
4438         close(fd);
4439         if (lines == NULL) {
4440                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4441                         fname, (unsigned int)sbuf.st_ex_uid ));
4442                 goto out;
4443         }
4444
4445         if (parse_usershare_file(ctx, &sbuf, file_name,
4446                         iService, lines, numlines, &sharepath,
4447                         &comment, &cp_service_name,
4448                         &psd, &guest_ok) != USERSHARE_OK) {
4449                 goto out;
4450         }
4451
4452         /* Everything ok - add the service possibly using a template. */
4453         if (iService < 0) {
4454                 const struct loadparm_service *sp = &sDefault;
4455                 if (snum_template != -1) {
4456                         sp = ServicePtrs[snum_template];
4457                 }
4458
4459                 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4460                         DEBUG(0, ("process_usershare_file: Failed to add "
4461                                 "new service %s\n", cp_service_name));
4462                         goto out;
4463                 }
4464
4465                 added_service = true;
4466
4467                 /* Read only is controlled by usershare ACL below. */
4468                 ServicePtrs[iService]->bRead_only = false;
4469         }
4470
4471         /* Write the ACL of the new/modified share. */
4472         if (!set_share_security(canon_name, psd)) {
4473                  DEBUG(0, ("process_usershare_file: Failed to set share "
4474                         "security for user share %s\n",
4475                         canon_name ));
4476                 goto out;
4477         }
4478
4479         /* If from a template it may be marked invalid. */
4480         ServicePtrs[iService]->valid = true;
4481
4482         /* Set the service as a valid usershare. */
4483         ServicePtrs[iService]->usershare = USERSHARE_VALID;
4484
4485         /* Set guest access. */
4486         if (lp_usershare_allow_guests()) {
4487                 ServicePtrs[iService]->bGuest_ok = guest_ok;
4488         }
4489
4490         /* And note when it was loaded. */
4491         ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4492         string_set(&ServicePtrs[iService]->szPath, sharepath);
4493         string_set(&ServicePtrs[iService]->comment, comment);
4494
4495         ret = iService;
4496
4497   out:
4498
4499         if (ret == -1 && iService != -1 && added_service) {
4500                 lp_remove_service(iService);
4501         }
4502
4503         TALLOC_FREE(lines);
4504         TALLOC_FREE(ctx);
4505         return ret;
4506 }
4507
4508 /***************************************************************************
4509  Checks if a usershare entry has been modified since last load.
4510 ***************************************************************************/
4511
4512 static bool usershare_exists(int iService, struct timespec *last_mod)
4513 {
4514         SMB_STRUCT_STAT lsbuf;
4515         const char *usersharepath = Globals.szUsersharePath;
4516         char *fname;
4517
4518         if (asprintf(&fname, "%s/%s",
4519                                 usersharepath,
4520                                 ServicePtrs[iService]->szService) < 0) {
4521                 return false;
4522         }
4523
4524         if (sys_lstat(fname, &lsbuf, false) != 0) {
4525                 SAFE_FREE(fname);
4526                 return false;
4527         }
4528
4529         if (!S_ISREG(lsbuf.st_ex_mode)) {
4530                 SAFE_FREE(fname);
4531                 return false;
4532         }
4533
4534         SAFE_FREE(fname);
4535         *last_mod = lsbuf.st_ex_mtime;
4536         return true;
4537 }
4538
4539 /***************************************************************************
4540  Load a usershare service by name. Returns a valid servicenumber or -1.
4541 ***************************************************************************/
4542
4543 int load_usershare_service(const char *servicename)
4544 {
4545         SMB_STRUCT_STAT sbuf;
4546         const char *usersharepath = Globals.szUsersharePath;
4547         int max_user_shares = Globals.iUsershareMaxShares;
4548         int snum_template = -1;
4549
4550         if (*usersharepath == 0 ||  max_user_shares == 0) {
4551                 return -1;
4552         }
4553
4554         if (sys_stat(usersharepath, &sbuf, false) != 0) {
4555                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4556                         usersharepath, strerror(errno) ));
4557                 return -1;
4558         }
4559
4560         if (!S_ISDIR(sbuf.st_ex_mode)) {
4561                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4562                         usersharepath ));
4563                 return -1;
4564         }
4565
4566         /*
4567          * This directory must be owned by root, and have the 't' bit set.
4568          * It also must not be writable by "other".
4569          */
4570
4571 #ifdef S_ISVTX
4572         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4573 #else
4574         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4575 #endif
4576                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4577                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4578                         usersharepath ));
4579                 return -1;
4580         }
4581
4582         /* Ensure the template share exists if it's set. */
4583         if (Globals.szUsershareTemplateShare[0]) {
4584                 /* We can't use lp_servicenumber here as we are recommending that
4585                    template shares have -valid=false set. */
4586                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4587                         if (ServicePtrs[snum_template]->szService &&
4588                                         strequal(ServicePtrs[snum_template]->szService,
4589                                                 Globals.szUsershareTemplateShare)) {
4590                                 break;
4591                         }
4592                 }
4593
4594                 if (snum_template == -1) {
4595                         DEBUG(0,("load_usershare_service: usershare template share %s "
4596                                 "does not exist.\n",
4597                                 Globals.szUsershareTemplateShare ));
4598                         return -1;
4599                 }
4600         }
4601
4602         return process_usershare_file(usersharepath, servicename, snum_template);
4603 }
4604
4605 /***************************************************************************
4606  Load all user defined shares from the user share directory.
4607  We only do this if we're enumerating the share list.
4608  This is the function that can delete usershares that have
4609  been removed.
4610 ***************************************************************************/
4611
4612 int load_usershare_shares(struct smbd_server_connection *sconn,
4613                           bool (*snumused) (struct smbd_server_connection *, int))
4614 {
4615         DIR *dp;
4616         SMB_STRUCT_STAT sbuf;
4617         struct dirent *de;
4618         int num_usershares = 0;
4619         int max_user_shares = Globals.iUsershareMaxShares;
4620         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4621         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4622         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4623         int iService;
4624         int snum_template = -1;
4625         const char *usersharepath = Globals.szUsersharePath;
4626         int ret = lp_numservices();
4627         TALLOC_CTX *tmp_ctx;
4628
4629         if (max_user_shares == 0 || *usersharepath == '\0') {
4630                 return lp_numservices();
4631         }
4632
4633         if (sys_stat(usersharepath, &sbuf, false) != 0) {
4634                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4635                         usersharepath, strerror(errno) ));
4636                 return ret;
4637         }
4638
4639         /*
4640          * This directory must be owned by root, and have the 't' bit set.
4641          * It also must not be writable by "other".
4642          */
4643
4644 #ifdef S_ISVTX
4645         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4646 #else
4647         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4648 #endif
4649                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4650                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4651                         usersharepath ));
4652                 return ret;
4653         }
4654
4655         /* Ensure the template share exists if it's set. */
4656         if (Globals.szUsershareTemplateShare[0]) {
4657                 /* We can't use lp_servicenumber here as we are recommending that
4658                    template shares have -valid=false set. */
4659                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4660                         if (ServicePtrs[snum_template]->szService &&
4661                                         strequal(ServicePtrs[snum_template]->szService,
4662                                                 Globals.szUsershareTemplateShare)) {
4663                                 break;
4664                         }
4665                 }
4666
4667                 if (snum_template == -1) {
4668                         DEBUG(0,("load_usershare_shares: usershare template share %s "
4669                                 "does not exist.\n",
4670                                 Globals.szUsershareTemplateShare ));
4671                         return ret;
4672                 }
4673         }
4674
4675         /* Mark all existing usershares as pending delete. */
4676         for (iService = iNumServices - 1; iService >= 0; iService--) {
4677                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4678                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4679                 }
4680         }
4681
4682         dp = opendir(usersharepath);
4683         if (!dp) {
4684                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4685                         usersharepath, strerror(errno) ));
4686                 return ret;
4687         }
4688
4689         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4690                         (de = readdir(dp));
4691                         num_dir_entries++ ) {
4692                 int r;
4693                 const char *n = de->d_name;
4694
4695                 /* Ignore . and .. */
4696                 if (*n == '.') {
4697                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4698                                 continue;
4699                         }
4700                 }
4701
4702                 if (n[0] == ':') {
4703                         /* Temporary file used when creating a share. */
4704                         num_tmp_dir_entries++;
4705                 }
4706
4707                 /* Allow 20% tmp entries. */
4708                 if (num_tmp_dir_entries > allowed_tmp_entries) {
4709                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4710                                 "in directory %s\n",
4711                                 num_tmp_dir_entries, usersharepath));
4712                         break;
4713                 }
4714
4715                 r = process_usershare_file(usersharepath, n, snum_template);
4716                 if (r == 0) {
4717                         /* Update the services count. */
4718                         num_usershares++;
4719                         if (num_usershares >= max_user_shares) {
4720                                 DEBUG(0,("load_usershare_shares: max user shares reached "
4721                                         "on file %s in directory %s\n",
4722                                         n, usersharepath ));
4723                                 break;
4724                         }
4725                 } else if (r == -1) {
4726                         num_bad_dir_entries++;
4727                 }
4728
4729                 /* Allow 20% bad entries. */
4730                 if (num_bad_dir_entries > allowed_bad_entries) {
4731                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4732                                 "in directory %s\n",
4733                                 num_bad_dir_entries, usersharepath));
4734                         break;
4735                 }
4736
4737                 /* Allow 20% bad entries. */
4738                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4739                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4740                         "in directory %s\n",
4741                         num_dir_entries, usersharepath));
4742                         break;
4743                 }
4744         }
4745
4746         closedir(dp);
4747
4748         /* Sweep through and delete any non-refreshed usershares that are
4749            not currently in use. */
4750         tmp_ctx = talloc_stackframe();
4751         for (iService = iNumServices - 1; iService >= 0; iService--) {
4752                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4753                         char *servname;
4754
4755                         if (snumused && snumused(sconn, iService)) {
4756                                 continue;
4757                         }
4758
4759                         servname = lp_servicename(tmp_ctx, iService);
4760
4761                         /* Remove from the share ACL db. */
4762                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4763                                   servname ));
4764                         delete_share_security(servname);
4765                         free_service_byindex(iService);
4766                 }
4767         }
4768         talloc_free(tmp_ctx);
4769
4770         return lp_numservices();
4771 }
4772
4773 /********************************************************
4774  Destroy global resources allocated in this file
4775 ********************************************************/
4776
4777 void gfree_loadparm(void)
4778 {
4779         int i;
4780
4781         free_file_list();
4782
4783         /* Free resources allocated to services */
4784
4785         for ( i = 0; i < iNumServices; i++ ) {
4786                 if ( VALID(i) ) {
4787                         free_service_byindex(i);
4788                 }
4789         }
4790
4791         SAFE_FREE( ServicePtrs );
4792         iNumServices = 0;
4793
4794         /* Now release all resources allocated to global
4795            parameters and the default service */
4796
4797         free_global_parameters();
4798 }
4799
4800
4801 /***************************************************************************
4802  Allow client apps to specify that they are a client
4803 ***************************************************************************/
4804 static void lp_set_in_client(bool b)
4805 {
4806     in_client = b;
4807 }
4808
4809
4810 /***************************************************************************
4811  Determine if we're running in a client app
4812 ***************************************************************************/
4813 static bool lp_is_in_client(void)
4814 {
4815     return in_client;
4816 }
4817
4818 /***************************************************************************
4819  Load the services array from the services file. Return true on success,
4820  false on failure.
4821 ***************************************************************************/
4822
4823 static bool lp_load_ex(const char *pszFname,
4824                        bool global_only,
4825                        bool save_defaults,
4826                        bool add_ipc,
4827                        bool initialize_globals,
4828                        bool allow_include_registry,
4829                        bool load_all_shares)
4830 {
4831         char *n2 = NULL;
4832         bool bRetval;
4833
4834         bRetval = false;
4835
4836         DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4837
4838         bInGlobalSection = true;
4839         bGlobalOnly = global_only;
4840         bAllowIncludeRegistry = allow_include_registry;
4841
4842         init_globals(initialize_globals);
4843
4844         free_file_list();
4845
4846         if (save_defaults) {
4847                 init_locals();
4848                 lp_save_defaults();
4849         }
4850
4851         if (!initialize_globals) {
4852                 free_param_opts(&Globals.param_opt);
4853                 apply_lp_set_cmdline();
4854         }
4855
4856         lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4857
4858         /* We get sections first, so have to start 'behind' to make up */
4859         iServiceIndex = -1;
4860
4861         if (lp_config_backend_is_file()) {
4862                 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4863                                         current_user_info.domain,
4864                                         pszFname);
4865                 if (!n2) {
4866                         smb_panic("lp_load_ex: out of memory");
4867                 }
4868
4869                 add_to_file_list(pszFname, n2);
4870
4871                 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4872                 TALLOC_FREE(n2);
4873
4874                 /* finish up the last section */
4875                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4876                 if (bRetval) {
4877                         if (iServiceIndex >= 0) {
4878                                 bRetval = service_ok(iServiceIndex);
4879                         }
4880                 }
4881
4882                 if (lp_config_backend_is_registry()) {
4883                         /* config backend changed to registry in config file */
4884                         /*
4885                          * We need to use this extra global variable here to
4886                          * survive restart: init_globals uses this as a default
4887                          * for ConfigBackend. Otherwise, init_globals would
4888                          *  send us into an endless loop here.
4889                          */
4890                         config_backend = CONFIG_BACKEND_REGISTRY;
4891                         /* start over */
4892                         DEBUG(1, ("lp_load_ex: changing to config backend "
4893                                   "registry\n"));
4894                         init_globals(true);
4895                         lp_kill_all_services();
4896                         return lp_load_ex(pszFname, global_only, save_defaults,
4897                                           add_ipc, initialize_globals,
4898                                           allow_include_registry,
4899                                           load_all_shares);
4900                 }
4901         } else if (lp_config_backend_is_registry()) {
4902                 bRetval = process_registry_globals();
4903         } else {
4904                 DEBUG(0, ("Illegal config  backend given: %d\n",
4905                           lp_config_backend()));
4906                 bRetval = false;
4907         }
4908
4909         if (bRetval && lp_registry_shares()) {
4910                 if (load_all_shares) {
4911                         bRetval = process_registry_shares();
4912                 } else {
4913                         bRetval = reload_registry_shares();
4914                 }
4915         }
4916
4917         {
4918                 char *serv = lp_auto_services(talloc_tos());
4919                 lp_add_auto_services(serv);
4920                 TALLOC_FREE(serv);
4921         }
4922
4923         if (add_ipc) {
4924                 /* When 'restrict anonymous = 2' guest connections to ipc$
4925                    are denied */
4926                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4927                 if ( lp_enable_asu_support() ) {
4928                         lp_add_ipc("ADMIN$", false);
4929                 }
4930         }
4931
4932         set_allowed_client_auth();
4933
4934         if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4935                 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4936                           lp_passwordserver()));
4937         }
4938
4939         bLoaded = true;
4940
4941         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4942         /* if bWINSsupport is true and we are in the client            */
4943         if (lp_is_in_client() && Globals.bWINSsupport) {
4944                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4945         }
4946
4947         init_iconv();
4948
4949         fault_configure(smb_panic_s3);
4950
4951         /*
4952          * We run this check once the whole smb.conf is parsed, to
4953          * force some settings for the standard way a AD DC is
4954          * operated.  We may changed these as our code evolves, which
4955          * is why we force these settings.
4956          */
4957         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4958                 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4959
4960                 lp_do_parameter(-1, "rpc_server:default", "external");
4961                 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4962                 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4963                 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4964                 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4965                 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4966                 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4967                 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4968                 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4969         }
4970
4971         bAllowIncludeRegistry = true;
4972
4973         return (bRetval);
4974 }
4975
4976 bool lp_load(const char *pszFname,
4977              bool global_only,
4978              bool save_defaults,
4979              bool add_ipc,
4980              bool initialize_globals)
4981 {
4982         return lp_load_ex(pszFname,
4983                           global_only,
4984                           save_defaults,
4985                           add_ipc,
4986                           initialize_globals,
4987                           true,   /* allow_include_registry */
4988                           false); /* load_all_shares*/
4989 }
4990
4991 bool lp_load_initial_only(const char *pszFname)
4992 {
4993         return lp_load_ex(pszFname,
4994                           true,   /* global only */
4995                           false,  /* save_defaults */
4996                           false,  /* add_ipc */
4997                           true,   /* initialize_globals */
4998                           false,  /* allow_include_registry */
4999                           false); /* load_all_shares*/
5000 }
5001
5002 /**
5003  * most common lp_load wrapper, loading only the globals
5004  */
5005 bool lp_load_global(const char *file_name)
5006 {
5007         return lp_load_ex(file_name,
5008                           true,   /* global_only */
5009                           false,  /* save_defaults */
5010                           false,  /* add_ipc */
5011                           true,   /* initialize_globals */
5012                           true,   /* allow_include_registry */
5013                           false); /* load_all_shares*/
5014 }
5015
5016 /**
5017  * lp_load wrapper, especially for clients
5018  */
5019 bool lp_load_client(const char *file_name)
5020 {
5021         lp_set_in_client(true);
5022
5023         return lp_load_global(file_name);
5024 }
5025
5026 /**
5027  * lp_load wrapper, loading only globals, but intended
5028  * for subsequent calls, not reinitializing the globals
5029  * to default values
5030  */
5031 bool lp_load_global_no_reinit(const char *file_name)
5032 {
5033         return lp_load_ex(file_name,
5034                           true,   /* global_only */
5035                           false,  /* save_defaults */
5036                           false,  /* add_ipc */
5037                           false,  /* initialize_globals */
5038                           true,   /* allow_include_registry */
5039                           false); /* load_all_shares*/
5040 }
5041
5042 /**
5043  * lp_load wrapper, especially for clients, no reinitialization
5044  */
5045 bool lp_load_client_no_reinit(const char *file_name)
5046 {
5047         lp_set_in_client(true);
5048
5049         return lp_load_global_no_reinit(file_name);
5050 }
5051
5052 bool lp_load_with_registry_shares(const char *pszFname,
5053                                   bool global_only,
5054                                   bool save_defaults,
5055                                   bool add_ipc,
5056                                   bool initialize_globals)
5057 {
5058         return lp_load_ex(pszFname,
5059                           global_only,
5060                           save_defaults,
5061                           add_ipc,
5062                           initialize_globals,
5063                           true,  /* allow_include_registry */
5064                           true); /* load_all_shares*/
5065 }
5066
5067 /***************************************************************************
5068  Return the max number of services.
5069 ***************************************************************************/
5070
5071 int lp_numservices(void)
5072 {
5073         return (iNumServices);
5074 }
5075
5076 /***************************************************************************
5077 Display the contents of the services array in human-readable form.
5078 ***************************************************************************/
5079
5080 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5081 {
5082         int iService;
5083
5084         if (show_defaults)
5085                 defaults_saved = false;
5086
5087         dump_globals(f);
5088
5089         dump_a_service(&sDefault, f);
5090
5091         for (iService = 0; iService < maxtoprint; iService++) {
5092                 fprintf(f,"\n");
5093                 lp_dump_one(f, show_defaults, iService);
5094         }
5095 }
5096
5097 /***************************************************************************
5098 Display the contents of one service in human-readable form.
5099 ***************************************************************************/
5100
5101 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5102 {
5103         if (VALID(snum)) {
5104                 if (ServicePtrs[snum]->szService[0] == '\0')
5105                         return;
5106                 dump_a_service(ServicePtrs[snum], f);
5107         }
5108 }
5109
5110 /***************************************************************************
5111 Return the number of the service with the given name, or -1 if it doesn't
5112 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5113 getservicebyname()! This works ONLY if all services have been loaded, and
5114 does not copy the found service.
5115 ***************************************************************************/
5116
5117 int lp_servicenumber(const char *pszServiceName)
5118 {
5119         int iService;
5120         fstring serviceName;
5121
5122         if (!pszServiceName) {
5123                 return GLOBAL_SECTION_SNUM;
5124         }
5125
5126         for (iService = iNumServices - 1; iService >= 0; iService--) {
5127                 if (VALID(iService) && ServicePtrs[iService]->szService) {
5128                         /*
5129                          * The substitution here is used to support %U is
5130                          * service names
5131                          */
5132                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
5133                         standard_sub_basic(get_current_username(),
5134                                            current_user_info.domain,
5135                                            serviceName,sizeof(serviceName));
5136                         if (strequal(serviceName, pszServiceName)) {
5137                                 break;
5138                         }
5139                 }
5140         }
5141
5142         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5143                 struct timespec last_mod;
5144
5145                 if (!usershare_exists(iService, &last_mod)) {
5146                         /* Remove the share security tdb entry for it. */
5147                         delete_share_security(lp_servicename(talloc_tos(), iService));
5148                         /* Remove it from the array. */
5149                         free_service_byindex(iService);
5150                         /* Doesn't exist anymore. */
5151                         return GLOBAL_SECTION_SNUM;
5152                 }
5153
5154                 /* Has it been modified ? If so delete and reload. */
5155                 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5156                                      &last_mod) < 0) {
5157                         /* Remove it from the array. */
5158                         free_service_byindex(iService);
5159                         /* and now reload it. */
5160                         iService = load_usershare_service(pszServiceName);
5161                 }
5162         }
5163
5164         if (iService < 0) {
5165                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5166                 return GLOBAL_SECTION_SNUM;
5167         }
5168
5169         return (iService);
5170 }
5171
5172 /*******************************************************************
5173  A useful volume label function. 
5174 ********************************************************************/
5175
5176 const char *volume_label(TALLOC_CTX *ctx, int snum)
5177 {
5178         char *ret;
5179         const char *label = lp_volume(ctx, snum);
5180         if (!*label) {
5181                 label = lp_servicename(ctx, snum);
5182         }
5183
5184         /* This returns a 33 byte guarenteed null terminated string. */
5185         ret = talloc_strndup(ctx, label, 32);
5186         if (!ret) {
5187                 return "";
5188         }               
5189         return ret;
5190 }
5191
5192 /*******************************************************************
5193  Get the default server type we will announce as via nmbd.
5194 ********************************************************************/
5195
5196 int lp_default_server_announce(void)
5197 {
5198         int default_server_announce = 0;
5199         default_server_announce |= SV_TYPE_WORKSTATION;
5200         default_server_announce |= SV_TYPE_SERVER;
5201         default_server_announce |= SV_TYPE_SERVER_UNIX;
5202
5203         /* note that the flag should be set only if we have a 
5204            printer service but nmbd doesn't actually load the 
5205            services so we can't tell   --jerry */
5206
5207         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5208
5209         default_server_announce |= SV_TYPE_SERVER_NT;
5210         default_server_announce |= SV_TYPE_NT;
5211
5212         switch (lp_server_role()) {
5213                 case ROLE_DOMAIN_MEMBER:
5214                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5215                         break;
5216                 case ROLE_DOMAIN_PDC:
5217                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5218                         break;
5219                 case ROLE_DOMAIN_BDC:
5220                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5221                         break;
5222                 case ROLE_STANDALONE:
5223                 default:
5224                         break;
5225         }
5226         if (lp_time_server())
5227                 default_server_announce |= SV_TYPE_TIME_SOURCE;
5228
5229         if (lp_host_msdfs())
5230                 default_server_announce |= SV_TYPE_DFS_SERVER;
5231
5232         return default_server_announce;
5233 }
5234
5235 /***********************************************************
5236  If we are PDC then prefer us as DMB
5237 ************************************************************/
5238
5239 bool lp_domain_master(void)
5240 {
5241         if (Globals.domain_master == Auto)
5242                 return (lp_server_role() == ROLE_DOMAIN_PDC);
5243
5244         return (bool)Globals.domain_master;
5245 }
5246
5247 /***********************************************************
5248  If we are PDC then prefer us as DMB
5249 ************************************************************/
5250
5251 static bool lp_domain_master_true_or_auto(void)
5252 {
5253         if (Globals.domain_master) /* auto or yes */
5254                 return true;
5255
5256         return false;
5257 }
5258
5259 /***********************************************************
5260  If we are DMB then prefer us as LMB
5261 ************************************************************/
5262
5263 bool lp_preferred_master(void)
5264 {
5265         if (Globals.iPreferredMaster == Auto)
5266                 return (lp_local_master() && lp_domain_master());
5267
5268         return (bool)Globals.iPreferredMaster;
5269 }
5270
5271 /*******************************************************************
5272  Remove a service.
5273 ********************************************************************/
5274
5275 void lp_remove_service(int snum)
5276 {
5277         ServicePtrs[snum]->valid = false;
5278         invalid_services[num_invalid_services++] = snum;
5279 }
5280
5281 /*******************************************************************
5282  Copy a service.
5283 ********************************************************************/
5284
5285 void lp_copy_service(int snum, const char *new_name)
5286 {
5287         do_section(new_name, NULL);
5288         if (snum >= 0) {
5289                 snum = lp_servicenumber(new_name);
5290                 if (snum >= 0) {
5291                         char *name = lp_servicename(talloc_tos(), snum);
5292                         lp_do_parameter(snum, "copy", name);
5293                 }
5294         }
5295 }
5296
5297 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5298 {
5299         const char *ret = lp__printername(talloc_tos(), snum);
5300         if (ret == NULL || *ret == '\0') {
5301                 ret = lp_const_servicename(snum);
5302         }
5303
5304         return ret;
5305 }
5306
5307
5308 /***********************************************************
5309  Allow daemons such as winbindd to fix their logfile name.
5310 ************************************************************/
5311
5312 void lp_set_logfile(const char *name)
5313 {
5314         string_set(&Globals.logfile, name);
5315         debug_set_logfile(name);
5316 }
5317
5318 /*******************************************************************
5319  Return the max print jobs per queue.
5320 ********************************************************************/
5321
5322 int lp_maxprintjobs(int snum)
5323 {
5324         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5325         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5326                 maxjobs = PRINT_MAX_JOBID - 1;
5327
5328         return maxjobs;
5329 }
5330
5331 const char *lp_printcapname(void)
5332 {
5333         if ((Globals.szPrintcapname != NULL) &&
5334             (Globals.szPrintcapname[0] != '\0'))
5335                 return Globals.szPrintcapname;
5336
5337         if (sDefault.iPrinting == PRINT_CUPS) {
5338                 return "cups";
5339         }
5340
5341         if (sDefault.iPrinting == PRINT_BSD)
5342                 return "/etc/printcap";
5343
5344         return PRINTCAP_NAME;
5345 }
5346
5347 static uint32 spoolss_state;
5348
5349 bool lp_disable_spoolss( void )
5350 {
5351         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5352                 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5353
5354         return spoolss_state == SVCCTL_STOPPED ? true : false;
5355 }
5356
5357 void lp_set_spoolss_state( uint32 state )
5358 {
5359         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5360
5361         spoolss_state = state;
5362 }
5363
5364 uint32 lp_get_spoolss_state( void )
5365 {
5366         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5367 }
5368
5369 /*******************************************************************
5370  Ensure we don't use sendfile if server smb signing is active.
5371 ********************************************************************/
5372
5373 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5374 {
5375         bool sign_active = false;
5376
5377         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5378         if (get_Protocol() < PROTOCOL_NT1) {
5379                 return false;
5380         }
5381         if (signing_state) {
5382                 sign_active = smb_signing_is_active(signing_state);
5383         }
5384         return (lp__use_sendfile(snum) &&
5385                         (get_remote_arch() != RA_WIN95) &&
5386                         !sign_active);
5387 }
5388
5389 /*******************************************************************
5390  Turn off sendfile if we find the underlying OS doesn't support it.
5391 ********************************************************************/
5392
5393 void set_use_sendfile(int snum, bool val)
5394 {
5395         if (LP_SNUM_OK(snum))
5396                 ServicePtrs[snum]->bUseSendfile = val;
5397         else
5398                 sDefault.bUseSendfile = val;
5399 }
5400
5401 /*******************************************************************
5402  Turn off storing DOS attributes if this share doesn't support it.
5403 ********************************************************************/
5404
5405 void set_store_dos_attributes(int snum, bool val)
5406 {
5407         if (!LP_SNUM_OK(snum))
5408                 return;
5409         ServicePtrs[(snum)]->bStoreDosAttributes = val;
5410 }
5411
5412 void lp_set_mangling_method(const char *new_method)
5413 {
5414         string_set(&Globals.szManglingMethod, new_method);
5415 }
5416
5417 /*******************************************************************
5418  Global state for POSIX pathname processing.
5419 ********************************************************************/
5420
5421 static bool posix_pathnames;
5422
5423 bool lp_posix_pathnames(void)
5424 {
5425         return posix_pathnames;
5426 }
5427
5428 /*******************************************************************
5429  Change everything needed to ensure POSIX pathname processing (currently
5430  not much).
5431 ********************************************************************/
5432
5433 void lp_set_posix_pathnames(void)
5434 {
5435         posix_pathnames = true;
5436 }
5437
5438 /*******************************************************************
5439  Global state for POSIX lock processing - CIFS unix extensions.
5440 ********************************************************************/
5441
5442 bool posix_default_lock_was_set;
5443 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5444
5445 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5446 {
5447         if (posix_default_lock_was_set) {
5448                 return posix_cifsx_locktype;
5449         } else {
5450                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5451         }
5452 }
5453
5454 /*******************************************************************
5455 ********************************************************************/
5456
5457 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5458 {
5459         posix_default_lock_was_set = true;
5460         posix_cifsx_locktype = val;
5461 }
5462
5463 int lp_min_receive_file_size(void)
5464 {
5465         if (Globals.iminreceivefile < 0) {
5466                 return 0;
5467         }
5468         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5469 }
5470
5471 /*******************************************************************
5472  Safe wide links checks.
5473  This helper function always verify the validity of wide links,
5474  even after a configuration file reload.
5475 ********************************************************************/
5476
5477 static bool lp_widelinks_internal(int snum)
5478 {
5479         return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5480                         sDefault.bWidelinks);
5481 }
5482
5483 void widelinks_warning(int snum)
5484 {
5485         if (lp_allow_insecure_widelinks()) {
5486                 return;
5487         }
5488
5489         if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5490                 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5491                         "These parameters are incompatible. "
5492                         "Wide links will be disabled for this share.\n",
5493                          lp_servicename(talloc_tos(), snum) ));
5494         }
5495 }
5496
5497 bool lp_widelinks(int snum)
5498 {
5499         /* wide links is always incompatible with unix extensions */
5500         if (lp_unix_extensions()) {
5501                 /*
5502                  * Unless we have "allow insecure widelinks"
5503                  * turned on.
5504                  */
5505                 if (!lp_allow_insecure_widelinks()) {
5506                         return false;
5507                 }
5508         }
5509
5510         return lp_widelinks_internal(snum);
5511 }
5512
5513 bool lp_writeraw(void)
5514 {
5515         if (lp_async_smb_echo_handler()) {
5516                 return false;
5517         }
5518         return lp__writeraw();
5519 }
5520
5521 bool lp_readraw(void)
5522 {
5523         if (lp_async_smb_echo_handler()) {
5524                 return false;
5525         }
5526         return lp__readraw();
5527 }
5528
5529 int lp_server_role(void)
5530 {
5531         return lp_find_server_role(lp__server_role(),
5532                                    lp__security(),
5533                                    lp__domain_logons(),
5534                                    lp_domain_master_true_or_auto());
5535 }
5536
5537 int lp_security(void)
5538 {
5539         return lp_find_security(lp__server_role(),
5540                                 lp__security());
5541 }