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