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