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