3e7883882028874641c2484d21a93b56a29fa546
[sfrench/samba-autobuild/.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12    Copyright (C) Michael Adam 2008
13    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14    Copyright (C) Andrew Bartlett 2011
15
16    This program is free software; you can redistribute it and/or modify
17    it under the terms of the GNU General Public License as published by
18    the Free Software Foundation; either version 3 of the License, or
19    (at your option) any later version.
20
21    This program is distributed in the hope that it will be useful,
22    but WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24    GNU General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 */
29
30 /*
31  *  Load parameters.
32  *
33  *  This module provides suitable callback functions for the params
34  *  module. It builds the internal table of service details which is
35  *  then used by the rest of the server.
36  *
37  * To add a parameter:
38  *
39  * 1) add it to the global or service structure definition
40  * 2) add it to the parm_table
41  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42  * 4) If it's a global then initialise it in init_globals. If a local
43  *    (ie. service) parameter then initialise it in the sDefault structure
44  *  
45  *
46  * Notes:
47  *   The configuration file is processed sequentially for speed. It is NOT
48  *   accessed randomly as happens in 'real' Windows. For this reason, there
49  *   is a fair bit of sequence-dependent code here - ie., code which assumes
50  *   that certain things happen before others. In particular, the code which
51  *   happens at the boundary between sections is delicately poised, so be
52  *   careful!
53  *
54  */
55
56 #include "includes.h"
57 #include "system/filesys.h"
58 #include "util_tdb.h"
59 #include "lib/param/loadparm.h"
60 #include "lib/param/param.h"
61 #include "printing.h"
62 #include "lib/smbconf/smbconf.h"
63 #include "lib/smbconf/smbconf_init.h"
64
65 #include "ads.h"
66 #include "../librpc/gen_ndr/svcctl.h"
67 #include "intl.h"
68 #include "../libcli/smb/smb_signing.h"
69 #include "dbwrap/dbwrap.h"
70 #include "dbwrap/dbwrap_rbt.h"
71 #include "../lib/util/bitmap.h"
72
73 #ifdef HAVE_SYS_SYSCTL_H
74 #include <sys/sysctl.h>
75 #endif
76
77 #ifdef HAVE_HTTPCONNECTENCRYPT
78 #include <cups/http.h>
79 #endif
80
81 #ifdef CLUSTER_SUPPORT
82 #include "ctdb_private.h"
83 #endif
84
85 bool bLoaded = false;
86
87 extern userdom_struct current_user_info;
88
89 /* the special value for the include parameter
90  * to be interpreted not as a file name but to
91  * trigger loading of the global smb.conf options
92  * from registry. */
93 #ifndef INCLUDE_REGISTRY_NAME
94 #define INCLUDE_REGISTRY_NAME "registry"
95 #endif
96
97 static bool in_client = false;          /* Not in the client by default */
98 static struct smbconf_csn conf_last_csn;
99
100 static int config_backend = CONFIG_BACKEND_FILE;
101
102 /* some helpful bits */
103 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
104 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
105
106 #define USERSHARE_VALID 1
107 #define USERSHARE_PENDING_DELETE 2
108
109 static bool defaults_saved = false;
110
111 #define LOADPARM_EXTRA_GLOBALS \
112         struct parmlist_entry *param_opt;                               \
113         char *realm_original;                                           \
114         char *loglevel;                                                 \
115         int iminreceivefile;                                            \
116         char *szPrintcapname;                                           \
117         int CupsEncrypt;                                                \
118         int  iPreferredMaster;                                          \
119         char *szLdapMachineSuffix;                                      \
120         char *szLdapUserSuffix;                                         \
121         char *szLdapIdmapSuffix;                                        \
122         char *szLdapGroupSuffix;                                        \
123         char *szStateDir;                                               \
124         char *szCacheDir;                                               \
125         char *szUsershareTemplateShare;                                 \
126         char *szIdmapUID;                                               \
127         char *szIdmapGID;                                               \
128         char *szIdmapBackend;                                           \
129         int winbindMaxDomainConnections;                                \
130         int ismb2_max_credits;                                          \
131         char *tls_keyfile;                                              \
132         char *tls_certfile;                                             \
133         char *tls_cafile;                                               \
134         char *tls_crlfile;                                              \
135         char *tls_dhpfile;
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         .path = NULL,
150         .username = NULL,
151         .invalid_users = NULL,
152         .valid_users = NULL,
153         .admin_users = NULL,
154         .szCopy = NULL,
155         .szInclude = NULL,
156         .preexec = NULL,
157         .postexec = NULL,
158         .rootpreexec = NULL,
159         .rootpostexec = NULL,
160         .cups_options = NULL,
161         .printcommand = NULL,
162         .lpqcommand = NULL,
163         .lprmcommand = NULL,
164         .lppausecommand = NULL,
165         .lpresumecommand = NULL,
166         .queuepausecommand = NULL,
167         .queueresumecommand = NULL,
168         ._printername = NULL,
169         .printjob_username = NULL,
170         .dontdescend = NULL,
171         .hosts_allow = NULL,
172         .hosts_deny = NULL,
173         .magicscript = NULL,
174         .magicoutput = NULL,
175         .veto_files = NULL,
176         .hide_files = NULL,
177         .veto_oplocks = 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         .vfs_objects = NULL,
186         .msdfs_proxy = NULL,
187         .aio_write_behind = NULL,
188         .dfree_command = NULL,
189         .minprintspace = 0,
190         .iMaxPrintJobs = 1000,
191         .max_reported_jobs = 0,
192         .write_cache_size = 0,
193         .create_mask = 0744,
194         .force_create_mode = 0,
195         .dir_mask = 0755,
196         .force_dir_mode = 0,
197         .max_connections = 0,
198         .defaultcase = CASE_LOWER,
199         .printing = DEFAULT_PRINTING,
200         .oplock_contention_limit = 2,
201         .csc_policy = 0,
202         .block_size = 1024,
203         .dfree_cache_time = 0,
204         .preexec_close = false,
205         .rootpreexec_close = false,
206         .casesensitive = Auto,
207         .preservecase = true,
208         .shortpreservecase = true,
209         .hide_dot_files = true,
210         .hide_special_files = false,
211         .hideunreadable = false,
212         .hideunwriteable_files = false,
213         .browseable = true,
214         .access_based_share_enum = false,
215         .bAvailable = true,
216         .read_only = true,
217         .guest_only = false,
218         .administrative_share = false,
219         .guest_ok = false,
220         .printable = false,
221         .print_notify_backchannel = false,
222         .map_system = false,
223         .map_hidden = false,
224         .map_archive = true,
225         .store_dos_attributes = false,
226         .dmapi_support = false,
227         .locking = true,
228         .strict_locking = Auto,
229         .posix_locking = true,
230         .oplocks = true,
231         .kernel_oplocks = false,
232         .level2_oplocks = true,
233         .onlyuser = false,
234         .manglednames = true,
235         .bWidelinks = false,
236         .symlinks = true,
237         .syncalways = false,
238         .strict_allocate = false,
239         .strict_sync = false,
240         .magicchar = '~',
241         .copymap = NULL,
242         .delete_readonly = false,
243         .fake_oplocks = false,
244         .recursive_veto_delete = false,
245         .dos_filemode = false,
246         .dos_filetimes = true,
247         .dos_filetime_resolution = false,
248         .fake_dir_create_times = false,
249         .blocking_locks = true,
250         .inherit_perms = false,
251         .inherit_acls = false,
252         .inherit_owner = false,
253         .msdfs_root = false,
254         .use_client_driver = false,
255         .default_devmode = true,
256         .force_printername = false,
257         .nt_acl_support = true,
258         .force_unknown_acl_user = false,
259         ._use_sendfile = false,
260         .profile_acls = false,
261         .map_acl_inherit = false,
262         .afs_share = false,
263         .ea_support = false,
264         .acl_check_permissions = true,
265         .acl_map_full_control = true,
266         .acl_group_control = false,
267         .acl_allow_execute_always = false,
268         .change_notify = true,
269         .kernel_change_notify = true,
270         .allocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
271         .aio_read_size = 0,
272         .aio_write_size = 0,
273         .map_readonly = MAP_READONLY_YES,
274         .directory_name_cache_size = 100,
275         .smb_encrypt = SMB_SIGNING_DEFAULT,
276         .kernel_share_modes = true,
277         .durable_handles = true,
278         .param_opt = NULL,
279         .dummy = ""
280 };
281
282 /* local variables */
283 static struct loadparm_service **ServicePtrs = NULL;
284 static int iNumServices = 0;
285 static int iServiceIndex = 0;
286 static struct db_context *ServiceHash;
287 static bool bInGlobalSection = true;
288 static bool bGlobalOnly = false;
289
290 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
291
292 /* prototypes for the special type handlers */
293 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
294 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
295 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
296 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
297 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
298 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
299 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
300 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
301 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
302 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
303 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
304 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
305
306 /* these are parameter handlers which are not needed in the
307  * source3 code
308  */
309
310 #define handle_logfile NULL
311
312 static void set_allowed_client_auth(void);
313
314 static void add_to_file_list(const char *fname, const char *subfname);
315 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
316 static void free_param_opts(struct parmlist_entry **popts);
317
318 #include "lib/param/param_table.c"
319
320 /* this is used to prevent lots of mallocs of size 1 */
321 static const char null_string[] = "";
322
323 /**
324  Set a string value, allocing the space for the string
325 **/
326
327 static bool string_init(char **dest,const char *src)
328 {
329         size_t l;
330
331         if (!src)
332                 src = "";
333
334         l = strlen(src);
335
336         if (l == 0) {
337                 *dest = discard_const_p(char, null_string);
338         } else {
339                 (*dest) = SMB_STRDUP(src);
340                 if ((*dest) == NULL) {
341                         DEBUG(0,("Out of memory in string_init\n"));
342                         return false;
343                 }
344         }
345         return(true);
346 }
347
348 /**
349  Free a string value.
350 **/
351
352 static void string_free(char **s)
353 {
354         if (!s || !(*s))
355                 return;
356         if (*s == null_string)
357                 *s = NULL;
358         SAFE_FREE(*s);
359 }
360
361 /**
362  Set a string value, deallocating any existing space, and allocing the space
363  for the string
364 **/
365
366 static bool string_set(char **dest,const char *src)
367 {
368         string_free(dest);
369         return(string_init(dest,src));
370 }
371
372 /***************************************************************************
373  Initialise the sDefault parameter structure for the printer values.
374 ***************************************************************************/
375
376 static void init_printer_values(struct loadparm_service *pService)
377 {
378         /* choose defaults depending on the type of printing */
379         switch (pService->printing) {
380                 case PRINT_BSD:
381                 case PRINT_AIX:
382                 case PRINT_LPRNT:
383                 case PRINT_LPROS2:
384                         string_set(&pService->lpqcommand, "lpq -P'%p'");
385                         string_set(&pService->lprmcommand, "lprm -P'%p' %j");
386                         string_set(&pService->printcommand, "lpr -r -P'%p' %s");
387                         break;
388
389                 case PRINT_LPRNG:
390                 case PRINT_PLP:
391                         string_set(&pService->lpqcommand, "lpq -P'%p'");
392                         string_set(&pService->lprmcommand, "lprm -P'%p' %j");
393                         string_set(&pService->printcommand, "lpr -r -P'%p' %s");
394                         string_set(&pService->queuepausecommand, "lpc stop '%p'");
395                         string_set(&pService->queueresumecommand, "lpc start '%p'");
396                         string_set(&pService->lppausecommand, "lpc hold '%p' %j");
397                         string_set(&pService->lpresumecommand, "lpc release '%p' %j");
398                         break;
399
400                 case PRINT_CUPS:
401                 case PRINT_IPRINT:
402                         /* set the lpq command to contain the destination printer
403                            name only.  This is used by cups_queue_get() */
404                         string_set(&pService->lpqcommand, "%p");
405                         string_set(&pService->lprmcommand, "");
406                         string_set(&pService->printcommand, "");
407                         string_set(&pService->lppausecommand, "");
408                         string_set(&pService->lpresumecommand, "");
409                         string_set(&pService->queuepausecommand, "");
410                         string_set(&pService->queueresumecommand, "");
411                         break;
412
413                 case PRINT_SYSV:
414                 case PRINT_HPUX:
415                         string_set(&pService->lpqcommand, "lpstat -o%p");
416                         string_set(&pService->lprmcommand, "cancel %p-%j");
417                         string_set(&pService->printcommand, "lp -c -d%p %s; rm %s");
418                         string_set(&pService->queuepausecommand, "disable %p");
419                         string_set(&pService->queueresumecommand, "enable %p");
420 #ifndef HPUX
421                         string_set(&pService->lppausecommand, "lp -i %p-%j -H hold");
422                         string_set(&pService->lpresumecommand, "lp -i %p-%j -H resume");
423 #endif /* HPUX */
424                         break;
425
426                 case PRINT_QNX:
427                         string_set(&pService->lpqcommand, "lpq -P%p");
428                         string_set(&pService->lprmcommand, "lprm -P%p %j");
429                         string_set(&pService->printcommand, "lp -r -P%p %s");
430                         break;
431
432 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
433
434         case PRINT_TEST:
435         case PRINT_VLP: {
436                 const char *tdbfile;
437                 TALLOC_CTX *tmp_ctx = talloc_stackframe();
438                 char *tmp;
439
440                 tdbfile = talloc_asprintf(
441                         tmp_ctx, "tdbfile=%s",
442                         lp_parm_const_string(-1, "vlp", "tdbfile",
443                                              "/tmp/vlp.tdb"));
444                 if (tdbfile == NULL) {
445                         tdbfile="tdbfile=/tmp/vlp.tdb";
446                 }
447
448                 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
449                                       tdbfile);
450                 string_set(&pService->printcommand,
451                            tmp ? tmp : "vlp print %p %s");
452
453                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
454                                       tdbfile);
455                 string_set(&pService->lpqcommand,
456                            tmp ? tmp : "vlp lpq %p");
457
458                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
459                                       tdbfile);
460                 string_set(&pService->lprmcommand,
461                            tmp ? tmp : "vlp lprm %p %j");
462
463                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
464                                       tdbfile);
465                 string_set(&pService->lppausecommand,
466                            tmp ? tmp : "vlp lppause %p %j");
467
468                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
469                                       tdbfile);
470                 string_set(&pService->lpresumecommand,
471                            tmp ? tmp : "vlp lpresume %p %j");
472
473                 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
474                                       tdbfile);
475                 string_set(&pService->queuepausecommand,
476                            tmp ? tmp : "vlp queuepause %p");
477
478                 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
479                                       tdbfile);
480                 string_set(&pService->queueresumecommand,
481                            tmp ? tmp : "vlp queueresume %p");
482                 TALLOC_FREE(tmp_ctx);
483
484                 break;
485         }
486 #endif /* DEVELOPER */
487
488         }
489 }
490 /**
491  *  Function to return the default value for the maximum number of open
492  *  file descriptors permitted.  This function tries to consult the
493  *  kernel-level (sysctl) and ulimit (getrlimit()) values and goes
494  *  the smaller of those.
495  */
496 static int max_open_files(void)
497 {
498         int sysctl_max = MAX_OPEN_FILES;
499         int rlimit_max = MAX_OPEN_FILES;
500
501 #ifdef HAVE_SYSCTLBYNAME
502         {
503                 size_t size = sizeof(sysctl_max);
504                 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
505                              0);
506         }
507 #endif
508
509 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
510         {
511                 struct rlimit rl;
512
513                 ZERO_STRUCT(rl);
514
515                 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
516                         rlimit_max = rl.rlim_cur;
517
518 #if defined(RLIM_INFINITY)
519                 if(rl.rlim_cur == RLIM_INFINITY)
520                         rlimit_max = MAX_OPEN_FILES;
521 #endif
522         }
523 #endif
524
525         if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
526                 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
527                         "minimum Windows limit (%d)\n",
528                         sysctl_max,
529                         MIN_OPEN_FILES_WINDOWS));
530                 sysctl_max = MIN_OPEN_FILES_WINDOWS;
531         }
532
533         if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
534                 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
535                         "minimum Windows limit (%d)\n",
536                         rlimit_max,
537                         MIN_OPEN_FILES_WINDOWS));
538                 rlimit_max = MIN_OPEN_FILES_WINDOWS;
539         }
540
541         return MIN(sysctl_max, rlimit_max);
542 }
543
544 /**
545  * Common part of freeing allocated data for one parameter.
546  */
547 static void free_one_parameter_common(void *parm_ptr,
548                                       struct parm_struct parm)
549 {
550         if ((parm.type == P_STRING) ||
551             (parm.type == P_USTRING))
552         {
553                 string_free((char**)parm_ptr);
554         } else if (parm.type == P_LIST) {
555                 TALLOC_FREE(*((char***)parm_ptr));
556         }
557 }
558
559 /**
560  * Free the allocated data for one parameter for a share
561  * given as a service struct.
562  */
563 static void free_one_parameter(struct loadparm_service *service,
564                                struct parm_struct parm)
565 {
566         void *parm_ptr;
567
568         if (parm.p_class != P_LOCAL) {
569                 return;
570         }
571
572         parm_ptr = lp_parm_ptr(service, &parm);
573
574         free_one_parameter_common(parm_ptr, parm);
575 }
576
577 /**
578  * Free the allocated parameter data of a share given
579  * as a service struct.
580  */
581 static void free_parameters(struct loadparm_service *service)
582 {
583         uint32_t i;
584
585         for (i=0; parm_table[i].label; i++) {
586                 free_one_parameter(service, parm_table[i]);
587         }
588 }
589
590 /**
591  * Free the allocated data for one parameter for a given share
592  * specified by an snum.
593  */
594 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
595 {
596         void *parm_ptr;
597
598         if (snum < 0) {
599                 parm_ptr = lp_parm_ptr(NULL, &parm);
600         } else if (parm.p_class != P_LOCAL) {
601                 return;
602         } else {
603                 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
604         }
605
606         free_one_parameter_common(parm_ptr, parm);
607 }
608
609 /**
610  * Free the allocated parameter data for a share specified
611  * by an snum.
612  */
613 static void free_parameters_by_snum(int snum)
614 {
615         uint32_t i;
616
617         for (i=0; parm_table[i].label; i++) {
618                 free_one_parameter_by_snum(snum, parm_table[i]);
619         }
620 }
621
622 /**
623  * Free the allocated global parameters.
624  */
625 static void free_global_parameters(void)
626 {
627         free_param_opts(&Globals.param_opt);
628         free_parameters_by_snum(GLOBAL_SECTION_SNUM);
629         TALLOC_FREE(Globals.ctx);
630 }
631
632 struct lp_stored_option {
633         struct lp_stored_option *prev, *next;
634         const char *label;
635         const char *value;
636 };
637
638 static struct lp_stored_option *stored_options;
639
640 /*
641   save options set by lp_set_cmdline() into a list. This list is
642   re-applied when we do a globals reset, so that cmdline set options
643   are sticky across reloads of smb.conf
644  */
645 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
646 {
647         struct lp_stored_option *entry, *entry_next;
648         for (entry = stored_options; entry != NULL; entry = entry_next) {
649                 entry_next = entry->next;
650                 if (strcmp(pszParmName, entry->label) == 0) {
651                         DLIST_REMOVE(stored_options, entry);
652                         talloc_free(entry);
653                         break;
654                 }
655         }
656
657         entry = talloc(NULL, struct lp_stored_option);
658         if (!entry) {
659                 return false;
660         }
661
662         entry->label = talloc_strdup(entry, pszParmName);
663         if (!entry->label) {
664                 talloc_free(entry);
665                 return false;
666         }
667
668         entry->value = talloc_strdup(entry, pszParmValue);
669         if (!entry->value) {
670                 talloc_free(entry);
671                 return false;
672         }
673
674         DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
675
676         return true;
677 }
678
679 static bool apply_lp_set_cmdline(void)
680 {
681         struct lp_stored_option *entry = NULL;
682         for (entry = stored_options; entry != NULL; entry = entry->next) {
683                 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
684                         DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
685                                   entry->label, entry->value));
686                         return false;
687                 }
688         }
689         return true;
690 }
691
692 /***************************************************************************
693  Initialise the global parameter structure.
694 ***************************************************************************/
695
696 static void init_globals(bool reinit_globals)
697 {
698         static bool done_init = false;
699         char *s = NULL;
700         int i;
701
702         /* If requested to initialize only once and we've already done it... */
703         if (!reinit_globals && done_init) {
704                 /* ... then we have nothing more to do */
705                 return;
706         }
707
708         if (!done_init) {
709                 /* The logfile can be set before this is invoked. Free it if so. */
710                 if (Globals.logfile != NULL) {
711                         string_free(&Globals.logfile);
712                         Globals.logfile = NULL;
713                 }
714                 done_init = true;
715         } else {
716                 free_global_parameters();
717         }
718
719         /* This memset and the free_global_parameters() above will
720          * wipe out smb.conf options set with lp_set_cmdline().  The
721          * apply_lp_set_cmdline() call puts these values back in the
722          * table once the defaults are set */
723         ZERO_STRUCT(Globals);
724
725         Globals.ctx = talloc_new(NULL);
726
727         for (i = 0; parm_table[i].label; i++) {
728                 if ((parm_table[i].type == P_STRING ||
729                      parm_table[i].type == P_USTRING))
730                 {
731                         string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
732                 }
733         }
734
735
736         string_set(&sDefault.fstype, FSTYPE_STRING);
737         string_set(&sDefault.printjob_username, "%U");
738
739         init_printer_values(&sDefault);
740
741         sDefault.ntvfs_handler = (const char **)str_list_make_v3(NULL, "unixuid default", NULL);
742
743         DEBUG(3, ("Initialising global parameters\n"));
744
745         /* Must manually force to upper case here, as this does not go via the handler */
746         string_set(&Globals.netbios_name, myhostname_upper());
747
748         string_set(&Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
749         string_set(&Globals.private_dir, get_dyn_PRIVATE_DIR());
750
751         /* use the new 'hash2' method by default, with a prefix of 1 */
752         string_set(&Globals.mangling_method, "hash2");
753         Globals.mangle_prefix = 1;
754
755         string_set(&Globals.guestaccount, GUEST_ACCOUNT);
756
757         /* using UTF8 by default allows us to support all chars */
758         string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
759
760         /* Use codepage 850 as a default for the dos character set */
761         string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
762
763         /*
764          * Allow the default PASSWD_CHAT to be overridden in local.h.
765          */
766         string_set(&Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
767
768         string_set(&Globals.workgroup, DEFAULT_WORKGROUP);
769
770         string_set(&Globals.passwd_program, "");
771         string_set(&Globals.lockdir, get_dyn_LOCKDIR());
772         string_set(&Globals.szStateDir, get_dyn_STATEDIR());
773         string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
774         string_set(&Globals.piddir, get_dyn_PIDDIR());
775         string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
776         /*
777          * By default support explicit binding to broadcast
778          * addresses.
779          */
780         Globals.nmbd_bind_explicit_broadcast = true;
781
782         if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
783                 smb_panic("init_globals: ENOMEM");
784         }
785         string_set(&Globals.serverstring, s);
786         SAFE_FREE(s);
787 #ifdef DEVELOPER
788         string_set(&Globals.panic_action, "/bin/sleep 999999999");
789 #endif
790
791         string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
792
793         string_set(&Globals.logon_drive, "");
794         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
795         string_set(&Globals.logon_home, "\\\\%N\\%U");
796         string_set(&Globals.logon_path, "\\\\%N\\%U\\profile");
797
798         Globals.name_resolve_order = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
799         string_set(&Globals.passwordserver, "*");
800
801         Globals.algorithmic_rid_base = BASE_RID;
802
803         Globals.load_printers = true;
804         Globals.printcap_cache_time = 750;      /* 12.5 minutes */
805
806         Globals.config_backend = config_backend;
807         Globals._server_role = ROLE_AUTO;
808
809         /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
810         /* Discovered by 2 days of pain by Don McCall @ HP :-). */
811         Globals.max_xmit = 0x4104;
812         Globals.maxmux = 50;    /* This is *needed* for profile support. */
813         Globals.lpqcachetime = 30;      /* changed to handle large print servers better -- jerry */
814         Globals._disable_spoolss = false;
815         Globals.max_smbd_processes = 0;/* no limit specified */
816         Globals.usernamelevel = 0;
817         Globals.deadtime = 0;
818         Globals.getwd_cache = true;
819         Globals.large_readwrite = true;
820         Globals.max_log_size = 5000;
821         Globals.max_open_files = max_open_files();
822         Globals.srv_maxprotocol = PROTOCOL_SMB3_00;
823         Globals.srv_minprotocol = PROTOCOL_LANMAN1;
824         Globals.cli_maxprotocol = PROTOCOL_NT1;
825         Globals.cli_minprotocol = PROTOCOL_CORE;
826         Globals._security = SEC_AUTO;
827         Globals.encrypted_passwords = true;
828         Globals.client_schannel = Auto;
829         Globals.winbind_sealed_pipes = true;
830         Globals.require_strong_key = true;
831         Globals.server_schannel = Auto;
832         Globals.bReadRaw = true;
833         Globals.bWriteRaw = true;
834         Globals.null_passwords = false;
835         Globals.obey_pam_restrictions = false;
836         Globals.syslog = 1;
837         Globals.syslog_only = false;
838         Globals.timestamp_logs = true;
839         string_set(&Globals.loglevel, "0");
840         Globals.debug_prefix_timestamp = false;
841         Globals.debug_hires_timestamp = true;
842         Globals.debug_pid = false;
843         Globals.debug_uid = false;
844         Globals.debug_class = false;
845         Globals.enable_core_files = true;
846         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
847         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
848         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
849         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
850         Globals.lm_announce = Auto;     /* = Auto: send only if LM clients found */
851         Globals.lm_interval = 60;
852 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
853         Globals.nis_home_map = false;
854 #ifdef WITH_NISPLUS_HOME
855         string_set(&Globals.nis_home_map_name, "auto_home.org_dir");
856 #else
857         string_set(&Globals.nis_home_map_name, "auto.home");
858 #endif
859 #endif
860         Globals.time_server = false;
861         Globals.bind_interfaces_only = false;
862         Globals.unix_password_sync = false;
863         Globals.pam_password_change = false;
864         Globals.passwd_chat_debug = false;
865         Globals.passwd_chat_timeout = 2; /* 2 second default. */
866         Globals.nt_pipe_support = true; /* Do NT pipes by default. */
867         Globals.nt_status_support = true; /* Use NT status by default. */
868         Globals.stat_cache = true;      /* use stat cache by default */
869         Globals.max_stat_cache_size = 256; /* 256k by default */
870         Globals.restrict_anonymous = 0;
871         Globals.client_lanman_auth = false;     /* Do NOT use the LanMan hash if it is available */
872         Globals.client_plaintext_auth = false;  /* Do NOT use a plaintext password even if is requested by the server */
873         Globals.lanman_auth = false;    /* Do NOT use the LanMan hash, even if it is supplied */
874         Globals.ntlm_auth = true;       /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
875         Globals.client_ntlmv2_auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
876         /* Note, that we will also use NTLM2 session security (which is different), if it is available */
877
878         Globals.map_to_guest = 0;       /* By Default, "Never" */
879         Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
880         Globals.enhanced_browsing = true;
881         Globals.lock_spin_time = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
882 #ifdef MMAP_BLACKLIST
883         Globals.use_mmap = false;
884 #else
885         Globals.use_mmap = true;
886 #endif
887         Globals.unicode = true;
888         Globals.unix_extensions = true;
889         Globals.reset_on_zero_vc = false;
890         Globals.log_writeable_files_on_exit = false;
891         Globals.create_krb5_conf = true;
892         Globals.winbindMaxDomainConnections = 1;
893
894         /* hostname lookups can be very expensive and are broken on
895            a large number of sites (tridge) */
896         Globals.hostname_lookups = false;
897
898         string_set(&Globals.passdb_backend, "tdbsam");
899         string_set(&Globals.ldap_suffix, "");
900         string_set(&Globals.szLdapMachineSuffix, "");
901         string_set(&Globals.szLdapUserSuffix, "");
902         string_set(&Globals.szLdapGroupSuffix, "");
903         string_set(&Globals.szLdapIdmapSuffix, "");
904
905         string_set(&Globals.ldap_admin_dn, "");
906         Globals.ldap_ssl = LDAP_SSL_START_TLS;
907         Globals.ldap_ssl_ads = false;
908         Globals.ldap_deref = -1;
909         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
910         Globals.ldap_delete_dn = false;
911         Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
912         Globals.ldap_follow_referral = Auto;
913         Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
914         Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
915         Globals.ldap_page_size = LDAP_PAGE_SIZE;
916
917         Globals.ldap_debug_level = 0;
918         Globals.ldap_debug_threshold = 10;
919
920         /* This is what we tell the afs client. in reality we set the token 
921          * to never expire, though, when this runs out the afs client will 
922          * forget the token. Set to 0 to get NEVERDATE.*/
923         Globals.afs_token_lifetime = 604800;
924         Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
925
926 /* these parameters are set to defaults that are more appropriate
927    for the increasing samba install base:
928
929    as a member of the workgroup, that will possibly become a
930    _local_ master browser (lm = true).  this is opposed to a forced
931    local master browser startup (pm = true).
932
933    doesn't provide WINS server service by default (wsupp = false),
934    and doesn't provide domain master browser services by default, either.
935
936 */
937
938         Globals.ms_add_printer_wizard = true;
939         Globals.os_level = 20;
940         Globals.local_master = true;
941         Globals._domain_master = Auto;  /* depending on _domain_logons */
942         Globals._domain_logons = false;
943         Globals.browse_list = true;
944         Globals.we_are_a_wins_server = false;
945         Globals.wins_proxy = false;
946
947         TALLOC_FREE(Globals.init_logon_delayed_hosts);
948         Globals.init_logon_delay = 100; /* 100 ms default delay */
949
950         Globals.wins_dns_proxy = true;
951
952         Globals.allow_trusted_domains = true;
953         string_set(&Globals.szIdmapBackend, "tdb");
954
955         string_set(&Globals.template_shell, "/bin/false");
956         string_set(&Globals.template_homedir, "/home/%D/%U");
957         string_set(&Globals.winbind_separator, "\\");
958         string_set(&Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
959
960         string_set(&Globals.cups_server, "");
961         string_set(&Globals.iprint_server, "");
962
963 #ifdef CLUSTER_SUPPORT
964         string_set(&Globals.ctdbd_socket, CTDB_PATH);
965 #else
966         string_set(&Globals.ctdbd_socket, "");
967 #endif
968
969         Globals.cluster_addresses = NULL;
970         Globals.clustering = false;
971         Globals.ctdb_timeout = 0;
972         Globals.ctdb_locktime_warn_threshold = 0;
973
974         Globals.winbind_cache_time = 300;       /* 5 minutes */
975         Globals.winbind_reconnect_delay = 30;   /* 30 seconds */
976         Globals.winbind_max_clients = 200;
977         Globals.winbind_enum_users = false;
978         Globals.winbind_enum_groups = false;
979         Globals.winbind_use_default_domain = false;
980         Globals.winbind_trusted_domains_only = false;
981         Globals.winbind_nested_groups = true;
982         Globals.winbind_expand_groups = 1;
983         Globals.winbind_nss_info = (const char **)str_list_make_v3(NULL, "template", NULL);
984         Globals.winbind_refresh_tickets = false;
985         Globals.winbind_offline_logon = false;
986
987         Globals.idmap_cache_time = 86400 * 7; /* a week by default */
988         Globals.idmap_negative_cache_time = 120; /* 2 minutes by default */
989
990         Globals.passdb_expand_explicit = false;
991
992         Globals.name_cache_timeout = 660; /* In seconds */
993
994         Globals.use_spnego = true;
995         Globals.client_use_spnego = true;
996
997         Globals.client_signing = SMB_SIGNING_DEFAULT;
998         Globals.server_signing = SMB_SIGNING_DEFAULT;
999
1000         Globals.defer_sharing_violations = true;
1001         Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
1002
1003         Globals.enable_privileges = true;
1004         Globals.host_msdfs        = true;
1005         Globals.enable_asu_support       = false;
1006
1007         /* User defined shares. */
1008         if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
1009                 smb_panic("init_globals: ENOMEM");
1010         }
1011         string_set(&Globals.usershare_path, s);
1012         SAFE_FREE(s);
1013         string_set(&Globals.szUsershareTemplateShare, "");
1014         Globals.usershare_max_shares = 0;
1015         /* By default disallow sharing of directories not owned by the sharer. */
1016         Globals.usershare_owner_only = true;
1017         /* By default disallow guest access to usershares. */
1018         Globals.usershare_allow_guests = false;
1019
1020         Globals.keepalive = DEFAULT_KEEPALIVE;
1021
1022         /* By default no shares out of the registry */
1023         Globals.registry_shares = false;
1024
1025         Globals.iminreceivefile = 0;
1026
1027         Globals.map_untrusted_to_domain = false;
1028         Globals.multicast_dns_register = true;
1029
1030         Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
1031         Globals.smb2_max_write = DEFAULT_SMB2_MAX_WRITE;
1032         Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
1033         Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1034
1035         string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1036
1037         Globals.server_services = (const char **)str_list_make_v3(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate dns", NULL);
1038
1039         Globals.dcerpc_endpoint_servers = (const char **)str_list_make_v3(NULL, "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver", NULL);
1040
1041         Globals.tls_enabled = true;
1042
1043         string_set(&Globals.tls_keyfile, "tls/key.pem");
1044         string_set(&Globals.tls_certfile, "tls/cert.pem");
1045         string_set(&Globals.tls_cafile, "tls/ca.pem");
1046
1047         string_set(&Globals.share_backend, "classic");
1048
1049         Globals.iPreferredMaster = Auto;
1050
1051         Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
1052
1053         string_set(&Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
1054
1055         string_set(&Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
1056
1057         if (asprintf(&s, "%s/samba_kcc", get_dyn_SCRIPTSBINDIR()) < 0) {
1058                 smb_panic("init_globals: ENOMEM");
1059         }
1060         Globals.samba_kcc_command = (const char **)str_list_make_v3(NULL, s, NULL);
1061         SAFE_FREE(s);
1062
1063         if (asprintf(&s, "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR()) < 0) {
1064                 smb_panic("init_globals: ENOMEM");
1065         }
1066         Globals.dns_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1067         SAFE_FREE(s);
1068
1069         if (asprintf(&s, "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR()) < 0) {
1070                 smb_panic("init_globals: ENOMEM");
1071         }
1072         Globals.spn_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1073         SAFE_FREE(s);
1074
1075         Globals.nsupdate_command = (const char **)str_list_make_v3(NULL, "/usr/bin/nsupdate -g", NULL);
1076
1077         Globals.rndc_command = (const char **)str_list_make_v3(NULL, "/usr/sbin/rndc", NULL);
1078
1079         Globals.cldap_port = 389;
1080
1081         Globals.dgram_port = 138;
1082
1083         Globals.nbt_port = 137;
1084
1085         Globals.krb5_port = 88;
1086
1087         Globals.kpasswd_port = 464;
1088
1089         Globals.web_port = 901;
1090
1091         /* Now put back the settings that were set with lp_set_cmdline() */
1092         apply_lp_set_cmdline();
1093 }
1094
1095 /*******************************************************************
1096  Convenience routine to grab string parameters into talloced memory
1097  and run standard_sub_basic on them. The buffers can be written to by
1098  callers without affecting the source string.
1099 ********************************************************************/
1100
1101 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1102 {
1103         char *ret;
1104
1105         /* The follow debug is useful for tracking down memory problems
1106            especially if you have an inner loop that is calling a lp_*()
1107            function that returns a string.  Perhaps this debug should be
1108            present all the time? */
1109
1110 #if 0
1111         DEBUG(10, ("lp_string(%s)\n", s));
1112 #endif
1113         if (!s) {
1114                 return NULL;
1115         }
1116
1117         ret = talloc_sub_basic(ctx,
1118                         get_current_username(),
1119                         current_user_info.domain,
1120                         s);
1121         if (trim_char(ret, '\"', '\"')) {
1122                 if (strchr(ret,'\"') != NULL) {
1123                         TALLOC_FREE(ret);
1124                         ret = talloc_sub_basic(ctx,
1125                                         get_current_username(),
1126                                         current_user_info.domain,
1127                                         s);
1128                 }
1129         }
1130         return ret;
1131 }
1132
1133 /*
1134    In this section all the functions that are used to access the
1135    parameters from the rest of the program are defined
1136 */
1137
1138 #define FN_GLOBAL_STRING(fn_name,ptr) \
1139 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1140 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1141  const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1142 #define FN_GLOBAL_LIST(fn_name,ptr) \
1143  const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1144 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1145  bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1146 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1147  char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1148 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1149  int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1150
1151 #define FN_LOCAL_STRING(fn_name,val) \
1152 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));}
1153 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1154  const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1155 #define FN_LOCAL_LIST(fn_name,val) \
1156  const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1157 #define FN_LOCAL_BOOL(fn_name,val) \
1158  bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1159 #define FN_LOCAL_INTEGER(fn_name,val) \
1160  int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1161
1162 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1163  bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1164 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1165  int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1166 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
1167  char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1168
1169
1170 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1171 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1172
1173 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1174  * build process or in smb.conf, we use that value.  Otherwise they
1175  * default to the value of lp_lockdir(). */
1176 const char *lp_statedir(void) {
1177         if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1178             (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1179                 return(*(char **)(&Globals.szStateDir) ?
1180                        *(char **)(&Globals.szStateDir) : "");
1181         else
1182                 return(*(char **)(&Globals.lockdir) ?
1183                        *(char **)(&Globals.lockdir) : "");
1184 }
1185 const char *lp_cachedir(void) {
1186         if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1187             (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1188                 return(*(char **)(&Globals.szCacheDir) ?
1189                        *(char **)(&Globals.szCacheDir) : "");
1190         else
1191                 return(*(char **)(&Globals.lockdir) ?
1192                        *(char **)(&Globals.lockdir) : "");
1193 }
1194 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1195                   winbindMaxDomainConnections)
1196
1197 int lp_winbind_max_domain_connections(void)
1198 {
1199         if (lp_winbind_offline_logon() &&
1200             lp_winbind_max_domain_connections_int() > 1) {
1201                 DEBUG(1, ("offline logons active, restricting max domain "
1202                           "connections to 1\n"));
1203                 return 1;
1204         }
1205         return MAX(1, lp_winbind_max_domain_connections_int());
1206 }
1207
1208 int lp_smb2_max_credits(void)
1209 {
1210         if (Globals.ismb2_max_credits == 0) {
1211                 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1212         }
1213         return Globals.ismb2_max_credits;
1214 }
1215 int lp_cups_encrypt(void)
1216 {
1217         int result = 0;
1218 #ifdef HAVE_HTTPCONNECTENCRYPT
1219         switch (Globals.CupsEncrypt) {
1220                 case Auto:
1221                         result = HTTP_ENCRYPT_REQUIRED;
1222                         break;
1223                 case true:
1224                         result = HTTP_ENCRYPT_ALWAYS;
1225                         break;
1226                 case false:
1227                         result = HTTP_ENCRYPT_NEVER;
1228                         break;
1229         }
1230 #endif
1231         return result;
1232 }
1233
1234 /* These functions remain in source3/param for now */
1235
1236 FN_GLOBAL_STRING(configfile, szConfigFile)
1237
1238 #include "lib/param/param_functions.c"
1239
1240 FN_LOCAL_STRING(servicename, szService)
1241 FN_LOCAL_CONST_STRING(const_servicename, szService)
1242
1243 /* local prototypes */
1244
1245 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1246 static const char *get_boolean(bool bool_value);
1247 static int getservicebyname(const char *pszServiceName,
1248                             struct loadparm_service *pserviceDest);
1249 static void copy_service(struct loadparm_service *pserviceDest,
1250                          struct loadparm_service *pserviceSource,
1251                          struct bitmap *pcopymapDest);
1252 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1253                          void *userdata);
1254 static bool do_section(const char *pszSectionName, void *userdata);
1255 static void init_copymap(struct loadparm_service *pservice);
1256 static bool hash_a_service(const char *name, int number);
1257 static void free_service_byindex(int iService);
1258 static void show_parameter(int parmIndex);
1259 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1260
1261 /*
1262  * This is a helper function for parametrical options support.  It returns a
1263  * pointer to parametrical option value if it exists or NULL otherwise. Actual
1264  * parametrical functions are quite simple
1265  */
1266 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1267                                                            const char *option)
1268 {
1269         bool global_section = false;
1270         char* param_key;
1271         struct parmlist_entry *data;
1272
1273         if (service == NULL) {
1274                 data = Globals.param_opt;
1275                 global_section = true;
1276         } else {
1277                 data = service->param_opt;
1278         }
1279
1280         if (asprintf(&param_key, "%s:%s", type, option) == -1) {
1281                 DEBUG(0,("asprintf failed!\n"));
1282                 return NULL;
1283         }
1284
1285         while (data) {
1286                 if (strwicmp(data->key, param_key) == 0) {
1287                         string_free(&param_key);
1288                         return data;
1289                 }
1290                 data = data->next;
1291         }
1292
1293         if (!global_section) {
1294                 /* Try to fetch the same option but from globals */
1295                 /* but only if we are not already working with Globals */
1296                 data = Globals.param_opt;
1297                 while (data) {
1298                         if (strwicmp(data->key, param_key) == 0) {
1299                                 string_free(&param_key);
1300                                 return data;
1301                         }
1302                         data = data->next;
1303                 }
1304         }
1305
1306         string_free(&param_key);
1307
1308         return NULL;
1309 }
1310
1311 /*
1312  * This is a helper function for parametrical options support.  It returns a
1313  * pointer to parametrical option value if it exists or NULL otherwise. Actual
1314  * parametrical functions are quite simple
1315  */
1316 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1317                                                 const char *option)
1318 {
1319         if (snum >= iNumServices) return NULL;
1320
1321         if (snum < 0) {
1322                 return get_parametrics_by_service(NULL, type, option);
1323         } else {
1324                 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1325         }
1326 }
1327
1328
1329 #define MISSING_PARAMETER(name) \
1330     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1331
1332 /*******************************************************************
1333 convenience routine to return int parameters.
1334 ********************************************************************/
1335 static int lp_int(const char *s)
1336 {
1337
1338         if (!s || !*s) {
1339                 MISSING_PARAMETER(lp_int);
1340                 return (-1);
1341         }
1342
1343         return (int)strtol(s, NULL, 0);
1344 }
1345
1346 /*******************************************************************
1347 convenience routine to return unsigned long parameters.
1348 ********************************************************************/
1349 static unsigned long lp_ulong(const char *s)
1350 {
1351
1352         if (!s || !*s) {
1353                 MISSING_PARAMETER(lp_ulong);
1354                 return (0);
1355         }
1356
1357         return strtoul(s, NULL, 0);
1358 }
1359
1360 /*******************************************************************
1361 convenience routine to return boolean parameters.
1362 ********************************************************************/
1363 static bool lp_bool(const char *s)
1364 {
1365         bool ret = false;
1366
1367         if (!s || !*s) {
1368                 MISSING_PARAMETER(lp_bool);
1369                 return false;
1370         }
1371
1372         if (!set_boolean(s, &ret)) {
1373                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1374                 return false;
1375         }
1376
1377         return ret;
1378 }
1379
1380 /*******************************************************************
1381 convenience routine to return enum parameters.
1382 ********************************************************************/
1383 static int lp_enum(const char *s,const struct enum_list *_enum)
1384 {
1385         int i;
1386
1387         if (!s || !*s || !_enum) {
1388                 MISSING_PARAMETER(lp_enum);
1389                 return (-1);
1390         }
1391
1392         for (i=0; _enum[i].name; i++) {
1393                 if (strequal(_enum[i].name,s))
1394                         return _enum[i].value;
1395         }
1396
1397         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1398         return (-1);
1399 }
1400
1401 #undef MISSING_PARAMETER
1402
1403 /* Return parametric option from a given service. Type is a part of option before ':' */
1404 /* Parametric option has following syntax: 'Type: option = value' */
1405 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1406 {
1407         struct parmlist_entry *data = get_parametrics(snum, type, option);
1408
1409         if (data == NULL||data->value==NULL) {
1410                 if (def) {
1411                         return lp_string(ctx, def);
1412                 } else {
1413                         return NULL;
1414                 }
1415         }
1416
1417         return lp_string(ctx, data->value);
1418 }
1419
1420 /* Return parametric option from a given service. Type is a part of option before ':' */
1421 /* Parametric option has following syntax: 'Type: option = value' */
1422 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1423 {
1424         struct parmlist_entry *data = get_parametrics(snum, type, option);
1425
1426         if (data == NULL||data->value==NULL)
1427                 return def;
1428
1429         return data->value;
1430 }
1431
1432 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1433 {
1434         struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1435
1436         if (data == NULL||data->value==NULL)
1437                 return NULL;
1438
1439         return data->value;
1440 }
1441
1442
1443 /* Return parametric option from a given service. Type is a part of option before ':' */
1444 /* Parametric option has following syntax: 'Type: option = value' */
1445
1446 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1447 {
1448         struct parmlist_entry *data = get_parametrics(snum, type, option);
1449
1450         if (data == NULL||data->value==NULL)
1451                 return (const char **)def;
1452
1453         if (data->list==NULL) {
1454                 data->list = str_list_make_v3(NULL, data->value, NULL);
1455         }
1456
1457         return (const char **)data->list;
1458 }
1459
1460 /* Return parametric option from a given service. Type is a part of option before ':' */
1461 /* Parametric option has following syntax: 'Type: option = value' */
1462
1463 int lp_parm_int(int snum, const char *type, const char *option, int def)
1464 {
1465         struct parmlist_entry *data = get_parametrics(snum, type, option);
1466
1467         if (data && data->value && *data->value)
1468                 return lp_int(data->value);
1469
1470         return def;
1471 }
1472
1473 /* Return parametric option from a given service. Type is a part of option before ':' */
1474 /* Parametric option has following syntax: 'Type: option = value' */
1475
1476 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1477 {
1478         struct parmlist_entry *data = get_parametrics(snum, type, option);
1479
1480         if (data && data->value && *data->value)
1481                 return lp_ulong(data->value);
1482
1483         return def;
1484 }
1485
1486 /* Return parametric option from a given service. Type is a part of option before ':' */
1487 /* Parametric option has following syntax: 'Type: option = value' */
1488
1489 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1490 {
1491         struct parmlist_entry *data = get_parametrics(snum, type, option);
1492
1493         if (data && data->value && *data->value)
1494                 return lp_bool(data->value);
1495
1496         return def;
1497 }
1498
1499 /* Return parametric option from a given service. Type is a part of option before ':' */
1500 /* Parametric option has following syntax: 'Type: option = value' */
1501
1502 int lp_parm_enum(int snum, const char *type, const char *option,
1503                  const struct enum_list *_enum, int def)
1504 {
1505         struct parmlist_entry *data = get_parametrics(snum, type, option);
1506
1507         if (data && data->value && *data->value && _enum)
1508                 return lp_enum(data->value, _enum);
1509
1510         return def;
1511 }
1512
1513
1514 /***************************************************************************
1515  Initialise a service to the defaults.
1516 ***************************************************************************/
1517
1518 static void init_service(struct loadparm_service *pservice)
1519 {
1520         memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1521         copy_service(pservice, &sDefault, NULL);
1522 }
1523
1524
1525 /**
1526  * free a param_opts structure.
1527  * param_opts handling should be moved to talloc;
1528  * then this whole functions reduces to a TALLOC_FREE().
1529  */
1530
1531 static void free_param_opts(struct parmlist_entry **popts)
1532 {
1533         struct parmlist_entry *opt, *next_opt;
1534
1535         if (*popts != NULL) {
1536                 DEBUG(5, ("Freeing parametrics:\n"));
1537         }
1538         opt = *popts;
1539         while (opt != NULL) {
1540                 string_free(&opt->key);
1541                 string_free(&opt->value);
1542                 TALLOC_FREE(opt->list);
1543                 next_opt = opt->next;
1544                 SAFE_FREE(opt);
1545                 opt = next_opt;
1546         }
1547         *popts = NULL;
1548 }
1549
1550 /***************************************************************************
1551  Free the dynamically allocated parts of a service struct.
1552 ***************************************************************************/
1553
1554 static void free_service(struct loadparm_service *pservice)
1555 {
1556         if (!pservice)
1557                 return;
1558
1559         if (pservice->szService)
1560                 DEBUG(5, ("free_service: Freeing service %s\n",
1561                        pservice->szService));
1562
1563         free_parameters(pservice);
1564
1565         string_free(&pservice->szService);
1566         TALLOC_FREE(pservice->copymap);
1567
1568         free_param_opts(&pservice->param_opt);
1569
1570         ZERO_STRUCTP(pservice);
1571 }
1572
1573
1574 /***************************************************************************
1575  remove a service indexed in the ServicePtrs array from the ServiceHash
1576  and free the dynamically allocated parts
1577 ***************************************************************************/
1578
1579 static void free_service_byindex(int idx)
1580 {
1581         if ( !LP_SNUM_OK(idx) ) 
1582                 return;
1583
1584         ServicePtrs[idx]->valid = false;
1585
1586         /* we have to cleanup the hash record */
1587
1588         if (ServicePtrs[idx]->szService) {
1589                 char *canon_name = canonicalize_servicename(
1590                         talloc_tos(),
1591                         ServicePtrs[idx]->szService );
1592
1593                 dbwrap_delete_bystring(ServiceHash, canon_name );
1594                 TALLOC_FREE(canon_name);
1595         }
1596
1597         free_service(ServicePtrs[idx]);
1598         talloc_free_children(ServicePtrs[idx]);
1599 }
1600
1601 /***************************************************************************
1602  Add a new service to the services array initialising it with the given 
1603  service. 
1604 ***************************************************************************/
1605
1606 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1607 {
1608         int i;
1609         struct loadparm_service tservice;
1610         int num_to_alloc = iNumServices + 1;
1611         struct loadparm_service **tsp = NULL;
1612
1613         tservice = *pservice;
1614
1615         /* it might already exist */
1616         if (name) {
1617                 i = getservicebyname(name, NULL);
1618                 if (i >= 0) {
1619                         return (i);
1620                 }
1621         }
1622
1623         /* if not, then create one */
1624         i = iNumServices;
1625         tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1626         if (tsp == NULL) {
1627                 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1628                 return (-1);
1629         }
1630         ServicePtrs = tsp;
1631         ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1632         if (!ServicePtrs[iNumServices]) {
1633                 DEBUG(0,("add_a_service: out of memory!\n"));
1634                 return (-1);
1635         }
1636         iNumServices++;
1637
1638         ServicePtrs[i]->valid = true;
1639
1640         init_service(ServicePtrs[i]);
1641         copy_service(ServicePtrs[i], &tservice, NULL);
1642         if (name)
1643                 string_set(&ServicePtrs[i]->szService, name);
1644
1645         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
1646                 i, ServicePtrs[i]->szService));
1647
1648         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1649                 return (-1);
1650         }
1651
1652         return (i);
1653 }
1654
1655 /***************************************************************************
1656   Convert a string to uppercase and remove whitespaces.
1657 ***************************************************************************/
1658
1659 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1660 {
1661         char *result;
1662
1663         if ( !src ) {
1664                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1665                 return NULL;
1666         }
1667
1668         result = talloc_strdup(ctx, src);
1669         SMB_ASSERT(result != NULL);
1670
1671         if (!strlower_m(result)) {
1672                 TALLOC_FREE(result);
1673                 return NULL;
1674         }
1675         return result;
1676 }
1677
1678 /***************************************************************************
1679   Add a name/index pair for the services array to the hash table.
1680 ***************************************************************************/
1681
1682 static bool hash_a_service(const char *name, int idx)
1683 {
1684         char *canon_name;
1685
1686         if ( !ServiceHash ) {
1687                 DEBUG(10,("hash_a_service: creating servicehash\n"));
1688                 ServiceHash = db_open_rbt(NULL);
1689                 if ( !ServiceHash ) {
1690                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1691                         return false;
1692                 }
1693         }
1694
1695         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1696                 idx, name));
1697
1698         canon_name = canonicalize_servicename(talloc_tos(), name );
1699
1700         dbwrap_store_bystring(ServiceHash, canon_name,
1701                               make_tdb_data((uint8 *)&idx, sizeof(idx)),
1702                               TDB_REPLACE);
1703
1704         TALLOC_FREE(canon_name);
1705
1706         return true;
1707 }
1708
1709 /***************************************************************************
1710  Add a new home service, with the specified home directory, defaults coming
1711  from service ifrom.
1712 ***************************************************************************/
1713
1714 bool lp_add_home(const char *pszHomename, int iDefaultService,
1715                  const char *user, const char *pszHomedir)
1716 {
1717         int i;
1718
1719         if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1720                         pszHomedir[0] == '\0') {
1721                 return false;
1722         }
1723
1724         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1725
1726         if (i < 0)
1727                 return false;
1728
1729         if (!(*(ServicePtrs[iDefaultService]->path))
1730             || strequal(ServicePtrs[iDefaultService]->path,
1731                         lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1732                 string_set(&ServicePtrs[i]->path, pszHomedir);
1733         }
1734
1735         if (!(*(ServicePtrs[i]->comment))) {
1736                 char *comment = NULL;
1737                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1738                         return false;
1739                 }
1740                 string_set(&ServicePtrs[i]->comment, comment);
1741                 SAFE_FREE(comment);
1742         }
1743
1744         /* set the browseable flag from the global default */
1745
1746         ServicePtrs[i]->browseable = sDefault.browseable;
1747         ServicePtrs[i]->access_based_share_enum = sDefault.access_based_share_enum;
1748
1749         ServicePtrs[i]->autoloaded = true;
1750
1751         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
1752                user, ServicePtrs[i]->path ));
1753
1754         return true;
1755 }
1756
1757 /***************************************************************************
1758  Add a new service, based on an old one.
1759 ***************************************************************************/
1760
1761 int lp_add_service(const char *pszService, int iDefaultService)
1762 {
1763         if (iDefaultService < 0) {
1764                 return add_a_service(&sDefault, pszService);
1765         }
1766
1767         return (add_a_service(ServicePtrs[iDefaultService], pszService));
1768 }
1769
1770 /***************************************************************************
1771  Add the IPC service.
1772 ***************************************************************************/
1773
1774 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1775 {
1776         char *comment = NULL;
1777         int i = add_a_service(&sDefault, ipc_name);
1778
1779         if (i < 0)
1780                 return false;
1781
1782         if (asprintf(&comment, "IPC Service (%s)",
1783                                 Globals.serverstring) < 0) {
1784                 return false;
1785         }
1786
1787         string_set(&ServicePtrs[i]->path, tmpdir());
1788         string_set(&ServicePtrs[i]->username, "");
1789         string_set(&ServicePtrs[i]->comment, comment);
1790         string_set(&ServicePtrs[i]->fstype, "IPC");
1791         ServicePtrs[i]->max_connections = 0;
1792         ServicePtrs[i]->bAvailable = true;
1793         ServicePtrs[i]->read_only = true;
1794         ServicePtrs[i]->guest_only = false;
1795         ServicePtrs[i]->administrative_share = true;
1796         ServicePtrs[i]->guest_ok = guest_ok;
1797         ServicePtrs[i]->printable = false;
1798         ServicePtrs[i]->browseable = sDefault.browseable;
1799
1800         DEBUG(3, ("adding IPC service\n"));
1801
1802         SAFE_FREE(comment);
1803         return true;
1804 }
1805
1806 /***************************************************************************
1807  Add a new printer service, with defaults coming from service iFrom.
1808 ***************************************************************************/
1809
1810 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1811 {
1812         const char *comment = "From Printcap";
1813         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1814
1815         if (i < 0)
1816                 return false;
1817
1818         /* note that we do NOT default the availability flag to true - */
1819         /* we take it from the default service passed. This allows all */
1820         /* dynamic printers to be disabled by disabling the [printers] */
1821         /* entry (if/when the 'available' keyword is implemented!).    */
1822
1823         /* the printer name is set to the service name. */
1824         string_set(&ServicePtrs[i]->_printername, pszPrintername);
1825         string_set(&ServicePtrs[i]->comment, comment);
1826
1827         /* set the browseable flag from the gloabl default */
1828         ServicePtrs[i]->browseable = sDefault.browseable;
1829
1830         /* Printers cannot be read_only. */
1831         ServicePtrs[i]->read_only = false;
1832         /* No oplocks on printer services. */
1833         ServicePtrs[i]->oplocks = false;
1834         /* Printer services must be printable. */
1835         ServicePtrs[i]->printable = true;
1836
1837         DEBUG(3, ("adding printer service %s\n", pszPrintername));
1838
1839         return true;
1840 }
1841
1842
1843 /***************************************************************************
1844  Check whether the given parameter name is valid.
1845  Parametric options (names containing a colon) are considered valid.
1846 ***************************************************************************/
1847
1848 bool lp_parameter_is_valid(const char *pszParmName)
1849 {
1850         return ((lpcfg_map_parameter(pszParmName) != -1) ||
1851                 (strchr(pszParmName, ':') != NULL));
1852 }
1853
1854 /***************************************************************************
1855  Check whether the given name is the name of a global parameter.
1856  Returns true for strings belonging to parameters of class
1857  P_GLOBAL, false for all other strings, also for parametric options
1858  and strings not belonging to any option.
1859 ***************************************************************************/
1860
1861 bool lp_parameter_is_global(const char *pszParmName)
1862 {
1863         int num = lpcfg_map_parameter(pszParmName);
1864
1865         if (num >= 0) {
1866                 return (parm_table[num].p_class == P_GLOBAL);
1867         }
1868
1869         return false;
1870 }
1871
1872 /**************************************************************************
1873  Check whether the given name is the canonical name of a parameter.
1874  Returns false if it is not a valid parameter Name.
1875  For parametric options, true is returned.
1876 **************************************************************************/
1877
1878 bool lp_parameter_is_canonical(const char *parm_name)
1879 {
1880         if (!lp_parameter_is_valid(parm_name)) {
1881                 return false;
1882         }
1883
1884         return (lpcfg_map_parameter(parm_name) ==
1885                 map_parameter_canonical(parm_name, NULL));
1886 }
1887
1888 /**************************************************************************
1889  Determine the canonical name for a parameter.
1890  Indicate when it is an inverse (boolean) synonym instead of a
1891  "usual" synonym.
1892 **************************************************************************/
1893
1894 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1895                                bool *inverse)
1896 {
1897         int num;
1898
1899         if (!lp_parameter_is_valid(parm_name)) {
1900                 *canon_parm = NULL;
1901                 return false;
1902         }
1903
1904         num = map_parameter_canonical(parm_name, inverse);
1905         if (num < 0) {
1906                 /* parametric option */
1907                 *canon_parm = parm_name;
1908         } else {
1909                 *canon_parm = parm_table[num].label;
1910         }
1911
1912         return true;
1913
1914 }
1915
1916 /**************************************************************************
1917  Determine the canonical name for a parameter.
1918  Turn the value given into the inverse boolean expression when
1919  the synonym is an invers boolean synonym.
1920
1921  Return true if parm_name is a valid parameter name and
1922  in case it is an invers boolean synonym, if the val string could
1923  successfully be converted to the reverse bool.
1924  Return false in all other cases.
1925 **************************************************************************/
1926
1927 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1928                                           const char *val,
1929                                           const char **canon_parm,
1930                                           const char **canon_val)
1931 {
1932         int num;
1933         bool inverse;
1934
1935         if (!lp_parameter_is_valid(parm_name)) {
1936                 *canon_parm = NULL;
1937                 *canon_val = NULL;
1938                 return false;
1939         }
1940
1941         num = map_parameter_canonical(parm_name, &inverse);
1942         if (num < 0) {
1943                 /* parametric option */
1944                 *canon_parm = parm_name;
1945                 *canon_val = val;
1946         } else {
1947                 *canon_parm = parm_table[num].label;
1948                 if (inverse) {
1949                         if (!lp_invert_boolean(val, canon_val)) {
1950                                 *canon_val = NULL;
1951                                 return false;
1952                         }
1953                 } else {
1954                         *canon_val = val;
1955                 }
1956         }
1957
1958         return true;
1959 }
1960
1961 /***************************************************************************
1962  Map a parameter's string representation to the index of the canonical
1963  form of the parameter (it might be a synonym).
1964  Returns -1 if the parameter string is not recognised.
1965 ***************************************************************************/
1966
1967 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1968 {
1969         int parm_num, canon_num;
1970         bool loc_inverse = false;
1971
1972         parm_num = lpcfg_map_parameter(pszParmName);
1973         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1974                 /* invalid, parametric or no canidate for synonyms ... */
1975                 goto done;
1976         }
1977
1978         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1979                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1980                         parm_num = canon_num;
1981                         goto done;
1982                 }
1983         }
1984
1985 done:
1986         if (inverse != NULL) {
1987                 *inverse = loc_inverse;
1988         }
1989         return parm_num;
1990 }
1991
1992 /***************************************************************************
1993  return true if parameter number parm1 is a synonym of parameter
1994  number parm2 (parm2 being the principal name).
1995  set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1996  false otherwise.
1997 ***************************************************************************/
1998
1999 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
2000 {
2001         if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
2002             (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
2003             (parm_table[parm1].flags & FLAG_HIDE) &&
2004             !(parm_table[parm2].flags & FLAG_HIDE))
2005         {
2006                 if (inverse != NULL) {
2007                         if ((parm_table[parm1].type == P_BOOLREV) &&
2008                             (parm_table[parm2].type == P_BOOL))
2009                         {
2010                                 *inverse = true;
2011                         } else {
2012                                 *inverse = false;
2013                         }
2014                 }
2015                 return true;
2016         }
2017         return false;
2018 }
2019
2020 /***************************************************************************
2021  Show one parameter's name, type, [values,] and flags.
2022  (helper functions for show_parameter_list)
2023 ***************************************************************************/
2024
2025 static void show_parameter(int parmIndex)
2026 {
2027         int enumIndex, flagIndex;
2028         int parmIndex2;
2029         bool hadFlag;
2030         bool hadSyn;
2031         bool inverse;
2032         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2033                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2034                 "P_ENUM", "P_SEP"};
2035         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2036                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2037                 FLAG_HIDE};
2038         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2039                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2040                 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2041
2042         printf("%s=%s", parm_table[parmIndex].label,
2043                type[parm_table[parmIndex].type]);
2044         if (parm_table[parmIndex].type == P_ENUM) {
2045                 printf(",");
2046                 for (enumIndex=0;
2047                      parm_table[parmIndex].enum_list[enumIndex].name;
2048                      enumIndex++)
2049                 {
2050                         printf("%s%s",
2051                                enumIndex ? "|" : "",
2052                                parm_table[parmIndex].enum_list[enumIndex].name);
2053                 }
2054         }
2055         printf(",");
2056         hadFlag = false;
2057         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2058                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2059                         printf("%s%s",
2060                                 hadFlag ? "|" : "",
2061                                 flag_names[flagIndex]);
2062                         hadFlag = true;
2063                 }
2064         }
2065
2066         /* output synonyms */
2067         hadSyn = false;
2068         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2069                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2070                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2071                                parm_table[parmIndex2].label);
2072                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2073                         if (!hadSyn) {
2074                                 printf(" (synonyms: ");
2075                                 hadSyn = true;
2076                         } else {
2077                                 printf(", ");
2078                         }
2079                         printf("%s%s", parm_table[parmIndex2].label,
2080                                inverse ? "[i]" : "");
2081                 }
2082         }
2083         if (hadSyn) {
2084                 printf(")");
2085         }
2086
2087         printf("\n");
2088 }
2089
2090 /***************************************************************************
2091  Show all parameter's name, type, [values,] and flags.
2092 ***************************************************************************/
2093
2094 void show_parameter_list(void)
2095 {
2096         int classIndex, parmIndex;
2097         const char *section_names[] = { "local", "global", NULL};
2098
2099         for (classIndex=0; section_names[classIndex]; classIndex++) {
2100                 printf("[%s]\n", section_names[classIndex]);
2101                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2102                         if (parm_table[parmIndex].p_class == classIndex) {
2103                                 show_parameter(parmIndex);
2104                         }
2105                 }
2106         }
2107 }
2108
2109 /***************************************************************************
2110  Check if a given string correctly represents a boolean value.
2111 ***************************************************************************/
2112
2113 bool lp_string_is_valid_boolean(const char *parm_value)
2114 {
2115         return set_boolean(parm_value, NULL);
2116 }
2117
2118 /***************************************************************************
2119  Get the standard string representation of a boolean value ("yes" or "no")
2120 ***************************************************************************/
2121
2122 static const char *get_boolean(bool bool_value)
2123 {
2124         static const char *yes_str = "yes";
2125         static const char *no_str = "no";
2126
2127         return (bool_value ? yes_str : no_str);
2128 }
2129
2130 /***************************************************************************
2131  Provide the string of the negated boolean value associated to the boolean
2132  given as a string. Returns false if the passed string does not correctly
2133  represent a boolean.
2134 ***************************************************************************/
2135
2136 bool lp_invert_boolean(const char *str, const char **inverse_str)
2137 {
2138         bool val;
2139
2140         if (!set_boolean(str, &val)) {
2141                 return false;
2142         }
2143
2144         *inverse_str = get_boolean(!val);
2145         return true;
2146 }
2147
2148 /***************************************************************************
2149  Provide the canonical string representation of a boolean value given
2150  as a string. Return true on success, false if the string given does
2151  not correctly represent a boolean.
2152 ***************************************************************************/
2153
2154 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2155 {
2156         bool val;
2157
2158         if (!set_boolean(str, &val)) {
2159                 return false;
2160         }
2161
2162         *canon_str = get_boolean(val);
2163         return true;
2164 }
2165
2166 /***************************************************************************
2167 Find a service by name. Otherwise works like get_service.
2168 ***************************************************************************/
2169
2170 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2171 {
2172         int iService = -1;
2173         char *canon_name;
2174         TDB_DATA data;
2175         NTSTATUS status;
2176
2177         if (ServiceHash == NULL) {
2178                 return -1;
2179         }
2180
2181         canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2182
2183         status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2184                                        &data);
2185
2186         if (NT_STATUS_IS_OK(status) &&
2187             (data.dptr != NULL) &&
2188             (data.dsize == sizeof(iService)))
2189         {
2190                 iService = *(int *)data.dptr;
2191         }
2192
2193         TALLOC_FREE(canon_name);
2194
2195         if ((iService != -1) && (LP_SNUM_OK(iService))
2196             && (pserviceDest != NULL)) {
2197                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2198         }
2199
2200         return (iService);
2201 }
2202
2203 /* Return a pointer to a service by name.  Unlike getservicebyname, it does not copy the service */
2204 struct loadparm_service *lp_service(const char *pszServiceName)
2205 {
2206         int iService = getservicebyname(pszServiceName, NULL);
2207         if (iService == -1 || !LP_SNUM_OK(iService)) {
2208                 return NULL;
2209         }
2210         return ServicePtrs[iService];
2211 }
2212
2213 struct loadparm_service *lp_servicebynum(int snum)
2214 {
2215         if ((snum == -1) || !LP_SNUM_OK(snum)) {
2216                 return NULL;
2217         }
2218         return ServicePtrs[snum];
2219 }
2220
2221 struct loadparm_service *lp_default_loadparm_service()
2222 {
2223         return &sDefault;
2224 }
2225
2226
2227 /***************************************************************************
2228  Copy a service structure to another.
2229  If pcopymapDest is NULL then copy all fields
2230 ***************************************************************************/
2231
2232 /**
2233  * Add a parametric option to a parmlist_entry,
2234  * replacing old value, if already present.
2235  */
2236 static void set_param_opt(struct parmlist_entry **opt_list,
2237                           const char *opt_name,
2238                           const char *opt_value,
2239                           unsigned priority)
2240 {
2241         struct parmlist_entry *new_opt, *opt;
2242         bool not_added;
2243
2244         opt = *opt_list;
2245         not_added = true;
2246
2247         /* Traverse destination */
2248         while (opt) {
2249                 /* If we already have same option, override it */
2250                 if (strwicmp(opt->key, opt_name) == 0) {
2251                         if ((opt->priority & FLAG_CMDLINE) &&
2252                             !(priority & FLAG_CMDLINE)) {
2253                                 /* it's been marked as not to be
2254                                    overridden */
2255                                 return;
2256                         }
2257                         string_free(&opt->value);
2258                         TALLOC_FREE(opt->list);
2259                         opt->value = SMB_STRDUP(opt_value);
2260                         opt->priority = priority;
2261                         not_added = false;
2262                         break;
2263                 }
2264                 opt = opt->next;
2265         }
2266         if (not_added) {
2267             new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2268             new_opt->key = SMB_STRDUP(opt_name);
2269             new_opt->value = SMB_STRDUP(opt_value);
2270             new_opt->list = NULL;
2271             new_opt->priority = priority;
2272             DLIST_ADD(*opt_list, new_opt);
2273         }
2274 }
2275
2276 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2277                          struct bitmap *pcopymapDest)
2278 {
2279         int i;
2280         bool bcopyall = (pcopymapDest == NULL);
2281         struct parmlist_entry *data;
2282
2283         for (i = 0; parm_table[i].label; i++)
2284                 if (parm_table[i].p_class == P_LOCAL &&
2285                     (bcopyall || bitmap_query(pcopymapDest,i))) {
2286                         void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2287                         void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2288
2289                         switch (parm_table[i].type) {
2290                                 case P_BOOL:
2291                                 case P_BOOLREV:
2292                                         *(bool *)dest_ptr = *(bool *)src_ptr;
2293                                         break;
2294
2295                                 case P_INTEGER:
2296                                 case P_ENUM:
2297                                 case P_OCTAL:
2298                                 case P_BYTES:
2299                                         *(int *)dest_ptr = *(int *)src_ptr;
2300                                         break;
2301
2302                                 case P_CHAR:
2303                                         *(char *)dest_ptr = *(char *)src_ptr;
2304                                         break;
2305
2306                                 case P_STRING:
2307                                         string_set((char **)dest_ptr,
2308                                                    *(char **)src_ptr);
2309                                         break;
2310
2311                                 case P_USTRING:
2312                                 {
2313                                         char *upper_string = strupper_talloc(talloc_tos(), 
2314                                                                              *(char **)src_ptr);
2315                                         string_set((char **)dest_ptr,
2316                                                    upper_string);
2317                                         TALLOC_FREE(upper_string);
2318                                         break;
2319                                 }
2320                                 case P_LIST:
2321                                         TALLOC_FREE(*((char ***)dest_ptr));
2322                                         *((char ***)dest_ptr) = str_list_copy(NULL, 
2323                                                       *(const char ***)src_ptr);
2324                                         break;
2325                                 default:
2326                                         break;
2327                         }
2328                 }
2329
2330         if (bcopyall) {
2331                 init_copymap(pserviceDest);
2332                 if (pserviceSource->copymap)
2333                         bitmap_copy(pserviceDest->copymap,
2334                                     pserviceSource->copymap);
2335         }
2336
2337         data = pserviceSource->param_opt;
2338         while (data) {
2339                 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2340                 data = data->next;
2341         }
2342 }
2343
2344 /***************************************************************************
2345 Check a service for consistency. Return false if the service is in any way
2346 incomplete or faulty, else true.
2347 ***************************************************************************/
2348
2349 bool service_ok(int iService)
2350 {
2351         bool bRetval;
2352
2353         bRetval = true;
2354         if (ServicePtrs[iService]->szService[0] == '\0') {
2355                 DEBUG(0, ("The following message indicates an internal error:\n"));
2356                 DEBUG(0, ("No service name in service entry.\n"));
2357                 bRetval = false;
2358         }
2359
2360         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2361         /* I can't see why you'd want a non-printable printer service...        */
2362         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2363                 if (!ServicePtrs[iService]->printable) {
2364                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2365                                ServicePtrs[iService]->szService));
2366                         ServicePtrs[iService]->printable = true;
2367                 }
2368                 /* [printers] service must also be non-browsable. */
2369                 if (ServicePtrs[iService]->browseable)
2370                         ServicePtrs[iService]->browseable = false;
2371         }
2372
2373         if (ServicePtrs[iService]->path[0] == '\0' &&
2374             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2375             ServicePtrs[iService]->msdfs_proxy[0] == '\0'
2376             ) {
2377                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2378                         ServicePtrs[iService]->szService));
2379                 ServicePtrs[iService]->bAvailable = false;
2380         }
2381
2382         /* If a service is flagged unavailable, log the fact at level 1. */
2383         if (!ServicePtrs[iService]->bAvailable)
2384                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2385                           ServicePtrs[iService]->szService));
2386
2387         return (bRetval);
2388 }
2389
2390 static struct smbconf_ctx *lp_smbconf_ctx(void)
2391 {
2392         sbcErr err;
2393         static struct smbconf_ctx *conf_ctx = NULL;
2394
2395         if (conf_ctx == NULL) {
2396                 err = smbconf_init(NULL, &conf_ctx, "registry:");
2397                 if (!SBC_ERROR_IS_OK(err)) {
2398                         DEBUG(1, ("error initializing registry configuration: "
2399                                   "%s\n", sbcErrorString(err)));
2400                         conf_ctx = NULL;
2401                 }
2402         }
2403
2404         return conf_ctx;
2405 }
2406
2407 static bool process_smbconf_service(struct smbconf_service *service)
2408 {
2409         uint32_t count;
2410         bool ret;
2411
2412         if (service == NULL) {
2413                 return false;
2414         }
2415
2416         ret = do_section(service->name, NULL);
2417         if (ret != true) {
2418                 return false;
2419         }
2420         for (count = 0; count < service->num_params; count++) {
2421                 ret = do_parameter(service->param_names[count],
2422                                    service->param_values[count],
2423                                    NULL);
2424                 if (ret != true) {
2425                         return false;
2426                 }
2427         }
2428         if (iServiceIndex >= 0) {
2429                 return service_ok(iServiceIndex);
2430         }
2431         return true;
2432 }
2433
2434 /**
2435  * load a service from registry and activate it
2436  */
2437 bool process_registry_service(const char *service_name)
2438 {
2439         sbcErr err;
2440         struct smbconf_service *service = NULL;
2441         TALLOC_CTX *mem_ctx = talloc_stackframe();
2442         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2443         bool ret = false;
2444
2445         if (conf_ctx == NULL) {
2446                 goto done;
2447         }
2448
2449         DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2450
2451         if (!smbconf_share_exists(conf_ctx, service_name)) {
2452                 /*
2453                  * Registry does not contain data for this service (yet),
2454                  * but make sure lp_load doesn't return false.
2455                  */
2456                 ret = true;
2457                 goto done;
2458         }
2459
2460         err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2461         if (!SBC_ERROR_IS_OK(err)) {
2462                 goto done;
2463         }
2464
2465         ret = process_smbconf_service(service);
2466         if (!ret) {
2467                 goto done;
2468         }
2469
2470         /* store the csn */
2471         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2472
2473 done:
2474         TALLOC_FREE(mem_ctx);
2475         return ret;
2476 }
2477
2478 /*
2479  * process_registry_globals
2480  */
2481 static bool process_registry_globals(void)
2482 {
2483         bool ret;
2484
2485         add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2486
2487         ret = do_parameter("registry shares", "yes", NULL);
2488         if (!ret) {
2489                 return ret;
2490         }
2491
2492         return process_registry_service(GLOBAL_NAME);
2493 }
2494
2495 bool process_registry_shares(void)
2496 {
2497         sbcErr err;
2498         uint32_t count;
2499         struct smbconf_service **service = NULL;
2500         uint32_t num_shares = 0;
2501         TALLOC_CTX *mem_ctx = talloc_stackframe();
2502         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2503         bool ret = false;
2504
2505         if (conf_ctx == NULL) {
2506                 goto done;
2507         }
2508
2509         err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2510         if (!SBC_ERROR_IS_OK(err)) {
2511                 goto done;
2512         }
2513
2514         ret = true;
2515
2516         for (count = 0; count < num_shares; count++) {
2517                 if (strequal(service[count]->name, GLOBAL_NAME)) {
2518                         continue;
2519                 }
2520                 ret = process_smbconf_service(service[count]);
2521                 if (!ret) {
2522                         goto done;
2523                 }
2524         }
2525
2526         /* store the csn */
2527         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2528
2529 done:
2530         TALLOC_FREE(mem_ctx);
2531         return ret;
2532 }
2533
2534 /**
2535  * reload those shares from registry that are already
2536  * activated in the services array.
2537  */
2538 static bool reload_registry_shares(void)
2539 {
2540         int i;
2541         bool ret = true;
2542
2543         for (i = 0; i < iNumServices; i++) {
2544                 if (!VALID(i)) {
2545                         continue;
2546                 }
2547
2548                 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2549                         continue;
2550                 }
2551
2552                 ret = process_registry_service(ServicePtrs[i]->szService);
2553                 if (!ret) {
2554                         goto done;
2555                 }
2556         }
2557
2558 done:
2559         return ret;
2560 }
2561
2562
2563 #define MAX_INCLUDE_DEPTH 100
2564
2565 static uint8_t include_depth;
2566
2567 static struct file_lists {
2568         struct file_lists *next;
2569         char *name;
2570         char *subfname;
2571         time_t modtime;
2572 } *file_lists = NULL;
2573
2574 /*******************************************************************
2575  Keep a linked list of all config files so we know when one has changed 
2576  it's date and needs to be reloaded.
2577 ********************************************************************/
2578
2579 static void add_to_file_list(const char *fname, const char *subfname)
2580 {
2581         struct file_lists *f = file_lists;
2582
2583         while (f) {
2584                 if (f->name && !strcmp(f->name, fname))
2585                         break;
2586                 f = f->next;
2587         }
2588
2589         if (!f) {
2590                 f = SMB_MALLOC_P(struct file_lists);
2591                 if (!f)
2592                         return;
2593                 f->next = file_lists;
2594                 f->name = SMB_STRDUP(fname);
2595                 if (!f->name) {
2596                         SAFE_FREE(f);
2597                         return;
2598                 }
2599                 f->subfname = SMB_STRDUP(subfname);
2600                 if (!f->subfname) {
2601                         SAFE_FREE(f->name);
2602                         SAFE_FREE(f);
2603                         return;
2604                 }
2605                 file_lists = f;
2606                 f->modtime = file_modtime(subfname);
2607         } else {
2608                 time_t t = file_modtime(subfname);
2609                 if (t)
2610                         f->modtime = t;
2611         }
2612         return;
2613 }
2614
2615 /**
2616  * Free the file lists
2617  */
2618 static void free_file_list(void)
2619 {
2620         struct file_lists *f;
2621         struct file_lists *next;
2622
2623         f = file_lists;
2624         while( f ) {
2625                 next = f->next;
2626                 SAFE_FREE( f->name );
2627                 SAFE_FREE( f->subfname );
2628                 SAFE_FREE( f );
2629                 f = next;
2630         }
2631         file_lists = NULL;
2632 }
2633
2634
2635 /**
2636  * Utility function for outsiders to check if we're running on registry.
2637  */
2638 bool lp_config_backend_is_registry(void)
2639 {
2640         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2641 }
2642
2643 /**
2644  * Utility function to check if the config backend is FILE.
2645  */
2646 bool lp_config_backend_is_file(void)
2647 {
2648         return (lp_config_backend() == CONFIG_BACKEND_FILE);
2649 }
2650
2651 /*******************************************************************
2652  Check if a config file has changed date.
2653 ********************************************************************/
2654
2655 bool lp_file_list_changed(void)
2656 {
2657         struct file_lists *f = file_lists;
2658
2659         DEBUG(6, ("lp_file_list_changed()\n"));
2660
2661         while (f) {
2662                 time_t mod_time;
2663
2664                 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2665                         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2666
2667                         if (conf_ctx == NULL) {
2668                                 return false;
2669                         }
2670                         if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2671                                             NULL))
2672                         {
2673                                 DEBUGADD(6, ("registry config changed\n"));
2674                                 return true;
2675                         }
2676                 } else {
2677                         char *n2 = NULL;
2678                         n2 = talloc_sub_basic(talloc_tos(),
2679                                               get_current_username(),
2680                                               current_user_info.domain,
2681                                               f->name);
2682                         if (!n2) {
2683                                 return false;
2684                         }
2685                         DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2686                                      f->name, n2, ctime(&f->modtime)));
2687
2688                         mod_time = file_modtime(n2);
2689
2690                         if (mod_time &&
2691                             ((f->modtime != mod_time) ||
2692                              (f->subfname == NULL) ||
2693                              (strcmp(n2, f->subfname) != 0)))
2694                         {
2695                                 DEBUGADD(6,
2696                                          ("file %s modified: %s\n", n2,
2697                                           ctime(&mod_time)));
2698                                 f->modtime = mod_time;
2699                                 SAFE_FREE(f->subfname);
2700                                 f->subfname = SMB_STRDUP(n2);
2701                                 TALLOC_FREE(n2);
2702                                 return true;
2703                         }
2704                         TALLOC_FREE(n2);
2705                 }
2706                 f = f->next;
2707         }
2708         return false;
2709 }
2710
2711
2712 /**
2713  * Initialize iconv conversion descriptors.
2714  *
2715  * This is called the first time it is needed, and also called again
2716  * every time the configuration is reloaded, because the charset or
2717  * codepage might have changed.
2718  **/
2719 static void init_iconv(void)
2720 {
2721         global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2722                                                       lp_unix_charset(),
2723                                                       true, global_iconv_handle);
2724 }
2725
2726 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2727 {
2728         if (strcmp(*ptr, pszParmValue) != 0) {
2729                 string_set(ptr, pszParmValue);
2730                 init_iconv();
2731         }
2732         return true;
2733 }
2734
2735 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2736 {
2737         bool is_utf8 = false;
2738         size_t len = strlen(pszParmValue);
2739
2740         if (len == 4 || len == 5) {
2741                 /* Don't use StrCaseCmp here as we don't want to
2742                    initialize iconv. */
2743                 if ((toupper_m(pszParmValue[0]) == 'U') &&
2744                     (toupper_m(pszParmValue[1]) == 'T') &&
2745                     (toupper_m(pszParmValue[2]) == 'F')) {
2746                         if (len == 4) {
2747                                 if (pszParmValue[3] == '8') {
2748                                         is_utf8 = true;
2749                                 }
2750                         } else {
2751                                 if (pszParmValue[3] == '-' &&
2752                                     pszParmValue[4] == '8') {
2753                                         is_utf8 = true;
2754                                 }
2755                         }
2756                 }
2757         }
2758
2759         if (strcmp(*ptr, pszParmValue) != 0) {
2760                 if (is_utf8) {
2761                         DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2762                                 "be UTF8, using (default value) %s instead.\n",
2763                                 DEFAULT_DOS_CHARSET));
2764                         pszParmValue = DEFAULT_DOS_CHARSET;
2765                 }
2766                 string_set(ptr, pszParmValue);
2767                 init_iconv();
2768         }
2769         return true;
2770 }
2771
2772 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2773 {
2774         bool ret = true;
2775         TALLOC_CTX *frame = talloc_stackframe();
2776         char *realm = strupper_talloc(frame, pszParmValue);
2777         char *dnsdomain = strlower_talloc(realm, pszParmValue);
2778
2779         ret &= string_set(&Globals.realm_original, pszParmValue);
2780         ret &= string_set(&Globals.realm, realm);
2781         ret &= string_set(&Globals.dnsdomain, dnsdomain);
2782         TALLOC_FREE(frame);
2783
2784         return ret;
2785 }
2786
2787 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2788 {
2789         TALLOC_FREE(Globals.netbios_aliases);
2790         Globals.netbios_aliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2791         return set_netbios_aliases(Globals.netbios_aliases);
2792 }
2793
2794 /***************************************************************************
2795  Handle the include operation.
2796 ***************************************************************************/
2797 static bool bAllowIncludeRegistry = true;
2798
2799 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2800 {
2801         char *fname;
2802
2803         if (include_depth >= MAX_INCLUDE_DEPTH) {
2804                 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2805                           include_depth));
2806                 return false;
2807         }
2808
2809         if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2810                 if (!bAllowIncludeRegistry) {
2811                         return true;
2812                 }
2813                 if (bInGlobalSection) {
2814                         bool ret;
2815                         include_depth++;
2816                         ret = process_registry_globals();
2817                         include_depth--;
2818                         return ret;
2819                 } else {
2820                         DEBUG(1, ("\"include = registry\" only effective "
2821                                   "in %s section\n", GLOBAL_NAME));
2822                         return false;
2823                 }
2824         }
2825
2826         fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2827                                  current_user_info.domain,
2828                                  pszParmValue);
2829
2830         add_to_file_list(pszParmValue, fname);
2831
2832         string_set(ptr, fname);
2833
2834         if (file_exist(fname)) {
2835                 bool ret;
2836                 include_depth++;
2837                 ret = pm_process(fname, do_section, do_parameter, NULL);
2838                 include_depth--;
2839                 TALLOC_FREE(fname);
2840                 return ret;
2841         }
2842
2843         DEBUG(2, ("Can't find include file %s\n", fname));
2844         TALLOC_FREE(fname);
2845         return true;
2846 }
2847
2848 /***************************************************************************
2849  Handle the interpretation of the copy parameter.
2850 ***************************************************************************/
2851
2852 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2853 {
2854         bool bRetval;
2855         int iTemp;
2856         struct loadparm_service serviceTemp;
2857
2858         string_set(ptr, pszParmValue);
2859
2860         init_service(&serviceTemp);
2861
2862         bRetval = false;
2863
2864         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2865
2866         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2867                 if (iTemp == iServiceIndex) {
2868                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2869                 } else {
2870                         copy_service(ServicePtrs[iServiceIndex],
2871                                      &serviceTemp,
2872                                      ServicePtrs[iServiceIndex]->copymap);
2873                         bRetval = true;
2874                 }
2875         } else {
2876                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2877                 bRetval = false;
2878         }
2879
2880         free_service(&serviceTemp);
2881         return (bRetval);
2882 }
2883
2884 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2885 {
2886         Globals.ldap_debug_level = lp_int(pszParmValue);
2887         init_ldap_debugging();
2888         return true;
2889 }
2890
2891 /*
2892  * idmap related parameters
2893  */
2894
2895 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2896 {
2897         lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2898
2899         return true;
2900 }
2901
2902 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2903 {
2904         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2905
2906         return true;
2907 }
2908
2909 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2910 {
2911         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2912
2913         return true;
2914 }
2915
2916 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2917 {
2918         char *config_option = NULL;
2919         const char *range = NULL;
2920         bool ret = false;
2921
2922         SMB_ASSERT(low != NULL);
2923         SMB_ASSERT(high != NULL);
2924
2925         if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2926                 domain_name = "*";
2927         }
2928
2929         config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2930                                         domain_name);
2931         if (config_option == NULL) {
2932                 DEBUG(0, ("out of memory\n"));
2933                 return false;
2934         }
2935
2936         range = lp_parm_const_string(-1, config_option, "range", NULL);
2937         if (range == NULL) {
2938                 DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2939                 goto done;
2940         }
2941
2942         if (sscanf(range, "%u - %u", low, high) != 2) {
2943                 DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2944                           range, domain_name));
2945                 goto done;
2946         }
2947
2948         ret = true;
2949
2950 done:
2951         talloc_free(config_option);
2952         return ret;
2953
2954 }
2955
2956 bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2957 {
2958         return lp_idmap_range("*", low, high);
2959 }
2960
2961 const char *lp_idmap_backend(const char *domain_name)
2962 {
2963         char *config_option = NULL;
2964         const char *backend = NULL;
2965
2966         if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2967                 domain_name = "*";
2968         }
2969
2970         config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2971                                         domain_name);
2972         if (config_option == NULL) {
2973                 DEBUG(0, ("out of memory\n"));
2974                 return false;
2975         }
2976
2977         backend = lp_parm_const_string(-1, config_option, "backend", NULL);
2978         if (backend == NULL) {
2979                 DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
2980                 goto done;
2981         }
2982
2983 done:
2984         talloc_free(config_option);
2985         return backend;
2986 }
2987
2988 const char *lp_idmap_default_backend(void)
2989 {
2990         return lp_idmap_backend("*");
2991 }
2992
2993 /***************************************************************************
2994  Handle the DEBUG level list.
2995 ***************************************************************************/
2996
2997 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2998 {
2999         string_set(ptr, pszParmValueIn);
3000         return debug_parse_levels(pszParmValueIn);
3001 }
3002
3003 /***************************************************************************
3004  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3005 ***************************************************************************/
3006
3007 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
3008 {
3009         const char *suffix_string;
3010
3011         suffix_string = talloc_asprintf(ctx, "%s,%s", str,
3012                                         Globals.ldap_suffix );
3013         if ( !suffix_string ) {
3014                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3015                 return "";
3016         }
3017
3018         return suffix_string;
3019 }
3020
3021 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
3022 {
3023         if (Globals.szLdapMachineSuffix[0])
3024                 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
3025
3026         return lp_string(ctx, Globals.ldap_suffix);
3027 }
3028
3029 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
3030 {
3031         if (Globals.szLdapUserSuffix[0])
3032                 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3033
3034         return lp_string(ctx, Globals.ldap_suffix);
3035 }
3036
3037 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3038 {
3039         if (Globals.szLdapGroupSuffix[0])
3040                 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3041
3042         return lp_string(ctx, Globals.ldap_suffix);
3043 }
3044
3045 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3046 {
3047         if (Globals.szLdapIdmapSuffix[0])
3048                 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3049
3050         return lp_string(ctx, Globals.ldap_suffix);
3051 }
3052
3053 /****************************************************************************
3054  set the value for a P_ENUM
3055  ***************************************************************************/
3056
3057 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3058                               int *ptr )
3059 {
3060         int i;
3061
3062         for (i = 0; parm->enum_list[i].name; i++) {
3063                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3064                         *ptr = parm->enum_list[i].value;
3065                         return;
3066                 }
3067         }
3068         DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3069                   pszParmValue, parm->label));
3070 }
3071
3072 /***************************************************************************
3073 ***************************************************************************/
3074
3075 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3076 {
3077         static int parm_num = -1;
3078         struct loadparm_service *s;
3079
3080         if ( parm_num == -1 )
3081                 parm_num = lpcfg_map_parameter( "printing" );
3082
3083         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3084
3085         if ( snum < 0 )
3086                 s = &sDefault;
3087         else
3088                 s = ServicePtrs[snum];
3089
3090         init_printer_values( s );
3091
3092         return true;
3093 }
3094
3095
3096 /***************************************************************************
3097  Initialise a copymap.
3098 ***************************************************************************/
3099
3100 static void init_copymap(struct loadparm_service *pservice)
3101 {
3102         int i;
3103
3104         TALLOC_FREE(pservice->copymap);
3105
3106         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3107         if (!pservice->copymap)
3108                 DEBUG(0,
3109                       ("Couldn't allocate copymap!! (size %d)\n",
3110                        (int)NUMPARAMETERS));
3111         else
3112                 for (i = 0; i < NUMPARAMETERS; i++)
3113                         bitmap_set(pservice->copymap, i);
3114 }
3115
3116 /**
3117   return the parameter pointer for a parameter
3118 */
3119 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3120 {
3121         if (service == NULL) {
3122                 if (parm->p_class == P_LOCAL)
3123                         return (void *)(((char *)&sDefault)+parm->offset);
3124                 else if (parm->p_class == P_GLOBAL)
3125                         return (void *)(((char *)&Globals)+parm->offset);
3126                 else return NULL;
3127         } else {
3128                 return (void *)(((char *)service) + parm->offset);
3129         }
3130 }
3131
3132 /***************************************************************************
3133  Return the local pointer to a parameter given the service number and parameter
3134 ***************************************************************************/
3135
3136 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3137 {
3138         return lp_parm_ptr(ServicePtrs[snum], parm);
3139 }
3140
3141 /***************************************************************************
3142  Process a parameter for a particular service number. If snum < 0
3143  then assume we are in the globals.
3144 ***************************************************************************/
3145
3146 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3147 {
3148         int parmnum, i;
3149         void *parm_ptr = NULL;  /* where we are going to store the result */
3150         struct parmlist_entry **opt_list;
3151
3152         parmnum = lpcfg_map_parameter(pszParmName);
3153
3154         if (parmnum < 0) {
3155                 if (strchr(pszParmName, ':') == NULL) {
3156                         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3157                                   pszParmName));
3158                         return true;
3159                 }
3160
3161                 /*
3162                  * We've got a parametric option
3163                  */
3164
3165                 opt_list = (snum < 0)
3166                         ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3167                 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3168
3169                 return true;
3170         }
3171
3172         /* if it's already been set by the command line, then we don't
3173            override here */
3174         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3175                 return true;
3176         }
3177
3178         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3179                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3180                           pszParmName));
3181         }
3182
3183         /* we might point at a service, the default service or a global */
3184         if (snum < 0) {
3185                 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3186         } else {
3187                 if (parm_table[parmnum].p_class == P_GLOBAL) {
3188                         DEBUG(0,
3189                               ("Global parameter %s found in service section!\n",
3190                                pszParmName));
3191                         return true;
3192                 }
3193                 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3194         }
3195
3196         if (snum >= 0) {
3197                 if (!ServicePtrs[snum]->copymap)
3198                         init_copymap(ServicePtrs[snum]);
3199
3200                 /* this handles the aliases - set the copymap for other entries with
3201                    the same data pointer */
3202                 for (i = 0; parm_table[i].label; i++) {
3203                         if ((parm_table[i].offset == parm_table[parmnum].offset)
3204                             && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3205                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
3206                         }
3207                 }
3208         }
3209
3210         /* if it is a special case then go ahead */
3211         if (parm_table[parmnum].special) {
3212                 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3213                                                    (char **)parm_ptr);
3214         }
3215
3216         /* now switch on the type of variable it is */
3217         switch (parm_table[parmnum].type)
3218         {
3219                 case P_BOOL:
3220                         *(bool *)parm_ptr = lp_bool(pszParmValue);
3221                         break;
3222
3223                 case P_BOOLREV:
3224                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
3225                         break;
3226
3227                 case P_INTEGER:
3228                         *(int *)parm_ptr = lp_int(pszParmValue);
3229                         break;
3230
3231                 case P_CHAR:
3232                         *(char *)parm_ptr = *pszParmValue;
3233                         break;
3234
3235                 case P_OCTAL:
3236                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3237                         if ( i != 1 ) {
3238                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3239                         }
3240                         break;
3241
3242                 case P_BYTES:
3243                 {
3244                         uint64_t val;
3245                         if (conv_str_size_error(pszParmValue, &val)) {
3246                                 if (val <= INT_MAX) {
3247                                         *(int *)parm_ptr = (int)val;
3248                                         break;
3249                                 }
3250                         }
3251
3252                         DEBUG(0,("lp_do_parameter(%s): value is not "
3253                             "a valid size specifier!\n", pszParmValue));
3254                         return false;
3255                 }
3256
3257                 case P_LIST:
3258                 case P_CMDLIST:
3259                         TALLOC_FREE(*((char ***)parm_ptr));
3260                         *(char ***)parm_ptr = str_list_make_v3(
3261                                 NULL, pszParmValue, NULL);
3262                         break;
3263
3264                 case P_STRING:
3265                         string_set((char **)parm_ptr, pszParmValue);
3266                         break;
3267
3268                 case P_USTRING:
3269                 {
3270                         char *upper_string = strupper_talloc(talloc_tos(), 
3271                                                              pszParmValue);
3272                         string_set((char **)parm_ptr, upper_string);
3273                         TALLOC_FREE(upper_string);
3274                         break;
3275                 }
3276                 case P_ENUM:
3277                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3278                         break;
3279                 case P_SEP:
3280                         break;
3281         }
3282
3283         return true;
3284 }
3285
3286 /***************************************************************************
3287 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3288 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3289 ***************************************************************************/
3290
3291 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3292 {
3293         int parmnum, i;
3294         parmnum = lpcfg_map_parameter(pszParmName);
3295         if (parmnum >= 0) {
3296                 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3297                 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3298                         return false;
3299                 }
3300                 parm_table[parmnum].flags |= FLAG_CMDLINE;
3301
3302                 /* we have to also set FLAG_CMDLINE on aliases.  Aliases must
3303                  * be grouped in the table, so we don't have to search the
3304                  * whole table */
3305                 for (i=parmnum-1;
3306                      i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3307                              && parm_table[i].p_class == parm_table[parmnum].p_class;
3308                      i--) {
3309                         parm_table[i].flags |= FLAG_CMDLINE;
3310                 }
3311                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3312                              && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3313                         parm_table[i].flags |= FLAG_CMDLINE;
3314                 }
3315
3316                 if (store_values) {
3317                         store_lp_set_cmdline(pszParmName, pszParmValue);
3318                 }
3319                 return true;
3320         }
3321
3322         /* it might be parametric */
3323         if (strchr(pszParmName, ':') != NULL) {
3324                 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3325                 if (store_values) {
3326                         store_lp_set_cmdline(pszParmName, pszParmValue);
3327                 }
3328                 return true;
3329         }
3330
3331         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
3332         return true;
3333 }
3334
3335 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3336 {
3337         return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3338 }
3339
3340 /***************************************************************************
3341  Process a parameter.
3342 ***************************************************************************/
3343
3344 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3345                          void *userdata)
3346 {
3347         if (!bInGlobalSection && bGlobalOnly)
3348                 return true;
3349
3350         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3351
3352         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3353                                 pszParmName, pszParmValue));
3354 }
3355
3356 /*
3357   set a option from the commandline in 'a=b' format. Use to support --option
3358 */
3359 bool lp_set_option(const char *option)
3360 {
3361         char *p, *s;
3362         bool ret;
3363
3364         s = talloc_strdup(NULL, option);
3365         if (!s) {
3366                 return false;
3367         }
3368
3369         p = strchr(s, '=');
3370         if (!p) {
3371                 talloc_free(s);
3372                 return false;
3373         }
3374
3375         *p = 0;
3376
3377         /* skip white spaces after the = sign */
3378         do {
3379                 p++;
3380         } while (*p == ' ');
3381
3382         ret = lp_set_cmdline(s, p);
3383         talloc_free(s);
3384         return ret;
3385 }
3386
3387 /***************************************************************************
3388  Initialize any local variables in the sDefault table, after parsing a
3389  [globals] section.
3390 ***************************************************************************/
3391
3392 static void init_locals(void)
3393 {
3394         /*
3395          * We run this check once the [globals] is parsed, to force
3396          * the VFS objects and other per-share settings we need for
3397          * the standard way a AD DC is operated.  We may change these
3398          * as our code evolves, which is why we force these settings.
3399          *
3400          * We can't do this at the end of lp_load_ex(), as by that
3401          * point the services have been loaded and they will already
3402          * have "" as their vfs objects.
3403          */
3404         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
3405                 const char **vfs_objects = lp_vfs_objects(-1);
3406                 if (!vfs_objects || !vfs_objects[0]) {
3407                         if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
3408                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
3409                         } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
3410                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
3411                         } else {
3412                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
3413                         }
3414                 }
3415
3416                 lp_do_parameter(-1, "map hidden", "no");
3417                 lp_do_parameter(-1, "map system", "no");
3418                 lp_do_parameter(-1, "map readonly", "no");
3419                 lp_do_parameter(-1, "map archive", "no");
3420                 lp_do_parameter(-1, "store dos attributes", "yes");
3421         }
3422 }
3423
3424 /***************************************************************************
3425  Process a new section (service). At this stage all sections are services.
3426  Later we'll have special sections that permit server parameters to be set.
3427  Returns true on success, false on failure.
3428 ***************************************************************************/
3429
3430 static bool do_section(const char *pszSectionName, void *userdata)
3431 {
3432         bool bRetval;
3433         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3434                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3435         bRetval = false;
3436
3437         /* if we were in a global section then do the local inits */
3438         if (bInGlobalSection && !isglobal)
3439                 init_locals();
3440
3441         /* if we've just struck a global section, note the fact. */
3442         bInGlobalSection = isglobal;
3443
3444         /* check for multiple global sections */
3445         if (bInGlobalSection) {
3446                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3447                 return true;
3448         }
3449
3450         if (!bInGlobalSection && bGlobalOnly)
3451                 return true;
3452
3453         /* if we have a current service, tidy it up before moving on */
3454         bRetval = true;
3455
3456         if (iServiceIndex >= 0)
3457                 bRetval = service_ok(iServiceIndex);
3458
3459         /* if all is still well, move to the next record in the services array */
3460         if (bRetval) {
3461                 /* We put this here to avoid an odd message order if messages are */
3462                 /* issued by the post-processing of a previous section. */
3463                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3464
3465                 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3466                 if (iServiceIndex < 0) {
3467                         DEBUG(0, ("Failed to add a new service\n"));
3468                         return false;
3469                 }
3470                 /* Clean all parametric options for service */
3471                 /* They will be added during parsing again */
3472                 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3473         }
3474
3475         return bRetval;
3476 }
3477
3478
3479 /***************************************************************************
3480  Determine if a partcular base parameter is currentl set to the default value.
3481 ***************************************************************************/
3482
3483 static bool is_default(int i)
3484 {
3485         switch (parm_table[i].type) {
3486                 case P_LIST:
3487                 case P_CMDLIST:
3488                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
3489                                               *(const char ***)lp_parm_ptr(NULL, 
3490                                                                            &parm_table[i]));
3491                 case P_STRING:
3492                 case P_USTRING:
3493                         return strequal(parm_table[i].def.svalue,
3494                                         *(char **)lp_parm_ptr(NULL, 
3495                                                               &parm_table[i]));
3496                 case P_BOOL:
3497                 case P_BOOLREV:
3498                         return parm_table[i].def.bvalue ==
3499                                 *(bool *)lp_parm_ptr(NULL, 
3500                                                      &parm_table[i]);
3501                 case P_CHAR:
3502                         return parm_table[i].def.cvalue ==
3503                                 *(char *)lp_parm_ptr(NULL, 
3504                                                      &parm_table[i]);
3505                 case P_INTEGER:
3506                 case P_OCTAL:
3507                 case P_ENUM:
3508                 case P_BYTES:
3509                         return parm_table[i].def.ivalue ==
3510                                 *(int *)lp_parm_ptr(NULL, 
3511                                                     &parm_table[i]);
3512                 case P_SEP:
3513                         break;
3514         }
3515         return false;
3516 }
3517
3518 /***************************************************************************
3519 Display the contents of the global structure.
3520 ***************************************************************************/
3521
3522 static void dump_globals(FILE *f)
3523 {
3524         int i;
3525         struct parmlist_entry *data;
3526
3527         fprintf(f, "[global]\n");
3528
3529         for (i = 0; parm_table[i].label; i++)
3530                 if (parm_table[i].p_class == P_GLOBAL &&
3531                     !(parm_table[i].flags & FLAG_META) &&
3532                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3533                         if (defaults_saved && is_default(i))
3534                                 continue;
3535                         fprintf(f, "\t%s = ", parm_table[i].label);
3536                         lpcfg_print_parameter(&parm_table[i], lp_parm_ptr(NULL,
3537                                                                           &parm_table[i]),
3538                                         f);
3539                         fprintf(f, "\n");
3540         }
3541         if (Globals.param_opt != NULL) {
3542                 data = Globals.param_opt;
3543                 while(data) {
3544                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3545                         data = data->next;
3546                 }
3547         }
3548
3549 }
3550
3551 /***************************************************************************
3552  Display the contents of a single services record.
3553 ***************************************************************************/
3554
3555 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3556 {
3557         int i;
3558         struct parmlist_entry *data;
3559
3560         if (pService != &sDefault)
3561                 fprintf(f, "[%s]\n", pService->szService);
3562
3563         for (i = 0; parm_table[i].label; i++) {
3564
3565                 if (parm_table[i].p_class == P_LOCAL &&
3566                     !(parm_table[i].flags & FLAG_META) &&
3567                     (*parm_table[i].label != '-') &&
3568                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
3569                 {
3570                         if (pService == &sDefault) {
3571                                 if (defaults_saved && is_default(i))
3572                                         continue;
3573                         } else {
3574                                 if (lpcfg_equal_parameter(parm_table[i].type,
3575                                                           lp_parm_ptr(pService, &parm_table[i]),
3576                                                           lp_parm_ptr(NULL, &parm_table[i])))
3577                                         continue;
3578                         }
3579
3580                         fprintf(f, "\t%s = ", parm_table[i].label);
3581                         lpcfg_print_parameter(&parm_table[i],
3582                                         lp_parm_ptr(pService, &parm_table[i]),
3583                                         f);
3584                         fprintf(f, "\n");
3585                 }
3586         }
3587
3588                 if (pService->param_opt != NULL) {
3589                         data = pService->param_opt;
3590                         while(data) {
3591                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
3592                                 data = data->next;
3593                         }
3594                 }
3595 }
3596
3597 /***************************************************************************
3598  Display the contents of a parameter of a single services record.
3599 ***************************************************************************/
3600
3601 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3602 {
3603         bool result = false;
3604         fstring local_parm_name;
3605         char *parm_opt;
3606         const char *parm_opt_value;
3607
3608         struct loadparm_context *lp_ctx;
3609
3610         /* check for parametrical option */
3611         fstrcpy( local_parm_name, parm_name);
3612         parm_opt = strchr( local_parm_name, ':');
3613
3614         if (parm_opt) {
3615                 *parm_opt = '\0';
3616                 parm_opt++;
3617                 if (strlen(parm_opt)) {
3618                         parm_opt_value = lp_parm_const_string( snum,
3619                                 local_parm_name, parm_opt, NULL);
3620                         if (parm_opt_value) {
3621                                 printf( "%s\n", parm_opt_value);
3622                                 result = true;
3623                         }
3624                 }
3625                 return result;
3626         }
3627
3628         lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
3629         if (lp_ctx == NULL) {
3630                 return false;
3631         }
3632
3633         if (isGlobal) {
3634                 result = lpcfg_dump_a_parameter(lp_ctx, NULL, parm_name, f);
3635         } else {
3636                 result = lpcfg_dump_a_parameter(lp_ctx, ServicePtrs[snum], parm_name, f);
3637         }
3638         TALLOC_FREE(lp_ctx);
3639         return result;
3640 }
3641
3642 /***************************************************************************
3643  Return info about the requested parameter (given as a string).
3644  Return NULL when the string is not a valid parameter name.
3645 ***************************************************************************/
3646
3647 struct parm_struct *lp_get_parameter(const char *param_name)
3648 {
3649         int num = lpcfg_map_parameter(param_name);
3650
3651         if (num < 0) {
3652                 return NULL;
3653         }
3654
3655         return &parm_table[num];
3656 }
3657
3658 #if 0
3659 /***************************************************************************
3660  Display the contents of a single copy structure.
3661 ***************************************************************************/
3662 static void dump_copy_map(bool *pcopymap)
3663 {
3664 &nb