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