lib/param: rename getservicebyname to lpcfg_getservicebyname to avoid conflicts
[mat/samba.git] / lib / 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) James Myers 2003 <myersjj@samba.org>
13    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14    Copyright (C) Andrew Bartlett 2011-2012
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 "version.h"
58 #include "dynconfig/dynconfig.h"
59 #include "system/time.h"
60 #include "system/locale.h"
61 #include "system/network.h" /* needed for TCP_NODELAY */
62 #include "../lib/util/dlinklist.h"
63 #include "lib/param/param.h"
64 #include "lib/param/loadparm.h"
65 #include "auth/gensec/gensec.h"
66 #include "lib/param/s3_param.h"
67 #include "lib/util/bitmap.h"
68 #include "libcli/smb/smb_constants.h"
69 #include "tdb.h"
70
71 #define standard_sub_basic talloc_strdup
72
73 static bool do_parameter(const char *, const char *, void *);
74 static bool defaults_saved = false;
75
76 #include "lib/param/param_global.h"
77
78 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
79
80 /* we don't need a special handler for "dos charset" and "unix charset" */
81 #define handle_dos_charset NULL
82 #define handle_charset NULL
83
84 /* these are parameter handlers which are not needed in the
85  * non-source3 code
86  */
87 #define handle_netbios_aliases NULL
88 #define handle_printing NULL
89 #define handle_ldap_debug_level NULL
90 #define handle_idmap_backend NULL
91 #define handle_idmap_uid NULL
92 #define handle_idmap_gid NULL
93
94 #ifndef N_
95 #define N_(x) x
96 #endif
97
98 /* prototypes for the special type handlers */
99 static bool handle_include(struct loadparm_context *lp_ctx, int unused,
100                            const char *pszParmValue, char **ptr);
101 static bool handle_copy(struct loadparm_context *lp_ctx, int unused,
102                         const char *pszParmValue, char **ptr);
103
104 #include "lib/param/param_table.c"
105
106 /* local variables */
107 struct loadparm_context {
108         const char *szConfigFile;
109         struct loadparm_global *globals;
110         struct loadparm_service **services;
111         struct loadparm_service *sDefault;
112         struct smb_iconv_handle *iconv_handle;
113         int iNumServices;
114         struct loadparm_service *currentService;
115         bool bInGlobalSection;
116         struct file_lists {
117                 struct file_lists *next;
118                 char *name;
119                 char *subfname;
120                 time_t modtime;
121         } *file_lists;
122         unsigned int flags[NUMPARAMETERS];
123         bool loaded;
124         bool refuse_free;
125         bool global; /* Is this the global context, which may set
126                       * global variables such as debug level etc? */
127         const struct loadparm_s3_helpers *s3_fns;
128 };
129
130
131 struct loadparm_service *lpcfg_default_service(struct loadparm_context *lp_ctx)
132 {
133         if (lp_ctx->s3_fns) {
134                 return lp_ctx->s3_fns->get_default_loadparm_service();
135         }
136         return lp_ctx->sDefault;
137 }
138
139 /**
140  * Convenience routine to grab string parameters into temporary memory
141  * and run standard_sub_basic on them.
142  *
143  * The buffers can be written to by
144  * callers without affecting the source string.
145  */
146
147 static const char *lpcfg_string(const char *s)
148 {
149 #if 0  /* until REWRITE done to make thread-safe */
150         size_t len = s ? strlen(s) : 0;
151         char *ret;
152 #endif
153
154         /* The follow debug is useful for tracking down memory problems
155            especially if you have an inner loop that is calling a lp_*()
156            function that returns a string.  Perhaps this debug should be
157            present all the time? */
158
159 #if 0
160         DEBUG(10, ("lpcfg_string(%s)\n", s));
161 #endif
162
163 #if 0  /* until REWRITE done to make thread-safe */
164         if (!lp_talloc)
165                 lp_talloc = talloc_init("lp_talloc");
166
167         ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
168
169         if (!ret)
170                 return NULL;
171
172         if (!s)
173                 *ret = 0;
174         else
175                 strlcpy(ret, s, len);
176
177         if (trim_string(ret, "\"", "\"")) {
178                 if (strchr(ret,'"') != NULL)
179                         strlcpy(ret, s, len);
180         }
181
182         standard_sub_basic(ret,len+100);
183         return (ret);
184 #endif
185         return s;
186 }
187
188 /*
189    In this section all the functions that are used to access the
190    parameters from the rest of the program are defined
191 */
192
193 /*
194  * the creation of separate lpcfg_*() and lp_*() functions is to allow
195  * for code compatibility between existing Samba4 and Samba3 code.
196  */
197
198 /* this global context supports the lp_*() function varients */
199 static struct loadparm_context *global_loadparm_context;
200
201 #define lpcfg_default_service global_loadparm_context->sDefault
202 #define lpcfg_global_service(i) global_loadparm_context->services[i]
203
204 #define FN_GLOBAL_STRING(fn_name,var_name) \
205  _PUBLIC_ char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx, TALLOC_CTX *ctx) {\
206          if (lp_ctx == NULL) return NULL;                               \
207          if (lp_ctx->s3_fns) {                                          \
208                  return lp_ctx->globals->var_name ? lp_ctx->s3_fns->lp_string(ctx, lp_ctx->globals->var_name) : talloc_strdup(ctx, ""); \
209          }                                                              \
210          return lp_ctx->globals->var_name ? talloc_strdup(ctx, lpcfg_string(lp_ctx->globals->var_name)) : talloc_strdup(ctx, ""); \
211 }
212
213 #define FN_GLOBAL_CONST_STRING(fn_name,var_name)                                \
214  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
215         if (lp_ctx == NULL) return NULL;                                \
216         return lp_ctx->globals->var_name ? lpcfg_string(lp_ctx->globals->var_name) : ""; \
217 }
218
219 #define FN_GLOBAL_LIST(fn_name,var_name)                                \
220  _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
221          if (lp_ctx == NULL) return NULL;                               \
222          return lp_ctx->globals->var_name;                              \
223  }
224
225 #define FN_GLOBAL_BOOL(fn_name,var_name) \
226  _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {\
227          if (lp_ctx == NULL) return false;                              \
228          return lp_ctx->globals->var_name;                              \
229 }
230
231 #define FN_GLOBAL_INTEGER(fn_name,var_name) \
232  _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
233          return lp_ctx->globals->var_name;                              \
234  }
235
236 /* Local parameters don't need the ->s3_fns because the struct
237  * loadparm_service is shared and lpcfg_service() checks the ->s3_fns
238  * hook */
239 #define FN_LOCAL_STRING(fn_name,val) \
240  _PUBLIC_ char *lpcfg_ ## fn_name(struct loadparm_service *service, \
241                                         struct loadparm_service *sDefault, TALLOC_CTX *ctx) { \
242          return(talloc_strdup(ctx, lpcfg_string((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault->val)))); \
243  }
244
245 #define FN_LOCAL_CONST_STRING(fn_name,val) \
246  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_service *service, \
247                                         struct loadparm_service *sDefault) { \
248          return((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault->val)); \
249  }
250
251 #define FN_LOCAL_LIST(fn_name,val) \
252  _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_service *service, \
253                                          struct loadparm_service *sDefault) {\
254          return(const char **)(service != NULL && service->val != NULL? service->val : sDefault->val); \
255  }
256
257 #define FN_LOCAL_PARM_BOOL(fn_name, val) FN_LOCAL_BOOL(fn_name, val)
258
259 #define FN_LOCAL_BOOL(fn_name,val) \
260  _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_service *service, \
261                                  struct loadparm_service *sDefault) {   \
262          return((service != NULL)? service->val : sDefault->val); \
263  }
264
265 #define FN_LOCAL_INTEGER(fn_name,val) \
266  _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_service *service, \
267                                 struct loadparm_service *sDefault) {    \
268          return((service != NULL)? service->val : sDefault->val); \
269  }
270
271 #define FN_LOCAL_PARM_INTEGER(fn_name, val) FN_LOCAL_INTEGER(fn_name, val)
272
273 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
274  _PUBLIC_ char lpcfg_ ## fn_name(struct loadparm_service *service, \
275                                 struct loadparm_service *sDefault) {    \
276          return((service != NULL)? service->val : sDefault->val); \
277  }
278
279 #include "lib/param/param_functions.c"
280
281 /* These functions cannot be auto-generated */
282 FN_LOCAL_BOOL(autoloaded, autoloaded)
283 FN_GLOBAL_CONST_STRING(dnsdomain, dnsdomain)
284
285 /* local prototypes */
286 static struct loadparm_service *lpcfg_getservicebyname(struct loadparm_context *lp_ctx,
287                                         const char *pszServiceName);
288 static bool lpcfg_service_ok(struct loadparm_service *service);
289 static bool do_section(const char *pszSectionName, void *);
290 static void init_copymap(struct loadparm_service *pservice);
291
292 /* This is a helper function for parametrical options support. */
293 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
294 /* Actual parametrical functions are quite simple */
295 const char *lpcfg_get_parametric(struct loadparm_context *lp_ctx,
296                               struct loadparm_service *service,
297                               const char *type, const char *option)
298 {
299         char *vfskey_tmp = NULL;
300         char *vfskey = NULL;
301         struct parmlist_entry *data;
302
303         if (lp_ctx == NULL)
304                 return NULL;
305
306         if (lp_ctx->s3_fns) {
307                 return lp_ctx->s3_fns->get_parametric(service, type, option);
308         }
309
310         data = (service == NULL ? lp_ctx->globals->param_opt : service->param_opt);
311
312         vfskey_tmp = talloc_asprintf(NULL, "%s:%s", type, option);
313         if (vfskey_tmp == NULL) return NULL;
314         vfskey = strlower_talloc(NULL, vfskey_tmp);
315         talloc_free(vfskey_tmp);
316
317         while (data) {
318                 if (strcmp(data->key, vfskey) == 0) {
319                         talloc_free(vfskey);
320                         return data->value;
321                 }
322                 data = data->next;
323         }
324
325         if (service != NULL) {
326                 /* Try to fetch the same option but from globals */
327                 /* but only if we are not already working with globals */
328                 for (data = lp_ctx->globals->param_opt; data;
329                      data = data->next) {
330                         if (strcmp(data->key, vfskey) == 0) {
331                                 talloc_free(vfskey);
332                                 return data->value;
333                         }
334                 }
335         }
336
337         talloc_free(vfskey);
338
339         return NULL;
340 }
341
342
343 /**
344  * convenience routine to return int parameters.
345  */
346 static int lp_int(const char *s)
347 {
348
349         if (!s) {
350                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
351                 return -1;
352         }
353
354         return strtol(s, NULL, 0);
355 }
356
357 /**
358  * convenience routine to return unsigned long parameters.
359  */
360 static unsigned long lp_ulong(const char *s)
361 {
362
363         if (!s) {
364                 DEBUG(0,("lp_ulong(%s): is called with NULL!\n",s));
365                 return -1;
366         }
367
368         return strtoul(s, NULL, 0);
369 }
370
371 /**
372  * convenience routine to return unsigned long parameters.
373  */
374 static long lp_long(const char *s)
375 {
376
377         if (!s) {
378                 DEBUG(0,("lp_long(%s): is called with NULL!\n",s));
379                 return -1;
380         }
381
382         return strtol(s, NULL, 0);
383 }
384
385 /**
386  * convenience routine to return unsigned long parameters.
387  */
388 static double lp_double(const char *s)
389 {
390
391         if (!s) {
392                 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
393                 return -1;
394         }
395
396         return strtod(s, NULL);
397 }
398
399 /**
400  * convenience routine to return boolean parameters.
401  */
402 static bool lp_bool(const char *s)
403 {
404         bool ret = false;
405
406         if (!s) {
407                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
408                 return false;
409         }
410
411         if (!set_boolean(s, &ret)) {
412                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
413                 return false;
414         }
415
416         return ret;
417 }
418
419
420 /**
421  * Return parametric option from a given service. Type is a part of option before ':'
422  * Parametric option has following syntax: 'Type: option = value'
423  * Returned value is allocated in 'lp_talloc' context
424  */
425
426 const char *lpcfg_parm_string(struct loadparm_context *lp_ctx,
427                               struct loadparm_service *service, const char *type,
428                               const char *option)
429 {
430         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
431
432         if (value)
433                 return lpcfg_string(value);
434
435         return NULL;
436 }
437
438 /**
439  * Return parametric option from a given service. Type is a part of option before ':'
440  * Parametric option has following syntax: 'Type: option = value'
441  * Returned value is allocated in 'lp_talloc' context
442  */
443
444 const char **lpcfg_parm_string_list(TALLOC_CTX *mem_ctx,
445                                     struct loadparm_context *lp_ctx,
446                                     struct loadparm_service *service,
447                                     const char *type,
448                                     const char *option, const char *separator)
449 {
450         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
451
452         if (value != NULL)
453                 return (const char **)str_list_make(mem_ctx, value, separator);
454
455         return NULL;
456 }
457
458 /**
459  * Return parametric option from a given service. Type is a part of option before ':'
460  * Parametric option has following syntax: 'Type: option = value'
461  */
462
463 int lpcfg_parm_int(struct loadparm_context *lp_ctx,
464                    struct loadparm_service *service, const char *type,
465                    const char *option, int default_v)
466 {
467         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
468
469         if (value)
470                 return lp_int(value);
471
472         return default_v;
473 }
474
475 /**
476  * Return parametric option from a given service. Type is a part of
477  * option before ':'.
478  * Parametric option has following syntax: 'Type: option = value'.
479  */
480
481 int lpcfg_parm_bytes(struct loadparm_context *lp_ctx,
482                   struct loadparm_service *service, const char *type,
483                   const char *option, int default_v)
484 {
485         uint64_t bval;
486
487         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
488
489         if (value && conv_str_size_error(value, &bval)) {
490                 if (bval <= INT_MAX) {
491                         return (int)bval;
492                 }
493         }
494
495         return default_v;
496 }
497
498 /**
499  * Return parametric option from a given service.
500  * Type is a part of option before ':'
501  * Parametric option has following syntax: 'Type: option = value'
502  */
503 unsigned long lpcfg_parm_ulong(struct loadparm_context *lp_ctx,
504                             struct loadparm_service *service, const char *type,
505                             const char *option, unsigned long default_v)
506 {
507         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
508
509         if (value)
510                 return lp_ulong(value);
511
512         return default_v;
513 }
514
515 long lpcfg_parm_long(struct loadparm_context *lp_ctx,
516                      struct loadparm_service *service, const char *type,
517                      const char *option, long default_v)
518 {
519         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
520
521         if (value)
522                 return lp_long(value);
523
524         return default_v;
525 }
526
527 double lpcfg_parm_double(struct loadparm_context *lp_ctx,
528                       struct loadparm_service *service, const char *type,
529                       const char *option, double default_v)
530 {
531         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
532
533         if (value != NULL)
534                 return lp_double(value);
535
536         return default_v;
537 }
538
539 /**
540  * Return parametric option from a given service. Type is a part of option before ':'
541  * Parametric option has following syntax: 'Type: option = value'
542  */
543
544 bool lpcfg_parm_bool(struct loadparm_context *lp_ctx,
545                      struct loadparm_service *service, const char *type,
546                      const char *option, bool default_v)
547 {
548         const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
549
550         if (value != NULL)
551                 return lp_bool(value);
552
553         return default_v;
554 }
555
556
557 /**
558  * Set a string value, deallocating any existing space, and allocing the space
559  * for the string
560  */
561 static bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
562 {
563         talloc_free(*dest);
564
565         if (src == NULL)
566                 src = "";
567
568         *dest = talloc_strdup(mem_ctx, src);
569         if ((*dest) == NULL) {
570                 DEBUG(0,("Out of memory in string_set\n"));
571                 return false;
572         }
573
574         return true;
575 }
576
577 /**
578  * Set a string value, deallocating any existing space, and allocing the space
579  * for the string
580  */
581 static bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
582 {
583         talloc_free(*dest);
584
585         if (src == NULL)
586                 src = "";
587
588         *dest = strupper_talloc(mem_ctx, src);
589         if ((*dest) == NULL) {
590                 DEBUG(0,("Out of memory in string_set_upper\n"));
591                 return false;
592         }
593
594         return true;
595 }
596
597
598
599 /**
600  * Add a new service to the services array initialising it with the given
601  * service.
602  */
603
604 struct loadparm_service *lpcfg_add_service(struct loadparm_context *lp_ctx,
605                                            const struct loadparm_service *pservice,
606                                            const char *name)
607 {
608         int i;
609         int num_to_alloc = lp_ctx->iNumServices + 1;
610         struct parmlist_entry *data, *pdata;
611
612         if (pservice == NULL) {
613                 pservice = lp_ctx->sDefault;
614         }
615
616         /* it might already exist */
617         if (name) {
618                 struct loadparm_service *service = lpcfg_getservicebyname(lp_ctx,
619                                                                     name);
620                 if (service != NULL) {
621                         /* Clean all parametric options for service */
622                         /* They will be added during parsing again */
623                         data = service->param_opt;
624                         while (data) {
625                                 pdata = data->next;
626                                 talloc_free(data);
627                                 data = pdata;
628                         }
629                         service->param_opt = NULL;
630                         return service;
631                 }
632         }
633
634         /* find an invalid one */
635         for (i = 0; i < lp_ctx->iNumServices; i++)
636                 if (lp_ctx->services[i] == NULL)
637                         break;
638
639         /* if not, then create one */
640         if (i == lp_ctx->iNumServices) {
641                 struct loadparm_service **tsp;
642
643                 tsp = talloc_realloc(lp_ctx, lp_ctx->services, struct loadparm_service *, num_to_alloc);
644
645                 if (!tsp) {
646                         DEBUG(0,("lpcfg_add_service: failed to enlarge services!\n"));
647                         return NULL;
648                 } else {
649                         lp_ctx->services = tsp;
650                         lp_ctx->services[lp_ctx->iNumServices] = NULL;
651                 }
652
653                 lp_ctx->iNumServices++;
654         }
655
656         lp_ctx->services[i] = talloc_zero(lp_ctx->services, struct loadparm_service);
657         if (lp_ctx->services[i] == NULL) {
658                 DEBUG(0,("lpcfg_add_service: out of memory!\n"));
659                 return NULL;
660         }
661         copy_service(lp_ctx->services[i], pservice, NULL);
662         if (name != NULL)
663                 lpcfg_string_set(lp_ctx->services[i], &lp_ctx->services[i]->szService, name);
664         return lp_ctx->services[i];
665 }
666
667 /**
668  * Add a new home service, with the specified home directory, defaults coming
669  * from service ifrom.
670  */
671
672 bool lpcfg_add_home(struct loadparm_context *lp_ctx,
673                  const char *pszHomename,
674                  struct loadparm_service *default_service,
675                  const char *user, const char *pszHomedir)
676 {
677         struct loadparm_service *service;
678
679         service = lpcfg_add_service(lp_ctx, default_service, pszHomename);
680
681         if (service == NULL)
682                 return false;
683
684         if (!(*(default_service->path))
685             || strequal(default_service->path, lp_ctx->sDefault->path)) {
686                 service->path = talloc_strdup(service, pszHomedir);
687         } else {
688                 service->path = string_sub_talloc(service, lpcfg_path(default_service, lp_ctx->sDefault, service), "%H", pszHomedir);
689         }
690
691         if (!(*(service->comment))) {
692                 service->comment = talloc_asprintf(service, "Home directory of %s", user);
693         }
694         service->bAvailable = default_service->bAvailable;
695         service->browseable = default_service->browseable;
696
697         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n",
698                   pszHomename, user, service->path));
699
700         return true;
701 }
702
703 /**
704  * Add a new printer service, with defaults coming from service iFrom.
705  */
706
707 bool lpcfg_add_printer(struct loadparm_context *lp_ctx,
708                        const char *pszPrintername,
709                        struct loadparm_service *default_service)
710 {
711         const char *comment = "From Printcap";
712         struct loadparm_service *service;
713         service = lpcfg_add_service(lp_ctx, default_service, pszPrintername);
714
715         if (service == NULL)
716                 return false;
717
718         /* note that we do NOT default the availability flag to True - */
719         /* we take it from the default service passed. This allows all */
720         /* dynamic printers to be disabled by disabling the [printers] */
721         /* entry (if/when the 'available' keyword is implemented!).    */
722
723         /* the printer name is set to the service name. */
724         lpcfg_string_set(service, &service->_printername, pszPrintername);
725         lpcfg_string_set(service, &service->comment, comment);
726         service->browseable = default_service->browseable;
727         /* Printers cannot be read_only. */
728         service->read_only = false;
729         /* Printer services must be printable. */
730         service->printable = true;
731
732         DEBUG(3, ("adding printer service %s\n", pszPrintername));
733
734         return true;
735 }
736
737 /**
738  * Map a parameter's string representation to something we can use.
739  * Returns False if the parameter string is not recognised, else TRUE.
740  */
741
742 int lpcfg_map_parameter(const char *pszParmName)
743 {
744         int iIndex;
745
746         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
747                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
748                         return iIndex;
749
750         /* Warn only if it isn't parametric option */
751         if (strchr(pszParmName, ':') == NULL)
752                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
753         /* We do return 'fail' for parametric options as well because they are
754            stored in different storage
755          */
756         return -1;
757 }
758
759
760 /**
761   return the parameter structure for a parameter
762 */
763 struct parm_struct *lpcfg_parm_struct(struct loadparm_context *lp_ctx, const char *name)
764 {
765         int parmnum;
766
767         if (lp_ctx->s3_fns) {
768                 return lp_ctx->s3_fns->get_parm_struct(name);
769         }
770
771         parmnum = lpcfg_map_parameter(name);
772         if (parmnum == -1) return NULL;
773         return &parm_table[parmnum];
774 }
775
776 /**
777   return the parameter pointer for a parameter
778 */
779 void *lpcfg_parm_ptr(struct loadparm_context *lp_ctx,
780                   struct loadparm_service *service, struct parm_struct *parm)
781 {
782         if (lp_ctx->s3_fns) {
783                 return lp_ctx->s3_fns->get_parm_ptr(service, parm);
784         }
785
786         if (service == NULL) {
787                 if (parm->p_class == P_LOCAL)
788                         return ((char *)lp_ctx->sDefault)+parm->offset;
789                 else if (parm->p_class == P_GLOBAL)
790                         return ((char *)lp_ctx->globals)+parm->offset;
791                 else return NULL;
792         } else {
793                 return ((char *)service) + parm->offset;
794         }
795 }
796
797 /**
798   return the parameter pointer for a parameter
799 */
800 bool lpcfg_parm_is_cmdline(struct loadparm_context *lp_ctx, const char *name)
801 {
802         int parmnum;
803
804         if (lp_ctx->s3_fns) {
805                 struct parm_struct *parm = lp_ctx->s3_fns->get_parm_struct(name);
806                 if (parm) {
807                         return parm->flags & FLAG_CMDLINE;
808                 }
809                 return false;
810         }
811
812         parmnum = lpcfg_map_parameter(name);
813         if (parmnum == -1) return false;
814
815         return lp_ctx->flags[parmnum] & FLAG_CMDLINE;
816 }
817
818 /**
819  * Find a service by name. Otherwise works like get_service.
820  */
821
822 static struct loadparm_service *lpcfg_getservicebyname(struct loadparm_context *lp_ctx,
823                                         const char *pszServiceName)
824 {
825         int iService;
826
827         if (lp_ctx->s3_fns) {
828                 return lp_ctx->s3_fns->get_service(pszServiceName);
829         }
830
831         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
832                 if (lp_ctx->services[iService] != NULL &&
833                     strwicmp(lp_ctx->services[iService]->szService, pszServiceName) == 0) {
834                         return lp_ctx->services[iService];
835                 }
836
837         return NULL;
838 }
839
840 /**
841  * Add a parametric option to a parmlist_entry,
842  * replacing old value, if already present.
843  */
844 void set_param_opt(TALLOC_CTX *mem_ctx,
845                    struct parmlist_entry **opt_list,
846                    const char *opt_name,
847                    const char *opt_value,
848                    unsigned priority)
849 {
850         struct parmlist_entry *new_opt, *opt;
851         bool not_added;
852
853         opt = *opt_list;
854         not_added = true;
855
856         /* Traverse destination */
857         while (opt) {
858                 /* If we already have same option, override it */
859                 if (strwicmp(opt->key, opt_name) == 0) {
860                         if ((opt->priority & FLAG_CMDLINE) &&
861                             !(priority & FLAG_CMDLINE)) {
862                                 /* it's been marked as not to be
863                                    overridden */
864                                 return;
865                         }
866                         TALLOC_FREE(opt->value);
867                         TALLOC_FREE(opt->list);
868                         opt->value = talloc_strdup(opt, opt_value);
869                         opt->priority = priority;
870                         not_added = false;
871                         break;
872                 }
873                 opt = opt->next;
874         }
875         if (not_added) {
876                 new_opt = talloc(mem_ctx, struct parmlist_entry);
877                 if (new_opt == NULL) {
878                         smb_panic("OOM");
879                 }
880
881                 new_opt->key = talloc_strdup(new_opt, opt_name);
882                 if (new_opt->key == NULL) {
883                         smb_panic("talloc_strdup failed");
884                 }
885
886                 new_opt->value = talloc_strdup(new_opt, opt_value);
887                 if (new_opt->value == NULL) {
888                         smb_panic("talloc_strdup failed");
889                 }
890
891                 new_opt->list = NULL;
892                 new_opt->priority = priority;
893                 DLIST_ADD(*opt_list, new_opt);
894         }
895 }
896
897 /**
898  * Copy a service structure to another.
899  * If pcopymapDest is NULL then copy all fields
900  */
901
902 void copy_service(struct loadparm_service *pserviceDest,
903                   const struct loadparm_service *pserviceSource,
904                   struct bitmap *pcopymapDest)
905 {
906         int i;
907         bool bcopyall = (pcopymapDest == NULL);
908         struct parmlist_entry *data;
909
910         for (i = 0; parm_table[i].label; i++)
911                 if (parm_table[i].p_class == P_LOCAL &&
912                     (bcopyall || bitmap_query(pcopymapDest, i))) {
913                         const void *src_ptr =
914                                 ((const char *)pserviceSource) + parm_table[i].offset;
915                         void *dest_ptr =
916                                 ((char *)pserviceDest) + parm_table[i].offset;
917
918                         switch (parm_table[i].type) {
919                                 case P_BOOL:
920                                 case P_BOOLREV:
921                                         *(bool *)dest_ptr = *(const bool *)src_ptr;
922                                         break;
923
924                                 case P_INTEGER:
925                                 case P_BYTES:
926                                 case P_OCTAL:
927                                 case P_ENUM:
928                                         *(int *)dest_ptr = *(const int *)src_ptr;
929                                         break;
930
931                                 case P_CHAR:
932                                         *(char *)dest_ptr = *(const char *)src_ptr;
933                                         break;
934
935                                 case P_STRING:
936                                         lpcfg_string_set(pserviceDest,
937                                                    (char **)dest_ptr,
938                                                    *(const char * const *)src_ptr);
939                                         break;
940
941                                 case P_USTRING:
942                                         lpcfg_string_set_upper(pserviceDest,
943                                                          (char **)dest_ptr,
944                                                          *(const char * const *)src_ptr);
945                                         break;
946                                 case P_LIST:
947                                         TALLOC_FREE(*((char ***)dest_ptr));
948                                         *(const char * const **)dest_ptr = (const char * const *)str_list_copy(pserviceDest,
949                                                                                   *(const char * * const *)src_ptr);
950                                         break;
951                                 default:
952                                         break;
953                         }
954                 }
955
956         if (bcopyall) {
957                 init_copymap(pserviceDest);
958                 if (pserviceSource->copymap)
959                         bitmap_copy(pserviceDest->copymap,
960                                     pserviceSource->copymap);
961         }
962
963         for (data = pserviceSource->param_opt; data != NULL; data = data->next) {
964                 set_param_opt(pserviceDest, &pserviceDest->param_opt,
965                               data->key, data->value, data->priority);
966         }
967 }
968
969 /**
970  * Check a service for consistency. Return False if the service is in any way
971  * incomplete or faulty, else True.
972  */
973 static bool lpcfg_service_ok(struct loadparm_service *service)
974 {
975         bool bRetval;
976
977         bRetval = true;
978         if (service->szService[0] == '\0') {
979                 DEBUG(0, ("The following message indicates an internal error:\n"));
980                 DEBUG(0, ("No service name in service entry.\n"));
981                 bRetval = false;
982         }
983
984         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
985         /* I can't see why you'd want a non-printable printer service...        */
986         if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
987                 if (!service->printable) {
988                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
989                                service->szService));
990                         service->printable = true;
991                 }
992                 /* [printers] service must also be non-browsable. */
993                 if (service->browseable)
994                         service->browseable = false;
995         }
996
997         /* If a service is flagged unavailable, log the fact at level 0. */
998         if (!service->bAvailable)
999                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1000                           service->szService));
1001
1002         return bRetval;
1003 }
1004
1005
1006 /*******************************************************************
1007  Keep a linked list of all config files so we know when one has changed
1008  it's date and needs to be reloaded.
1009 ********************************************************************/
1010
1011 static void add_to_file_list(struct loadparm_context *lp_ctx,
1012                              const char *fname, const char *subfname)
1013 {
1014         struct file_lists *f = lp_ctx->file_lists;
1015
1016         while (f) {
1017                 if (f->name && !strcmp(f->name, fname))
1018                         break;
1019                 f = f->next;
1020         }
1021
1022         if (!f) {
1023                 f = talloc(lp_ctx, struct file_lists);
1024                 if (!f)
1025                         return;
1026                 f->next = lp_ctx->file_lists;
1027                 f->name = talloc_strdup(f, fname);
1028                 if (!f->name) {
1029                         talloc_free(f);
1030                         return;
1031                 }
1032                 f->subfname = talloc_strdup(f, subfname);
1033                 if (!f->subfname) {
1034                         talloc_free(f);
1035                         return;
1036                 }
1037                 lp_ctx->file_lists = f;
1038                 f->modtime = file_modtime(subfname);
1039         } else {
1040                 time_t t = file_modtime(subfname);
1041                 if (t)
1042                         f->modtime = t;
1043         }
1044 }
1045
1046 /*******************************************************************
1047  Check if a config file has changed date.
1048 ********************************************************************/
1049 bool lpcfg_file_list_changed(struct loadparm_context *lp_ctx)
1050 {
1051         struct file_lists *f;
1052         DEBUG(6, ("lpcfg_file_list_changed()\n"));
1053
1054         for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
1055                 char *n2;
1056                 time_t mod_time;
1057
1058                 n2 = standard_sub_basic(lp_ctx, f->name);
1059
1060                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
1061                              f->name, n2, ctime(&f->modtime)));
1062
1063                 mod_time = file_modtime(n2);
1064
1065                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1066                         DEBUGADD(6, ("file %s modified: %s\n", n2,
1067                                   ctime(&mod_time)));
1068                         f->modtime = mod_time;
1069                         talloc_free(f->subfname);
1070                         f->subfname = talloc_strdup(f, n2);
1071                         return true;
1072                 }
1073         }
1074         return false;
1075 }
1076
1077 /***************************************************************************
1078  Handle the "realm" parameter
1079 ***************************************************************************/
1080
1081 bool handle_realm(struct loadparm_context *lp_ctx, int unused,
1082                   const char *pszParmValue, char **ptr)
1083 {
1084         char *upper;
1085         char *lower;
1086
1087         upper = strupper_talloc(lp_ctx, pszParmValue);
1088         if (upper == NULL) {
1089                 return false;
1090         }
1091
1092         lower = strlower_talloc(lp_ctx, pszParmValue);
1093         if (lower == NULL) {
1094                 TALLOC_FREE(upper);
1095                 return false;
1096         }
1097
1098         if (lp_ctx->s3_fns != NULL) {
1099                 lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
1100                 lp_ctx->s3_fns->lp_string_set(&lp_ctx->globals->realm, upper);
1101                 lp_ctx->s3_fns->lp_string_set(&lp_ctx->globals->dnsdomain, lower);
1102         } else {
1103                 lpcfg_string_set(lp_ctx, ptr, pszParmValue);
1104                 lpcfg_string_set(lp_ctx, &lp_ctx->globals->realm, upper);
1105                 lpcfg_string_set(lp_ctx, &lp_ctx->globals->dnsdomain, lower);
1106         }
1107
1108         return true;
1109 }
1110
1111 /***************************************************************************
1112  Handle the include operation.
1113 ***************************************************************************/
1114
1115 static bool handle_include(struct loadparm_context *lp_ctx, int unused,
1116                            const char *pszParmValue, char **ptr)
1117 {
1118         char *fname = standard_sub_basic(lp_ctx, pszParmValue);
1119
1120         add_to_file_list(lp_ctx, pszParmValue, fname);
1121
1122         lpcfg_string_set(lp_ctx, ptr, fname);
1123
1124         if (file_exist(fname))
1125                 return pm_process(fname, do_section, do_parameter, lp_ctx);
1126
1127         DEBUG(2, ("Can't find include file %s\n", fname));
1128
1129         return false;
1130 }
1131
1132 /***************************************************************************
1133  Handle the interpretation of the copy parameter.
1134 ***************************************************************************/
1135
1136 static bool handle_copy(struct loadparm_context *lp_ctx, int unused,
1137                         const char *pszParmValue, char **ptr)
1138 {
1139         bool bRetval;
1140         struct loadparm_service *serviceTemp;
1141
1142         lpcfg_string_set(lp_ctx, ptr, pszParmValue);
1143
1144         bRetval = false;
1145
1146         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1147
1148         serviceTemp = lpcfg_getservicebyname(lp_ctx, pszParmValue);
1149
1150         if (serviceTemp != NULL) {
1151                 if (serviceTemp == lp_ctx->currentService) {
1152                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1153                 } else {
1154                         copy_service(lp_ctx->currentService,
1155                                      serviceTemp,
1156                                      lp_ctx->currentService->copymap);
1157                         bRetval = true;
1158                 }
1159         } else {
1160                 DEBUG(0, ("Unable to copy service - source not found: %s\n",
1161                           pszParmValue));
1162                 bRetval = false;
1163         }
1164
1165         return bRetval;
1166 }
1167
1168 bool handle_debug_list(struct loadparm_context *lp_ctx, int unused,
1169                         const char *pszParmValue, char **ptr)
1170 {
1171         if (lp_ctx->s3_fns != NULL) {
1172                 lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
1173         } else {
1174                 lpcfg_string_set(lp_ctx, ptr, pszParmValue);
1175         }
1176
1177         return debug_parse_levels(pszParmValue);
1178 }
1179
1180 bool handle_logfile(struct loadparm_context *lp_ctx, int unused,
1181                     const char *pszParmValue, char **ptr)
1182 {
1183         if (lp_ctx->s3_fns != NULL) {
1184                 lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
1185         } else {
1186                 debug_set_logfile(pszParmValue);
1187                 lpcfg_string_set(lp_ctx, ptr, pszParmValue);
1188         }
1189
1190         return true;
1191 }
1192
1193 /***************************************************************************
1194  Initialise a copymap.
1195 ***************************************************************************/
1196
1197 static void init_copymap(struct loadparm_service *pservice)
1198 {
1199         int i;
1200
1201         TALLOC_FREE(pservice->copymap);
1202
1203         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
1204         if (!pservice->copymap)
1205                 DEBUG(0,
1206                       ("Couldn't allocate copymap!! (size %d)\n",
1207                        (int)NUMPARAMETERS));
1208         else
1209                 for (i = 0; i < NUMPARAMETERS; i++)
1210                         bitmap_set(pservice->copymap, i);
1211 }
1212
1213 /**
1214  * Process a parametric option
1215  */
1216 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
1217                                        struct loadparm_service *service,
1218                                        const char *pszParmName,
1219                                        const char *pszParmValue, int flags)
1220 {
1221         struct parmlist_entry *paramo, *data;
1222         char *name;
1223         TALLOC_CTX *mem_ctx;
1224
1225         while (isspace((unsigned char)*pszParmName)) {
1226                 pszParmName++;
1227         }
1228
1229         name = strlower_talloc(lp_ctx, pszParmName);
1230         if (!name) return false;
1231
1232         if (service == NULL) {
1233                 data = lp_ctx->globals->param_opt;
1234                 mem_ctx = lp_ctx->globals;
1235         } else {
1236                 data = service->param_opt;
1237                 mem_ctx = service;
1238         }
1239
1240         /* Traverse destination */
1241         for (paramo=data; paramo; paramo=paramo->next) {
1242                 /* If we already have the option set, override it unless
1243                    it was a command line option and the new one isn't */
1244                 if (strcmp(paramo->key, name) == 0) {
1245                         if ((paramo->priority & FLAG_CMDLINE) &&
1246                             !(flags & FLAG_CMDLINE)) {
1247                                 talloc_free(name);
1248                                 return true;
1249                         }
1250
1251                         talloc_free(paramo->value);
1252                         paramo->value = talloc_strdup(paramo, pszParmValue);
1253                         paramo->priority = flags;
1254                         talloc_free(name);
1255                         return true;
1256                 }
1257         }
1258
1259         paramo = talloc_zero(mem_ctx, struct parmlist_entry);
1260         if (!paramo)
1261                 smb_panic("OOM");
1262         paramo->key = talloc_strdup(paramo, name);
1263         paramo->value = talloc_strdup(paramo, pszParmValue);
1264         paramo->priority = flags;
1265         if (service == NULL) {
1266                 DLIST_ADD(lp_ctx->globals->param_opt, paramo);
1267         } else {
1268                 DLIST_ADD(service->param_opt, paramo);
1269         }
1270
1271         talloc_free(name);
1272
1273         return true;
1274 }
1275
1276 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
1277                          const char *pszParmName, const char *pszParmValue,
1278                          struct loadparm_context *lp_ctx, bool on_globals)
1279 {
1280         int i;
1281         /* if it is a special case then go ahead */
1282         if (parm_table[parmnum].special) {
1283                 bool ret;
1284                 ret = parm_table[parmnum].special(lp_ctx, -1, pszParmValue,
1285                                                   (char **)parm_ptr);
1286                 if (!ret) {
1287                         return false;
1288                 }
1289                 goto mark_non_default;
1290         }
1291
1292         /* now switch on the type of variable it is */
1293         switch (parm_table[parmnum].type)
1294         {
1295                 case P_BOOL: {
1296                         bool b;
1297                         if (!set_boolean(pszParmValue, &b)) {
1298                                 DEBUG(0, ("set_variable(%s): value is not "
1299                                           "boolean!\n", pszParmValue));
1300                                 return false;
1301                         }
1302                         *(bool *)parm_ptr = b;
1303                         }
1304                         break;
1305
1306                 case P_BOOLREV: {
1307                         bool b;
1308                         if (!set_boolean(pszParmValue, &b)) {
1309                                 DEBUG(0, ("set_variable(%s): value is not "
1310                                           "boolean!\n", pszParmValue));
1311                                 return false;
1312                         }
1313                         *(bool *)parm_ptr = !b;
1314                         }
1315                         break;
1316
1317                 case P_INTEGER:
1318                         *(int *)parm_ptr = atoi(pszParmValue);
1319                         break;
1320
1321                 case P_CHAR:
1322                         *(char *)parm_ptr = *pszParmValue;
1323                         break;
1324
1325                 case P_OCTAL:
1326                         *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1327                         break;
1328
1329                 case P_BYTES:
1330                 {
1331                         uint64_t val;
1332                         if (conv_str_size_error(pszParmValue, &val)) {
1333                                 if (val <= INT_MAX) {
1334                                         *(int *)parm_ptr = (int)val;
1335                                         break;
1336                                 }
1337                         }
1338
1339                         DEBUG(0, ("set_variable(%s): value is not "
1340                                   "a valid size specifier!\n", pszParmValue));
1341                         return false;
1342                 }
1343
1344                 case P_CMDLIST:
1345                         *(const char * const **)parm_ptr
1346                                 = (const char * const *)str_list_make(mem_ctx,
1347                                                                       pszParmValue, NULL);
1348                         break;
1349                 case P_LIST:
1350                 {
1351                         char **new_list = str_list_make(mem_ctx,
1352                                                         pszParmValue, NULL);
1353                         for (i=0; new_list[i]; i++) {
1354                                 if (*(const char ***)parm_ptr != NULL &&
1355                                     new_list[i][0] == '+' &&
1356                                     new_list[i][1])
1357                                 {
1358                                         if (!str_list_check(*(const char ***)parm_ptr,
1359                                                             &new_list[i][1])) {
1360                                                 *(const char ***)parm_ptr = str_list_add(*(const char ***)parm_ptr,
1361                                                                                          &new_list[i][1]);
1362                                         }
1363                                 } else if (*(const char ***)parm_ptr != NULL &&
1364                                            new_list[i][0] == '-' &&
1365                                            new_list[i][1])
1366                                 {
1367                                         str_list_remove(*(const char ***)parm_ptr,
1368                                                         &new_list[i][1]);
1369                                 } else {
1370                                         if (i != 0) {
1371                                                 DEBUG(0, ("Unsupported list syntax for: %s = %s\n",
1372                                                           pszParmName, pszParmValue));
1373                                                 return false;
1374                                         }
1375                                         *(const char * const **)parm_ptr = (const char * const *) new_list;
1376                                         break;
1377                                 }
1378                         }
1379                         break;
1380                 }
1381                 case P_STRING:
1382                         lpcfg_string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1383                         break;
1384
1385                 case P_USTRING:
1386                         lpcfg_string_set_upper(mem_ctx, (char **)parm_ptr, pszParmValue);
1387                         break;
1388
1389                 case P_ENUM:
1390                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1391                                 if (strequal
1392                                     (pszParmValue,
1393                                      parm_table[parmnum].enum_list[i].name)) {
1394                                         *(int *)parm_ptr =
1395                                                 parm_table[parmnum].
1396                                                 enum_list[i].value;
1397                                         break;
1398                                 }
1399                         }
1400                         if (!parm_table[parmnum].enum_list[i].name) {
1401                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
1402                                          pszParmValue, pszParmName));
1403                                 return false;
1404                         }
1405                         break;
1406
1407                 case P_SEP:
1408                         break;
1409         }
1410
1411 mark_non_default:
1412         if (on_globals && (lp_ctx->flags[parmnum] & FLAG_DEFAULT)) {
1413                 lp_ctx->flags[parmnum] &= ~FLAG_DEFAULT;
1414                 /* we have to also unset FLAG_DEFAULT on aliases */
1415                 for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
1416                         lp_ctx->flags[i] &= ~FLAG_DEFAULT;
1417                 }
1418                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
1419                         lp_ctx->flags[i] &= ~FLAG_DEFAULT;
1420                 }
1421         }
1422         return true;
1423 }
1424
1425
1426 bool lpcfg_do_global_parameter(struct loadparm_context *lp_ctx,
1427                                const char *pszParmName, const char *pszParmValue)
1428 {
1429         int parmnum = lpcfg_map_parameter(pszParmName);
1430         void *parm_ptr;
1431
1432         if (parmnum < 0) {
1433                 if (strchr(pszParmName, ':')) {
1434                         return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, pszParmValue, 0);
1435                 }
1436                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1437                 return true;
1438         }
1439
1440         /* if the flag has been set on the command line, then don't allow override,
1441            but don't report an error */
1442         if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
1443                 return true;
1444         }
1445
1446         parm_ptr = lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[parmnum]);
1447
1448         return set_variable(lp_ctx->globals, parmnum, parm_ptr,
1449                             pszParmName, pszParmValue, lp_ctx, true);
1450 }
1451
1452 bool lpcfg_do_service_parameter(struct loadparm_context *lp_ctx,
1453                                 struct loadparm_service *service,
1454                                 const char *pszParmName, const char *pszParmValue)
1455 {
1456         void *parm_ptr;
1457         int i;
1458         int parmnum = lpcfg_map_parameter(pszParmName);
1459
1460         if (parmnum < 0) {
1461                 if (strchr(pszParmName, ':')) {
1462                         return lp_do_parameter_parametric(lp_ctx, service, pszParmName, pszParmValue, 0);
1463                 }
1464                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1465                 return true;
1466         }
1467
1468         /* if the flag has been set on the command line, then don't allow override,
1469            but don't report an error */
1470         if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
1471                 return true;
1472         }
1473
1474         if (parm_table[parmnum].p_class == P_GLOBAL) {
1475                 DEBUG(0,
1476                       ("Global parameter %s found in service section!\n",
1477                        pszParmName));
1478                 return true;
1479         }
1480         parm_ptr = ((char *)service) + parm_table[parmnum].offset;
1481
1482         if (!service->copymap)
1483                 init_copymap(service);
1484
1485         /* this handles the aliases - set the copymap for other
1486          * entries with the same data pointer */
1487         for (i = 0; parm_table[i].label; i++)
1488                 if (parm_table[i].offset == parm_table[parmnum].offset &&
1489                     parm_table[i].p_class == parm_table[parmnum].p_class)
1490                         bitmap_clear(service->copymap, i);
1491
1492         return set_variable(service, parmnum, parm_ptr, pszParmName,
1493                             pszParmValue, lp_ctx, false);
1494 }
1495
1496 /**
1497  * Process a parameter.
1498  */
1499
1500 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1501                          void *userdata)
1502 {
1503         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1504
1505         if (lp_ctx->bInGlobalSection)
1506                 return lpcfg_do_global_parameter(lp_ctx, pszParmName,
1507                                               pszParmValue);
1508         else
1509                 return lpcfg_do_service_parameter(lp_ctx, lp_ctx->currentService,
1510                                                   pszParmName, pszParmValue);
1511 }
1512
1513 /*
1514   variable argument do parameter
1515 */
1516 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
1517 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx,
1518                                 const char *pszParmName, const char *fmt, ...)
1519 {
1520         char *s;
1521         bool ret;
1522         va_list ap;
1523
1524         va_start(ap, fmt);
1525         s = talloc_vasprintf(NULL, fmt, ap);
1526         va_end(ap);
1527         ret = lpcfg_do_global_parameter(lp_ctx, pszParmName, s);
1528         talloc_free(s);
1529         return ret;
1530 }
1531
1532
1533 /*
1534   set a parameter from the commandline - this is called from command line parameter
1535   parsing code. It sets the parameter then marks the parameter as unable to be modified
1536   by smb.conf processing
1537 */
1538 bool lpcfg_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
1539                        const char *pszParmValue)
1540 {
1541         int parmnum;
1542         int i;
1543
1544         if (lp_ctx->s3_fns) {
1545                 return lp_ctx->s3_fns->set_cmdline(pszParmName, pszParmValue);
1546         }
1547
1548         parmnum = lpcfg_map_parameter(pszParmName);
1549
1550         while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1551
1552
1553         if (parmnum < 0 && strchr(pszParmName, ':')) {
1554                 /* set a parametric option */
1555                 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
1556                                                   pszParmValue, FLAG_CMDLINE);
1557         }
1558
1559         if (parmnum < 0) {
1560                 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1561                 return false;
1562         }
1563
1564         /* reset the CMDLINE flag in case this has been called before */
1565         lp_ctx->flags[parmnum] &= ~FLAG_CMDLINE;
1566
1567         if (!lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
1568                 return false;
1569         }
1570
1571         lp_ctx->flags[parmnum] |= FLAG_CMDLINE;
1572
1573         /* we have to also set FLAG_CMDLINE on aliases */
1574         for (i=parmnum-1;
1575              i>=0 && parm_table[i].p_class == parm_table[parmnum].p_class &&
1576              parm_table[i].offset == parm_table[parmnum].offset;
1577              i--) {
1578                 lp_ctx->flags[i] |= FLAG_CMDLINE;
1579         }
1580         for (i=parmnum+1;
1581              i<NUMPARAMETERS &&
1582              parm_table[i].p_class == parm_table[parmnum].p_class &&
1583              parm_table[i].offset == parm_table[parmnum].offset;
1584              i++) {
1585                 lp_ctx->flags[i] |= FLAG_CMDLINE;
1586         }
1587
1588         return true;
1589 }
1590
1591 /*
1592   set a option from the commandline in 'a=b' format. Use to support --option
1593 */
1594 bool lpcfg_set_option(struct loadparm_context *lp_ctx, const char *option)
1595 {
1596         char *p, *s;
1597         bool ret;
1598
1599         s = talloc_strdup(NULL, option);
1600         if (!s) {
1601                 return false;
1602         }
1603
1604         p = strchr(s, '=');
1605         if (!p) {
1606                 talloc_free(s);
1607                 return false;
1608         }
1609
1610         *p = 0;
1611
1612         ret = lpcfg_set_cmdline(lp_ctx, s, p+1);
1613         talloc_free(s);
1614         return ret;
1615 }
1616
1617
1618 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1619
1620 /**
1621  * Print a parameter of the specified type.
1622  */
1623
1624 void lpcfg_print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1625 {
1626         /* For the seperation of lists values that we print below */
1627         const char *list_sep = ", ";
1628         int i;
1629         switch (p->type)
1630         {
1631                 case P_ENUM:
1632                         for (i = 0; p->enum_list[i].name; i++) {
1633                                 if (*(int *)ptr == p->enum_list[i].value) {
1634                                         fprintf(f, "%s",
1635                                                 p->enum_list[i].name);
1636                                         break;
1637                                 }
1638                         }
1639                         break;
1640
1641                 case P_BOOL:
1642                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
1643                         break;
1644
1645                 case P_BOOLREV:
1646                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
1647                         break;
1648
1649                 case P_INTEGER:
1650                 case P_BYTES:
1651                         fprintf(f, "%d", *(int *)ptr);
1652                         break;
1653
1654                 case P_CHAR:
1655                         fprintf(f, "%c", *(char *)ptr);
1656                         break;
1657
1658                 case P_OCTAL: {
1659                         int val = *(int *)ptr; 
1660                         if (val == -1) {
1661                                 fprintf(f, "-1");
1662                         } else {
1663                                 fprintf(f, "0%03o", val);
1664                         }
1665                         break;
1666                 }
1667
1668                 case P_CMDLIST:
1669                         list_sep = " ";
1670                         /* fall through */
1671                 case P_LIST:
1672                         if ((char ***)ptr && *(char ***)ptr) {
1673                                 char **list = *(char ***)ptr;
1674                                 for (; *list; list++) {
1675                                         /* surround strings with whitespace in double quotes */
1676                                         if (*(list+1) == NULL) {
1677                                                 /* last item, no extra separator */
1678                                                 list_sep = "";
1679                                         }
1680                                         if ( strchr_m( *list, ' ' ) ) {
1681                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
1682                                         } else {
1683                                                 fprintf(f, "%s%s", *list, list_sep);
1684                                         }
1685                                 }
1686                         }
1687                         break;
1688
1689                 case P_STRING:
1690                 case P_USTRING:
1691                         if (*(char **)ptr) {
1692                                 fprintf(f, "%s", *(char **)ptr);
1693                         }
1694                         break;
1695                 case P_SEP:
1696                         break;
1697         }
1698 }
1699
1700 /**
1701  * Check if two parameters are equal.
1702  */
1703
1704  bool lpcfg_equal_parameter(parm_type type, void *ptr1, void *ptr2)
1705 {
1706         switch (type) {
1707                 case P_BOOL:
1708                 case P_BOOLREV:
1709                         return (*((bool *)ptr1) == *((bool *)ptr2));
1710
1711                 case P_INTEGER:
1712                 case P_ENUM:
1713                 case P_OCTAL:
1714                 case P_BYTES:
1715                         return (*((int *)ptr1) == *((int *)ptr2));
1716
1717                 case P_CHAR:
1718                         return (*((char *)ptr1) == *((char *)ptr2));
1719
1720                 case P_LIST:
1721                 case P_CMDLIST:
1722                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
1723
1724                 case P_STRING:
1725                 case P_USTRING:
1726                 {
1727                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1728                         if (p1 && !*p1)
1729                                 p1 = NULL;
1730                         if (p2 && !*p2)
1731                                 p2 = NULL;
1732                         return (p1 == p2 || strequal(p1, p2));
1733                 }
1734                 case P_SEP:
1735                         break;
1736         }
1737         return false;
1738 }
1739
1740 /**
1741  * Process a new section (service).
1742  *
1743  * At this stage all sections are services.
1744  * Later we'll have special sections that permit server parameters to be set.
1745  * Returns True on success, False on failure.
1746  */
1747
1748 static bool do_section(const char *pszSectionName, void *userdata)
1749 {
1750         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1751         bool bRetval;
1752         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1753                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1754         bRetval = false;
1755
1756         /* if we've just struck a global section, note the fact. */
1757         lp_ctx->bInGlobalSection = isglobal;
1758
1759         /* check for multiple global sections */
1760         if (lp_ctx->bInGlobalSection) {
1761                 DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
1762                 return true;
1763         }
1764
1765         /* if we have a current service, tidy it up before moving on */
1766         bRetval = true;
1767
1768         if (lp_ctx->currentService != NULL)
1769                 bRetval = lpcfg_service_ok(lp_ctx->currentService);
1770
1771         /* if all is still well, move to the next record in the services array */
1772         if (bRetval) {
1773                 /* We put this here to avoid an odd message order if messages are */
1774                 /* issued by the post-processing of a previous section. */
1775                 DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
1776
1777                 if ((lp_ctx->currentService = lpcfg_add_service(lp_ctx, lp_ctx->sDefault,
1778                                                                    pszSectionName))
1779                     == NULL) {
1780                         DEBUG(0, ("Failed to add a new service\n"));
1781                         return false;
1782                 }
1783         }
1784
1785         return bRetval;
1786 }
1787
1788
1789 /**
1790  * Determine if a particular base parameter is currently set to the default value.
1791  */
1792
1793 static bool is_default(struct loadparm_service *sDefault, int i)
1794 {
1795         void *def_ptr = ((char *)sDefault) + parm_table[i].offset;
1796         switch (parm_table[i].type) {
1797                 case P_CMDLIST:
1798                 case P_LIST:
1799                         return str_list_equal((const char * const *)parm_table[i].def.lvalue,
1800                                               (const char **)def_ptr);
1801                 case P_STRING:
1802                 case P_USTRING:
1803                         return strequal(parm_table[i].def.svalue,
1804                                         *(char **)def_ptr);
1805                 case P_BOOL:
1806                 case P_BOOLREV:
1807                         return parm_table[i].def.bvalue ==
1808                                 *(bool *)def_ptr;
1809                 case P_INTEGER:
1810                 case P_CHAR:
1811                 case P_OCTAL:
1812                 case P_BYTES:
1813                 case P_ENUM:
1814                         return parm_table[i].def.ivalue ==
1815                                 *(int *)def_ptr;
1816                 case P_SEP:
1817                         break;
1818         }
1819         return false;
1820 }
1821
1822 /**
1823  *Display the contents of the global structure.
1824  */
1825
1826 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f,
1827                          bool show_defaults)
1828 {
1829         int i;
1830         struct parmlist_entry *data;
1831
1832         fprintf(f, "# Global parameters\n[global]\n");
1833
1834         for (i = 0; parm_table[i].label; i++)
1835                 if (parm_table[i].p_class == P_GLOBAL &&
1836                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
1837                         if (!show_defaults && (lp_ctx->flags[i] & FLAG_DEFAULT))
1838                                 continue;
1839                         fprintf(f, "\t%s = ", parm_table[i].label);
1840                         lpcfg_print_parameter(&parm_table[i], lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[i]), f);
1841                         fprintf(f, "\n");
1842         }
1843         if (lp_ctx->globals->param_opt != NULL) {
1844                 for (data = lp_ctx->globals->param_opt; data;
1845                      data = data->next) {
1846                         if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
1847                                 continue;
1848                         }
1849                         fprintf(f, "\t%s = %s\n", data->key, data->value);
1850                 }
1851         }
1852
1853 }
1854
1855 /**
1856  * Display the contents of a single services record.
1857  */
1858
1859 static void dump_a_service(struct loadparm_service * pService, struct loadparm_service *sDefault, FILE * f,
1860                            unsigned int *flags)
1861 {
1862         int i;
1863         struct parmlist_entry *data;
1864
1865         if (pService != sDefault)
1866                 fprintf(f, "\n[%s]\n", pService->szService);
1867
1868         for (i = 0; parm_table[i].label; i++) {
1869                 if (parm_table[i].p_class == P_LOCAL &&
1870                     (*parm_table[i].label != '-') &&
1871                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset)))
1872                 {
1873                         if (pService == sDefault) {
1874                                 if (flags && (flags[i] & FLAG_DEFAULT)) {
1875                                         continue;
1876                                 }
1877                                 if (defaults_saved) {
1878                                         if (is_default(sDefault, i)) {
1879                                                 continue;
1880                                         }
1881                                 }
1882                         } else {
1883                                 if (lpcfg_equal_parameter(parm_table[i].type,
1884                                                           ((char *)pService) +
1885                                                           parm_table[i].offset,
1886                                                           ((char *)sDefault) +
1887                                                           parm_table[i].offset))
1888                                         continue;
1889                         }
1890
1891                         fprintf(f, "\t%s = ", parm_table[i].label);
1892                         lpcfg_print_parameter(&parm_table[i],
1893                                         ((char *)pService) + parm_table[i].offset, f);
1894                         fprintf(f, "\n");
1895                 }
1896         }
1897         if (pService->param_opt != NULL) {
1898                 for (data = pService->param_opt; data; data = data->next) {
1899                         fprintf(f, "\t%s = %s\n", data->key, data->value);
1900                 }
1901         }
1902 }
1903
1904 bool lpcfg_dump_a_parameter(struct loadparm_context *lp_ctx,
1905                             struct loadparm_service *service,
1906                             const char *parm_name, FILE * f)
1907 {
1908         struct parm_struct *parm;
1909         void *ptr;
1910
1911         parm = lpcfg_parm_struct(lp_ctx, parm_name);
1912         if (!parm) {
1913                 return false;
1914         }
1915
1916         if (service != NULL && parm->p_class == P_GLOBAL) {
1917                 return false;
1918         }
1919
1920         ptr = lpcfg_parm_ptr(lp_ctx, service,parm);
1921
1922         lpcfg_print_parameter(parm, ptr, f);
1923         fprintf(f, "\n");
1924         return true;
1925 }
1926
1927 /**
1928  * Auto-load some home services.
1929  */
1930 static void lpcfg_add_auto_services(struct loadparm_context *lp_ctx,
1931                                     const char *str)
1932 {
1933         return;
1934 }
1935
1936
1937 /**
1938  * Unload unused services.
1939  */
1940
1941 void lpcfg_killunused(struct loadparm_context *lp_ctx,
1942                    struct smbsrv_connection *smb,
1943                    bool (*snumused) (struct smbsrv_connection *, int))
1944 {
1945         int i;
1946         for (i = 0; i < lp_ctx->iNumServices; i++) {
1947                 if (lp_ctx->services[i] == NULL)
1948                         continue;
1949
1950                 if (!snumused || !snumused(smb, i)) {
1951                         talloc_free(lp_ctx->services[i]);
1952                         lp_ctx->services[i] = NULL;
1953                 }
1954         }
1955 }
1956
1957
1958 static int lpcfg_destructor(struct loadparm_context *lp_ctx)
1959 {
1960         struct parmlist_entry *data;
1961
1962         if (lp_ctx->refuse_free) {
1963                 /* someone is trying to free the
1964                    global_loadparm_context.
1965                    We can't allow that. */
1966                 return -1;
1967         }
1968
1969         if (lp_ctx->globals->param_opt != NULL) {
1970                 struct parmlist_entry *next;
1971                 for (data = lp_ctx->globals->param_opt; data; data=next) {
1972                         next = data->next;
1973                         if (data->priority & FLAG_CMDLINE) continue;
1974                         DLIST_REMOVE(lp_ctx->globals->param_opt, data);
1975                         talloc_free(data);
1976                 }
1977         }
1978
1979         return 0;
1980 }
1981
1982 /**
1983  * Initialise the global parameter structure.
1984  *
1985  * Note that most callers should use loadparm_init_global() instead
1986  */
1987 struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
1988 {
1989         int i;
1990         char *myname;
1991         struct loadparm_context *lp_ctx;
1992         struct parmlist_entry *parm;
1993         char *logfile;
1994
1995         lp_ctx = talloc_zero(mem_ctx, struct loadparm_context);
1996         if (lp_ctx == NULL)
1997                 return NULL;
1998
1999         talloc_set_destructor(lp_ctx, lpcfg_destructor);
2000         lp_ctx->bInGlobalSection = true;
2001         lp_ctx->globals = talloc_zero(lp_ctx, struct loadparm_global);
2002         lp_ctx->sDefault = talloc_zero(lp_ctx, struct loadparm_service);
2003
2004         lp_ctx->sDefault->iMaxPrintJobs = 1000;
2005         lp_ctx->sDefault->bAvailable = true;
2006         lp_ctx->sDefault->browseable = true;
2007         lp_ctx->sDefault->read_only = true;
2008         lp_ctx->sDefault->map_archive = true;
2009         lp_ctx->sDefault->strict_locking = true;
2010         lp_ctx->sDefault->oplocks = true;
2011         lp_ctx->sDefault->create_mask = 0744;
2012         lp_ctx->sDefault->force_create_mode = 0000;
2013         lp_ctx->sDefault->directory_mask = 0755;
2014         lp_ctx->sDefault->force_directory_mode = 0000;
2015
2016         DEBUG(3, ("Initialising global parameters\n"));
2017
2018         for (i = 0; parm_table[i].label; i++) {
2019                 if ((parm_table[i].type == P_STRING ||
2020                      parm_table[i].type == P_USTRING) &&
2021                     !(lp_ctx->flags[i] & FLAG_CMDLINE)) {
2022                         char **r;
2023                         if (parm_table[i].p_class == P_LOCAL) {
2024                                 r = (char **)(((char *)lp_ctx->sDefault) + parm_table[i].offset);
2025                         } else {
2026                                 r = (char **)(((char *)lp_ctx->globals) + parm_table[i].offset);
2027                         }
2028                         *r = talloc_strdup(lp_ctx, "");
2029                 }
2030         }
2031
2032         logfile = talloc_asprintf(lp_ctx, "%s/log.samba", dyn_LOGFILEBASE);
2033         lpcfg_do_global_parameter(lp_ctx, "log file", logfile);
2034         talloc_free(logfile);
2035
2036         lpcfg_do_global_parameter(lp_ctx, "log level", "0");
2037
2038         lpcfg_do_global_parameter(lp_ctx, "syslog", "1");
2039         lpcfg_do_global_parameter(lp_ctx, "syslog only", "No");
2040         lpcfg_do_global_parameter(lp_ctx, "debug timestamp", "Yes");
2041         lpcfg_do_global_parameter(lp_ctx, "debug prefix timestamp", "No");
2042         lpcfg_do_global_parameter(lp_ctx, "debug hires timestamp", "Yes");
2043         lpcfg_do_global_parameter(lp_ctx, "debug pid", "No");
2044         lpcfg_do_global_parameter(lp_ctx, "debug uid", "No");
2045         lpcfg_do_global_parameter(lp_ctx, "debug class", "No");
2046
2047         lpcfg_do_global_parameter(lp_ctx, "share backend", "classic");
2048
2049         lpcfg_do_global_parameter(lp_ctx, "server role", "auto");
2050         lpcfg_do_global_parameter(lp_ctx, "domain logons", "No");
2051         lpcfg_do_global_parameter(lp_ctx, "domain master", "Auto");
2052
2053         /* options that can be set on the command line must be initialised via
2054            the slower lpcfg_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
2055 #ifdef TCP_NODELAY
2056         lpcfg_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
2057 #endif
2058         lpcfg_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
2059         myname = get_myname(lp_ctx);
2060         lpcfg_do_global_parameter(lp_ctx, "netbios name", myname);
2061         talloc_free(myname);
2062         lpcfg_do_global_parameter(lp_ctx, "name resolve order", "lmhosts wins host bcast");
2063
2064         lpcfg_do_global_parameter(lp_ctx, "fstype", "NTFS");
2065
2066         lpcfg_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
2067         lpcfg_do_global_parameter(lp_ctx, "max connections", "0");
2068
2069         lpcfg_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver");
2070         lpcfg_do_global_parameter(lp_ctx, "server services", "s3fs rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate dns");
2071         lpcfg_do_global_parameter(lp_ctx, "kccsrv:samba_kcc", "true");
2072         /* the winbind method for domain controllers is for both RODC
2073            auth forwarding and for trusted domains */
2074         lpcfg_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
2075         lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
2076
2077         /* This hive should be dynamically generated by Samba using
2078            data from the sam, but for the moment leave it in a tdb to
2079            keep regedt32 from popping up an annoying dialog. */
2080         lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
2081
2082         /* using UTF8 by default allows us to support all chars */
2083         lpcfg_do_global_parameter(lp_ctx, "unix charset", "UTF-8");
2084
2085         /* Use codepage 850 as a default for the dos character set */
2086         lpcfg_do_global_parameter(lp_ctx, "dos charset", "CP850");
2087
2088         /*
2089          * Allow the default PASSWD_CHAT to be overridden in local.h.
2090          */
2091         lpcfg_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
2092
2093         lpcfg_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
2094         lpcfg_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
2095         lpcfg_do_global_parameter(lp_ctx, "state directory", dyn_STATEDIR);
2096         lpcfg_do_global_parameter(lp_ctx, "cache directory", dyn_CACHEDIR);
2097         lpcfg_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
2098
2099         lpcfg_do_global_parameter(lp_ctx, "nbt client socket address", "0.0.0.0");
2100         lpcfg_do_global_parameter_var(lp_ctx, "server string",
2101                                    "Samba %s", SAMBA_VERSION_STRING);
2102
2103         lpcfg_do_global_parameter(lp_ctx, "password server", "*");
2104
2105         lpcfg_do_global_parameter(lp_ctx, "max mux", "50");
2106         lpcfg_do_global_parameter(lp_ctx, "max xmit", "16644");
2107         lpcfg_do_global_parameter(lp_ctx, "host msdfs", "true");
2108
2109         lpcfg_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
2110         lpcfg_do_global_parameter(lp_ctx, "server min protocol", "LANMAN1");
2111         lpcfg_do_global_parameter(lp_ctx, "server max protocol", "SMB3");
2112         lpcfg_do_global_parameter(lp_ctx, "client min protocol", "CORE");
2113         lpcfg_do_global_parameter(lp_ctx, "client max protocol", "NT1");
2114         lpcfg_do_global_parameter(lp_ctx, "security", "AUTO");
2115         lpcfg_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
2116         lpcfg_do_global_parameter(lp_ctx, "ReadRaw", "True");
2117         lpcfg_do_global_parameter(lp_ctx, "WriteRaw", "True");
2118         lpcfg_do_global_parameter(lp_ctx, "NullPasswords", "False");
2119         lpcfg_do_global_parameter(lp_ctx, "old password allowed period", "60");
2120         lpcfg_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
2121
2122         lpcfg_do_global_parameter(lp_ctx, "TimeServer", "False");
2123         lpcfg_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
2124         lpcfg_do_global_parameter(lp_ctx, "Unicode", "True");
2125         lpcfg_do_global_parameter(lp_ctx, "ClientLanManAuth", "False");
2126         lpcfg_do_global_parameter(lp_ctx, "ClientNTLMv2Auth", "True");
2127         lpcfg_do_global_parameter(lp_ctx, "LanmanAuth", "False");
2128         lpcfg_do_global_parameter(lp_ctx, "NTLMAuth", "True");
2129         lpcfg_do_global_parameter(lp_ctx, "client use spnego principal", "False");
2130
2131         lpcfg_do_global_parameter(lp_ctx, "UnixExtensions", "True");
2132
2133         lpcfg_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
2134         lpcfg_do_global_parameter(lp_ctx, "LocalMaster", "True");
2135
2136         lpcfg_do_global_parameter(lp_ctx, "wins support", "False");
2137         lpcfg_do_global_parameter(lp_ctx, "dns proxy", "True");
2138
2139         lpcfg_do_global_parameter(lp_ctx, "winbind separator", "\\");
2140         lpcfg_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
2141         lpcfg_do_global_parameter(lp_ctx, "require strong key", "True");
2142         lpcfg_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
2143         lpcfg_do_global_parameter(lp_ctx, "winbindd privileged socket directory", dyn_WINBINDD_PRIVILEGED_SOCKET_DIR);
2144         lpcfg_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR);
2145         lpcfg_do_global_parameter_var(lp_ctx, "dns update command", "%s/samba_dnsupdate", dyn_SCRIPTSBINDIR);
2146         lpcfg_do_global_parameter_var(lp_ctx, "spn update command", "%s/samba_spnupdate", dyn_SCRIPTSBINDIR);
2147         lpcfg_do_global_parameter_var(lp_ctx, "samba kcc command",
2148                                         "%s/samba_kcc", dyn_SCRIPTSBINDIR);
2149         lpcfg_do_global_parameter(lp_ctx, "template shell", "/bin/false");
2150         lpcfg_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
2151
2152         lpcfg_do_global_parameter(lp_ctx, "client signing", "default");
2153         lpcfg_do_global_parameter(lp_ctx, "server signing", "default");
2154
2155         lpcfg_do_global_parameter(lp_ctx, "use spnego", "True");
2156
2157         lpcfg_do_global_parameter(lp_ctx, "use mmap", "True");
2158
2159         lpcfg_do_global_parameter(lp_ctx, "smb ports", "445 139");
2160         lpcfg_do_global_parameter(lp_ctx, "nbt port", "137");
2161         lpcfg_do_global_parameter(lp_ctx, "dgram port", "138");
2162         lpcfg_do_global_parameter(lp_ctx, "cldap port", "389");
2163         lpcfg_do_global_parameter(lp_ctx, "krb5 port", "88");
2164         lpcfg_do_global_parameter(lp_ctx, "kpasswd port", "464");
2165         lpcfg_do_global_parameter(lp_ctx, "web port", "901");
2166
2167         lpcfg_do_global_parameter(lp_ctx, "nt status support", "True");
2168
2169         lpcfg_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
2170         lpcfg_do_global_parameter(lp_ctx, "min wins ttl", "21600");
2171
2172         lpcfg_do_global_parameter(lp_ctx, "tls enabled", "True");
2173         lpcfg_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
2174         lpcfg_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
2175         lpcfg_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
2176         lpcfg_do_global_parameter(lp_ctx, "prefork children:smb", "4");
2177
2178         lpcfg_do_global_parameter(lp_ctx, "rndc command", "/usr/sbin/rndc");
2179         lpcfg_do_global_parameter(lp_ctx, "nsupdate command", "/usr/bin/nsupdate -g");
2180
2181         lpcfg_do_global_parameter(lp_ctx, "allow dns updates", "secure only");
2182         lpcfg_do_global_parameter(lp_ctx, "dns forwarder", "");
2183
2184         lpcfg_do_global_parameter(lp_ctx, "algorithmic rid base", "1000");
2185
2186         lpcfg_do_global_parameter(lp_ctx, "enhanced browsing", "True");
2187
2188         lpcfg_do_global_parameter(lp_ctx, "winbind nss info", "template");
2189
2190         lpcfg_do_global_parameter(lp_ctx, "server schannel", "Auto");
2191
2192         lpcfg_do_global_parameter(lp_ctx, "short preserve case", "True");
2193
2194         lpcfg_do_global_parameter(lp_ctx, "max open files", "16384");
2195
2196         lpcfg_do_global_parameter(lp_ctx, "cups connection timeout", "30");
2197
2198         lpcfg_do_global_parameter(lp_ctx, "locking", "True");
2199
2200         lpcfg_do_global_parameter(lp_ctx, "block size", "1024");
2201
2202         lpcfg_do_global_parameter(lp_ctx, "client use spnego", "True");
2203
2204         lpcfg_do_global_parameter(lp_ctx, "change notify", "True");
2205
2206         lpcfg_do_global_parameter(lp_ctx, "name cache timeout", "660");
2207
2208         lpcfg_do_global_parameter(lp_ctx, "defer sharing violations", "True");
2209
2210         lpcfg_do_global_parameter(lp_ctx, "ldap replication sleep", "1000");
2211
2212         lpcfg_do_global_parameter(lp_ctx, "idmap backend", "tdb");
2213
2214         lpcfg_do_global_parameter(lp_ctx, "enable privileges", "True");
2215
2216         lpcfg_do_global_parameter_var(lp_ctx, "smb2 max write", "%u", DEFAULT_SMB2_MAX_WRITE);
2217
2218         lpcfg_do_global_parameter(lp_ctx, "passdb backend", "tdbsam");
2219
2220         lpcfg_do_global_parameter(lp_ctx, "getwd cache", "True");
2221
2222         lpcfg_do_global_parameter(lp_ctx, "winbind nested groups", "True");
2223
2224         lpcfg_do_global_parameter(lp_ctx, "mangled names", "True");
2225
2226         lpcfg_do_global_parameter_var(lp_ctx, "smb2 max credits", "%u", DEFAULT_SMB2_MAX_CREDITS);
2227
2228         lpcfg_do_global_parameter(lp_ctx, "ldap ssl", "start tls");
2229
2230         lpcfg_do_global_parameter(lp_ctx, "ldap deref", "auto");
2231
2232         lpcfg_do_global_parameter(lp_ctx, "lm interval", "60");
2233
2234         lpcfg_do_global_parameter(lp_ctx, "mangling method", "hash2");
2235
2236         lpcfg_do_global_parameter(lp_ctx, "hide dot files", "True");
2237
2238         lpcfg_do_global_parameter(lp_ctx, "browse list", "True");
2239
2240         lpcfg_do_global_parameter(lp_ctx, "passwd chat timeout", "2");
2241
2242         lpcfg_do_global_parameter(lp_ctx, "guest account", GUEST_ACCOUNT);
2243
2244         lpcfg_do_global_parameter(lp_ctx, "client schannel", "auto");
2245
2246         lpcfg_do_global_parameter(lp_ctx, "smb encrypt", "default");
2247
2248         lpcfg_do_global_parameter(lp_ctx, "max log size", "5000");
2249
2250         lpcfg_do_global_parameter(lp_ctx, "idmap negative cache time", "120");
2251
2252         lpcfg_do_global_parameter(lp_ctx, "ldap follow referral", "auto");
2253
2254         lpcfg_do_global_parameter(lp_ctx, "multicast dns register", "yes");
2255
2256         lpcfg_do_global_parameter(lp_ctx, "winbind reconnect delay", "30");
2257
2258         lpcfg_do_global_parameter(lp_ctx, "nt acl support", "yes");
2259
2260         lpcfg_do_global_parameter(lp_ctx, "acl check permissions", "yes");
2261
2262         lpcfg_do_global_parameter(lp_ctx, "keepalive", "300");
2263
2264         lpcfg_do_global_parameter(lp_ctx, "winbind cache time", "300");
2265
2266         lpcfg_do_global_parameter(lp_ctx, "level2 oplocks", "yes");
2267
2268         lpcfg_do_global_parameter(lp_ctx, "show add printer wizard", "yes");
2269
2270         lpcfg_do_global_parameter(lp_ctx, "allocation roundup size", "1048576");
2271
2272         lpcfg_do_global_parameter(lp_ctx, "ldap page size", "1024");
2273
2274         lpcfg_do_global_parameter(lp_ctx, "kernel share modes", "yes");
2275
2276         lpcfg_do_global_parameter(lp_ctx, "strict locking", "Auto");
2277
2278         lpcfg_do_global_parameter(lp_ctx, "map readonly", "yes");
2279
2280         lpcfg_do_global_parameter(lp_ctx, "allow trusted domains", "yes");
2281
2282         lpcfg_do_global_parameter(lp_ctx, "default devmode", "yes");
2283
2284         lpcfg_do_global_parameter(lp_ctx, "os level", "20");
2285
2286         lpcfg_do_global_parameter(lp_ctx, "dos filetimes", "yes");
2287
2288         lpcfg_do_global_parameter(lp_ctx, "mangling char", "~");
2289
2290         lpcfg_do_global_parameter(lp_ctx, "printcap cache time", "750");
2291
2292         lpcfg_do_global_parameter(lp_ctx, "create krb5 conf", "yes");
2293
2294         lpcfg_do_global_parameter(lp_ctx, "winbind max clients", "200");
2295
2296         lpcfg_do_global_parameter(lp_ctx, "acl map full control", "yes");
2297
2298         lpcfg_do_global_parameter(lp_ctx, "nt pipe support", "yes");
2299
2300         lpcfg_do_global_parameter(lp_ctx, "ldap debug threshold", "10");
2301
2302         lpcfg_do_global_parameter(lp_ctx, "follow symlinks", "yes");
2303
2304         lpcfg_do_global_parameter(lp_ctx, "machine password timeout", "604800");
2305
2306         lpcfg_do_global_parameter(lp_ctx, "ldap connection timeout", "2");
2307
2308         lpcfg_do_global_parameter(lp_ctx, "winbind expand groups", "1");
2309
2310         lpcfg_do_global_parameter(lp_ctx, "stat cache", "yes");
2311
2312         lpcfg_do_global_parameter(lp_ctx, "lpq cache time", "30");
2313
2314         lpcfg_do_global_parameter_var(lp_ctx, "smb2 max trans", "%u", DEFAULT_SMB2_MAX_TRANSACT);
2315
2316         lpcfg_do_global_parameter_var(lp_ctx, "smb2 max read", "%u", DEFAULT_SMB2_MAX_READ);
2317
2318         lpcfg_do_global_parameter(lp_ctx, "durable handles", "yes");
2319
2320         lpcfg_do_global_parameter(lp_ctx, "max stat cache size", "256");
2321
2322         lpcfg_do_global_parameter(lp_ctx, "ldap passwd sync", "no");
2323
2324         lpcfg_do_global_parameter(lp_ctx, "kernel change notify", "yes");
2325
2326         lpcfg_do_global_parameter(lp_ctx, "max ttl", "259200");
2327
2328         lpcfg_do_global_parameter(lp_ctx, "blocking locks", "yes");
2329
2330         lpcfg_do_global_parameter(lp_ctx, "oplock contention limit", "2");
2331
2332         lpcfg_do_global_parameter(lp_ctx, "load printers", "yes");
2333
2334         lpcfg_do_global_parameter(lp_ctx, "idmap cache time", "604800");
2335
2336         lpcfg_do_global_parameter(lp_ctx, "preserve case", "yes");
2337
2338         lpcfg_do_global_parameter(lp_ctx, "lm announce", "auto");
2339
2340         lpcfg_do_global_parameter(lp_ctx, "afs token lifetime", "604800");
2341
2342         lpcfg_do_global_parameter(lp_ctx, "enable core files", "yes");
2343
2344         lpcfg_do_global_parameter(lp_ctx, "winbind max domain connections", "1");
2345
2346         lpcfg_do_global_parameter(lp_ctx, "case sensitive", "auto");
2347
2348         lpcfg_do_global_parameter(lp_ctx, "ldap timeout", "15");
2349
2350         lpcfg_do_global_parameter(lp_ctx, "mangle prefix", "1");
2351
2352         lpcfg_do_global_parameter(lp_ctx, "posix locking", "yes");
2353
2354         lpcfg_do_global_parameter(lp_ctx, "lock spin time", "200");
2355
2356         lpcfg_do_global_parameter(lp_ctx, "directory name cache size", "100");
2357
2358         lpcfg_do_global_parameter(lp_ctx, "nmbd bind explicit broadcast", "yes");
2359
2360         lpcfg_do_global_parameter(lp_ctx, "init logon delay", "100");
2361
2362         lpcfg_do_global_parameter(lp_ctx, "usershare owner only", "yes");
2363
2364         lpcfg_do_global_parameter(lp_ctx, "-valid", "yes");
2365
2366         lpcfg_do_global_parameter_var(lp_ctx, "usershare path", "%s/usershares", get_dyn_STATEDIR());
2367
2368 #ifdef DEVELOPER
2369         lpcfg_do_global_parameter_var(lp_ctx, "panic action", "/bin/sleep 999999999");
2370 #endif
2371
2372         lpcfg_do_global_parameter(lp_ctx, "smb passwd file", get_dyn_SMB_PASSWD_FILE());
2373
2374         lpcfg_do_global_parameter(lp_ctx, "logon home", "\\\\%N\\%U");
2375
2376         lpcfg_do_global_parameter(lp_ctx, "logon path", "\\\\%N\\%U\\profile");
2377
2378         lpcfg_do_global_parameter(lp_ctx, "printjob username", "%U");
2379
2380         for (i = 0; parm_table[i].label; i++) {
2381                 if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
2382                         lp_ctx->flags[i] |= FLAG_DEFAULT;
2383                 }
2384         }
2385
2386         for (parm=lp_ctx->globals->param_opt; parm; parm=parm->next) {
2387                 if (!(parm->priority & FLAG_CMDLINE)) {
2388                         parm->priority |= FLAG_DEFAULT;
2389                 }
2390         }
2391
2392         return lp_ctx;
2393 }
2394
2395 /**
2396  * Initialise the global parameter structure.
2397  */
2398 struct loadparm_context *loadparm_init_global(bool load_default)
2399 {
2400         if (global_loadparm_context == NULL) {
2401                 global_loadparm_context = loadparm_init(NULL);
2402         }
2403         if (global_loadparm_context == NULL) {
2404                 return NULL;
2405         }
2406         global_loadparm_context->global = true;
2407         if (load_default && !global_loadparm_context->loaded) {
2408                 lpcfg_load_default(global_loadparm_context);
2409         }
2410         global_loadparm_context->refuse_free = true;
2411         return global_loadparm_context;
2412 }
2413
2414 /**
2415  * Initialise the global parameter structure.
2416  */
2417 struct loadparm_context *loadparm_init_s3(TALLOC_CTX *mem_ctx, 
2418                                           const struct loadparm_s3_helpers *s3_fns)
2419 {
2420         struct loadparm_context *loadparm_context = talloc_zero(mem_ctx, struct loadparm_context);
2421         if (!loadparm_context) {
2422                 return NULL;
2423         }
2424         loadparm_context->s3_fns = s3_fns;
2425         loadparm_context->globals = s3_fns->globals;
2426         return loadparm_context;
2427 }
2428
2429 const char *lpcfg_configfile(struct loadparm_context *lp_ctx)
2430 {
2431         return lp_ctx->szConfigFile;
2432 }
2433
2434 const char *lp_default_path(void)
2435 {
2436     if (getenv("SMB_CONF_PATH"))
2437         return getenv("SMB_CONF_PATH");
2438     else
2439         return dyn_CONFIGFILE;
2440 }
2441
2442 /**
2443  * Update the internal state of a loadparm context after settings 
2444  * have changed.
2445  */
2446 static bool lpcfg_update(struct loadparm_context *lp_ctx)
2447 {
2448         struct debug_settings settings;
2449         TALLOC_CTX *tmp_ctx;
2450
2451         tmp_ctx = talloc_new(lp_ctx);
2452         if (tmp_ctx == NULL) {
2453                 return false;
2454         }
2455
2456         lpcfg_add_auto_services(lp_ctx, lpcfg_auto_services(lp_ctx, tmp_ctx));
2457
2458         if (!lp_ctx->globals->wins_server_list && lp_ctx->globals->we_are_a_wins_server) {
2459                 lpcfg_do_global_parameter(lp_ctx, "wins server", "127.0.0.1");
2460         }
2461
2462         if (!lp_ctx->global) {
2463                 TALLOC_FREE(tmp_ctx);
2464                 return true;
2465         }
2466
2467         panic_action = lp_ctx->globals->panic_action;
2468
2469         reload_charcnv(lp_ctx);
2470
2471         ZERO_STRUCT(settings);
2472         /* Add any more debug-related smb.conf parameters created in
2473          * future here */
2474         settings.syslog = lp_ctx->globals->syslog;
2475         settings.syslog_only = lp_ctx->globals->syslog_only;
2476         settings.timestamp_logs = lp_ctx->globals->timestamp_logs;
2477         settings.debug_prefix_timestamp = lp_ctx->globals->debug_prefix_timestamp;
2478         settings.debug_hires_timestamp = lp_ctx->globals->debug_hires_timestamp;
2479         settings.debug_pid = lp_ctx->globals->debug_pid;
2480         settings.debug_uid = lp_ctx->globals->debug_uid;
2481         settings.debug_class = lp_ctx->globals->debug_class;
2482         debug_set_settings(&settings);
2483
2484         /* FIXME: This is a bit of a hack, but we can't use a global, since 
2485          * not everything that uses lp also uses the socket library */
2486         if (lpcfg_parm_bool(lp_ctx, NULL, "socket", "testnonblock", false)) {
2487                 setenv("SOCKET_TESTNONBLOCK", "1", 1);
2488         } else {
2489                 unsetenv("SOCKET_TESTNONBLOCK");
2490         }
2491
2492         TALLOC_FREE(tmp_ctx);
2493         return true;
2494 }
2495
2496 bool lpcfg_load_default(struct loadparm_context *lp_ctx)
2497 {
2498     const char *path;
2499
2500     path = lp_default_path();
2501
2502     if (!file_exist(path)) {
2503             /* We allow the default smb.conf file to not exist, 
2504              * basically the equivalent of an empty file. */
2505             return lpcfg_update(lp_ctx);
2506     }
2507
2508     return lpcfg_load(lp_ctx, path);
2509 }
2510
2511 /**
2512  * Load the services array from the services file.
2513  *
2514  * Return True on success, False on failure.
2515  */
2516 bool lpcfg_load(struct loadparm_context *lp_ctx, const char *filename)
2517 {
2518         char *n2;
2519         bool bRetval;
2520
2521         filename = talloc_strdup(lp_ctx, filename);
2522
2523         lp_ctx->szConfigFile = filename;
2524
2525         if (lp_ctx->s3_fns) {
2526                 return lp_ctx->s3_fns->load(filename);
2527         }
2528
2529         lp_ctx->bInGlobalSection = true;
2530         n2 = standard_sub_basic(lp_ctx, lp_ctx->szConfigFile);
2531         DEBUG(2, ("lpcfg_load: refreshing parameters from %s\n", n2));
2532
2533         add_to_file_list(lp_ctx, lp_ctx->szConfigFile, n2);
2534
2535         /* We get sections first, so have to start 'behind' to make up */
2536         lp_ctx->currentService = NULL;
2537         bRetval = pm_process(n2, do_section, do_parameter, lp_ctx);
2538
2539         /* finish up the last section */
2540         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2541         if (bRetval)
2542                 if (lp_ctx->currentService != NULL)
2543                         bRetval = lpcfg_service_ok(lp_ctx->currentService);
2544
2545         bRetval = bRetval && lpcfg_update(lp_ctx);
2546
2547         /* we do this unconditionally, so that it happens even
2548            for a missing smb.conf */
2549         reload_charcnv(lp_ctx);
2550
2551         if (bRetval == true) {
2552                 /* set this up so that any child python tasks will
2553                    find the right smb.conf */
2554                 setenv("SMB_CONF_PATH", filename, 1);
2555
2556                 /* set the context used by the lp_*() function
2557                    varients */
2558                 global_loadparm_context = lp_ctx;
2559                 lp_ctx->loaded = true;
2560         }
2561
2562         return bRetval;
2563 }
2564
2565 /**
2566  * Return the max number of services.
2567  */
2568
2569 int lpcfg_numservices(struct loadparm_context *lp_ctx)
2570 {
2571         if (lp_ctx->s3_fns) {
2572                 return lp_ctx->s3_fns->get_numservices();
2573         }
2574
2575         return lp_ctx->iNumServices;
2576 }
2577
2578 /**
2579  * Display the contents of the services array in human-readable form.
2580  */
2581
2582 void lpcfg_dump(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults,
2583              int maxtoprint)
2584 {
2585         int iService;
2586
2587         if (lp_ctx->s3_fns) {
2588                 lp_ctx->s3_fns->dump(f, show_defaults, maxtoprint);
2589                 return;
2590         }
2591
2592         defaults_saved = !show_defaults;
2593
2594         dump_globals(lp_ctx, f, show_defaults);
2595
2596         dump_a_service(lp_ctx->sDefault, lp_ctx->sDefault, f, lp_ctx->flags);
2597
2598         for (iService = 0; iService < maxtoprint; iService++)
2599                 lpcfg_dump_one(f, show_defaults, lp_ctx->services[iService], lp_ctx->sDefault);
2600 }
2601
2602 /**
2603  * Display the contents of one service in human-readable form.
2604  */
2605 void lpcfg_dump_one(FILE *f, bool show_defaults, struct loadparm_service *service, struct loadparm_service *sDefault)
2606 {
2607         if (service != NULL) {
2608                 if (service->szService[0] == '\0')
2609                         return;
2610                 dump_a_service(service, sDefault, f, NULL);
2611         }
2612 }
2613
2614 struct loadparm_service *lpcfg_servicebynum(struct loadparm_context *lp_ctx,
2615                                             int snum)
2616 {
2617         if (lp_ctx->s3_fns) {
2618                 return lp_ctx->s3_fns->get_servicebynum(snum);
2619         }
2620
2621         return lp_ctx->services[snum];
2622 }
2623
2624 struct loadparm_service *lpcfg_service(struct loadparm_context *lp_ctx,
2625                                     const char *service_name)
2626 {
2627         int iService;
2628         char *serviceName;
2629
2630         if (lp_ctx->s3_fns) {
2631                 return lp_ctx->s3_fns->get_service(service_name);
2632         }
2633
2634         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) {
2635                 if (lp_ctx->services[iService] &&
2636                     lp_ctx->services[iService]->szService) {
2637                         /*
2638                          * The substitution here is used to support %U is
2639                          * service names
2640                          */
2641                         serviceName = standard_sub_basic(
2642                                         lp_ctx->services[iService],
2643                                         lp_ctx->services[iService]->szService);
2644                         if (strequal(serviceName, service_name)) {
2645                                 talloc_free(serviceName);
2646                                 return lp_ctx->services[iService];
2647                         }
2648                         talloc_free(serviceName);
2649                 }
2650         }
2651
2652         DEBUG(7,("lpcfg_servicenumber: couldn't find %s\n", service_name));
2653         return NULL;
2654 }
2655
2656 const char *lpcfg_servicename(const struct loadparm_service *service)
2657 {
2658         return lpcfg_string((const char *)service->szService);
2659 }
2660
2661 /**
2662  * A useful volume label function.
2663  */
2664 const char *lpcfg_volume_label(struct loadparm_service *service, struct loadparm_service *sDefault)
2665 {
2666         const char *ret;
2667         ret = lpcfg_string((const char *)((service != NULL && service->volume != NULL) ?
2668                                        service->volume : sDefault->volume));
2669         if (!*ret)
2670                 return lpcfg_servicename(service);
2671         return ret;
2672 }
2673
2674 /**
2675  * Return the correct printer name.
2676  */
2677 const char *lpcfg_printername(struct loadparm_service *service, struct loadparm_service *sDefault)
2678 {
2679         const char *ret;
2680         ret = lpcfg_string((const char *)((service != NULL && service->_printername != NULL) ?
2681                                        service->_printername : sDefault->_printername));
2682         if (ret == NULL || (ret != NULL && *ret == '\0'))
2683                 ret = lpcfg_servicename(service);
2684
2685         return ret;
2686 }
2687
2688
2689 /**
2690  * Return the max print jobs per queue.
2691  */
2692 int lpcfg_maxprintjobs(struct loadparm_service *service, struct loadparm_service *sDefault)
2693 {
2694         int maxjobs = (service != NULL) ? service->iMaxPrintJobs : sDefault->iMaxPrintJobs;
2695         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2696                 maxjobs = PRINT_MAX_JOBID - 1;
2697
2698         return maxjobs;
2699 }
2700
2701 struct smb_iconv_handle *lpcfg_iconv_handle(struct loadparm_context *lp_ctx)
2702 {
2703         if (lp_ctx == NULL) {
2704                 return get_iconv_handle();
2705         }
2706         return lp_ctx->iconv_handle;
2707 }
2708
2709 _PUBLIC_ void reload_charcnv(struct loadparm_context *lp_ctx)
2710 {
2711         struct smb_iconv_handle *old_ic = lp_ctx->iconv_handle;
2712         if (!lp_ctx->global) {
2713                 return;
2714         }
2715
2716         if (old_ic == NULL) {
2717                 old_ic = global_iconv_handle;
2718         }
2719         lp_ctx->iconv_handle = smb_iconv_handle_reinit_lp(lp_ctx, lp_ctx, old_ic);
2720         global_iconv_handle = lp_ctx->iconv_handle;
2721 }
2722
2723 _PUBLIC_ char *lpcfg_tls_keyfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2724 {
2725         return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_keyfile(lp_ctx));
2726 }
2727
2728 _PUBLIC_ char *lpcfg_tls_certfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2729 {
2730         return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_certfile(lp_ctx));
2731 }
2732
2733 _PUBLIC_ char *lpcfg_tls_cafile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2734 {
2735         return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_cafile(lp_ctx));
2736 }
2737
2738 _PUBLIC_ char *lpcfg_tls_crlfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2739 {
2740         return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_crlfile(lp_ctx));
2741 }
2742
2743 _PUBLIC_ char *lpcfg_tls_dhpfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2744 {
2745         return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_dhpfile(lp_ctx));
2746 }
2747
2748 struct gensec_settings *lpcfg_gensec_settings(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
2749 {
2750         struct gensec_settings *settings = talloc_zero(mem_ctx, struct gensec_settings);
2751         if (settings == NULL)
2752                 return NULL;
2753         SMB_ASSERT(lp_ctx != NULL);
2754         settings->lp_ctx = talloc_reference(settings, lp_ctx);
2755         settings->target_hostname = lpcfg_parm_string(lp_ctx, NULL, "gensec", "target_hostname");
2756         return settings;
2757 }
2758
2759 int lpcfg_server_role(struct loadparm_context *lp_ctx)
2760 {
2761         int domain_master = lpcfg__domain_master(lp_ctx);
2762
2763         return lp_find_server_role(lpcfg__server_role(lp_ctx),
2764                                    lpcfg__security(lp_ctx),
2765                                    lpcfg__domain_logons(lp_ctx),
2766                                    (domain_master == true) ||
2767                                    (domain_master == Auto));
2768 }
2769
2770 int lpcfg_security(struct loadparm_context *lp_ctx)
2771 {
2772         return lp_find_security(lpcfg__server_role(lp_ctx),
2773                                 lpcfg__security(lp_ctx));
2774 }
2775
2776 bool lpcfg_server_signing_allowed(struct loadparm_context *lp_ctx, bool *mandatory)
2777 {
2778         bool allowed = true;
2779         enum smb_signing_setting signing_setting = lpcfg_server_signing(lp_ctx);
2780
2781         *mandatory = false;
2782
2783         if (signing_setting == SMB_SIGNING_DEFAULT) {
2784                 /*
2785                  * If we are a domain controller, SMB signing is
2786                  * really important, as it can prevent a number of
2787                  * attacks on communications between us and the
2788                  * clients
2789                  *
2790                  * However, it really sucks (no sendfile, CPU
2791                  * overhead) performance-wise when used on a
2792                  * file server, so disable it by default
2793                  * on non-DCs
2794                  */
2795
2796                 if (lpcfg_server_role(lp_ctx) >= ROLE_ACTIVE_DIRECTORY_DC) {
2797                         signing_setting = SMB_SIGNING_REQUIRED;
2798                 } else {
2799                         signing_setting = SMB_SIGNING_OFF;
2800                 }
2801         }
2802
2803         switch (signing_setting) {
2804         case SMB_SIGNING_REQUIRED:
2805                 *mandatory = true;
2806                 break;
2807         case SMB_SIGNING_IF_REQUIRED:
2808                 break;
2809         case SMB_SIGNING_DEFAULT:
2810         case SMB_SIGNING_OFF:
2811                 allowed = false;
2812                 break;
2813         }
2814
2815         return allowed;
2816 }
2817
2818 int lpcfg_tdb_hash_size(struct loadparm_context *lp_ctx, const char *name)
2819 {
2820         const char *base;
2821
2822         if (name == NULL) {
2823                 return 0;
2824         }
2825
2826         base = strrchr_m(name, '/');
2827         if (base != NULL) {
2828                 base += 1;
2829         } else {
2830                 base = name;
2831         }
2832         return lpcfg_parm_int(lp_ctx, NULL, "tdb_hashsize", base, 0);
2833
2834 }
2835
2836 int lpcfg_tdb_flags(struct loadparm_context *lp_ctx, int tdb_flags)
2837 {
2838         if (!lpcfg_use_mmap(lp_ctx)) {
2839                 tdb_flags |= TDB_NOMMAP;
2840         }
2841         return tdb_flags;
2842 }