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