param: don't ignore some parameters when performing map_parameter
[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         if (asprintf(&s, "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR()) < 0) {
1077                 smb_panic("init_globals: ENOMEM");
1078         }
1079         Globals.spn_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
1080         SAFE_FREE(s);
1081
1082         Globals.nsupdate_command = (const char **)str_list_make_v3(NULL, "/usr/bin/nsupdate -g", NULL);
1083
1084         Globals.rndc_command = (const char **)str_list_make_v3(NULL, "/usr/sbin/rndc", NULL);
1085
1086         Globals.cldap_port = 389;
1087
1088         Globals.dgram_port = 138;
1089
1090         Globals.nbt_port = 137;
1091
1092         Globals.krb5_port = 88;
1093
1094         Globals.kpasswd_port = 464;
1095
1096         Globals.web_port = 901;
1097
1098         /* Now put back the settings that were set with lp_set_cmdline() */
1099         apply_lp_set_cmdline();
1100 }
1101
1102 /*******************************************************************
1103  Convenience routine to grab string parameters into talloced memory
1104  and run standard_sub_basic on them. The buffers can be written to by
1105  callers without affecting the source string.
1106 ********************************************************************/
1107
1108 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1109 {
1110         char *ret;
1111
1112         /* The follow debug is useful for tracking down memory problems
1113            especially if you have an inner loop that is calling a lp_*()
1114            function that returns a string.  Perhaps this debug should be
1115            present all the time? */
1116
1117 #if 0
1118         DEBUG(10, ("lp_string(%s)\n", s));
1119 #endif
1120         if (!s) {
1121                 return NULL;
1122         }
1123
1124         ret = talloc_sub_basic(ctx,
1125                         get_current_username(),
1126                         current_user_info.domain,
1127                         s);
1128         if (trim_char(ret, '\"', '\"')) {
1129                 if (strchr(ret,'\"') != NULL) {
1130                         TALLOC_FREE(ret);
1131                         ret = talloc_sub_basic(ctx,
1132                                         get_current_username(),
1133                                         current_user_info.domain,
1134                                         s);
1135                 }
1136         }
1137         return ret;
1138 }
1139
1140 /*
1141    In this section all the functions that are used to access the
1142    parameters from the rest of the program are defined
1143 */
1144
1145 #define FN_GLOBAL_STRING(fn_name,ptr) \
1146 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1147 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1148  const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1149 #define FN_GLOBAL_LIST(fn_name,ptr) \
1150  const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1151 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1152  bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1153 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1154  char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1155 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1156  int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1157
1158 #define FN_LOCAL_STRING(fn_name,val) \
1159 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));}
1160 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1161  const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1162 #define FN_LOCAL_LIST(fn_name,val) \
1163  const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1164 #define FN_LOCAL_BOOL(fn_name,val) \
1165  bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1166 #define FN_LOCAL_INTEGER(fn_name,val) \
1167  int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1168
1169 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1170  bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1171 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1172  int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1173 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
1174  char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1175
1176
1177 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1178 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1179
1180 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1181  * build process or in smb.conf, we use that value.  Otherwise they
1182  * default to the value of lp_lockdir(). */
1183 const char *lp_statedir(void) {
1184         if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1185             (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1186                 return(*(char **)(&Globals.szStateDir) ?
1187                        *(char **)(&Globals.szStateDir) : "");
1188         else
1189                 return(*(char **)(&Globals.lockdir) ?
1190                        *(char **)(&Globals.lockdir) : "");
1191 }
1192 const char *lp_cachedir(void) {
1193         if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1194             (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1195                 return(*(char **)(&Globals.szCacheDir) ?
1196                        *(char **)(&Globals.szCacheDir) : "");
1197         else
1198                 return(*(char **)(&Globals.lockdir) ?
1199                        *(char **)(&Globals.lockdir) : "");
1200 }
1201 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1202                   winbindMaxDomainConnections)
1203
1204 int lp_winbind_max_domain_connections(void)
1205 {
1206         if (lp_winbind_offline_logon() &&
1207             lp_winbind_max_domain_connections_int() > 1) {
1208                 DEBUG(1, ("offline logons active, restricting max domain "
1209                           "connections to 1\n"));
1210                 return 1;
1211         }
1212         return MAX(1, lp_winbind_max_domain_connections_int());
1213 }
1214
1215 int lp_smb2_max_credits(void)
1216 {
1217         if (Globals.ismb2_max_credits == 0) {
1218                 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1219         }
1220         return Globals.ismb2_max_credits;
1221 }
1222 int lp_cups_encrypt(void)
1223 {
1224         int result = 0;
1225 #ifdef HAVE_HTTPCONNECTENCRYPT
1226         switch (Globals.CupsEncrypt) {
1227                 case Auto:
1228                         result = HTTP_ENCRYPT_REQUIRED;
1229                         break;
1230                 case true:
1231                         result = HTTP_ENCRYPT_ALWAYS;
1232                         break;
1233                 case false:
1234                         result = HTTP_ENCRYPT_NEVER;
1235                         break;
1236         }
1237 #endif
1238         return result;
1239 }
1240
1241 /* These functions remain in source3/param for now */
1242
1243 FN_GLOBAL_STRING(configfile, szConfigFile)
1244
1245 #include "lib/param/param_functions.c"
1246
1247 FN_LOCAL_STRING(servicename, szService)
1248 FN_LOCAL_CONST_STRING(const_servicename, szService)
1249
1250 /* local prototypes */
1251
1252 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1253 static const char *get_boolean(bool bool_value);
1254 static int getservicebyname(const char *pszServiceName,
1255                             struct loadparm_service *pserviceDest);
1256 static void copy_service(struct loadparm_service *pserviceDest,
1257                          struct loadparm_service *pserviceSource,
1258                          struct bitmap *pcopymapDest);
1259 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1260                          void *userdata);
1261 static bool do_section(const char *pszSectionName, void *userdata);
1262 static void init_copymap(struct loadparm_service *pservice);
1263 static bool hash_a_service(const char *name, int number);
1264 static void free_service_byindex(int iService);
1265 static void show_parameter(int parmIndex);
1266 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1267
1268 /*
1269  * This is a helper function for parametrical options support.  It returns a
1270  * pointer to parametrical option value if it exists or NULL otherwise. Actual
1271  * parametrical functions are quite simple
1272  */
1273 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1274                                                            const char *option)
1275 {
1276         bool global_section = false;
1277         char* param_key;
1278         struct parmlist_entry *data;
1279
1280         if (service == NULL) {
1281                 data = Globals.param_opt;
1282                 global_section = true;
1283         } else {
1284                 data = service->param_opt;
1285         }
1286
1287         if (asprintf(&param_key, "%s:%s", type, option) == -1) {
1288                 DEBUG(0,("asprintf failed!\n"));
1289                 return NULL;
1290         }
1291
1292         while (data) {
1293                 if (strwicmp(data->key, param_key) == 0) {
1294                         string_free(&param_key);
1295                         return data;
1296                 }
1297                 data = data->next;
1298         }
1299
1300         if (!global_section) {
1301                 /* Try to fetch the same option but from globals */
1302                 /* but only if we are not already working with Globals */
1303                 data = Globals.param_opt;
1304                 while (data) {
1305                         if (strwicmp(data->key, param_key) == 0) {
1306                                 string_free(&param_key);
1307                                 return data;
1308                         }
1309                         data = data->next;
1310                 }
1311         }
1312
1313         string_free(&param_key);
1314
1315         return NULL;
1316 }
1317
1318 /*
1319  * This is a helper function for parametrical options support.  It returns a
1320  * pointer to parametrical option value if it exists or NULL otherwise. Actual
1321  * parametrical functions are quite simple
1322  */
1323 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1324                                                 const char *option)
1325 {
1326         if (snum >= iNumServices) return NULL;
1327
1328         if (snum < 0) {
1329                 return get_parametrics_by_service(NULL, type, option);
1330         } else {
1331                 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1332         }
1333 }
1334
1335
1336 #define MISSING_PARAMETER(name) \
1337     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1338
1339 /*******************************************************************
1340 convenience routine to return int parameters.
1341 ********************************************************************/
1342 static int lp_int(const char *s)
1343 {
1344
1345         if (!s || !*s) {
1346                 MISSING_PARAMETER(lp_int);
1347                 return (-1);
1348         }
1349
1350         return (int)strtol(s, NULL, 0);
1351 }
1352
1353 /*******************************************************************
1354 convenience routine to return unsigned long parameters.
1355 ********************************************************************/
1356 static unsigned long lp_ulong(const char *s)
1357 {
1358
1359         if (!s || !*s) {
1360                 MISSING_PARAMETER(lp_ulong);
1361                 return (0);
1362         }
1363
1364         return strtoul(s, NULL, 0);
1365 }
1366
1367 /*******************************************************************
1368 convenience routine to return boolean parameters.
1369 ********************************************************************/
1370 static bool lp_bool(const char *s)
1371 {
1372         bool ret = false;
1373
1374         if (!s || !*s) {
1375                 MISSING_PARAMETER(lp_bool);
1376                 return false;
1377         }
1378
1379         if (!set_boolean(s, &ret)) {
1380                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1381                 return false;
1382         }
1383
1384         return ret;
1385 }
1386
1387 /*******************************************************************
1388 convenience routine to return enum parameters.
1389 ********************************************************************/
1390 static int lp_enum(const char *s,const struct enum_list *_enum)
1391 {
1392         int i;
1393
1394         if (!s || !*s || !_enum) {
1395                 MISSING_PARAMETER(lp_enum);
1396                 return (-1);
1397         }
1398
1399         for (i=0; _enum[i].name; i++) {
1400                 if (strequal(_enum[i].name,s))
1401                         return _enum[i].value;
1402         }
1403
1404         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1405         return (-1);
1406 }
1407
1408 #undef MISSING_PARAMETER
1409
1410 /* Return parametric option from a given service. Type is a part of option before ':' */
1411 /* Parametric option has following syntax: 'Type: option = value' */
1412 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1413 {
1414         struct parmlist_entry *data = get_parametrics(snum, type, option);
1415
1416         if (data == NULL||data->value==NULL) {
1417                 if (def) {
1418                         return lp_string(ctx, def);
1419                 } else {
1420                         return NULL;
1421                 }
1422         }
1423
1424         return lp_string(ctx, data->value);
1425 }
1426
1427 /* Return parametric option from a given service. Type is a part of option before ':' */
1428 /* Parametric option has following syntax: 'Type: option = value' */
1429 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1430 {
1431         struct parmlist_entry *data = get_parametrics(snum, type, option);
1432
1433         if (data == NULL||data->value==NULL)
1434                 return def;
1435
1436         return data->value;
1437 }
1438
1439 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1440 {
1441         struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1442
1443         if (data == NULL||data->value==NULL)
1444                 return NULL;
1445
1446         return data->value;
1447 }
1448
1449
1450 /* Return parametric option from a given service. Type is a part of option before ':' */
1451 /* Parametric option has following syntax: 'Type: option = value' */
1452
1453 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1454 {
1455         struct parmlist_entry *data = get_parametrics(snum, type, option);
1456
1457         if (data == NULL||data->value==NULL)
1458                 return (const char **)def;
1459
1460         if (data->list==NULL) {
1461                 data->list = str_list_make_v3(NULL, data->value, NULL);
1462         }
1463
1464         return (const char **)data->list;
1465 }
1466
1467 /* Return parametric option from a given service. Type is a part of option before ':' */
1468 /* Parametric option has following syntax: 'Type: option = value' */
1469
1470 int lp_parm_int(int snum, const char *type, const char *option, int def)
1471 {
1472         struct parmlist_entry *data = get_parametrics(snum, type, option);
1473
1474         if (data && data->value && *data->value)
1475                 return lp_int(data->value);
1476
1477         return def;
1478 }
1479
1480 /* Return parametric option from a given service. Type is a part of option before ':' */
1481 /* Parametric option has following syntax: 'Type: option = value' */
1482
1483 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1484 {
1485         struct parmlist_entry *data = get_parametrics(snum, type, option);
1486
1487         if (data && data->value && *data->value)
1488                 return lp_ulong(data->value);
1489
1490         return def;
1491 }
1492
1493 /* Return parametric option from a given service. Type is a part of option before ':' */
1494 /* Parametric option has following syntax: 'Type: option = value' */
1495
1496 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1497 {
1498         struct parmlist_entry *data = get_parametrics(snum, type, option);
1499
1500         if (data && data->value && *data->value)
1501                 return lp_bool(data->value);
1502
1503         return def;
1504 }
1505
1506 /* Return parametric option from a given service. Type is a part of option before ':' */
1507 /* Parametric option has following syntax: 'Type: option = value' */
1508
1509 int lp_parm_enum(int snum, const char *type, const char *option,
1510                  const struct enum_list *_enum, int def)
1511 {
1512         struct parmlist_entry *data = get_parametrics(snum, type, option);
1513
1514         if (data && data->value && *data->value && _enum)
1515                 return lp_enum(data->value, _enum);
1516
1517         return def;
1518 }
1519
1520
1521 /***************************************************************************
1522  Initialise a service to the defaults.
1523 ***************************************************************************/
1524
1525 static void init_service(struct loadparm_service *pservice)
1526 {
1527         memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1528         copy_service(pservice, &sDefault, NULL);
1529 }
1530
1531
1532 /**
1533  * free a param_opts structure.
1534  * param_opts handling should be moved to talloc;
1535  * then this whole functions reduces to a TALLOC_FREE().
1536  */
1537
1538 static void free_param_opts(struct parmlist_entry **popts)
1539 {
1540         struct parmlist_entry *opt, *next_opt;
1541
1542         if (*popts != NULL) {
1543                 DEBUG(5, ("Freeing parametrics:\n"));
1544         }
1545         opt = *popts;
1546         while (opt != NULL) {
1547                 string_free(&opt->key);
1548                 string_free(&opt->value);
1549                 TALLOC_FREE(opt->list);
1550                 next_opt = opt->next;
1551                 SAFE_FREE(opt);
1552                 opt = next_opt;
1553         }
1554         *popts = NULL;
1555 }
1556
1557 /***************************************************************************
1558  Free the dynamically allocated parts of a service struct.
1559 ***************************************************************************/
1560
1561 static void free_service(struct loadparm_service *pservice)
1562 {
1563         if (!pservice)
1564                 return;
1565
1566         if (pservice->szService)
1567                 DEBUG(5, ("free_service: Freeing service %s\n",
1568                        pservice->szService));
1569
1570         free_parameters(pservice);
1571
1572         string_free(&pservice->szService);
1573         TALLOC_FREE(pservice->copymap);
1574
1575         free_param_opts(&pservice->param_opt);
1576
1577         ZERO_STRUCTP(pservice);
1578 }
1579
1580
1581 /***************************************************************************
1582  remove a service indexed in the ServicePtrs array from the ServiceHash
1583  and free the dynamically allocated parts
1584 ***************************************************************************/
1585
1586 static void free_service_byindex(int idx)
1587 {
1588         if ( !LP_SNUM_OK(idx) ) 
1589                 return;
1590
1591         ServicePtrs[idx]->valid = false;
1592
1593         /* we have to cleanup the hash record */
1594
1595         if (ServicePtrs[idx]->szService) {
1596                 char *canon_name = canonicalize_servicename(
1597                         talloc_tos(),
1598                         ServicePtrs[idx]->szService );
1599
1600                 dbwrap_delete_bystring(ServiceHash, canon_name );
1601                 TALLOC_FREE(canon_name);
1602         }
1603
1604         free_service(ServicePtrs[idx]);
1605         talloc_free_children(ServicePtrs[idx]);
1606 }
1607
1608 /***************************************************************************
1609  Add a new service to the services array initialising it with the given 
1610  service. 
1611 ***************************************************************************/
1612
1613 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1614 {
1615         int i;
1616         struct loadparm_service tservice;
1617         int num_to_alloc = iNumServices + 1;
1618         struct loadparm_service **tsp = NULL;
1619
1620         tservice = *pservice;
1621
1622         /* it might already exist */
1623         if (name) {
1624                 i = getservicebyname(name, NULL);
1625                 if (i >= 0) {
1626                         return (i);
1627                 }
1628         }
1629
1630         /* if not, then create one */
1631         i = iNumServices;
1632         tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1633         if (tsp == NULL) {
1634                 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1635                 return (-1);
1636         }
1637         ServicePtrs = tsp;
1638         ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1639         if (!ServicePtrs[iNumServices]) {
1640                 DEBUG(0,("add_a_service: out of memory!\n"));
1641                 return (-1);
1642         }
1643         iNumServices++;
1644
1645         ServicePtrs[i]->valid = true;
1646
1647         init_service(ServicePtrs[i]);
1648         copy_service(ServicePtrs[i], &tservice, NULL);
1649         if (name)
1650                 string_set(&ServicePtrs[i]->szService, name);
1651
1652         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
1653                 i, ServicePtrs[i]->szService));
1654
1655         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1656                 return (-1);
1657         }
1658
1659         return (i);
1660 }
1661
1662 /***************************************************************************
1663   Convert a string to uppercase and remove whitespaces.
1664 ***************************************************************************/
1665
1666 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1667 {
1668         char *result;
1669
1670         if ( !src ) {
1671                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1672                 return NULL;
1673         }
1674
1675         result = talloc_strdup(ctx, src);
1676         SMB_ASSERT(result != NULL);
1677
1678         if (!strlower_m(result)) {
1679                 TALLOC_FREE(result);
1680                 return NULL;
1681         }
1682         return result;
1683 }
1684
1685 /***************************************************************************
1686   Add a name/index pair for the services array to the hash table.
1687 ***************************************************************************/
1688
1689 static bool hash_a_service(const char *name, int idx)
1690 {
1691         char *canon_name;
1692
1693         if ( !ServiceHash ) {
1694                 DEBUG(10,("hash_a_service: creating servicehash\n"));
1695                 ServiceHash = db_open_rbt(NULL);
1696                 if ( !ServiceHash ) {
1697                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1698                         return false;
1699                 }
1700         }
1701
1702         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1703                 idx, name));
1704
1705         canon_name = canonicalize_servicename(talloc_tos(), name );
1706
1707         dbwrap_store_bystring(ServiceHash, canon_name,
1708                               make_tdb_data((uint8 *)&idx, sizeof(idx)),
1709                               TDB_REPLACE);
1710
1711         TALLOC_FREE(canon_name);
1712
1713         return true;
1714 }
1715
1716 /***************************************************************************
1717  Add a new home service, with the specified home directory, defaults coming
1718  from service ifrom.
1719 ***************************************************************************/
1720
1721 bool lp_add_home(const char *pszHomename, int iDefaultService,
1722                  const char *user, const char *pszHomedir)
1723 {
1724         int i;
1725
1726         if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1727                         pszHomedir[0] == '\0') {
1728                 return false;
1729         }
1730
1731         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1732
1733         if (i < 0)
1734                 return false;
1735
1736         if (!(*(ServicePtrs[iDefaultService]->pathname))
1737             || strequal(ServicePtrs[iDefaultService]->pathname,
1738                         lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1739                 string_set(&ServicePtrs[i]->pathname, pszHomedir);
1740         }
1741
1742         if (!(*(ServicePtrs[i]->comment))) {
1743                 char *comment = NULL;
1744                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1745                         return false;
1746                 }
1747                 string_set(&ServicePtrs[i]->comment, comment);
1748                 SAFE_FREE(comment);
1749         }
1750
1751         /* set the browseable flag from the global default */
1752
1753         ServicePtrs[i]->browseable = sDefault.browseable;
1754         ServicePtrs[i]->access_based_share_enum = sDefault.access_based_share_enum;
1755
1756         ServicePtrs[i]->autoloaded = true;
1757
1758         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
1759                user, ServicePtrs[i]->pathname ));
1760
1761         return true;
1762 }
1763
1764 /***************************************************************************
1765  Add a new service, based on an old one.
1766 ***************************************************************************/
1767
1768 int lp_add_service(const char *pszService, int iDefaultService)
1769 {
1770         if (iDefaultService < 0) {
1771                 return add_a_service(&sDefault, pszService);
1772         }
1773
1774         return (add_a_service(ServicePtrs[iDefaultService], pszService));
1775 }
1776
1777 /***************************************************************************
1778  Add the IPC service.
1779 ***************************************************************************/
1780
1781 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1782 {
1783         char *comment = NULL;
1784         int i = add_a_service(&sDefault, ipc_name);
1785
1786         if (i < 0)
1787                 return false;
1788
1789         if (asprintf(&comment, "IPC Service (%s)",
1790                                 Globals.serverstring) < 0) {
1791                 return false;
1792         }
1793
1794         string_set(&ServicePtrs[i]->pathname, tmpdir());
1795         string_set(&ServicePtrs[i]->username, "");
1796         string_set(&ServicePtrs[i]->comment, comment);
1797         string_set(&ServicePtrs[i]->fstype, "IPC");
1798         ServicePtrs[i]->max_connections = 0;
1799         ServicePtrs[i]->bAvailable = true;
1800         ServicePtrs[i]->readonly = true;
1801         ServicePtrs[i]->guest_only = false;
1802         ServicePtrs[i]->administrative_share = true;
1803         ServicePtrs[i]->guest_ok = guest_ok;
1804         ServicePtrs[i]->print_ok = false;
1805         ServicePtrs[i]->browseable = sDefault.browseable;
1806
1807         DEBUG(3, ("adding IPC service\n"));
1808
1809         SAFE_FREE(comment);
1810         return true;
1811 }
1812
1813 /***************************************************************************
1814  Add a new printer service, with defaults coming from service iFrom.
1815 ***************************************************************************/
1816
1817 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1818 {
1819         const char *comment = "From Printcap";
1820         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1821
1822         if (i < 0)
1823                 return false;
1824
1825         /* note that we do NOT default the availability flag to true - */
1826         /* we take it from the default service passed. This allows all */
1827         /* dynamic printers to be disabled by disabling the [printers] */
1828         /* entry (if/when the 'available' keyword is implemented!).    */
1829
1830         /* the printer name is set to the service name. */
1831         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1832         string_set(&ServicePtrs[i]->comment, comment);
1833
1834         /* set the browseable flag from the gloabl default */
1835         ServicePtrs[i]->browseable = sDefault.browseable;
1836
1837         /* Printers cannot be read_only. */
1838         ServicePtrs[i]->readonly = false;
1839         /* No oplocks on printer services. */
1840         ServicePtrs[i]->oplocks = false;
1841         /* Printer services must be printable. */
1842         ServicePtrs[i]->print_ok = true;
1843
1844         DEBUG(3, ("adding printer service %s\n", pszPrintername));
1845
1846         return true;
1847 }
1848
1849
1850 /***************************************************************************
1851  Check whether the given parameter name is valid.
1852  Parametric options (names containing a colon) are considered valid.
1853 ***************************************************************************/
1854
1855 bool lp_parameter_is_valid(const char *pszParmName)
1856 {
1857         return ((map_parameter(pszParmName) != -1) ||
1858                 (strchr(pszParmName, ':') != NULL));
1859 }
1860
1861 /***************************************************************************
1862  Check whether the given name is the name of a global parameter.
1863  Returns true for strings belonging to parameters of class
1864  P_GLOBAL, false for all other strings, also for parametric options
1865  and strings not belonging to any option.
1866 ***************************************************************************/
1867
1868 bool lp_parameter_is_global(const char *pszParmName)
1869 {
1870         int num = map_parameter(pszParmName);
1871
1872         if (num >= 0) {
1873                 return (parm_table[num].p_class == P_GLOBAL);
1874         }
1875
1876         return false;
1877 }
1878
1879 /**************************************************************************
1880  Check whether the given name is the canonical name of a parameter.
1881  Returns false if it is not a valid parameter Name.
1882  For parametric options, true is returned.
1883 **************************************************************************/
1884
1885 bool lp_parameter_is_canonical(const char *parm_name)
1886 {
1887         if (!lp_parameter_is_valid(parm_name)) {
1888                 return false;
1889         }
1890
1891         return (map_parameter(parm_name) ==
1892                 map_parameter_canonical(parm_name, NULL));
1893 }
1894
1895 /**************************************************************************
1896  Determine the canonical name for a parameter.
1897  Indicate when it is an inverse (boolean) synonym instead of a
1898  "usual" synonym.
1899 **************************************************************************/
1900
1901 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1902                                bool *inverse)
1903 {
1904         int num;
1905
1906         if (!lp_parameter_is_valid(parm_name)) {
1907                 *canon_parm = NULL;
1908                 return false;
1909         }
1910
1911         num = map_parameter_canonical(parm_name, inverse);
1912         if (num < 0) {
1913                 /* parametric option */
1914                 *canon_parm = parm_name;
1915         } else {
1916                 *canon_parm = parm_table[num].label;
1917         }
1918
1919         return true;
1920
1921 }
1922
1923 /**************************************************************************
1924  Determine the canonical name for a parameter.
1925  Turn the value given into the inverse boolean expression when
1926  the synonym is an invers boolean synonym.
1927
1928  Return true if parm_name is a valid parameter name and
1929  in case it is an invers boolean synonym, if the val string could
1930  successfully be converted to the reverse bool.
1931  Return false in all other cases.
1932 **************************************************************************/
1933
1934 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1935                                           const char *val,
1936                                           const char **canon_parm,
1937                                           const char **canon_val)
1938 {
1939         int num;
1940         bool inverse;
1941
1942         if (!lp_parameter_is_valid(parm_name)) {
1943                 *canon_parm = NULL;
1944                 *canon_val = NULL;
1945                 return false;
1946         }
1947
1948         num = map_parameter_canonical(parm_name, &inverse);
1949         if (num < 0) {
1950                 /* parametric option */
1951                 *canon_parm = parm_name;
1952                 *canon_val = val;
1953         } else {
1954                 *canon_parm = parm_table[num].label;
1955                 if (inverse) {
1956                         if (!lp_invert_boolean(val, canon_val)) {
1957                                 *canon_val = NULL;
1958                                 return false;
1959                         }
1960                 } else {
1961                         *canon_val = val;
1962                 }
1963         }
1964
1965         return true;
1966 }
1967
1968 /***************************************************************************
1969  Map a parameter's string representation to something we can use. 
1970  Returns false if the parameter string is not recognised, else TRUE.
1971 ***************************************************************************/
1972
1973 static int map_parameter(const char *pszParmName)
1974 {
1975         int iIndex;
1976
1977         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1978                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1979                         return (iIndex);
1980
1981         /* Warn only if it isn't parametric option */
1982         if (strchr(pszParmName, ':') == NULL)
1983                 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1984         /* We do return 'fail' for parametric options as well because they are
1985            stored in different storage
1986          */
1987         return (-1);
1988 }
1989
1990 /***************************************************************************
1991  Map a parameter's string representation to the index of the canonical
1992  form of the parameter (it might be a synonym).
1993  Returns -1 if the parameter string is not recognised.
1994 ***************************************************************************/
1995
1996 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1997 {
1998         int parm_num, canon_num;
1999         bool loc_inverse = false;
2000
2001         parm_num = map_parameter(pszParmName);
2002         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
2003                 /* invalid, parametric or no canidate for synonyms ... */
2004                 goto done;
2005         }
2006
2007         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
2008                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
2009                         parm_num = canon_num;
2010                         goto done;
2011                 }
2012         }
2013
2014 done:
2015         if (inverse != NULL) {
2016                 *inverse = loc_inverse;
2017         }
2018         return parm_num;
2019 }
2020
2021 /***************************************************************************
2022  return true if parameter number parm1 is a synonym of parameter
2023  number parm2 (parm2 being the principal name).
2024  set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
2025  false otherwise.
2026 ***************************************************************************/
2027
2028 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
2029 {
2030         if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
2031             (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
2032             (parm_table[parm1].flags & FLAG_HIDE) &&
2033             !(parm_table[parm2].flags & FLAG_HIDE))
2034         {
2035                 if (inverse != NULL) {
2036                         if ((parm_table[parm1].type == P_BOOLREV) &&
2037                             (parm_table[parm2].type == P_BOOL))
2038                         {
2039                                 *inverse = true;
2040                         } else {
2041                                 *inverse = false;
2042                         }
2043                 }
2044                 return true;
2045         }
2046         return false;
2047 }
2048
2049 /***************************************************************************
2050  Show one parameter's name, type, [values,] and flags.
2051  (helper functions for show_parameter_list)
2052 ***************************************************************************/
2053
2054 static void show_parameter(int parmIndex)
2055 {
2056         int enumIndex, flagIndex;
2057         int parmIndex2;
2058         bool hadFlag;
2059         bool hadSyn;
2060         bool inverse;
2061         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2062                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2063                 "P_ENUM", "P_SEP"};
2064         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2065                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2066                 FLAG_HIDE};
2067         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2068                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2069                 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2070
2071         printf("%s=%s", parm_table[parmIndex].label,
2072                type[parm_table[parmIndex].type]);
2073         if (parm_table[parmIndex].type == P_ENUM) {
2074                 printf(",");
2075                 for (enumIndex=0;
2076                      parm_table[parmIndex].enum_list[enumIndex].name;
2077                      enumIndex++)
2078                 {
2079                         printf("%s%s",
2080                                enumIndex ? "|" : "",
2081                                parm_table[parmIndex].enum_list[enumIndex].name);
2082                 }
2083         }
2084         printf(",");
2085         hadFlag = false;
2086         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2087                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2088                         printf("%s%s",
2089                                 hadFlag ? "|" : "",
2090                                 flag_names[flagIndex]);
2091                         hadFlag = true;
2092                 }
2093         }
2094
2095         /* output synonyms */
2096         hadSyn = false;
2097         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2098                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2099                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2100                                parm_table[parmIndex2].label);
2101                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2102                         if (!hadSyn) {
2103                                 printf(" (synonyms: ");
2104                                 hadSyn = true;
2105                         } else {
2106                                 printf(", ");
2107                         }
2108                         printf("%s%s", parm_table[parmIndex2].label,
2109                                inverse ? "[i]" : "");
2110                 }
2111         }
2112         if (hadSyn) {
2113                 printf(")");
2114         }
2115
2116         printf("\n");
2117 }
2118
2119 /***************************************************************************
2120  Show all parameter's name, type, [values,] and flags.
2121 ***************************************************************************/
2122
2123 void show_parameter_list(void)
2124 {
2125         int classIndex, parmIndex;
2126         const char *section_names[] = { "local", "global", NULL};
2127
2128         for (classIndex=0; section_names[classIndex]; classIndex++) {
2129                 printf("[%s]\n", section_names[classIndex]);
2130                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2131                         if (parm_table[parmIndex].p_class == classIndex) {
2132                                 show_parameter(parmIndex);
2133                         }
2134                 }
2135         }
2136 }
2137
2138 /***************************************************************************
2139  Check if a given string correctly represents a boolean value.
2140 ***************************************************************************/
2141
2142 bool lp_string_is_valid_boolean(const char *parm_value)
2143 {
2144         return set_boolean(parm_value, NULL);
2145 }
2146
2147 /***************************************************************************
2148  Get the standard string representation of a boolean value ("yes" or "no")
2149 ***************************************************************************/
2150
2151 static const char *get_boolean(bool bool_value)
2152 {
2153         static const char *yes_str = "yes";
2154         static const char *no_str = "no";
2155
2156         return (bool_value ? yes_str : no_str);
2157 }
2158
2159 /***************************************************************************
2160  Provide the string of the negated boolean value associated to the boolean
2161  given as a string. Returns false if the passed string does not correctly
2162  represent a boolean.
2163 ***************************************************************************/
2164
2165 bool lp_invert_boolean(const char *str, const char **inverse_str)
2166 {
2167         bool val;
2168
2169         if (!set_boolean(str, &val)) {
2170                 return false;
2171         }
2172
2173         *inverse_str = get_boolean(!val);
2174         return true;
2175 }
2176
2177 /***************************************************************************
2178  Provide the canonical string representation of a boolean value given
2179  as a string. Return true on success, false if the string given does
2180  not correctly represent a boolean.
2181 ***************************************************************************/
2182
2183 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2184 {
2185         bool val;
2186
2187         if (!set_boolean(str, &val)) {
2188                 return false;
2189         }
2190
2191         *canon_str = get_boolean(val);
2192         return true;
2193 }
2194
2195 /***************************************************************************
2196 Find a service by name. Otherwise works like get_service.
2197 ***************************************************************************/
2198
2199 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2200 {
2201         int iService = -1;
2202         char *canon_name;
2203         TDB_DATA data;
2204         NTSTATUS status;
2205
2206         if (ServiceHash == NULL) {
2207                 return -1;
2208         }
2209
2210         canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2211
2212         status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2213                                        &data);
2214
2215         if (NT_STATUS_IS_OK(status) &&
2216             (data.dptr != NULL) &&
2217             (data.dsize == sizeof(iService)))
2218         {
2219                 iService = *(int *)data.dptr;
2220         }
2221
2222         TALLOC_FREE(canon_name);
2223
2224         if ((iService != -1) && (LP_SNUM_OK(iService))
2225             && (pserviceDest != NULL)) {
2226                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2227         }
2228
2229         return (iService);
2230 }
2231
2232 /* Return a pointer to a service by name.  Unlike getservicebyname, it does not copy the service */
2233 struct loadparm_service *lp_service(const char *pszServiceName)
2234 {
2235         int iService = getservicebyname(pszServiceName, NULL);
2236         if (iService == -1 || !LP_SNUM_OK(iService)) {
2237                 return NULL;
2238         }
2239         return ServicePtrs[iService];
2240 }
2241
2242 struct loadparm_service *lp_servicebynum(int snum)
2243 {
2244         if ((snum == -1) || !LP_SNUM_OK(snum)) {
2245                 return NULL;
2246         }
2247         return ServicePtrs[snum];
2248 }
2249
2250 struct loadparm_service *lp_default_loadparm_service()
2251 {
2252         return &sDefault;
2253 }
2254
2255
2256 /***************************************************************************
2257  Copy a service structure to another.
2258  If pcopymapDest is NULL then copy all fields
2259 ***************************************************************************/
2260
2261 /**
2262  * Add a parametric option to a parmlist_entry,
2263  * replacing old value, if already present.
2264  */
2265 static void set_param_opt(struct parmlist_entry **opt_list,
2266                           const char *opt_name,
2267                           const char *opt_value,
2268                           unsigned priority)
2269 {
2270         struct parmlist_entry *new_opt, *opt;
2271         bool not_added;
2272
2273         opt = *opt_list;
2274         not_added = true;
2275
2276         /* Traverse destination */
2277         while (opt) {
2278                 /* If we already have same option, override it */
2279                 if (strwicmp(opt->key, opt_name) == 0) {
2280                         if ((opt->priority & FLAG_CMDLINE) &&
2281                             !(priority & FLAG_CMDLINE)) {
2282                                 /* it's been marked as not to be
2283                                    overridden */
2284                                 return;
2285                         }
2286                         string_free(&opt->value);
2287                         TALLOC_FREE(opt->list);
2288                         opt->value = SMB_STRDUP(opt_value);
2289                         opt->priority = priority;
2290                         not_added = false;
2291                         break;
2292                 }
2293                 opt = opt->next;
2294         }
2295         if (not_added) {
2296             new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2297             new_opt->key = SMB_STRDUP(opt_name);
2298             new_opt->value = SMB_STRDUP(opt_value);
2299             new_opt->list = NULL;
2300             new_opt->priority = priority;
2301             DLIST_ADD(*opt_list, new_opt);
2302         }
2303 }
2304
2305 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2306                          struct bitmap *pcopymapDest)
2307 {
2308         int i;
2309         bool bcopyall = (pcopymapDest == NULL);
2310         struct parmlist_entry *data;
2311
2312         for (i = 0; parm_table[i].label; i++)
2313                 if (parm_table[i].p_class == P_LOCAL &&
2314                     (bcopyall || bitmap_query(pcopymapDest,i))) {
2315                         void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2316                         void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2317
2318                         switch (parm_table[i].type) {
2319                                 case P_BOOL:
2320                                 case P_BOOLREV:
2321                                         *(bool *)dest_ptr = *(bool *)src_ptr;
2322                                         break;
2323
2324                                 case P_INTEGER:
2325                                 case P_ENUM:
2326                                 case P_OCTAL:
2327                                 case P_BYTES:
2328                                         *(int *)dest_ptr = *(int *)src_ptr;
2329                                         break;
2330
2331                                 case P_CHAR:
2332                                         *(char *)dest_ptr = *(char *)src_ptr;
2333                                         break;
2334
2335                                 case P_STRING:
2336                                         string_set((char **)dest_ptr,
2337                                                    *(char **)src_ptr);
2338                                         break;
2339
2340                                 case P_USTRING:
2341                                 {
2342                                         char *upper_string = strupper_talloc(talloc_tos(), 
2343                                                                              *(char **)src_ptr);
2344                                         string_set((char **)dest_ptr,
2345                                                    upper_string);
2346                                         TALLOC_FREE(upper_string);
2347                                         break;
2348                                 }
2349                                 case P_LIST:
2350                                         TALLOC_FREE(*((char ***)dest_ptr));
2351                                         *((char ***)dest_ptr) = str_list_copy(NULL, 
2352                                                       *(const char ***)src_ptr);
2353                                         break;
2354                                 default:
2355                                         break;
2356                         }
2357                 }
2358
2359         if (bcopyall) {
2360                 init_copymap(pserviceDest);
2361                 if (pserviceSource->copymap)
2362                         bitmap_copy(pserviceDest->copymap,
2363                                     pserviceSource->copymap);
2364         }
2365
2366         data = pserviceSource->param_opt;
2367         while (data) {
2368                 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2369                 data = data->next;
2370         }
2371 }
2372
2373 /***************************************************************************
2374 Check a service for consistency. Return false if the service is in any way
2375 incomplete or faulty, else true.
2376 ***************************************************************************/
2377
2378 bool service_ok(int iService)
2379 {
2380         bool bRetval;
2381
2382         bRetval = true;
2383         if (ServicePtrs[iService]->szService[0] == '\0') {
2384                 DEBUG(0, ("The following message indicates an internal error:\n"));
2385                 DEBUG(0, ("No service name in service entry.\n"));
2386                 bRetval = false;
2387         }
2388
2389         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2390         /* I can't see why you'd want a non-printable printer service...        */
2391         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2392                 if (!ServicePtrs[iService]->print_ok) {
2393                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2394                                ServicePtrs[iService]->szService));
2395                         ServicePtrs[iService]->print_ok = true;
2396                 }
2397                 /* [printers] service must also be non-browsable. */
2398                 if (ServicePtrs[iService]->browseable)
2399                         ServicePtrs[iService]->browseable = false;
2400         }
2401
2402         if (ServicePtrs[iService]->pathname[0] == '\0' &&
2403             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2404             ServicePtrs[iService]->msdfs_proxy[0] == '\0'
2405             ) {
2406                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2407                         ServicePtrs[iService]->szService));
2408                 ServicePtrs[iService]->bAvailable = false;
2409         }
2410
2411         /* If a service is flagged unavailable, log the fact at level 1. */
2412         if (!ServicePtrs[iService]->bAvailable)
2413                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2414                           ServicePtrs[iService]->szService));
2415
2416         return (bRetval);
2417 }
2418
2419 static struct smbconf_ctx *lp_smbconf_ctx(void)
2420 {
2421         sbcErr err;
2422         static struct smbconf_ctx *conf_ctx = NULL;
2423
2424         if (conf_ctx == NULL) {
2425                 err = smbconf_init(NULL, &conf_ctx, "registry:");
2426                 if (!SBC_ERROR_IS_OK(err)) {
2427                         DEBUG(1, ("error initializing registry configuration: "
2428                                   "%s\n", sbcErrorString(err)));
2429                         conf_ctx = NULL;
2430                 }
2431         }
2432
2433         return conf_ctx;
2434 }
2435
2436 static bool process_smbconf_service(struct smbconf_service *service)
2437 {
2438         uint32_t count;
2439         bool ret;
2440
2441         if (service == NULL) {
2442                 return false;
2443         }
2444
2445         ret = do_section(service->name, NULL);
2446         if (ret != true) {
2447                 return false;
2448         }
2449         for (count = 0; count < service->num_params; count++) {
2450                 ret = do_parameter(service->param_names[count],
2451                                    service->param_values[count],
2452                                    NULL);
2453                 if (ret != true) {
2454                         return false;
2455                 }
2456         }
2457         if (iServiceIndex >= 0) {
2458                 return service_ok(iServiceIndex);
2459         }
2460         return true;
2461 }
2462
2463 /**
2464  * load a service from registry and activate it
2465  */
2466 bool process_registry_service(const char *service_name)
2467 {
2468         sbcErr err;
2469         struct smbconf_service *service = NULL;
2470         TALLOC_CTX *mem_ctx = talloc_stackframe();
2471         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2472         bool ret = false;
2473
2474         if (conf_ctx == NULL) {
2475                 goto done;
2476         }
2477
2478         DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2479
2480         if (!smbconf_share_exists(conf_ctx, service_name)) {
2481                 /*
2482                  * Registry does not contain data for this service (yet),
2483                  * but make sure lp_load doesn't return false.
2484                  */
2485                 ret = true;
2486                 goto done;
2487         }
2488
2489         err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2490         if (!SBC_ERROR_IS_OK(err)) {
2491                 goto done;
2492         }
2493
2494         ret = process_smbconf_service(service);
2495         if (!ret) {
2496                 goto done;
2497         }
2498
2499         /* store the csn */
2500         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2501
2502 done:
2503         TALLOC_FREE(mem_ctx);
2504         return ret;
2505 }
2506
2507 /*
2508  * process_registry_globals
2509  */
2510 static bool process_registry_globals(void)
2511 {
2512         bool ret;
2513
2514         add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2515
2516         ret = do_parameter("registry shares", "yes", NULL);
2517         if (!ret) {
2518                 return ret;
2519         }
2520
2521         return process_registry_service(GLOBAL_NAME);
2522 }
2523
2524 bool process_registry_shares(void)
2525 {
2526         sbcErr err;
2527         uint32_t count;
2528         struct smbconf_service **service = NULL;
2529         uint32_t num_shares = 0;
2530         TALLOC_CTX *mem_ctx = talloc_stackframe();
2531         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2532         bool ret = false;
2533
2534         if (conf_ctx == NULL) {
2535                 goto done;
2536         }
2537
2538         err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2539         if (!SBC_ERROR_IS_OK(err)) {
2540                 goto done;
2541         }
2542
2543         ret = true;
2544
2545         for (count = 0; count < num_shares; count++) {
2546                 if (strequal(service[count]->name, GLOBAL_NAME)) {
2547                         continue;
2548                 }
2549                 ret = process_smbconf_service(service[count]);
2550                 if (!ret) {
2551                         goto done;
2552                 }
2553         }
2554
2555         /* store the csn */
2556         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2557
2558 done:
2559         TALLOC_FREE(mem_ctx);
2560         return ret;
2561 }
2562
2563 /**
2564  * reload those shares from registry that are already
2565  * activated in the services array.
2566  */
2567 static bool reload_registry_shares(void)
2568 {
2569         int i;
2570         bool ret = true;
2571
2572         for (i = 0; i < iNumServices; i++) {
2573                 if (!VALID(i)) {
2574                         continue;
2575                 }
2576
2577                 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2578                         continue;
2579                 }
2580
2581                 ret = process_registry_service(ServicePtrs[i]->szService);
2582                 if (!ret) {
2583                         goto done;
2584                 }
2585         }
2586
2587 done:
2588         return ret;
2589 }
2590
2591
2592 #define MAX_INCLUDE_DEPTH 100
2593
2594 static uint8_t include_depth;
2595
2596 static struct file_lists {
2597         struct file_lists *next;
2598         char *name;
2599         char *subfname;
2600         time_t modtime;
2601 } *file_lists = NULL;
2602
2603 /*******************************************************************
2604  Keep a linked list of all config files so we know when one has changed 
2605  it's date and needs to be reloaded.
2606 ********************************************************************/
2607
2608 static void add_to_file_list(const char *fname, const char *subfname)
2609 {
2610         struct file_lists *f = file_lists;
2611
2612         while (f) {
2613                 if (f->name && !strcmp(f->name, fname))
2614                         break;
2615                 f = f->next;
2616         }
2617
2618         if (!f) {
2619                 f = SMB_MALLOC_P(struct file_lists);
2620                 if (!f)
2621                         return;
2622                 f->next = file_lists;
2623                 f->name = SMB_STRDUP(fname);
2624                 if (!f->name) {
2625                         SAFE_FREE(f);
2626                         return;
2627                 }
2628                 f->subfname = SMB_STRDUP(subfname);
2629                 if (!f->subfname) {
2630                         SAFE_FREE(f->name);
2631                         SAFE_FREE(f);
2632                         return;
2633                 }
2634                 file_lists = f;
2635                 f->modtime = file_modtime(subfname);
2636         } else {
2637                 time_t t = file_modtime(subfname);
2638                 if (t)
2639                         f->modtime = t;
2640         }
2641         return;
2642 }
2643
2644 /**
2645  * Free the file lists
2646  */
2647 static void free_file_list(void)
2648 {
2649         struct file_lists *f;
2650         struct file_lists *next;
2651
2652         f = file_lists;
2653         while( f ) {
2654                 next = f->next;
2655                 SAFE_FREE( f->name );
2656                 SAFE_FREE( f->subfname );
2657                 SAFE_FREE( f );
2658                 f = next;
2659         }
2660         file_lists = NULL;
2661 }
2662
2663
2664 /**
2665  * Utility function for outsiders to check if we're running on registry.
2666  */
2667 bool lp_config_backend_is_registry(void)
2668 {
2669         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2670 }
2671
2672 /**
2673  * Utility function to check if the config backend is FILE.
2674  */
2675 bool lp_config_backend_is_file(void)
2676 {
2677         return (lp_config_backend() == CONFIG_BACKEND_FILE);
2678 }
2679
2680 /*******************************************************************
2681  Check if a config file has changed date.
2682 ********************************************************************/
2683
2684 bool lp_file_list_changed(void)
2685 {
2686         struct file_lists *f = file_lists;
2687
2688         DEBUG(6, ("lp_file_list_changed()\n"));
2689
2690         while (f) {
2691                 time_t mod_time;
2692
2693                 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2694                         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2695
2696                         if (conf_ctx == NULL) {
2697                                 return false;
2698                         }
2699                         if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2700                                             NULL))
2701                         {
2702                                 DEBUGADD(6, ("registry config changed\n"));
2703                                 return true;
2704                         }
2705                 } else {
2706                         char *n2 = NULL;
2707                         n2 = talloc_sub_basic(talloc_tos(),
2708                                               get_current_username(),
2709                                               current_user_info.domain,
2710                                               f->name);
2711                         if (!n2) {
2712                                 return false;
2713                         }
2714                         DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2715                                      f->name, n2, ctime(&f->modtime)));
2716
2717                         mod_time = file_modtime(n2);
2718
2719                         if (mod_time &&
2720                             ((f->modtime != mod_time) ||
2721                              (f->subfname == NULL) ||
2722                              (strcmp(n2, f->subfname) != 0)))
2723                         {
2724                                 DEBUGADD(6,
2725                                          ("file %s modified: %s\n", n2,
2726                                           ctime(&mod_time)));
2727                                 f->modtime = mod_time;
2728                                 SAFE_FREE(f->subfname);
2729                                 f->subfname = SMB_STRDUP(n2);
2730                                 TALLOC_FREE(n2);
2731                                 return true;
2732                         }
2733                         TALLOC_FREE(n2);
2734                 }
2735                 f = f->next;
2736         }
2737         return false;
2738 }
2739
2740
2741 /**
2742  * Initialize iconv conversion descriptors.
2743  *
2744  * This is called the first time it is needed, and also called again
2745  * every time the configuration is reloaded, because the charset or
2746  * codepage might have changed.
2747  **/
2748 static void init_iconv(void)
2749 {
2750         global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2751                                                       lp_unix_charset(),
2752                                                       true, global_iconv_handle);
2753 }
2754
2755 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2756 {
2757         if (strcmp(*ptr, pszParmValue) != 0) {
2758                 string_set(ptr, pszParmValue);
2759                 init_iconv();
2760         }
2761         return true;
2762 }
2763
2764 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2765 {
2766         bool is_utf8 = false;
2767         size_t len = strlen(pszParmValue);
2768
2769         if (len == 4 || len == 5) {
2770                 /* Don't use StrCaseCmp here as we don't want to
2771                    initialize iconv. */
2772                 if ((toupper_m(pszParmValue[0]) == 'U') &&
2773                     (toupper_m(pszParmValue[1]) == 'T') &&
2774                     (toupper_m(pszParmValue[2]) == 'F')) {
2775                         if (len == 4) {
2776                                 if (pszParmValue[3] == '8') {
2777                                         is_utf8 = true;
2778                                 }
2779                         } else {
2780                                 if (pszParmValue[3] == '-' &&
2781                                     pszParmValue[4] == '8') {
2782                                         is_utf8 = true;
2783                                 }
2784                         }
2785                 }
2786         }
2787
2788         if (strcmp(*ptr, pszParmValue) != 0) {
2789                 if (is_utf8) {
2790                         DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2791                                 "be UTF8, using (default value) %s instead.\n",
2792                                 DEFAULT_DOS_CHARSET));
2793                         pszParmValue = DEFAULT_DOS_CHARSET;
2794                 }
2795                 string_set(ptr, pszParmValue);
2796                 init_iconv();
2797         }
2798         return true;
2799 }
2800
2801 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2802 {
2803         bool ret = true;
2804         TALLOC_CTX *frame = talloc_stackframe();
2805         char *realm = strupper_talloc(frame, pszParmValue);
2806         char *dnsdomain = strlower_talloc(realm, pszParmValue);
2807
2808         ret &= string_set(&Globals.realm_original, pszParmValue);
2809         ret &= string_set(&Globals.realm, realm);
2810         ret &= string_set(&Globals.dnsdomain, dnsdomain);
2811         TALLOC_FREE(frame);
2812
2813         return ret;
2814 }
2815
2816 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2817 {
2818         TALLOC_FREE(Globals.netbios_aliases);
2819         Globals.netbios_aliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2820         return set_netbios_aliases(Globals.netbios_aliases);
2821 }
2822
2823 /***************************************************************************
2824  Handle the include operation.
2825 ***************************************************************************/
2826 static bool bAllowIncludeRegistry = true;
2827
2828 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2829 {
2830         char *fname;
2831
2832         if (include_depth >= MAX_INCLUDE_DEPTH) {
2833                 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2834                           include_depth));
2835                 return false;
2836         }
2837
2838         if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2839                 if (!bAllowIncludeRegistry) {
2840                         return true;
2841                 }
2842                 if (bInGlobalSection) {
2843                         bool ret;
2844                         include_depth++;
2845                         ret = process_registry_globals();
2846                         include_depth--;
2847                         return ret;
2848                 } else {
2849                         DEBUG(1, ("\"include = registry\" only effective "
2850                                   "in %s section\n", GLOBAL_NAME));
2851                         return false;
2852                 }
2853         }
2854
2855         fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2856                                  current_user_info.domain,
2857                                  pszParmValue);
2858
2859         add_to_file_list(pszParmValue, fname);
2860
2861         string_set(ptr, fname);
2862
2863         if (file_exist(fname)) {
2864                 bool ret;
2865                 include_depth++;
2866                 ret = pm_process(fname, do_section, do_parameter, NULL);
2867                 include_depth--;
2868                 TALLOC_FREE(fname);
2869                 return ret;
2870         }
2871
2872         DEBUG(2, ("Can't find include file %s\n", fname));
2873         TALLOC_FREE(fname);
2874         return true;
2875 }
2876
2877 /***************************************************************************
2878  Handle the interpretation of the copy parameter.
2879 ***************************************************************************/
2880
2881 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2882 {
2883         bool bRetval;
2884         int iTemp;
2885         struct loadparm_service serviceTemp;
2886
2887         string_set(ptr, pszParmValue);
2888
2889         init_service(&serviceTemp);
2890
2891         bRetval = false;
2892
2893         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2894
2895         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2896                 if (iTemp == iServiceIndex) {
2897                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2898                 } else {
2899                         copy_service(ServicePtrs[iServiceIndex],
2900                                      &serviceTemp,
2901                                      ServicePtrs[iServiceIndex]->copymap);
2902                         bRetval = true;
2903                 }
2904         } else {
2905                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2906                 bRetval = false;
2907         }
2908
2909         free_service(&serviceTemp);
2910         return (bRetval);
2911 }
2912
2913 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2914 {
2915         Globals.ldap_debug_level = lp_int(pszParmValue);
2916         init_ldap_debugging();
2917         return true;
2918 }
2919
2920 /*
2921  * idmap related parameters
2922  */
2923
2924 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2925 {
2926         lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2927
2928         return true;
2929 }
2930
2931 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2932 {
2933         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2934
2935         return true;
2936 }
2937
2938 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2939 {
2940         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2941
2942         return true;
2943 }
2944
2945 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
2946 {
2947         char *config_option = NULL;
2948         const char *range = NULL;
2949         bool ret = false;
2950
2951         SMB_ASSERT(low != NULL);
2952         SMB_ASSERT(high != NULL);
2953
2954         if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2955                 domain_name = "*";
2956         }
2957
2958         config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
2959                                         domain_name);
2960         if (config_option == NULL) {
2961                 DEBUG(0, ("out of memory\n"));
2962                 return false;
2963         }
2964
2965         range = lp_parm_const_string(-1, config_option, "range", NULL);
2966         if (range == NULL) {
2967                 DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
2968                 goto done;
2969         }
2970
2971         if (sscanf(range, "%u - %u", low, high) != 2) {
2972                 DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
2973                           range, domain_name));
2974                 goto done;
2975         }
2976
2977         ret = true;
2978
2979 done:
2980         talloc_free(config_option);
2981         return ret;
2982
2983 }
2984
2985 bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
2986 {
2987         return lp_idmap_range("*", low, high);
2988 }
2989
2990 const char *lp_idmap_backend(const char *domain_name)
2991 {
2992         char *config_option = NULL;
2993         const char *backend = NULL;
2994
2995         if ((domain_name == NULL) || (domain_name[0] == '\0')) {
2996                 domain_name = "*";
2997         }
2998
2999         config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
3000                                         domain_name);
3001         if (config_option == NULL) {
3002                 DEBUG(0, ("out of memory\n"));
3003                 return false;
3004         }
3005
3006         backend = lp_parm_const_string(-1, config_option, "backend", NULL);
3007         if (backend == NULL) {
3008                 DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
3009                 goto done;
3010         }
3011
3012 done:
3013         talloc_free(config_option);
3014         return backend;
3015 }
3016
3017 const char *lp_idmap_default_backend(void)
3018 {
3019         return lp_idmap_backend("*");
3020 }
3021
3022 /***************************************************************************
3023  Handle the DEBUG level list.
3024 ***************************************************************************/
3025
3026 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
3027 {
3028         string_set(ptr, pszParmValueIn);
3029         return debug_parse_levels(pszParmValueIn);
3030 }
3031
3032 /***************************************************************************
3033  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3034 ***************************************************************************/
3035
3036 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
3037 {
3038         const char *suffix_string;
3039
3040         suffix_string = talloc_asprintf(ctx, "%s,%s", str,
3041                                         Globals.ldap_suffix );
3042         if ( !suffix_string ) {
3043                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3044                 return "";
3045         }
3046
3047         return suffix_string;
3048 }
3049
3050 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
3051 {
3052         if (Globals.szLdapMachineSuffix[0])
3053                 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
3054
3055         return lp_string(ctx, Globals.ldap_suffix);
3056 }
3057
3058 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
3059 {
3060         if (Globals.szLdapUserSuffix[0])
3061                 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3062
3063         return lp_string(ctx, Globals.ldap_suffix);
3064 }
3065
3066 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3067 {
3068         if (Globals.szLdapGroupSuffix[0])
3069                 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3070
3071         return lp_string(ctx, Globals.ldap_suffix);
3072 }
3073
3074 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3075 {
3076         if (Globals.szLdapIdmapSuffix[0])
3077                 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3078
3079         return lp_string(ctx, Globals.ldap_suffix);
3080 }
3081
3082 /****************************************************************************
3083  set the value for a P_ENUM
3084  ***************************************************************************/
3085
3086 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3087                               int *ptr )
3088 {
3089         int i;
3090
3091         for (i = 0; parm->enum_list[i].name; i++) {
3092                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3093                         *ptr = parm->enum_list[i].value;
3094                         return;
3095                 }
3096         }
3097         DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3098                   pszParmValue, parm->label));
3099 }
3100
3101 /***************************************************************************
3102 ***************************************************************************/
3103
3104 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3105 {
3106         static int parm_num = -1;
3107         struct loadparm_service *s;
3108
3109         if ( parm_num == -1 )
3110                 parm_num = map_parameter( "printing" );
3111
3112         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3113
3114         if ( snum < 0 )
3115                 s = &sDefault;
3116         else
3117                 s = ServicePtrs[snum];
3118
3119         init_printer_values( s );
3120
3121         return true;
3122 }
3123
3124
3125 /***************************************************************************
3126  Initialise a copymap.
3127 ***************************************************************************/
3128
3129 static void init_copymap(struct loadparm_service *pservice)
3130 {
3131         int i;
3132
3133         TALLOC_FREE(pservice->copymap);
3134
3135         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3136         if (!pservice->copymap)
3137                 DEBUG(0,
3138                       ("Couldn't allocate copymap!! (size %d)\n",
3139                        (int)NUMPARAMETERS));
3140         else
3141                 for (i = 0; i < NUMPARAMETERS; i++)
3142                         bitmap_set(pservice->copymap, i);
3143 }
3144
3145 /**
3146   return the parameter pointer for a parameter
3147 */
3148 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3149 {
3150         if (service == NULL) {
3151                 if (parm->p_class == P_LOCAL)
3152                         return (void *)(((char *)&sDefault)+parm->offset);
3153                 else if (parm->p_class == P_GLOBAL)
3154                         return (void *)(((char *)&Globals)+parm->offset);
3155                 else return NULL;
3156         } else {
3157                 return (void *)(((char *)service) + parm->offset);
3158         }
3159 }
3160
3161 /***************************************************************************
3162  Return the local pointer to a parameter given the service number and parameter
3163 ***************************************************************************/
3164
3165 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3166 {
3167         return lp_parm_ptr(ServicePtrs[snum], parm);
3168 }
3169
3170 /***************************************************************************
3171  Process a parameter for a particular service number. If snum < 0
3172  then assume we are in the globals.
3173 ***************************************************************************/
3174
3175 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3176 {
3177         int parmnum, i;
3178         void *parm_ptr = NULL;  /* where we are going to store the result */
3179         struct parmlist_entry **opt_list;
3180
3181         parmnum = map_parameter(pszParmName);
3182
3183         if (parmnum < 0) {
3184                 if (strchr(pszParmName, ':') == NULL) {
3185                         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3186                                   pszParmName));
3187                         return true;
3188                 }
3189
3190                 /*
3191                  * We've got a parametric option
3192                  */
3193
3194                 opt_list = (snum < 0)
3195                         ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3196                 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3197
3198                 return true;
3199         }
3200
3201         /* if it's already been set by the command line, then we don't
3202            override here */
3203         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3204                 return true;
3205         }
3206
3207         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3208                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3209                           pszParmName));
3210         }
3211
3212         /* we might point at a service, the default service or a global */
3213         if (snum < 0) {
3214                 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3215         } else {
3216                 if (parm_table[parmnum].p_class == P_GLOBAL) {
3217                         DEBUG(0,
3218                               ("Global parameter %s found in service section!\n",
3219                                pszParmName));
3220                         return true;
3221                 }
3222                 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3223         }
3224
3225         if (snum >= 0) {
3226                 if (!ServicePtrs[snum]->copymap)
3227                         init_copymap(ServicePtrs[snum]);
3228
3229                 /* this handles the aliases - set the copymap for other entries with
3230                    the same data pointer */
3231                 for (i = 0; parm_table[i].label; i++) {
3232                         if ((parm_table[i].offset == parm_table[parmnum].offset)
3233                             && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3234                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
3235                         }
3236                 }
3237         }
3238
3239         /* if it is a special case then go ahead */
3240         if (parm_table[parmnum].special) {
3241                 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3242                                                    (char **)parm_ptr);
3243         }
3244
3245         /* now switch on the type of variable it is */
3246         switch (parm_table[parmnum].type)
3247         {
3248                 case P_BOOL:
3249                         *(bool *)parm_ptr = lp_bool(pszParmValue);
3250                         break;
3251
3252                 case P_BOOLREV:
3253                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
3254                         break;
3255
3256                 case P_INTEGER:
3257                         *(int *)parm_ptr = lp_int(pszParmValue);
3258                         break;
3259
3260                 case P_CHAR:
3261                         *(char *)parm_ptr = *pszParmValue;
3262                         break;
3263
3264                 case P_OCTAL:
3265                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3266                         if ( i != 1 ) {
3267                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3268                         }
3269                         break;
3270
3271                 case P_BYTES:
3272                 {
3273                         uint64_t val;
3274                         if (conv_str_size_error(pszParmValue, &val)) {
3275                                 if (val <= INT_MAX) {
3276                                         *(int *)parm_ptr = (int)val;
3277                                         break;
3278                                 }
3279                         }
3280
3281                         DEBUG(0,("lp_do_parameter(%s): value is not "
3282                             "a valid size specifier!\n", pszParmValue));
3283                         return false;
3284                 }
3285
3286                 case P_LIST:
3287                 case P_CMDLIST:
3288                         TALLOC_FREE(*((char ***)parm_ptr));
3289                         *(char ***)parm_ptr = str_list_make_v3(
3290                                 NULL, pszParmValue, NULL);
3291                         break;
3292
3293                 case P_STRING:
3294                         string_set((char **)parm_ptr, pszParmValue);
3295                         break;
3296
3297                 case P_USTRING:
3298                 {
3299                         char *upper_string = strupper_talloc(talloc_tos(), 
3300                                                              pszParmValue);
3301                         string_set((char **)parm_ptr, upper_string);
3302                         TALLOC_FREE(upper_string);
3303                         break;
3304                 }
3305                 case P_ENUM:
3306                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3307                         break;
3308                 case P_SEP:
3309                         break;
3310         }
3311
3312         return true;
3313 }
3314
3315 /***************************************************************************
3316 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3317 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3318 ***************************************************************************/
3319
3320 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3321 {
3322         int parmnum, i;
3323         parmnum = map_parameter(pszParmName);
3324         if (parmnum >= 0) {
3325                 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3326                 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3327                         return false;
3328                 }
3329                 parm_table[parmnum].flags |= FLAG_CMDLINE;
3330
3331                 /* we have to also set FLAG_CMDLINE on aliases.  Aliases must
3332                  * be grouped in the table, so we don't have to search the
3333                  * whole table */
3334                 for (i=parmnum-1;
3335                      i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3336                              && parm_table[i].p_class == parm_table[parmnum].p_class;
3337                      i--) {
3338                         parm_table[i].flags |= FLAG_CMDLINE;
3339                 }
3340                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3341                              && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3342                         parm_table[i].flags |= FLAG_CMDLINE;
3343                 }
3344
3345                 if (store_values) {
3346                         store_lp_set_cmdline(pszParmName, pszParmValue);
3347                 }
3348                 return true;
3349         }
3350
3351         /* it might be parametric */
3352         if (strchr(pszParmName, ':') != NULL) {
3353                 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3354                 if (store_values) {
3355                         store_lp_set_cmdline(pszParmName, pszParmValue);
3356                 }
3357                 return true;
3358         }
3359
3360         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
3361         return true;
3362 }
3363
3364 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3365 {
3366         return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3367 }
3368
3369 /***************************************************************************
3370  Process a parameter.
3371 ***************************************************************************/
3372
3373 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3374                          void *userdata)
3375 {
3376         if (!bInGlobalSection && bGlobalOnly)
3377                 return true;
3378
3379         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3380
3381         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3382                                 pszParmName, pszParmValue));
3383 }
3384
3385 /*
3386   set a option from the commandline in 'a=b' format. Use to support --option
3387 */
3388 bool lp_set_option(const char *option)
3389 {
3390         char *p, *s;
3391         bool ret;
3392
3393         s = talloc_strdup(NULL, option);
3394         if (!s) {
3395                 return false;
3396         }
3397
3398         p = strchr(s, '=');
3399         if (!p) {
3400                 talloc_free(s);
3401                 return false;
3402         }
3403
3404         *p = 0;
3405
3406         /* skip white spaces after the = sign */
3407         do {
3408                 p++;
3409         } while (*p == ' ');
3410
3411         ret = lp_set_cmdline(s, p);
3412         talloc_free(s);
3413         return ret;
3414 }
3415
3416 /**************************************************************************
3417  Print a parameter of the specified type.
3418 ***************************************************************************/
3419
3420 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3421 {
3422         /* For the seperation of lists values that we print below */
3423         const char *list_sep = ", ";
3424         int i;
3425         switch (p->type)
3426         {
3427                 case P_ENUM:
3428                         for (i = 0; p->enum_list[i].name; i++) {
3429                                 if (*(int *)ptr == p->enum_list[i].value) {
3430                                         fprintf(f, "%s",
3431                                                 p->enum_list[i].name);
3432                                         break;
3433                                 }
3434                         }
3435                         break;
3436
3437                 case P_BOOL:
3438                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3439                         break;
3440
3441                 case P_BOOLREV:
3442                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3443                         break;
3444
3445                 case P_INTEGER:
3446                 case P_BYTES:
3447                         fprintf(f, "%d", *(int *)ptr);
3448                         break;
3449
3450                 case P_CHAR:
3451                         fprintf(f, "%c", *(char *)ptr);
3452                         break;
3453
3454                 case P_OCTAL: {
3455                         int val = *(int *)ptr; 
3456                         if (val == -1) {
3457                                 fprintf(f, "-1");
3458                         } else {
3459                                 fprintf(f, "0%o", val);
3460                         }
3461                         break;
3462                 }
3463
3464                 case P_CMDLIST:
3465                         list_sep = " ";
3466                         /* fall through */
3467                 case P_LIST:
3468                         if ((char ***)ptr && *(char ***)ptr) {
3469                                 char **list = *(char ***)ptr;
3470                                 for (; *list; list++) {
3471                                         /* surround strings with whitespace in double quotes */
3472                                         if (*(list+1) == NULL) {
3473                                                 /* last item, no extra separator */
3474                                                 list_sep = "";
3475                                         }
3476                                         if ( strchr_m( *list, ' ' ) ) {
3477                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
3478                                         } else {
3479                                                 fprintf(f, "%s%s", *list, list_sep);
3480                                         }
3481                                 }
3482                         }
3483                         break;
3484
3485                 case P_STRING:
3486                 case P_USTRING:
3487                         if (*(char **)ptr) {
3488                                 fprintf(f, "%s", *(char **)ptr);
3489                         }
3490                         break;
3491                 case P_SEP:
3492                         break;
3493         }
3494 }
3495
3496 /***************************************************************************
3497  Check if two parameters are equal.
3498 ***************************************************************************/
3499
3500 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3501 {
3502         switch (type) {
3503                 case P_BOOL:
3504                 case P_BOOLREV:
3505                         return (*((bool *)ptr1) == *((bool *)ptr2));
3506
3507                 case P_INTEGER:
3508                 case P_ENUM:
3509                 case P_OCTAL:
3510                 case P_BYTES:
3511                         return (*((int *)ptr1) == *((int *)ptr2));
3512
3513                 case P_CHAR:
3514                         return (*((char *)ptr1) == *((char *)ptr2));
3515
3516                 case P_LIST:
3517                 case P_CMDLIST:
3518                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3519
3520                 case P_STRING:
3521                 case P_USTRING:
3522                 {
3523                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3524                         if (p1 && !*p1)
3525                                 p1 = NULL;
3526                         if (p2 && !*p2)
3527                                 p2 = NULL;
3528                         return (p1 == p2 || strequal(p1, p2));
3529                 }
3530                 case P_SEP:
3531                         break;
3532         }
3533         return false;
3534 }
3535
3536 /***************************************************************************
3537  Initialize any local variables in the sDefault table, after parsing a
3538  [globals] section.
3539 ***************************************************************************/
3540
3541 static void init_locals(void)
3542 {
3543         /*
3544          * We run this check once the [globals] is parsed, to force
3545          * the VFS objects and other per-share settings we need for
3546          * the standard way a AD DC is operated.  We may change these
3547          * as our code evolves, which is why we force these settings.
3548          *
3549          * We can't do this at the end of lp_load_ex(), as by that
3550          * point the services have been loaded and they will already
3551          * have "" as their vfs objects.
3552          */
3553         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
3554                 const char **vfs_objects = lp_vfs_objects(-1);
3555                 if (!vfs_objects || !vfs_objects[0]) {
3556                         if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
3557                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
3558                         } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
3559                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
3560                         } else {
3561                                 lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
3562                         }
3563                 }
3564
3565                 lp_do_parameter(-1, "map hidden", "no");
3566                 lp_do_parameter(-1, "map system", "no");
3567                 lp_do_parameter(-1, "map readonly", "no");
3568                 lp_do_parameter(-1, "map archive", "no");
3569                 lp_do_parameter(-1, "store dos attributes", "yes");
3570         }
3571 }
3572
3573 /***************************************************************************
3574  Process a new section (service). At this stage all sections are services.
3575  Later we'll have special sections that permit server parameters to be set.
3576  Returns true on success, false on failure.
3577 ***************************************************************************/
3578
3579 static bool do_section(const char *pszSectionName, void *userdata)
3580 {
3581         bool bRetval;
3582         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3583                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3584         bRetval = false;
3585
3586         /* if we were in a global section then do the local inits */
3587         if (bInGlobalSection && !isglobal)
3588                 init_locals();
3589
3590         /* if we've just struck a global section, note the fact. */
3591         bInGlobalSection = isglobal;
3592
3593         /* check for multiple global sections */
3594         if (bInGlobalSection) {
3595                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3596                 return true;
3597         }
3598
3599         if (!bInGlobalSection && bGlobalOnly)
3600                 return true;
3601
3602         /* if we have a current service, tidy it up before moving on */
3603         bRetval = true;
3604
3605         if (iServiceIndex >= 0)
3606                 bRetval = service_ok(iServiceIndex);
3607
3608         /* if all is still well, move to the next record in the services array */
3609         if (bRetval) {
3610                 /* We put this here to avoid an odd message order if messages are */
3611                 /* issued by the post-processing of a previous section. */
3612                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3613
3614                 iServiceIndex = add_a_service(&sDefault, pszSectionName);
3615                 if (iServiceIndex < 0) {
3616                         DEBUG(0, ("Failed to add a new service\n"));
3617                         return false;
3618                 }
3619                 /* Clean all parametric options for service */
3620                 /* They will be added during parsing again */
3621                 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
3622         }
3623
3624         return bRetval;
3625 }
3626
3627
3628 /***************************************************************************
3629  Determine if a partcular base parameter is currentl set to the default value.
3630 ***************************************************************************/
3631
3632 static bool is_default(int i)
3633 {
3634         if (!defaults_saved)
3635                 return false;
3636         switch (parm_table[i].type) {
3637                 case P_LIST:
3638                 case P_CMDLIST:
3639                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
3640                                               *(const char ***)lp_parm_ptr(NULL, 
3641                                                                            &parm_table[i]));
3642                 case P_STRING:
3643                 case P_USTRING:
3644                         return strequal(parm_table[i].def.svalue,
3645                                         *(char **)lp_parm_ptr(NULL, 
3646                                                               &parm_table[i]));
3647                 case P_BOOL:
3648                 case P_BOOLREV:
3649                         return parm_table[i].def.bvalue ==
3650                                 *(bool *)lp_parm_ptr(NULL, 
3651                                                      &parm_table[i]);
3652                 case P_CHAR:
3653                         return parm_table[i].def.cvalue ==
3654                                 *(char *)lp_parm_ptr(NULL, 
3655                                                      &parm_table[i]);
3656                 case P_INTEGER:
3657                 case P_OCTAL:
3658                 case P_ENUM:
3659                 case P_BYTES:
3660                         return parm_table[i].def.ivalue ==
3661                                 *(int *)lp_parm_ptr(NULL, 
3662                                                     &parm_table[i]);
3663                 case P_SEP:
3664                         break;
3665         }
3666         return false;
3667 }
3668
3669 /***************************************************************************
3670 Display the contents of the global structure.
3671 ***************************************************************************/
3672
3673 static void dump_globals(FILE *f)
3674 {
3675         int i;
3676         struct parmlist_entry *data;
3677
3678         fprintf(f, "[global]\n");
3679
3680         for (i = 0; parm_table[i].label; i++)
3681                 if (parm_table[i].p_class == P_GLOBAL &&
3682                     !(parm_table[i].flags & FLAG_META) &&
3683                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
3684                         if (defaults_saved && is_default(i))
3685                                 continue;
3686                         fprintf(f, "\t%s = ", parm_table[i].label);
3687                         print_parameter(&parm_table[i], lp_parm_ptr(NULL, 
3688                                                                     &parm_table[i]),
3689                                         f);
3690                         fprintf(f, "\n");
3691         }
3692         if (Globals.param_opt != NULL) {
3693                 data = Globals.param_opt;
3694                 while(data) {
3695                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3696                         data = data->next;
3697                 }
3698         }
3699
3700 }
3701
3702 /***************************************************************************
3703  Return true if a local parameter is currently set to the global default.
3704 ***************************************************************************/
3705
3706 bool lp_is_default(int snum, struct parm_struct *parm)
3707 {
3708         return equal_parameter(parm->type,
3709                                lp_parm_ptr(ServicePtrs[snum], parm),
3710                                lp_parm_ptr(NULL, parm));
3711 }
3712
3713 /***************************************************************************
3714  Display the contents of a single services record.
3715 ***************************************************************************/
3716
3717 static void dump_a_service(struct loadparm_service *pService, FILE * f)
3718 {
3719         int i;
3720         struct parmlist_entry *data;
3721
3722         if (pService != &sDefault)
3723                 fprintf(f, "[%s]\n", pService->szService);
3724
3725         for (i = 0; parm_table[i].label; i++) {
3726
3727                 if (parm_table[i].p_class == P_LOCAL &&
3728                     !(parm_table[i].flags & FLAG_META) &&
3729                     (*parm_table[i].label != '-') &&
3730                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
3731                 {
3732                         if (pService == &sDefault) {
3733                                 if (defaults_saved && is_default(i))
3734                                         continue;
3735                         } else {
3736                                 if (equal_parameter(parm_table[i].type,
3737                                                     lp_parm_ptr(pService, &parm_table[i]),
3738                                                     lp_parm_ptr(NULL, &parm_table[i])))
3739                                         continue;
3740                         }
3741
3742                         fprintf(f, "\t%s = ", parm_table[i].label);
3743                         print_parameter(&parm_table[i],
3744                                         lp_parm_ptr(pService, &parm_table[i]),
3745                                         f);
3746                         fprintf(f, "\n");
3747                 }
3748         }
3749
3750                 if (pService->param_opt != NULL) {
3751                         data = pService->param_opt;
3752                         while(data) {
3753                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
3754                                 data = data->next;
3755                         }
3756                 }
3757 }
3758
3759 /***************************************************************************
3760  Display the contents of a parameter of a single services record.
3761 ***************************************************************************/
3762
3763 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
3764 {
3765         int i;
3766         bool result = false;
3767         parm_class p_class;
3768         unsigned flag = 0;
3769         fstring local_parm_name;
3770         char *parm_opt;
3771         const char *parm_opt_value;
3772
3773         /* check for parametrical option */
3774         fstrcpy( local_parm_name, parm_name);
3775         parm_opt = strchr( local_parm_name, ':');
3776
3777         if (parm_opt) {
3778                 *parm_opt = '\0';
3779                 parm_opt++;
3780                 if (strlen(parm_opt)) {
3781                         parm_opt_value = lp_parm_const_string( snum,
3782                                 local_parm_name, parm_opt, NULL);
3783                         if (parm_opt_value) {
3784                                 printf( "%s\n", parm_opt_value);
3785                                 result = true;
3786                         }
3787                 }
3788                 return result;
3789         }
3790
3791         /* check for a key and print the value */
3792         if (isGlobal) {
3793                 p_class = P_GLOBAL;
3794                 flag = FLAG_GLOBAL;
3795         } else
3796                 p_class = P_LOCAL;
3797
3798         for (i = 0; parm_table[i].label; i++) {
3799                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3800                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag))
3801                 {
3802                         void *ptr;
3803
3804                         if (isGlobal) {
3805                                 ptr = lp_parm_ptr(NULL, 
3806                                                   &parm_table[i]);
3807                         } else {
3808                                 ptr = lp_parm_ptr(ServicePtrs[snum], 
3809                                                   &parm_table[i]);
3810                         }
3811
3812                         print_parameter(&parm_table[i],
3813                                         ptr, f);
3814                         fprintf(f, "\n");
3815                         result = true;
3816                         break;
3817                 }
3818         }
3819
3820         return result;
3821 }
3822
3823 /***************************************************************************
3824  Return info about the requested parameter (given as a string).
3825  Return NULL when the string is not a valid parameter name.
3826 ***************************************************************************/
3827
3828 struct parm_struct *lp_get_parameter(const char *param_name)
3829 {
3830         int num = map_parameter(param_name);
3831
3832         if (num < 0) {
3833                 return NULL;
3834         }
3835
3836         return &parm_table[num];
3837 }
3838
3839 /***************************************************************************
3840  Return info about the next parameter in a service.
3841  snum==GLOBAL_SECTION_SNUM gives the globals.
3842  Return NULL when out of parameters.
3843 ***************************************************************************/
3844
3845 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3846 {
3847         if (snum < 0) {
3848                 /* do the globals */
3849                 for (; parm_table[*i].label; (*i)++) {
3850                         if (parm_table[*i].p_class == P_SEPARATOR)
3851                                 return &parm_table[(*i)++];
3852
3853                         if ((*parm_table[*i].label == '-'))
3854                                 continue;
3855
3856                         if ((*i) > 0
3857                             && (parm_table[*i].offset ==
3858                                 parm_table[(*i) - 1].offset)
3859                             && (parm_table[*i].p_class ==
3860                                 parm_table[(*i) - 1].p_class))
3861                                 continue;
3862
3863                         if (is_default(*i) && !allparameters)
3864                                 continue;
3865
3866                         return &parm_table[(*i)++];
3867                 }
3868         } else {
3869                 struct loadparm_service *pService = ServicePtrs[snum];
3870
3871                 for (; parm_table[*i].label; (*i)++) {
3872                         if (parm_table[*i].p_class == P_SEPARATOR)
3873                                 return &parm_table[(*i)++];
3874
3875                         if (parm_table[*i].p_class == P_LOCAL &&
3876                             (*parm_table[*i].label != '-') &&
3877                             ((*i) == 0 ||
3878                              (parm_table[*i].offset !=
3879                               parm_table[(*i) - 1].offset)))
3880                         {
3881                                 if (allparameters ||
3882                                     !equal_parameter(parm_table[*i].type,
3883                                                      lp_parm_ptr(pService, 
3884                                                                  &parm_table[*i]),
3885                                                      lp_parm_ptr(NULL, 
3886                                                                  &parm_table[*i])))
3887                                 {
3888                                         return &parm_table[(*i)++];
3889                                 }
3890                         }
3891                 }
3892         }
3893
3894         return NULL;
3895 }
3896
3897
3898 #if 0
3899 /***************************************************************************
3900  Display the contents of a single copy structure.
3901 ***************************************************************************/
3902 static void dump_copy_map(bool *pcopymap)
3903 {
3904         int i;
3905         if (!pcopymap)
3906                 return;
3907
3908         printf("\n\tNon-Copied parameters:\n");
3909
3910         for (i = 0; parm_table[i].label; i++)
3911                 if (parm_table[i].p_class == P_LOCAL &&
3912                     parm_table[i].ptr && !pcopymap[i] &&
3913                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3914                 {
3915                         printf("\t\t%s\n", parm_table[i].label);
3916                 }
3917 }
3918 #endif
3919
3920 /***************************************************************************
3921  Return TRUE if the passed service number is within range.
3922 ***************************************************************************/
3923
3924 bool lp_snum_ok(int iService)
3925 {
3926         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3927 }
3928
3929 /***************************************************************************
3930  Auto-load some home services.
3931 ***************************************************************************/
3932
3933 static void lp_add_auto_services(char *str)
3934 {
3935         char *s;
3936         char *p;
3937         int homes;
3938         char *saveptr;
3939
3940         if (!str)
3941                 return;
3942
3943         s = SMB_STRDUP(str);
3944         if (!s)
3945                 return;
3946
3947         homes = lp_servicenumber(HOMES_NAME);
3948
3949         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
3950              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
3951                 char *home;
3952
3953                 if (lp_servicenumber(p) >= 0)
3954                         continue;
3955
3956                 home = get_user_home_dir(talloc_tos(), p);
3957
3958                 if (home && home[0] && homes >= 0)
3959                         lp_add_home(p, homes, p, home);
3960
3961                 TALLOC_FREE(home);
3962         }
3963         SAFE_FREE(s);
3964 }
3965
3966 /***************************************************************************
3967  Auto-load one printer.
3968 ***************************************************************************/
3969
3970 void lp_add_one_printer(const char *name, const char *comment,
3971                         const char *location, void *pdata)
3972 {
3973         int printers = lp_servicenumber(PRINTERS_NAME);
3974         int i;
3975
3976         if (lp_servicenumber(name) < 0) {
3977                 lp_add_printer(name, printers);
3978                 if ((i = lp_servicenumber(name)) >= 0) {
3979                         string_set(&ServicePtrs[i]->comment, comment);
3980                         ServicePtrs[i]->autoloaded = true;
3981                 }
3982         }
3983 }
3984
3985 /***************************************************************************
3986  Have we loaded a services file yet?
3987 ***************************************************************************/
3988
3989 bool lp_loaded(void)
3990 {
3991         return (bLoaded);
3992 }
3993
3994 /***************************************************************************
3995  Unload unused services.
3996 ***************************************************************************/
3997
3998 void lp_killunused(struct smbd_server_connection *sconn,
3999                    bool (*snumused) (struct smbd_server_connection *, int))
4000 {
4001         int i;
4002         for (i = 0; i < iNumServices; i++) {
4003                 if (!VALID(i))
4004                         continue;
4005
4006                 /* don't kill autoloaded or usershare services */
4007                 if ( ServicePtrs[i]->autoloaded ||
4008                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
4009                         continue;
4010                 }
4011
4012                 if (!snumused || !snumused(sconn, i)) {
4013                         free_service_byindex(i);
4014                 }
4015         }
4016 }
4017
4018 /**
4019  * Kill all except autoloaded and usershare services - convenience wrapper
4020  */
4021 void lp_kill_all_services(void)
4022 {
4023         lp_killunused(NULL, NULL);
4024 }
4025
4026 /***************************************************************************
4027  Unload a service.
4028 ***************************************************************************/
4029
4030 void lp_killservice(int iServiceIn)
4031 {
4032         if (VALID(iServiceIn)) {
4033                 free_service_byindex(iServiceIn);
4034         }
4035 }
4036
4037 /***************************************************************************
4038  Save the curent values of all global and sDefault parameters into the 
4039  defaults union. This allows testparm to show only the
4040  changed (ie. non-default) parameters.
4041 ***************************************************************************/
4042
4043 static void lp_save_defaults(void)
4044 {
4045         int i;
4046         for (i = 0; parm_table[i].label; i++) {
4047                 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
4048                     && parm_table[i].p_class == parm_table[i - 1].p_class)
4049                         continue;
4050                 switch (parm_table[i].type) {
4051                         case P_LIST:
4052                         case P_CMDLIST:
4053                                 parm_table[i].def.lvalue = str_list_copy(
4054                                         NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
4055                                 break;
4056                         case P_STRING:
4057                         case P_USTRING:
4058                                 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
4059                                 break;
4060                         case P_BOOL:
4061                         case P_BOOLREV:
4062                                 parm_table[i].def.bvalue =
4063                                         *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
4064                                 break;
4065                         case P_CHAR:
4066                                 parm_table[i].def.cvalue =
4067                                         *(char *)lp_parm_ptr(NULL, &parm_table[i]);
4068                                 break;
4069                         case P_INTEGER:
4070                         case P_OCTAL:
4071                         case P_ENUM:
4072                         case P_BYTES:
4073                                 parm_table[i].def.ivalue =
4074                                         *(int *)lp_parm_ptr(NULL, &parm_table[i]);
4075                                 break;
4076                         case P_SEP:
4077                                 break;
4078                 }
4079         }
4080         defaults_saved = true;
4081 }
4082
4083 /***********************************************************
4084  If we should send plaintext/LANMAN passwords in the clinet
4085 ************************************************************/
4086
4087 static void set_allowed_client_auth(void)
4088 {
4089         if (Globals.client_ntlmv2_auth) {
4090                 Globals.client_lanman_auth = false;
4091         }
4092         if (!Globals.client_lanman_auth) {
4093                 Globals.client_plaintext_auth = false;
4094         }
4095 }
4096
4097 /***************************************************************************
4098  JRA.
4099  The following code allows smbd to read a user defined share file.
4100  Yes, this is my intent. Yes, I'm comfortable with that...
4101
4102  THE FOLLOWING IS SECURITY CRITICAL CODE.
4103
4104  It washes your clothes, it cleans your house, it guards you while you sleep...
4105  Do not f%^k with it....
4106 ***************************************************************************/
4107
4108 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4109
4110 /***************************************************************************
4111  Check allowed stat state of a usershare file.
4112  Ensure we print out who is dicking with us so the admin can
4113  get their sorry ass fired.
4114 ***************************************************************************/
4115
4116 static bool check_usershare_stat(const char *fname,
4117                                  const SMB_STRUCT_STAT *psbuf)
4118 {
4119         if (!S_ISREG(psbuf->st_ex_mode)) {
4120                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4121                         "not a regular file\n",
4122                         fname, (unsigned int)psbuf->st_ex_uid ));
4123                 return false;
4124         }
4125
4126         /* Ensure this doesn't have the other write bit set. */
4127         if (psbuf->st_ex_mode & S_IWOTH) {
4128                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4129                         "public write. Refusing to allow as a usershare file.\n",
4130                         fname, (unsigned int)psbuf->st_ex_uid ));
4131                 return false;
4132         }
4133
4134         /* Should be 10k or less. */
4135         if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
4136                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4137                         "too large (%u) to be a user share file.\n",
4138                         fname, (unsigned int)psbuf->st_ex_uid,
4139                         (unsigned int)psbuf->st_ex_size ));
4140                 return false;
4141         }
4142
4143         return true;
4144 }
4145
4146 /***************************************************************************
4147  Parse the contents of a usershare file.
4148 ***************************************************************************/
4149
4150 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4151                         SMB_STRUCT_STAT *psbuf,
4152                         const char *servicename,
4153                         int snum,
4154                         char **lines,
4155                         int numlines,
4156                         char **pp_sharepath,
4157                         char **pp_comment,
4158                         char **pp_cp_servicename,
4159                         struct security_descriptor **ppsd,
4160                         bool *pallow_guest)
4161 {
4162         const char **prefixallowlist = lp_usershare_prefix_allow_list();
4163         const char **prefixdenylist = lp_usershare_prefix_deny_list();
4164         int us_vers;
4165         DIR *dp;
4166         SMB_STRUCT_STAT sbuf;
4167         char *sharepath = NULL;
4168         char *comment = NULL;
4169
4170         *pp_sharepath = NULL;
4171         *pp_comment = NULL;
4172
4173         *pallow_guest = false;
4174
4175         if (numlines < 4) {
4176                 return USERSHARE_MALFORMED_FILE;
4177         }
4178
4179         if (strcmp(lines[0], "#VERSION 1") == 0) {
4180                 us_vers = 1;
4181         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4182                 us_vers = 2;
4183                 if (numlines < 5) {
4184                         return USERSHARE_MALFORMED_FILE;
4185                 }
4186         } else {
4187                 return USERSHARE_BAD_VERSION;
4188         }
4189
4190         if (strncmp(lines[1], "path=", 5) != 0) {
4191                 return USERSHARE_MALFORMED_PATH;
4192         }
4193
4194         sharepath = talloc_strdup(ctx, &lines[1][5]);
4195         if (!sharepath) {
4196                 return USERSHARE_POSIX_ERR;
4197         }
4198         trim_string(sharepath, " ", " ");
4199
4200         if (strncmp(lines[2], "comment=", 8) != 0) {
4201                 return USERSHARE_MALFORMED_COMMENT_DEF;
4202         }
4203
4204         comment = talloc_strdup(ctx, &lines[2][8]);
4205         if (!comment) {
4206                 return USERSHARE_POSIX_ERR;
4207         }
4208         trim_string(comment, " ", " ");
4209         trim_char(comment, '"', '"');
4210
4211         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4212                 return USERSHARE_MALFORMED_ACL_DEF;
4213         }
4214
4215         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4216                 return USERSHARE_ACL_ERR;
4217         }
4218
4219         if (us_vers == 2) {
4220                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4221                         return USERSHARE_MALFORMED_ACL_DEF;
4222                 }
4223                 if (lines[4][9] == 'y') {
4224                         *pallow_guest = true;
4225                 }
4226
4227                 /* Backwards compatible extension to file version #2. */
4228                 if (numlines > 5) {
4229                         if (strncmp(lines[5], "sharename=", 10) != 0) {
4230                                 return USERSHARE_MALFORMED_SHARENAME_DEF;
4231                         }
4232                         if (!strequal(&lines[5][10], servicename)) {
4233                                 return USERSHARE_BAD_SHARENAME;
4234                         }
4235                         *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
4236                         if (!*pp_cp_servicename) {
4237                                 return USERSHARE_POSIX_ERR;
4238                         }
4239                 }
4240         }
4241
4242         if (*pp_cp_servicename == NULL) {
4243                 *pp_cp_servicename = talloc_strdup(ctx, servicename);
4244                 if (!*pp_cp_servicename) {
4245                         return USERSHARE_POSIX_ERR;
4246                 }
4247         }
4248
4249         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->pathname) == 0)) {
4250                 /* Path didn't change, no checks needed. */
4251                 *pp_sharepath = sharepath;
4252                 *pp_comment = comment;
4253                 return USERSHARE_OK;
4254         }
4255
4256         /* The path *must* be absolute. */
4257         if (sharepath[0] != '/') {
4258                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4259                         servicename, sharepath));
4260                 return USERSHARE_PATH_NOT_ABSOLUTE;
4261         }
4262
4263         /* If there is a usershare prefix deny list ensure one of these paths
4264            doesn't match the start of the user given path. */
4265         if (prefixdenylist) {
4266                 int i;
4267                 for ( i=0; prefixdenylist[i]; i++ ) {
4268                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4269                                 servicename, i, prefixdenylist[i], sharepath ));
4270                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4271                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4272                                         "usershare prefix deny list entries.\n",
4273                                         servicename, sharepath));
4274                                 return USERSHARE_PATH_IS_DENIED;
4275                         }
4276                 }
4277         }
4278
4279         /* If there is a usershare prefix allow list ensure one of these paths
4280            does match the start of the user given path. */
4281
4282         if (prefixallowlist) {
4283                 int i;
4284                 for ( i=0; prefixallowlist[i]; i++ ) {
4285                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4286                                 servicename, i, prefixallowlist[i], sharepath ));
4287                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4288                                 break;
4289                         }
4290                 }
4291                 if (prefixallowlist[i] == NULL) {
4292                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4293                                 "usershare prefix allow list entries.\n",
4294                                 servicename, sharepath));
4295                         return USERSHARE_PATH_NOT_ALLOWED;
4296                 }
4297         }
4298
4299         /* Ensure this is pointing to a directory. */
4300         dp = opendir(sharepath);
4301
4302         if (!dp) {
4303                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4304                         servicename, sharepath));
4305                 return USERSHARE_PATH_NOT_DIRECTORY;
4306         }
4307
4308         /* Ensure the owner of the usershare file has permission to share
4309            this directory. */
4310
4311         if (sys_stat(sharepath, &sbuf, false) == -1) {
4312                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4313                         servicename, sharepath, strerror(errno) ));
4314                 closedir(dp);
4315                 return USERSHARE_POSIX_ERR;
4316         }
4317
4318         closedir(dp);
4319
4320         if (!S_ISDIR(sbuf.st_ex_mode)) {
4321                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4322                         servicename, sharepath ));
4323                 return USERSHARE_PATH_NOT_DIRECTORY;
4324         }
4325
4326         /* Check if sharing is restricted to owner-only. */
4327         /* psbuf is the stat of the usershare definition file,
4328            sbuf is the stat of the target directory to be shared. */
4329
4330         if (lp_usershare_owner_only()) {
4331                 /* root can share anything. */
4332                 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
4333                         return USERSHARE_PATH_NOT_ALLOWED;
4334                 }
4335         }
4336
4337         *pp_sharepath = sharepath;
4338         *pp_comment = comment;
4339         return USERSHARE_OK;
4340 }
4341
4342 /***************************************************************************
4343  Deal with a usershare file.
4344  Returns:
4345         >= 0 - snum
4346         -1 - Bad name, invalid contents.
4347            - service name already existed and not a usershare, problem
4348             with permissions to share directory etc.
4349 ***************************************************************************/
4350
4351 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4352 {
4353         SMB_STRUCT_STAT sbuf;
4354         SMB_STRUCT_STAT lsbuf;
4355         char *fname = NULL;
4356         char *sharepath = NULL;
4357         char *comment = NULL;
4358         char *cp_service_name = NULL;
4359         char **lines = NULL;
4360         int numlines = 0;
4361         int fd = -1;
4362         int iService = -1;
4363         TALLOC_CTX *ctx = talloc_stackframe();
4364         struct security_descriptor *psd = NULL;
4365         bool guest_ok = false;
4366         char *canon_name = NULL;
4367         bool added_service = false;
4368         int ret = -1;
4369
4370         /* Ensure share name doesn't contain invalid characters. */
4371         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4372                 DEBUG(0,("process_usershare_file: share name %s contains "
4373                         "invalid characters (any of %s)\n",
4374                         file_name, INVALID_SHARENAME_CHARS ));
4375                 goto out;
4376         }
4377
4378         canon_name = canonicalize_servicename(ctx, file_name);
4379         if (!canon_name) {
4380                 goto out;
4381         }
4382
4383         fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
4384         if (!fname) {
4385                 goto out;
4386         }
4387
4388         /* Minimize the race condition by doing an lstat before we
4389            open and fstat. Ensure this isn't a symlink link. */
4390
4391         if (sys_lstat(fname, &lsbuf, false) != 0) {
4392                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4393                         fname, strerror(errno) ));
4394                 goto out;
4395         }
4396
4397         /* This must be a regular file, not a symlink, directory or
4398            other strange filetype. */
4399         if (!check_usershare_stat(fname, &lsbuf)) {
4400                 goto out;
4401         }
4402
4403         {
4404                 TDB_DATA data;
4405                 NTSTATUS status;
4406
4407                 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
4408                                                canon_name, &data);
4409
4410                 iService = -1;
4411
4412                 if (NT_STATUS_IS_OK(status) &&
4413                     (data.dptr != NULL) &&
4414                     (data.dsize == sizeof(iService))) {
4415                         memcpy(&iService, data.dptr, sizeof(iService));
4416                 }
4417         }
4418
4419         if (iService != -1 &&
4420             timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
4421                              &lsbuf.st_ex_mtime) == 0) {
4422                 /* Nothing changed - Mark valid and return. */
4423                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4424                         canon_name ));
4425                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4426                 ret = iService;
4427                 goto out;
4428         }
4429
4430         /* Try and open the file read only - no symlinks allowed. */
4431 #ifdef O_NOFOLLOW
4432         fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
4433 #else
4434         fd = open(fname, O_RDONLY, 0);
4435 #endif
4436
4437         if (fd == -1) {
4438                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4439                         fname, strerror(errno) ));
4440                 goto out;
4441         }
4442
4443         /* Now fstat to be *SURE* it's a regular file. */
4444         if (sys_fstat(fd, &sbuf, false) != 0) {
4445                 close(fd);
4446                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4447                         fname, strerror(errno) ));
4448                 goto out;
4449         }
4450
4451         /* Is it the same dev/inode as was lstated ? */
4452         if (!check_same_stat(&lsbuf, &sbuf)) {
4453                 close(fd);
4454                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4455                         "Symlink spoofing going on ?\n", fname ));
4456                 goto out;
4457         }
4458
4459         /* This must be a regular file, not a symlink, directory or
4460            other strange filetype. */
4461         if (!check_usershare_stat(fname, &sbuf)) {
4462                 close(fd);
4463                 goto out;
4464         }
4465
4466         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
4467
4468         close(fd);
4469         if (lines == NULL) {
4470                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4471                         fname, (unsigned int)sbuf.st_ex_uid ));
4472                 goto out;
4473         }
4474
4475         if (parse_usershare_file(ctx, &sbuf, file_name,
4476                         iService, lines, numlines, &sharepath,
4477                         &comment, &cp_service_name,
4478                         &psd, &guest_ok) != USERSHARE_OK) {
4479                 goto out;
4480         }
4481
4482         /* Everything ok - add the service possibly using a template. */
4483         if (iService < 0) {
4484                 const struct loadparm_service *sp = &sDefault;
4485                 if (snum_template != -1) {
4486                         sp = ServicePtrs[snum_template];
4487                 }
4488
4489                 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
4490                         DEBUG(0, ("process_usershare_file: Failed to add "
4491                                 "new service %s\n", cp_service_name));
4492                         goto out;
4493                 }
4494
4495                 added_service = true;
4496
4497                 /* Read only is controlled by usershare ACL below. */
4498                 ServicePtrs[iService]->readonly = false;
4499         }
4500
4501         /* Write the ACL of the new/modified share. */
4502         if (!set_share_security(canon_name, psd)) {
4503                  DEBUG(0, ("process_usershare_file: Failed to set share "
4504                         "security for user share %s\n",
4505                         canon_name ));
4506                 goto out;
4507         }
4508
4509         /* If from a template it may be marked invalid. */
4510         ServicePtrs[iService]->valid = true;
4511
4512         /* Set the service as a valid usershare. */
4513         ServicePtrs[iService]->usershare = USERSHARE_VALID;
4514
4515         /* Set guest access. */
4516         if (lp_usershare_allow_guests()) {
4517                 ServicePtrs[iService]->guest_ok = guest_ok;
4518         }
4519
4520         /* And note when it was loaded. */
4521         ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
4522         string_set(&ServicePtrs[iService]->pathname, sharepath);
4523         string_set(&ServicePtrs[iService]->comment, comment);
4524
4525         ret = iService;
4526
4527   out:
4528
4529         if (ret == -1 && iService != -1 && added_service) {
4530                 lp_remove_service(iService);
4531         }
4532
4533         TALLOC_FREE(lines);
4534         TALLOC_FREE(ctx);
4535         return ret;
4536 }
4537
4538 /***************************************************************************
4539  Checks if a usershare entry has been modified since last load.
4540 ***************************************************************************/
4541
4542 static bool usershare_exists(int iService, struct timespec *last_mod)
4543 {
4544         SMB_STRUCT_STAT lsbuf;
4545         const char *usersharepath = Globals.usershare_path;
4546         char *fname;
4547
4548         if (asprintf(&fname, "%s/%s",
4549                                 usersharepath,
4550                                 ServicePtrs[iService]->szService) < 0) {
4551                 return false;
4552         }
4553
4554         if (sys_lstat(fname, &lsbuf, false) != 0) {
4555                 SAFE_FREE(fname);
4556                 return false;
4557         }
4558
4559         if (!S_ISREG(lsbuf.st_ex_mode)) {
4560                 SAFE_FREE(fname);
4561                 return false;
4562         }
4563
4564         SAFE_FREE(fname);
4565         *last_mod = lsbuf.st_ex_mtime;
4566         return true;
4567 }
4568
4569 /***************************************************************************
4570  Load a usershare service by name. Returns a valid servicenumber or -1.
4571 ***************************************************************************/
4572
4573 int load_usershare_service(const char *servicename)
4574 {
4575         SMB_STRUCT_STAT sbuf;
4576         const char *usersharepath = Globals.usershare_path;
4577         int max_user_shares = Globals.usershare_max_shares;
4578         int snum_template = -1;
4579
4580         if (*usersharepath == 0 ||  max_user_shares == 0) {
4581                 return -1;
4582         }
4583
4584         if (sys_stat(usersharepath, &sbuf, false) != 0) {
4585                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4586                         usersharepath, strerror(errno) ));
4587                 return -1;
4588         }
4589
4590         if (!S_ISDIR(sbuf.st_ex_mode)) {
4591                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4592                         usersharepath ));
4593                 return -1;
4594         }
4595
4596         /*
4597          * This directory must be owned by root, and have the 't' bit set.
4598          * It also must not be writable by "other".
4599          */
4600
4601 #ifdef S_ISVTX
4602         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4603 #else
4604         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4605 #endif
4606                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4607                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4608                         usersharepath ));
4609                 return -1;
4610         }
4611
4612         /* Ensure the template share exists if it's set. */
4613         if (Globals.szUsershareTemplateShare[0]) {
4614                 /* We can't use lp_servicenumber here as we are recommending that
4615                    template shares have -valid=false set. */
4616                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4617                         if (ServicePtrs[snum_template]->szService &&
4618                                         strequal(ServicePtrs[snum_template]->szService,
4619                                                 Globals.szUsershareTemplateShare)) {
4620                                 break;
4621                         }
4622                 }
4623
4624                 if (snum_template == -1) {
4625                         DEBUG(0,("load_usershare_service: usershare template share %s "
4626                                 "does not exist.\n",
4627                                 Globals.szUsershareTemplateShare ));
4628                         return -1;
4629                 }
4630         }
4631
4632         return process_usershare_file(usersharepath, servicename, snum_template);
4633 }
4634
4635 /***************************************************************************
4636  Load all user defined shares from the user share directory.
4637  We only do this if we're enumerating the share list.
4638  This is the function that can delete usershares that have
4639  been removed.
4640 ***************************************************************************/
4641
4642 int load_usershare_shares(struct smbd_server_connection *sconn,
4643                           bool (*snumused) (struct smbd_server_connection *, int))
4644 {
4645         DIR *dp;
4646         SMB_STRUCT_STAT sbuf;
4647         struct dirent *de;
4648         int num_usershares = 0;
4649         int max_user_shares = Globals.usershare_max_shares;
4650         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4651         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4652         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4653         int iService;
4654         int snum_template = -1;
4655         const char *usersharepath = Globals.usershare_path;
4656         int ret = lp_numservices();
4657         TALLOC_CTX *tmp_ctx;
4658
4659         if (max_user_shares == 0 || *usersharepath == '\0') {
4660                 return lp_numservices();
4661         }
4662
4663         if (sys_stat(usersharepath, &sbuf, false) != 0) {
4664                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4665                         usersharepath, strerror(errno) ));
4666                 return ret;
4667         }
4668
4669         /*
4670          * This directory must be owned by root, and have the 't' bit set.
4671          * It also must not be writable by "other".
4672          */
4673
4674 #ifdef S_ISVTX
4675         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
4676 #else
4677         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
4678 #endif
4679                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4680                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4681                         usersharepath ));
4682                 return ret;
4683         }
4684
4685         /* Ensure the template share exists if it's set. */
4686         if (Globals.szUsershareTemplateShare[0]) {
4687                 /* We can't use lp_servicenumber here as we are recommending that
4688                    template shares have -valid=false set. */
4689                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4690                         if (ServicePtrs[snum_template]->szService &&
4691                                         strequal(ServicePtrs[snum_template]->szService,
4692                                                 Globals.szUsershareTemplateShare)) {
4693                                 break;
4694                         }
4695                 }
4696
4697                 if (snum_template == -1) {
4698                         DEBUG(0,("load_usershare_shares: usershare template share %s "
4699                                 "does not exist.\n",
4700                                 Globals.szUsershareTemplateShare ));
4701                         return ret;
4702                 }
4703         }
4704
4705         /* Mark all existing usershares as pending delete. */
4706         for (iService = iNumServices - 1; iService >= 0; iService--) {
4707                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4708                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4709                 }
4710         }
4711
4712         dp = opendir(usersharepath);
4713         if (!dp) {
4714                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4715                         usersharepath, strerror(errno) ));
4716                 return ret;
4717         }
4718
4719         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4720                         (de = readdir(dp));
4721                         num_dir_entries++ ) {
4722                 int r;
4723                 const char *n = de->d_name;
4724
4725                 /* Ignore . and .. */
4726                 if (*n == '.') {
4727                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4728                                 continue;
4729                         }
4730                 }
4731
4732                 if (n[0] == ':') {
4733                         /* Temporary file used when creating a share. */
4734                         num_tmp_dir_entries++;
4735                 }
4736
4737                 /* Allow 20% tmp entries. */
4738                 if (num_tmp_dir_entries > allowed_tmp_entries) {
4739                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4740                                 "in directory %s\n",
4741                                 num_tmp_dir_entries, usersharepath));
4742                         break;
4743                 }
4744
4745                 r = process_usershare_file(usersharepath, n, snum_template);
4746                 if (r == 0) {
4747                         /* Update the services count. */
4748                         num_usershares++;
4749                         if (num_usershares >= max_user_shares) {
4750                                 DEBUG(0,("load_usershare_shares: max user shares reached "
4751                                         "on file %s in directory %s\n",
4752                                         n, usersharepath ));
4753                                 break;
4754                         }
4755                 } else if (r == -1) {
4756                         num_bad_dir_entries++;
4757                 }
4758
4759                 /* Allow 20% bad entries. */
4760                 if (num_bad_dir_entries > allowed_bad_entries) {
4761                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4762                                 "in directory %s\n",
4763                                 num_bad_dir_entries, usersharepath));
4764                         break;
4765                 }
4766
4767                 /* Allow 20% bad entries. */
4768                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4769                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4770                         "in directory %s\n",
4771                         num_dir_entries, usersharepath));
4772                         break;
4773                 }
4774         }
4775
4776         closedir(dp);
4777
4778         /* Sweep through and delete any non-refreshed usershares that are
4779            not currently in use. */
4780         tmp_ctx = talloc_stackframe();
4781         for (iService = iNumServices - 1; iService >= 0; iService--) {
4782                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4783                         char *servname;
4784
4785                         if (snumused && snumused(sconn, iService)) {
4786                                 continue;
4787                         }
4788
4789                         servname = lp_servicename(tmp_ctx, iService);
4790
4791                         /* Remove from the share ACL db. */
4792                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4793                                   servname ));
4794                         delete_share_security(servname);
4795                         free_service_byindex(iService);
4796                 }
4797         }
4798         talloc_free(tmp_ctx);
4799
4800         return lp_numservices();
4801 }
4802
4803 /********************************************************
4804  Destroy global resources allocated in this file
4805 ********************************************************/
4806
4807 void gfree_loadparm(void)
4808 {
4809         int i;
4810
4811         free_file_list();
4812
4813         /* Free resources allocated to services */
4814
4815         for ( i = 0; i < iNumServices; i++ ) {
4816                 if ( VALID(i) ) {
4817                         free_service_byindex(i);
4818                 }
4819         }
4820
4821         SAFE_FREE( ServicePtrs );
4822         iNumServices = 0;
4823
4824         /* Now release all resources allocated to global
4825            parameters and the default service */
4826
4827         free_global_parameters();
4828 }
4829
4830
4831 /***************************************************************************
4832  Allow client apps to specify that they are a client
4833 ***************************************************************************/
4834 static void lp_set_in_client(bool b)
4835 {
4836     in_client = b;
4837 }
4838
4839
4840 /***************************************************************************
4841  Determine if we're running in a client app
4842 ***************************************************************************/
4843 static bool lp_is_in_client(void)
4844 {
4845     return in_client;
4846 }
4847
4848 /***************************************************************************
4849  Load the services array from the services file. Return true on success,
4850  false on failure.
4851 ***************************************************************************/
4852
4853 static bool lp_load_ex(const char *pszFname,
4854                        bool global_only,
4855                        bool save_defaults,
4856                        bool add_ipc,
4857                        bool initialize_globals,
4858                        bool allow_include_registry,
4859                        bool load_all_shares)
4860 {
4861         char *n2 = NULL;
4862         bool bRetval;
4863
4864         bRetval = false;
4865
4866         DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4867
4868         bInGlobalSection = true;
4869         bGlobalOnly = global_only;
4870         bAllowIncludeRegistry = allow_include_registry;
4871
4872         init_globals(initialize_globals);
4873
4874         free_file_list();
4875
4876         if (save_defaults) {
4877                 init_locals();
4878                 lp_save_defaults();
4879         }
4880
4881         if (!initialize_globals) {
4882                 free_param_opts(&Globals.param_opt);
4883                 apply_lp_set_cmdline();
4884         }
4885
4886         lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
4887
4888         /* We get sections first, so have to start 'behind' to make up */
4889         iServiceIndex = -1;
4890
4891         if (lp_config_backend_is_file()) {
4892                 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
4893                                         current_user_info.domain,
4894                                         pszFname);
4895                 if (!n2) {
4896                         smb_panic("lp_load_ex: out of memory");
4897                 }
4898
4899                 add_to_file_list(pszFname, n2);
4900
4901                 bRetval = pm_process(n2, do_section, do_parameter, NULL);
4902                 TALLOC_FREE(n2);
4903
4904                 /* finish up the last section */
4905                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
4906                 if (bRetval) {
4907                         if (iServiceIndex >= 0) {
4908                                 bRetval = service_ok(iServiceIndex);
4909                         }
4910                 }
4911
4912                 if (lp_config_backend_is_registry()) {
4913                         /* config backend changed to registry in config file */
4914                         /*
4915                          * We need to use this extra global variable here to
4916                          * survive restart: init_globals uses this as a default
4917                          * for config_backend. Otherwise, init_globals would
4918                          *  send us into an endless loop here.
4919                          */
4920                         config_backend = CONFIG_BACKEND_REGISTRY;
4921                         /* start over */
4922                         DEBUG(1, ("lp_load_ex: changing to config backend "
4923                                   "registry\n"));
4924                         init_globals(true);
4925                         lp_kill_all_services();
4926                         return lp_load_ex(pszFname, global_only, save_defaults,
4927                                           add_ipc, initialize_globals,
4928                                           allow_include_registry,
4929                                           load_all_shares);
4930                 }
4931         } else if (lp_config_backend_is_registry()) {
4932                 bRetval = process_registry_globals();
4933         } else {
4934                 DEBUG(0, ("Illegal config  backend given: %d\n",
4935                           lp_config_backend()));
4936                 bRetval = false;
4937         }
4938
4939         if (bRetval && lp_registry_shares()) {
4940                 if (load_all_shares) {
4941                         bRetval = process_registry_shares();
4942                 } else {
4943                         bRetval = reload_registry_shares();
4944                 }
4945         }
4946
4947         {
4948                 char *serv = lp_auto_services(talloc_tos());
4949                 lp_add_auto_services(serv);
4950                 TALLOC_FREE(serv);
4951         }
4952
4953         if (add_ipc) {
4954                 /* When 'restrict anonymous = 2' guest connections to ipc$
4955                    are denied */
4956                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4957                 if ( lp_enable_asu_support() ) {
4958                         lp_add_ipc("ADMIN$", false);
4959                 }
4960         }
4961
4962         set_allowed_client_auth();
4963
4964         if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
4965                 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4966                           lp_passwordserver()));
4967         }
4968
4969         bLoaded = true;
4970
4971         /* Now we check we_are_a_wins_server and set szWINSserver to 127.0.0.1 */
4972         /* if we_are_a_wins_server is true and we are in the client            */
4973         if (lp_is_in_client() && Globals.we_are_a_wins_server) {
4974                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
4975         }
4976
4977         init_iconv();
4978
4979         fault_configure(smb_panic_s3);
4980
4981         /*
4982          * We run this check once the whole smb.conf is parsed, to
4983          * force some settings for the standard way a AD DC is
4984          * operated.  We may changed these as our code evolves, which
4985          * is why we force these settings.
4986          */
4987         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
4988                 lp_do_parameter(-1, "passdb backend", "samba_dsdb");
4989
4990                 lp_do_parameter(-1, "rpc_server:default", "external");
4991                 lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
4992                 lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
4993                 lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
4994                 lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
4995                 lp_do_parameter(-1, "rpc_server:winreg", "embedded");
4996                 lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
4997                 lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
4998                 lp_do_parameter(-1, "rpc_server:tcpip", "no");
4999         }
5000
5001         bAllowIncludeRegistry = true;
5002
5003         return (bRetval);
5004 }
5005
5006 bool lp_load(const char *pszFname,
5007              bool global_only,
5008              bool save_defaults,
5009              bool add_ipc,
5010              bool initialize_globals)
5011 {
5012         return lp_load_ex(pszFname,
5013                           global_only,
5014                           save_defaults,
5015                           add_ipc,
5016                           initialize_globals,
5017                           true,   /* allow_include_registry */
5018                           false); /* load_all_shares*/
5019 }
5020
5021 bool lp_load_initial_only(const char *pszFname)
5022 {
5023         return lp_load_ex(pszFname,
5024                           true,   /* global only */
5025                           false,  /* save_defaults */
5026                           false,  /* add_ipc */
5027                           true,   /* initialize_globals */
5028                           false,  /* allow_include_registry */
5029                           false); /* load_all_shares*/
5030 }
5031
5032 /**
5033  * most common lp_load wrapper, loading only the globals
5034  */
5035 bool lp_load_global(const char *file_name)
5036 {
5037         return lp_load_ex(file_name,
5038                           true,   /* global_only */
5039                           false,  /* save_defaults */
5040                           false,  /* add_ipc */
5041                           true,   /* initialize_globals */
5042                           true,   /* allow_include_registry */
5043                           false); /* load_all_shares*/
5044 }
5045
5046 /**
5047  * lp_load wrapper, especially for clients
5048  */
5049 bool lp_load_client(const char *file_name)
5050 {
5051         lp_set_in_client(true);
5052
5053         return lp_load_global(file_name);
5054 }
5055
5056 /**
5057  * lp_load wrapper, loading only globals, but intended
5058  * for subsequent calls, not reinitializing the globals
5059  * to default values
5060  */
5061 bool lp_load_global_no_reinit(const char *file_name)
5062 {
5063         return lp_load_ex(file_name,
5064                           true,   /* global_only */
5065                           false,  /* save_defaults */
5066                           false,  /* add_ipc */
5067                           false,  /* initialize_globals */
5068                           true,   /* allow_include_registry */
5069                           false); /* load_all_shares*/
5070 }
5071
5072 /**
5073  * lp_load wrapper, especially for clients, no reinitialization
5074  */
5075 bool lp_load_client_no_reinit(const char *file_name)
5076 {
5077         lp_set_in_client(true);
5078
5079         return lp_load_global_no_reinit(file_name);
5080 }
5081
5082 bool lp_load_with_registry_shares(const char *pszFname,
5083                                   bool global_only,
5084                                   bool save_defaults,
5085                                   bool add_ipc,
5086                                   bool initialize_globals)
5087 {
5088         return lp_load_ex(pszFname,
5089                           global_only,
5090                           save_defaults,
5091                           add_ipc,
5092                           initialize_globals,
5093                           true,  /* allow_include_registry */
5094                           true); /* load_all_shares*/
5095 }
5096
5097 /***************************************************************************
5098  Return the max number of services.
5099 ***************************************************************************/
5100
5101 int lp_numservices(void)
5102 {
5103         return (iNumServices);
5104 }
5105
5106 /***************************************************************************
5107 Display the contents of the services array in human-readable form.
5108 ***************************************************************************/
5109
5110 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5111 {
5112         int iService;
5113
5114         if (show_defaults)
5115                 defaults_saved = false;
5116
5117         dump_globals(f);
5118
5119         dump_a_service(&sDefault, f);
5120
5121         for (iService = 0; iService < maxtoprint; iService++) {
5122                 fprintf(f,"\n");
5123                 lp_dump_one(f, show_defaults, iService);
5124         }
5125 }
5126
5127 /***************************************************************************
5128 Display the contents of one service in human-readable form.
5129 ***************************************************************************/
5130
5131 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5132 {
5133         if (VALID(snum)) {
5134                 if (ServicePtrs[snum]->szService[0] == '\0')
5135                         return;
5136                 dump_a_service(ServicePtrs[snum], f);
5137         }
5138 }
5139
5140 /***************************************************************************
5141 Return the number of the service with the given name, or -1 if it doesn't
5142 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5143 getservicebyname()! This works ONLY if all services have been loaded, and
5144 does not copy the found service.
5145 ***************************************************************************/
5146
5147 int lp_servicenumber(const char *pszServiceName)
5148 {
5149         int iService;
5150         fstring serviceName;
5151
5152         if (!pszServiceName) {
5153                 return GLOBAL_SECTION_SNUM;
5154         }
5155
5156         for (iService = iNumServices - 1; iService >= 0; iService--) {
5157                 if (VALID(iService) && ServicePtrs[iService]->szService) {
5158                         /*
5159                          * The substitution here is used to support %U is
5160                          * service names
5161                          */
5162                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
5163                         standard_sub_basic(get_current_username(),
5164                                            current_user_info.domain,
5165                                            serviceName,sizeof(serviceName));
5166                         if (strequal(serviceName, pszServiceName)) {
5167                                 break;
5168                         }
5169                 }
5170         }
5171
5172         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5173                 struct timespec last_mod;
5174
5175                 if (!usershare_exists(iService, &last_mod)) {
5176                         /* Remove the share security tdb entry for it. */
5177                         delete_share_security(lp_servicename(talloc_tos(), iService));
5178                         /* Remove it from the array. */
5179                         free_service_byindex(iService);
5180                         /* Doesn't exist anymore. */
5181                         return GLOBAL_SECTION_SNUM;
5182                 }
5183
5184                 /* Has it been modified ? If so delete and reload. */
5185                 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
5186                                      &last_mod) < 0) {
5187                         /* Remove it from the array. */
5188                         free_service_byindex(iService);
5189                         /* and now reload it. */
5190                         iService = load_usershare_service(pszServiceName);
5191                 }
5192         }
5193
5194         if (iService < 0) {
5195                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5196                 return GLOBAL_SECTION_SNUM;
5197         }
5198
5199         return (iService);
5200 }
5201
5202 /*******************************************************************
5203  A useful volume label function. 
5204 ********************************************************************/
5205
5206 const char *volume_label(TALLOC_CTX *ctx, int snum)
5207 {
5208         char *ret;
5209         const char *label = lp_volume(ctx, snum);
5210         if (!*label) {
5211                 label = lp_servicename(ctx, snum);
5212         }
5213
5214         /* This returns a 33 byte guarenteed null terminated string. */
5215         ret = talloc_strndup(ctx, label, 32);
5216         if (!ret) {
5217                 return "";
5218         }               
5219         return ret;
5220 }
5221
5222 /*******************************************************************
5223  Get the default server type we will announce as via nmbd.
5224 ********************************************************************/
5225
5226 int lp_default_server_announce(void)
5227 {
5228         int default_server_announce = 0;
5229         default_server_announce |= SV_TYPE_WORKSTATION;
5230         default_server_announce |= SV_TYPE_SERVER;
5231         default_server_announce |= SV_TYPE_SERVER_UNIX;
5232
5233         /* note that the flag should be set only if we have a 
5234            printer service but nmbd doesn't actually load the 
5235            services so we can't tell   --jerry */
5236
5237         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5238
5239         default_server_announce |= SV_TYPE_SERVER_NT;
5240         default_server_announce |= SV_TYPE_NT;
5241
5242         switch (lp_server_role()) {
5243                 case ROLE_DOMAIN_MEMBER:
5244                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5245                         break;
5246                 case ROLE_DOMAIN_PDC:
5247                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5248                         break;
5249                 case ROLE_DOMAIN_BDC:
5250                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5251                         break;
5252                 case ROLE_STANDALONE:
5253                 default:
5254                         break;
5255         }
5256         if (lp_time_server())
5257                 default_server_announce |= SV_TYPE_TIME_SOURCE;
5258
5259         if (lp_host_msdfs())
5260                 default_server_announce |= SV_TYPE_DFS_SERVER;
5261
5262         return default_server_announce;
5263 }
5264
5265 /***********************************************************
5266  If we are PDC then prefer us as DMB
5267 ************************************************************/
5268
5269 bool lp_domain_master(void)
5270 {
5271         if (Globals._domain_master == Auto)
5272                 return (lp_server_role() == ROLE_DOMAIN_PDC);
5273
5274         return (bool)Globals._domain_master;
5275 }
5276
5277 /***********************************************************
5278  If we are PDC then prefer us as DMB
5279 ************************************************************/
5280
5281 static bool lp_domain_master_true_or_auto(void)
5282 {
5283         if (Globals._domain_master) /* auto or yes */
5284                 return true;
5285
5286         return false;
5287 }
5288
5289 /***********************************************************
5290  If we are DMB then prefer us as LMB
5291 ************************************************************/
5292
5293 bool lp_preferred_master(void)
5294 {
5295         if (Globals.iPreferredMaster == Auto)
5296                 return (lp_local_master() && lp_domain_master());
5297
5298         return (bool)Globals.iPreferredMaster;
5299 }
5300
5301 /*******************************************************************
5302  Remove a service.
5303 ********************************************************************/
5304
5305 void lp_remove_service(int snum)
5306 {
5307         ServicePtrs[snum]->valid = false;
5308 }
5309
5310 /*******************************************************************
5311  Copy a service.
5312 ********************************************************************/
5313
5314 void lp_copy_service(int snum, const char *new_name)
5315 {
5316         do_section(new_name, NULL);
5317         if (snum >= 0) {
5318                 snum = lp_servicenumber(new_name);
5319                 if (snum >= 0) {
5320                         char *name = lp_servicename(talloc_tos(), snum);
5321                         lp_do_parameter(snum, "copy", name);
5322                 }
5323         }
5324 }
5325
5326 const char *lp_printername(TALLOC_CTX *ctx, int snum)
5327 {
5328         const char *ret = lp__printername(ctx, snum);
5329         if (ret == NULL || *ret == '\0') {
5330                 ret = lp_const_servicename(snum);
5331         }
5332
5333         return ret;
5334 }
5335
5336
5337 /***********************************************************
5338  Allow daemons such as winbindd to fix their logfile name.
5339 ************************************************************/
5340
5341 void lp_set_logfile(const char *name)
5342 {
5343         string_set(&Globals.logfile, name);
5344         debug_set_logfile(name);
5345 }
5346
5347 /*******************************************************************
5348  Return the max print jobs per queue.
5349 ********************************************************************/
5350
5351 int lp_maxprintjobs(int snum)
5352 {
5353         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5354         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5355                 maxjobs = PRINT_MAX_JOBID - 1;
5356
5357         return maxjobs;
5358 }
5359
5360 const char *lp_printcapname(void)
5361 {
5362         if ((Globals.szPrintcapname != NULL) &&
5363             (Globals.szPrintcapname[0] != '\0'))
5364                 return Globals.szPrintcapname;
5365
5366         if (sDefault.printing == PRINT_CUPS) {
5367                 return "cups";
5368         }
5369
5370         if (sDefault.printing == PRINT_BSD)
5371                 return "/etc/printcap";
5372
5373         return PRINTCAP_NAME;
5374 }
5375
5376 static uint32 spoolss_state;
5377
5378 bool lp_disable_spoolss( void )
5379 {
5380         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5381                 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5382
5383         return spoolss_state == SVCCTL_STOPPED ? true : false;
5384 }
5385
5386 void lp_set_spoolss_state( uint32 state )
5387 {
5388         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5389
5390         spoolss_state = state;
5391 }
5392
5393 uint32 lp_get_spoolss_state( void )
5394 {
5395         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5396 }
5397
5398 /*******************************************************************
5399  Ensure we don't use sendfile if server smb signing is active.
5400 ********************************************************************/
5401
5402 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
5403 {
5404         bool sign_active = false;
5405
5406         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5407         if (get_Protocol() < PROTOCOL_NT1) {
5408                 return false;
5409         }
5410         if (signing_state) {
5411                 sign_active = smb_signing_is_active(signing_state);
5412         }
5413         return (lp__use_sendfile(snum) &&
5414                         (get_remote_arch() != RA_WIN95) &&
5415                         !sign_active);
5416 }
5417
5418 /*******************************************************************
5419  Turn off sendfile if we find the underlying OS doesn't support it.
5420 ********************************************************************/
5421
5422 void set_use_sendfile(int snum, bool val)
5423 {
5424         if (LP_SNUM_OK(snum))
5425                 ServicePtrs[snum]->_use_sendfile = val;
5426         else
5427                 sDefault._use_sendfile = val;
5428 }
5429
5430 /*******************************************************************
5431  Turn off storing DOS attributes if this share doesn't support it.
5432 ********************************************************************/
5433
5434 void set_store_dos_attributes(int snum, bool val)
5435 {
5436         if (!LP_SNUM_OK(snum))
5437                 return;
5438         ServicePtrs[(snum)]->store_dos_attributes = val;
5439 }
5440
5441 void lp_set_mangling_method(const char *new_method)
5442 {
5443         string_set(&Globals.mangling_method, new_method);
5444 }
5445
5446 /*******************************************************************
5447  Global state for POSIX pathname processing.
5448 ********************************************************************/
5449
5450 static bool posix_pathnames;
5451
5452 bool lp_posix_pathnames(void)
5453 {
5454         return posix_pathnames;
5455 }
5456
5457 /*******************************************************************
5458  Change everything needed to ensure POSIX pathname processing (currently
5459  not much).
5460 ********************************************************************/
5461
5462 void lp_set_posix_pathnames(void)
5463 {
5464         posix_pathnames = true;
5465 }
5466
5467 /*******************************************************************
5468  Global state for POSIX lock processing - CIFS unix extensions.
5469 ********************************************************************/
5470
5471 bool posix_default_lock_was_set;
5472 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5473
5474 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
5475 {
5476         if (posix_default_lock_was_set) {
5477                 return posix_cifsx_locktype;
5478         } else {
5479                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
5480         }
5481 }
5482
5483 /*******************************************************************
5484 ********************************************************************/
5485
5486 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
5487 {
5488         posix_default_lock_was_set = true;
5489         posix_cifsx_locktype = val;
5490 }
5491
5492 int lp_min_receive_file_size(void)
5493 {
5494         if (Globals.iminreceivefile < 0) {
5495                 return 0;
5496         }
5497         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
5498 }
5499
5500 /*******************************************************************
5501  Safe wide links checks.
5502  This helper function always verify the validity of wide links,
5503  even after a configuration file reload.
5504 ********************************************************************/
5505
5506 static bool lp_widelinks_internal(int snum)
5507 {
5508         return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
5509                         sDefault.bWidelinks);
5510 }
5511
5512 void widelinks_warning(int snum)
5513 {
5514         if (lp_allow_insecure_widelinks()) {
5515                 return;
5516         }
5517
5518         if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
5519                 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5520                         "These parameters are incompatible. "
5521                         "Wide links will be disabled for this share.\n",
5522                          lp_servicename(talloc_tos(), snum) ));
5523         }
5524 }
5525
5526 bool lp_widelinks(int snum)
5527 {
5528         /* wide links is always incompatible with unix extensions */
5529         if (lp_unix_extensions()) {
5530                 /*
5531                  * Unless we have "allow insecure widelinks"
5532                  * turned on.
5533                  */
5534                 if (!lp_allow_insecure_widelinks()) {
5535                         return false;
5536                 }
5537         }
5538
5539         return lp_widelinks_internal(snum);
5540 }
5541
5542 bool lp_writeraw(void)
5543 {
5544         if (lp_async_smb_echo_handler()) {
5545                 return false;
5546         }
5547         return lp__writeraw();
5548 }
5549
5550 bool lp_readraw(void)
5551 {
5552         if (lp_async_smb_echo_handler()) {
5553                 return false;
5554         }
5555         return lp__readraw();
5556 }
5557
5558 int lp_server_role(void)
5559 {
5560         return lp_find_server_role(lp__server_role(),
5561                                    lp__security(),
5562                                    lp__domain_logons(),
5563                                    lp_domain_master_true_or_auto());
5564 }
5565
5566 int lp_security(void)
5567 {
5568         return lp_find_security(lp__server_role(),
5569                                 lp__security());
5570 }