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