r25430: Add the loadparm context to all parametric options.
[jelmer/samba4-debian.git] / source / 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) James Myers 2003 <myersjj@samba.org>
13    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14    
15    This program is free software; you can redistribute it and/or modify
16    it under the terms of the GNU General Public License as published by
17    the Free Software Foundation; either version 3 of the License, or
18    (at your option) any later version.
19    
20    This program is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23    GNU General Public License for more details.
24    
25    You should have received a copy of the GNU General Public License
26    along with this program.  If not, see <http://www.gnu.org/licenses/>.
27 */
28
29 /*
30  *  Load parameters.
31  *
32  *  This module provides suitable callback functions for the params
33  *  module. It builds the internal table of service details which is
34  *  then used by the rest of the server.
35  *
36  * To add a parameter:
37  *
38  * 1) add it to the global or service structure definition
39  * 2) add it to the parm_table
40  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
41  * 4) If it's a global then initialise it in init_globals. If a local
42  *    (ie. service) parameter then initialise it in the sDefault structure
43  *  
44  *
45  * Notes:
46  *   The configuration file is processed sequentially for speed. It is NOT
47  *   accessed randomly as happens in 'real' Windows. For this reason, there
48  *   is a fair bit of sequence-dependent code here - ie., code which assumes
49  *   that certain things happen before others. In particular, the code which
50  *   happens at the boundary between sections is delicately poised, so be
51  *   careful!
52  *
53  */
54
55 #include "includes.h"
56 #include "version.h"
57 #include "dynconfig.h"
58 #include "system/time.h"
59 #include "system/locale.h"
60 #include "system/network.h" /* needed for TCP_NODELAY */
61 #include "smb_server/smb_server.h"
62 #include "libcli/raw/signing.h"
63 #include "lib/util/dlinklist.h"
64 #include "param/param.h"
65 #include "param/loadparm.h"
66
67 static bool bLoaded = false;
68
69 #define standard_sub_basic talloc_strdup
70
71 static bool do_parameter(const char *, const char *, void *);
72 static bool defaults_saved = false;
73
74 struct param_opt {
75         struct param_opt *prev, *next;
76         char *key;
77         char *value;
78         int flags;
79 };
80
81 /* 
82  * This structure describes global (ie., server-wide) parameters.
83  */
84 struct loadparm_global
85 {
86         enum server_role server_role;
87
88         const char **smb_ports;
89         char *ncalrpc_dir;
90         char *szLockDir;
91         char *szModulesDir;
92         char *szPidDir;
93         char *szSetupDir;
94         char *szServerString;
95         char *szAutoServices;
96         char *szPasswdChat;
97         const char *szConfigFile;
98         char *szShareBackend;
99         char *szSAM_URL;
100         char *szSECRETS_URL;
101         char *szSPOOLSS_URL;
102         char *szWINS_CONFIG_URL;
103         char *szWINS_URL;
104         char *szPrivateDir;
105         const char **jsInclude;
106         char *jsonrpcServicesDir;
107         const char **szPasswordServers;
108         char *szSocketOptions;
109         char *szRealm;
110         const char **szWINSservers;
111         const char **szInterfaces;
112         char *szSocketAddress;
113         char *szAnnounceVersion;        /* This is initialised in init_globals */
114         char *szWorkgroup;
115         char *szNetbiosName;
116         const char **szNetbiosAliases;
117         char *szNetbiosScope;
118         char *szDomainOtherSIDs;
119         const char **szNameResolveOrder;
120         const char **dcerpc_ep_servers;
121         const char **server_services;
122         char *ntptr_providor;
123         char *szWinbindSeparator;
124         char *szWinbinddSocketDirectory;
125         char *szTemplateShell;
126         char *szTemplateHomedir;
127         int bWinbindSealedPipes;
128         char *swat_directory;
129         int tls_enabled;
130         char *tls_keyfile;
131         char *tls_certfile;
132         char *tls_cafile;
133         char *tls_crlfile;
134         char *tls_dhpfile;
135         int max_mux;
136         int max_xmit;
137         int pwordlevel;
138         int srv_maxprotocol;
139         int srv_minprotocol;
140         int cli_maxprotocol;
141         int cli_minprotocol;
142         int security;
143         int paranoid_server_security;
144         int max_wins_ttl;
145         int min_wins_ttl;
146         int announce_as;        /* This is initialised in init_globals */
147         int nbt_port;
148         int dgram_port;
149         int cldap_port;
150         int krb5_port;
151         int kpasswd_port;
152         int web_port;
153         char *socket_options;
154         int bWINSsupport;
155         int bWINSdnsProxy;
156         char *szWINSHook; 
157         int bLocalMaster;
158         int bPreferredMaster;
159         int bEncryptPasswords;
160         int bNullPasswords;
161         int bObeyPamRestrictions;
162         int bLargeReadwrite;
163         int bReadRaw;
164         int bWriteRaw;
165         int bTimeServer;
166         int bBindInterfacesOnly;
167         int bNTSmbSupport;
168         int bNTStatusSupport;
169         int bLanmanAuth;
170         int bNTLMAuth;
171         int bUseSpnego;
172         int server_signing;
173         int client_signing;
174         int bClientPlaintextAuth;
175         int bClientLanManAuth;
176         int bClientNTLMv2Auth;
177         int client_use_spnego_principal;
178         int bHostMSDfs;
179         int bUnicode;
180         int bUnixExtensions;
181         int bDisableNetbios;
182         int bRpcBigEndian;
183         struct param_opt *param_opt;
184 };
185
186
187 /* 
188  * This structure describes a single service. 
189  */
190 struct loadparm_service
191 {
192         char *szService;
193         char *szPath;
194         char *szCopy;
195         char *szInclude;
196         char *szPrintername;
197         char **szHostsallow;
198         char **szHostsdeny;
199         char *comment;
200         char *volume;
201         char *fstype;
202         char **ntvfs_handler;
203         int iMaxPrintJobs;
204         int iMaxConnections;
205         int iCSCPolicy;
206         int bAvailable;
207         int bBrowseable;
208         int bRead_only;
209         int bPrint_ok;
210         int bMap_system;
211         int bMap_hidden;
212         int bMap_archive;
213         int bStrictLocking;
214         int iCreate_mask;
215         int iCreate_force_mode;
216         int iDir_mask;
217         int iDir_force_mode;
218         int *copymap;
219         int bMSDfsRoot;
220         int bStrictSync;
221         int bCIFileSystem;
222         struct param_opt *param_opt;
223
224         char dummy[3];          /* for alignment */
225 };
226
227
228 /* This is a default service used to prime a services structure */
229 static struct loadparm_service sDefault = {
230         .szService = NULL,
231         .szPath = NULL,
232         .szCopy = NULL,
233         .szInclude = NULL,
234         .szPrintername = NULL,                  
235         .szHostsallow = NULL,                   
236         .szHostsdeny = NULL,                    
237         .comment = NULL,                        
238         .volume = NULL,                 
239         .fstype = NULL,                 
240         .ntvfs_handler = NULL,                   
241         .iMaxPrintJobs = 1000,                  
242         .iMaxConnections = 0,                   
243         .iCSCPolicy = 0,                        
244         .bAvailable = true,                     
245         .bBrowseable = true,                    
246         .bRead_only = true,                     
247         .bPrint_ok = false,                     
248         .bMap_system = false,                   
249         .bMap_hidden = false,                   
250         .bMap_archive = true,                   
251         .bStrictLocking = true,                 
252         .iCreate_mask = 0744,                   
253         .iCreate_force_mode = 0000,
254         .iDir_mask = 0755,                      
255         .iDir_force_mode = 0000,                        
256         .copymap = NULL,
257         .bMSDfsRoot = false,
258         .bStrictSync = false,
259         .bCIFileSystem = false,
260 };
261
262 /* local variables */
263 static struct loadparm_context {
264         struct loadparm_global Globals;
265         struct loadparm_service **ServicePtrs;
266         int iNumServices;
267         struct loadparm_service *currentService;
268         bool bInGlobalSection;
269         struct file_lists {
270                 struct file_lists *next;
271                 char *name;
272                 char *subfname;
273                 time_t modtime;
274         } *file_lists;
275 } loadparm;
276
277 struct loadparm_context *global_loadparm = &loadparm;
278
279 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
280
281 /* prototypes for the special type handlers */
282 static bool handle_include(struct loadparm_context *lp_ctx, 
283                            const char *pszParmValue, char **ptr);
284 static bool handle_copy(struct loadparm_context *lp_ctx, 
285                         const char *pszParmValue, char **ptr);
286
287 static const struct enum_list enum_protocol[] = {
288         {PROTOCOL_SMB2, "SMB2"},
289         {PROTOCOL_NT1, "NT1"},
290         {PROTOCOL_LANMAN2, "LANMAN2"},
291         {PROTOCOL_LANMAN1, "LANMAN1"},
292         {PROTOCOL_CORE, "CORE"},
293         {PROTOCOL_COREPLUS, "COREPLUS"},
294         {PROTOCOL_COREPLUS, "CORE+"},
295         {-1, NULL}
296 };
297
298 static const struct enum_list enum_security[] = {
299         {SEC_SHARE, "SHARE"},
300         {SEC_USER, "USER"},
301         {-1, NULL}
302 };
303
304 static const struct enum_list enum_announce_as[] = {
305         {ANNOUNCE_AS_NT_SERVER, "NT"},
306         {ANNOUNCE_AS_NT_SERVER, "NT Server"},
307         {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
308         {ANNOUNCE_AS_WIN95, "win95"},
309         {ANNOUNCE_AS_WFW, "WfW"},
310         {-1, NULL}
311 };
312
313 static const struct enum_list enum_bool_auto[] = {
314         {false, "No"},
315         {false, "False"},
316         {false, "0"},
317         {true, "Yes"},
318         {true, "True"},
319         {true, "1"},
320         {Auto, "Auto"},
321         {-1, NULL}
322 };
323
324 /* Client-side offline caching policy types */
325 #define CSC_POLICY_MANUAL 0
326 #define CSC_POLICY_DOCUMENTS 1
327 #define CSC_POLICY_PROGRAMS 2
328 #define CSC_POLICY_DISABLE 3
329
330 static const struct enum_list enum_csc_policy[] = {
331         {CSC_POLICY_MANUAL, "manual"},
332         {CSC_POLICY_DOCUMENTS, "documents"},
333         {CSC_POLICY_PROGRAMS, "programs"},
334         {CSC_POLICY_DISABLE, "disable"},
335         {-1, NULL}
336 };
337
338 /* SMB signing types. */
339 static const struct enum_list enum_smb_signing_vals[] = {
340         {SMB_SIGNING_OFF, "No"},
341         {SMB_SIGNING_OFF, "False"},
342         {SMB_SIGNING_OFF, "0"},
343         {SMB_SIGNING_OFF, "Off"},
344         {SMB_SIGNING_OFF, "disabled"},
345         {SMB_SIGNING_SUPPORTED, "Yes"},
346         {SMB_SIGNING_SUPPORTED, "True"},
347         {SMB_SIGNING_SUPPORTED, "1"},
348         {SMB_SIGNING_SUPPORTED, "On"},
349         {SMB_SIGNING_SUPPORTED, "enabled"},
350         {SMB_SIGNING_REQUIRED, "required"},
351         {SMB_SIGNING_REQUIRED, "mandatory"},
352         {SMB_SIGNING_REQUIRED, "force"},
353         {SMB_SIGNING_REQUIRED, "forced"},
354         {SMB_SIGNING_REQUIRED, "enforced"},
355         {SMB_SIGNING_AUTO, "auto"},
356         {-1, NULL}
357 };
358
359 static const struct enum_list enum_server_role[] = {
360         {ROLE_STANDALONE, "standalone"},
361         {ROLE_DOMAIN_MEMBER, "member server"},
362         {ROLE_DOMAIN_CONTROLLER, "domain controller"},
363         {-1, NULL}
364 };
365
366
367 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
368  *
369  * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
370  * is implied in current control logic. This may change at some later time. A
371  * flag value of 0 means - show as development option only.
372  *
373  * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
374  * screen in SWAT. This is used to exclude parameters as well as to squash all
375  * parameters that have been duplicated by pseudonyms.
376  */
377 static struct parm_struct parm_table[] = {
378         {"Base Options", P_SEP, P_SEPARATOR},
379
380         {"config file", P_STRING, P_GLOBAL, &loadparm.Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
381
382         {"server role", P_ENUM, P_GLOBAL, &loadparm.Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
383
384         {"dos charset", P_STRING, P_GLOBAL, &dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
385         {"unix charset", P_STRING, P_GLOBAL, &unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
386         {"ncalrpc dir", P_STRING, P_GLOBAL, &loadparm.Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
387         {"display charset", P_STRING, P_GLOBAL, &display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
388         {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
389         {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
390         {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
391         {"workgroup", P_USTRING, P_GLOBAL, &loadparm.Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392         {"realm", P_STRING, P_GLOBAL, &loadparm.Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393         {"netbios name", P_USTRING, P_GLOBAL, &loadparm.Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
394         {"netbios aliases", P_LIST, P_GLOBAL, &loadparm.Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
395         {"netbios scope", P_USTRING, P_GLOBAL, &loadparm.Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
396         {"server string", P_STRING, P_GLOBAL, &loadparm.Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED  | FLAG_DEVELOPER},
397         {"interfaces", P_LIST, P_GLOBAL, &loadparm.Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
398         {"bind interfaces only", P_BOOL, P_GLOBAL, &loadparm.Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
399         {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
400         {"ntptr providor", P_STRING, P_GLOBAL, &loadparm.Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
401         {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &loadparm.Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
402         {"server services", P_LIST, P_GLOBAL, &loadparm.Globals.server_services, NULL, NULL, FLAG_ADVANCED},
403
404         {"Security Options", P_SEP, P_SEPARATOR},
405         
406         {"security", P_ENUM, P_GLOBAL, &loadparm.Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
407         {"encrypt passwords", P_BOOL, P_GLOBAL, &loadparm.Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
408         {"null passwords", P_BOOL, P_GLOBAL, &loadparm.Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409         {"obey pam restrictions", P_BOOL, P_GLOBAL, &loadparm.Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410         {"password server", P_LIST, P_GLOBAL, &loadparm.Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
411         {"sam database", P_STRING, P_GLOBAL, &loadparm.Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412         {"secrets database", P_STRING, P_GLOBAL, &loadparm.Globals.szSECRETS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413         {"spoolss database", P_STRING, P_GLOBAL, &loadparm.Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414         {"wins config database", P_STRING, P_GLOBAL, &loadparm.Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415         {"wins database", P_STRING, P_GLOBAL, &loadparm.Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416         {"private dir", P_STRING, P_GLOBAL, &loadparm.Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417         {"passwd chat", P_STRING, P_GLOBAL, &loadparm.Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418         {"password level", P_INTEGER, P_GLOBAL, &loadparm.Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419         {"lanman auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420         {"ntlm auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421         {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422         {"client lanman auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423         {"client plaintext auth", P_BOOL, P_GLOBAL, &loadparm.Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
424         {"client use spnego principal", P_BOOL, P_GLOBAL, &loadparm.Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
425         
426         {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
427
428         {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
429         {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
430         {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
431         {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
432
433         {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
434         {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
435
436         {"Logging Options", P_SEP, P_SEPARATOR},
437
438         {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439         {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
440         {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441         
442         {"Protocol Options", P_SEP, P_SEPARATOR},
443         
444         {"smb ports", P_LIST, P_GLOBAL, &loadparm.Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445         {"nbt port", P_INTEGER, P_GLOBAL, &loadparm.Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446         {"dgram port", P_INTEGER, P_GLOBAL, &loadparm.Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447         {"cldap port", P_INTEGER, P_GLOBAL, &loadparm.Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448         {"krb5 port", P_INTEGER, P_GLOBAL, &loadparm.Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449         {"kpasswd port", P_INTEGER, P_GLOBAL, &loadparm.Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450         {"web port", P_INTEGER, P_GLOBAL, &loadparm.Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451         {"tls enabled", P_BOOL, P_GLOBAL, &loadparm.Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452         {"tls keyfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
453         {"tls certfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454         {"tls cafile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455         {"tls crlfile", P_STRING, P_GLOBAL, &loadparm.Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
456         {"tls dh params file", P_STRING, P_GLOBAL, &loadparm.Globals.tls_dhpfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457         {"swat directory", P_STRING, P_GLOBAL, &loadparm.Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
458         {"large readwrite", P_BOOL, P_GLOBAL, &loadparm.Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
459         {"server max protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.srv_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
460         {"server min protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.srv_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
461         {"client max protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.cli_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
462         {"client min protocol", P_ENUM, P_GLOBAL, &loadparm.Globals.cli_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
463         {"unicode", P_BOOL, P_GLOBAL, &loadparm.Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
464         {"read raw", P_BOOL, P_GLOBAL, &loadparm.Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
465         {"write raw", P_BOOL, P_GLOBAL, &loadparm.Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
466         {"disable netbios", P_BOOL, P_GLOBAL, &loadparm.Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467         
468         {"nt status support", P_BOOL, P_GLOBAL, &loadparm.Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469
470         {"announce version", P_STRING, P_GLOBAL, &loadparm.Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
471         {"announce as", P_ENUM, P_GLOBAL, &loadparm.Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
472         {"max mux", P_INTEGER, P_GLOBAL, &loadparm.Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
473         {"max xmit", P_BYTES, P_GLOBAL, &loadparm.Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
474
475         {"name resolve order", P_LIST, P_GLOBAL, &loadparm.Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
476         {"max wins ttl", P_INTEGER, P_GLOBAL, &loadparm.Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
477         {"min wins ttl", P_INTEGER, P_GLOBAL, &loadparm.Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
478         {"time server", P_BOOL, P_GLOBAL, &loadparm.Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
479         {"unix extensions", P_BOOL, P_GLOBAL, &loadparm.Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
480         {"use spnego", P_BOOL, P_GLOBAL, &loadparm.Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
481         {"server signing", P_ENUM, P_GLOBAL, &loadparm.Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
482         {"client signing", P_ENUM, P_GLOBAL, &loadparm.Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
483         {"rpc big endian", P_BOOL, P_GLOBAL, &loadparm.Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
484
485         {"Tuning Options", P_SEP, P_SEPARATOR},
486                 
487         {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
488         {"paranoid server security", P_BOOL, P_GLOBAL, &loadparm.Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
489         {"socket options", P_STRING, P_GLOBAL, &loadparm.Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
490
491         {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
492         {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
493
494         {"Printing Options", P_SEP, P_SEPARATOR},
495         
496         {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
497         {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
498         {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
499         
500         {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
501         {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
502
503         {"Filename Handling", P_SEP, P_SEPARATOR},
504         
505         {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
506         {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
507         {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
508
509         {"Domain Options", P_SEP, P_SEPARATOR},
510         
511         {"Logon Options", P_SEP, P_SEPARATOR},
512
513
514         {"Browse Options", P_SEP, P_SEPARATOR},
515         
516         {"preferred master", P_ENUM, P_GLOBAL, &loadparm.Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
517         {"prefered master", P_ENUM, P_GLOBAL, &loadparm.Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
518         {"local master", P_BOOL, P_GLOBAL, &loadparm.Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
519         {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
520         {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
521
522         {"WINS Options", P_SEP, P_SEPARATOR},
523         
524         {"wins server", P_LIST, P_GLOBAL, &loadparm.Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
525         {"wins support", P_BOOL, P_GLOBAL, &loadparm.Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
526         {"dns proxy", P_BOOL, P_GLOBAL, &loadparm.Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
527         {"wins hook", P_STRING, P_GLOBAL, &loadparm.Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED}, 
528
529         {"Locking Options", P_SEP, P_SEPARATOR},
530         
531         {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
532         
533         {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
534
535         {"Miscellaneous Options", P_SEP, P_SEPARATOR},
536         
537         {"share backend", P_STRING, P_GLOBAL, &loadparm.Globals.szShareBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
538         {"preload", P_STRING, P_GLOBAL, &loadparm.Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
539         {"auto services", P_STRING, P_GLOBAL, &loadparm.Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
540         {"lock dir", P_STRING, P_GLOBAL, &loadparm.Globals.szLockDir, NULL, NULL, FLAG_HIDE}, 
541         {"lock directory", P_STRING, P_GLOBAL, &loadparm.Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
542         {"modules dir", P_STRING, P_GLOBAL, &loadparm.Globals.szModulesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
543         {"pid directory", P_STRING, P_GLOBAL, &loadparm.Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
544         {"js include", P_LIST, P_GLOBAL, &loadparm.Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
545         {"setup directory", P_STRING, P_GLOBAL, &loadparm.Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
546         
547         {"socket address", P_STRING, P_GLOBAL, &loadparm.Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
548         {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
549         {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
550         
551         {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
552         {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
553         {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
554
555         {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
556
557         {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
558         {"host msdfs", P_BOOL, P_GLOBAL, &loadparm.Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
559         {"winbind separator", P_STRING, P_GLOBAL, &loadparm.Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
560         {"winbindd socket directory", P_STRING, P_GLOBAL, &loadparm.Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
561         {"winbind sealed pipes", P_BOOL, P_GLOBAL, &loadparm.Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
562         {"template shell", P_STRING, P_GLOBAL, &loadparm.Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
563         {"template homedir", P_STRING, P_GLOBAL, &loadparm.Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
564
565         {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
566 };
567
568
569 /*
570   return the parameter table
571 */
572 struct parm_struct *lp_parm_table(void)
573 {
574         return parm_table;
575 }
576
577 static TALLOC_CTX *lp_talloc;
578
579 /******************************************************************* a
580  Free up temporary memory - called from the main loop.
581 ********************************************************************/
582
583 void lp_talloc_free(void)
584 {
585         if (!lp_talloc)
586                 return;
587         talloc_free(lp_talloc);
588         lp_talloc = NULL;
589 }
590
591 /*******************************************************************
592  Convenience routine to grab string parameters into temporary memory
593  and run standard_sub_basic on them. The buffers can be written to by
594  callers without affecting the source string.
595 ********************************************************************/
596
597 static const char *lp_string(const char *s)
598 {
599 #if 0  /* until REWRITE done to make thread-safe */
600         size_t len = s ? strlen(s) : 0;
601         char *ret;
602 #endif
603
604         /* The follow debug is useful for tracking down memory problems
605            especially if you have an inner loop that is calling a lp_*()
606            function that returns a string.  Perhaps this debug should be
607            present all the time? */
608
609 #if 0
610         DEBUG(10, ("lp_string(%s)\n", s));
611 #endif
612
613 #if 0  /* until REWRITE done to make thread-safe */
614         if (!lp_talloc)
615                 lp_talloc = talloc_init("lp_talloc");
616
617         ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
618
619         if (!ret)
620                 return NULL;
621
622         if (!s)
623                 *ret = 0;
624         else
625                 strlcpy(ret, s, len);
626
627         if (trim_string(ret, "\"", "\"")) {
628                 if (strchr(ret,'"') != NULL)
629                         strlcpy(ret, s, len);
630         }
631
632         standard_sub_basic(ret,len+100);
633         return (ret);
634 #endif
635         return s;
636 }
637
638 /*
639    In this section all the functions that are used to access the 
640    parameters from the rest of the program are defined 
641 */
642
643 #define FN_GLOBAL_STRING(fn_name,var_name) \
644  const char *fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->Globals.var_name ? lp_string(lp_ctx->Globals.var_name) : "";}
645 #define FN_GLOBAL_CONST_STRING(fn_name,var_name) \
646  const char *fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->Globals.var_name ? lp_ctx->Globals.var_name : "";}
647 #define FN_GLOBAL_LIST(fn_name,var_name) \
648  const char **fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->Globals.var_name;}
649 #define FN_GLOBAL_BOOL(fn_name,var_name) \
650  bool fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return false; return lp_ctx->Globals.var_name;}
651 #if 0 /* unused */
652 #define FN_GLOBAL_CHAR(fn_name,ptr) \
653  char fn_name(void) {return(*(char *)(ptr));}
654 #endif
655 #define FN_GLOBAL_INTEGER(fn_name,var_name) \
656  int fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return 0; return lp_ctx->Globals.var_name;}
657
658 #define FN_LOCAL_STRING(fn_name,val) \
659  const char *fn_name(struct loadparm_service *service) {return(lp_string((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault.val)));}
660 #define FN_LOCAL_CONST_STRING(fn_name,val) \
661  const char *fn_name(struct loadparm_service *service) {return (const char *)(service != NULL && service->val != NULL) ? service->val : sDefault.val;}
662 #define FN_LOCAL_LIST(fn_name,val) \
663  const char **fn_name(struct loadparm_service *service) {return(const char **)(service != NULL && service->val != NULL? service->val : sDefault.val);}
664 #define FN_LOCAL_BOOL(fn_name,val) \
665  bool fn_name(struct loadparm_service *service) {return((service != NULL)? service->val : sDefault.val);}
666 #define FN_LOCAL_INTEGER(fn_name,val) \
667  int fn_name(struct loadparm_service *service) {return((service != NULL)? service->val : sDefault.val);}
668
669 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, server_role)
670 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, smb_ports)
671 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, nbt_port)
672 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, dgram_port)
673 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, cldap_port)
674 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, krb5_port)
675 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, kpasswd_port)
676 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, web_port)
677 _PUBLIC_ FN_GLOBAL_STRING(lp_swat_directory, swat_directory)
678 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, tls_enabled)
679 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, tls_keyfile)
680 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, tls_certfile)
681 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, tls_cafile)
682 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, tls_crlfile)
683 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, tls_dhpfile)
684 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, szShareBackend)
685 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, szSAM_URL)
686 _PUBLIC_ FN_GLOBAL_STRING(lp_secrets_url, szSECRETS_URL)
687 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, szSPOOLSS_URL)
688 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, szWINS_CONFIG_URL)
689 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, szWINS_URL)
690 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, szWinbindSeparator)
691 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, szWinbinddSocketDirectory)
692 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_shell, szTemplateShell)
693 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_homedir, szTemplateHomedir)
694 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, bWinbindSealedPipes)
695 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, szPrivateDir)
696 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, szServerString)
697 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, szLockDir)
698 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, szModulesDir)
699 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, szSetupDir)
700 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, ncalrpc_dir)
701 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, szPidDir)
702 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, dcerpc_ep_servers)
703 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, server_services)
704 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, ntptr_providor)
705 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, szAutoServices)
706 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, szPasswdChat)
707 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, szPasswordServers)
708 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, szNameResolveOrder)
709 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, szRealm)
710 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, socket_options)
711 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, szWorkgroup)
712 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, szNetbiosName)
713 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, szNetbiosScope)
714 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, szWINSservers)
715 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, szInterfaces)
716 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, szSocketAddress)
717 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, szNetbiosAliases)
718
719 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, bDisableNetbios)
720 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, bWINSsupport)
721 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, bWINSdnsProxy)
722 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, szWINSHook)
723 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, szConfigFile)
724 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, bLocalMaster)
725 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, bReadRaw)
726 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, bLargeReadwrite)
727 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, bWriteRaw)
728 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, bNullPasswords)
729 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, bObeyPamRestrictions)
730 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, bEncryptPasswords)
731 _PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, bTimeServer)
732 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, bBindInterfacesOnly)
733 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, bUnicode)
734 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, bNTStatusSupport)
735 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, bLanmanAuth)
736 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, bNTLMAuth)
737 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, bClientPlaintextAuth)
738 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, bClientLanManAuth)
739 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, bClientNTLMv2Auth)
740 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, client_use_spnego_principal)
741 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, bHostMSDfs)
742 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, bUnixExtensions)
743 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, bUseSpnego)
744 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, bRpcBigEndian)
745 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, max_wins_ttl)
746 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, min_wins_ttl)
747 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, max_mux)
748 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, max_xmit)
749 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, pwordlevel)
750 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, srv_maxprotocol)
751 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, srv_minprotocol)
752 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, cli_maxprotocol)
753 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, cli_minprotocol)
754 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, security)
755 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, paranoid_server_security)
756 _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, announce_as)
757 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, jsInclude)
758 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
759 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
760 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
761 static FN_LOCAL_STRING(_lp_printername, szPrintername)
762 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
763 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
764 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
765 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
766 static FN_LOCAL_STRING(lp_volume, volume)
767 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
768 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
769 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
770 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
771 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
772 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
773 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
774 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
775 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
776 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
777 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
778 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
779 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
780 _PUBLIC_ FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
781 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
782 _PUBLIC_ FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
783 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
784 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, server_signing)
785 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, client_signing)
786
787 /* local prototypes */
788 static int map_parameter(const char *pszParmName);
789 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx, 
790                                         const char *pszServiceName);
791 static void copy_service(struct loadparm_service *pserviceDest,
792                          struct loadparm_service *pserviceSource, 
793                          int *pcopymapDest);
794 static bool service_ok(struct loadparm_service *service);
795 static bool do_section(const char *pszSectionName, void *);
796 static void init_copymap(struct loadparm_service *pservice);
797
798 /* This is a helper function for parametrical options support. */
799 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
800 /* Actual parametrical functions are quite simple */
801 const char *lp_get_parametric(struct loadparm_context *lp_ctx, 
802                               struct loadparm_service *service, 
803                               const char *type, const char *option)
804 {
805         char *vfskey;
806         struct param_opt *data;
807         
808         data = (service == NULL ? lp_ctx->Globals.param_opt : service->param_opt);
809     
810         asprintf(&vfskey, "%s:%s", type, option);
811         strlower(vfskey);
812
813         while (data) {
814                 if (strcmp(data->key, vfskey) == 0) {
815                         free(vfskey);
816                         return data->value;
817                 }
818                 data = data->next;
819         }
820
821         if (service != NULL) {
822                 /* Try to fetch the same option but from globals */
823                 /* but only if we are not already working with Globals */
824                 for (data = lp_ctx->Globals.param_opt; data; 
825                      data = data->next) {
826                         if (strcmp(data->key, vfskey) == 0) {
827                                 free(vfskey);
828                                 return data->value;
829                         }
830                 }
831         }
832
833         free(vfskey);
834         
835         return NULL;
836 }
837
838
839 /*******************************************************************
840 convenience routine to return int parameters.
841 ********************************************************************/
842 static int lp_int(const char *s)
843 {
844
845         if (!s) {
846                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
847                 return -1;
848         }
849
850         return strtol(s, NULL, 0); 
851 }
852
853 /*******************************************************************
854 convenience routine to return unsigned long parameters.
855 ********************************************************************/
856 static int lp_ulong(const char *s)
857 {
858
859         if (!s) {
860                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
861                 return -1;
862         }
863
864         return strtoul(s, NULL, 0);
865 }
866
867 /*******************************************************************
868 convenience routine to return unsigned long parameters.
869 ********************************************************************/
870 static double lp_double(const char *s)
871 {
872
873         if (!s) {
874                 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
875                 return -1;
876         }
877
878         return strtod(s, NULL);
879 }
880
881 /*******************************************************************
882 convenience routine to return boolean parameters.
883 ********************************************************************/
884 static bool lp_bool(const char *s)
885 {
886         bool ret = false;
887
888         if (!s) {
889                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
890                 return false;
891         }
892         
893         if (!set_boolean(s, &ret)) {
894                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
895                 return false;
896         }
897
898         return ret;
899 }
900
901
902 /* Return parametric option from a given service. Type is a part of option before ':' */
903 /* Parametric option has following syntax: 'Type: option = value' */
904 /* Returned value is allocated in 'lp_talloc' context */
905
906 const char *lp_parm_string(struct loadparm_context *lp_ctx, 
907                            struct loadparm_service *service, const char *type, 
908                            const char *option)
909 {
910         const char *value = lp_get_parametric(lp_ctx, service, type, option);
911
912         if (value)
913                 return lp_string(value);
914
915         return NULL;
916 }
917
918 /* Return parametric option from a given service. Type is a part of option before ':' */
919 /* Parametric option has following syntax: 'Type: option = value' */
920 /* Returned value is allocated in 'lp_talloc' context */
921
922 const char **lp_parm_string_list(struct loadparm_context *lp_ctx, 
923                                  struct loadparm_service *service, 
924                                  const char *type, 
925                                  const char *option, const char *separator)
926 {
927         const char *value = lp_get_parametric(lp_ctx, service, type, option);
928         
929         if (value)
930                 return str_list_make(talloc_autofree_context(), value, 
931                                      separator);
932
933         return NULL;
934 }
935
936 /* Return parametric option from a given service. Type is a part of option before ':' */
937 /* Parametric option has following syntax: 'Type: option = value' */
938
939 int lp_parm_int(struct loadparm_context *lp_ctx, 
940                 struct loadparm_service *service, const char *type, 
941                 const char *option, int default_v)
942 {
943         const char *value = lp_get_parametric(lp_ctx, service, type, option);
944         
945         if (value)
946                 return lp_int(value);
947
948         return default_v;
949 }
950
951 /* Return parametric option from a given service. Type is a part of
952  * option before ':'.
953  * Parametric option has following syntax: 'Type: option = value'.
954  */
955
956 int lp_parm_bytes(struct loadparm_context *lp_ctx, 
957                   struct loadparm_service *service, const char *type, 
958                   const char *option, int default_v)
959 {
960         uint64_t bval;
961
962         const char *value = lp_get_parametric(lp_ctx, service, type, option);
963
964         if (value && conv_str_size(value, &bval)) {
965                 if (bval <= INT_MAX) {
966                         return (int)bval;
967                 }
968         }
969
970         return default_v;
971 }
972
973 /* Return parametric option from a given service. Type is a part of option before ':' */
974 /* Parametric option has following syntax: 'Type: option = value' */
975
976 unsigned long lp_parm_ulong(struct loadparm_context *lp_ctx, 
977                             struct loadparm_service *service, const char *type, 
978                             const char *option, unsigned long default_v)
979 {
980         const char *value = lp_get_parametric(lp_ctx, service, type, option);
981         
982         if (value)
983                 return lp_ulong(value);
984
985         return default_v;
986 }
987
988
989 double lp_parm_double(struct loadparm_context *lp_ctx, 
990                       struct loadparm_service *service, const char *type, 
991                       const char *option, double default_v)
992 {
993         const char *value = lp_get_parametric(lp_ctx, service, type, option);
994         
995         if (value)
996                 return lp_double(value);
997
998         return default_v;
999 }
1000
1001 /* Return parametric option from a given service. Type is a part of option before ':' */
1002 /* Parametric option has following syntax: 'Type: option = value' */
1003
1004 bool lp_parm_bool(struct loadparm_context *lp_ctx, 
1005                   struct loadparm_service *service, const char *type, 
1006                   const char *option, bool default_v)
1007 {
1008         const char *value = lp_get_parametric(lp_ctx, service, type, option);
1009         
1010         if (value)
1011                 return lp_bool(value);
1012
1013         return default_v;
1014 }
1015
1016
1017 /***************************************************************************
1018  Initialise a service to the defaults.
1019 ***************************************************************************/
1020
1021 static struct loadparm_service *init_service(TALLOC_CTX *mem_ctx)
1022 {
1023         struct loadparm_service *pservice = 
1024                 talloc_zero(mem_ctx, struct loadparm_service);
1025         copy_service(pservice, &sDefault, NULL);
1026         return pservice;
1027 }
1028
1029 /**
1030  Set a string value, deallocating any existing space, and allocing the space
1031  for the string
1032 **/
1033 static bool string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
1034 {
1035         talloc_free(*dest);
1036
1037         if (src == NULL) 
1038                 src = "";
1039
1040         *dest = talloc_strdup(mem_ctx, src);
1041         if ((*dest) == NULL) {
1042                 DEBUG(0,("Out of memory in string_init\n"));
1043                 return false;
1044         }
1045
1046         return true;
1047 }
1048
1049
1050
1051 /***************************************************************************
1052  Add a new service to the services array initialising it with the given 
1053  service. 
1054 ***************************************************************************/
1055
1056 static struct loadparm_service *add_a_service(struct loadparm_context *lp_ctx, 
1057                                      const struct loadparm_service *pservice, 
1058                                      const char *name)
1059 {
1060         int i;
1061         struct loadparm_service tservice;
1062         int num_to_alloc = lp_ctx->iNumServices + 1;
1063         struct param_opt *data, *pdata;
1064
1065         tservice = *pservice;
1066
1067         /* it might already exist */
1068         if (name) {
1069                 struct loadparm_service *service = getservicebyname(lp_ctx, 
1070                                                                     name);
1071                 if (service != NULL) {
1072                         /* Clean all parametric options for service */
1073                         /* They will be added during parsing again */
1074                         data = service->param_opt;
1075                         while (data) {
1076                                 pdata = data->next;
1077                                 talloc_free(data);
1078                                 data = pdata;
1079                         }
1080                         service->param_opt = NULL;
1081                         return service;
1082                 }
1083         }
1084
1085         /* find an invalid one */
1086         for (i = 0; i < lp_ctx->iNumServices; i++)
1087                 if (lp_ctx->ServicePtrs[i] == NULL)
1088                         break;
1089
1090         /* if not, then create one */
1091         if (i == lp_ctx->iNumServices) {
1092                 struct loadparm_service **tsp;
1093                 
1094                 tsp = realloc_p(lp_ctx->ServicePtrs, struct loadparm_service *, 
1095                                 num_to_alloc);
1096                                            
1097                 if (!tsp) {
1098                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1099                         return NULL;
1100                 }
1101                 else {
1102                         lp_ctx->ServicePtrs = tsp;
1103                         lp_ctx->ServicePtrs[lp_ctx->iNumServices] = NULL;
1104                 }
1105
1106                 lp_ctx->iNumServices++;
1107         } 
1108
1109         lp_ctx->ServicePtrs[i] = init_service(talloc_autofree_context());
1110         if (lp_ctx->ServicePtrs[i] == NULL) {
1111                 DEBUG(0,("add_a_service: out of memory!\n"));
1112                 return NULL;
1113         }
1114         copy_service(lp_ctx->ServicePtrs[i], &tservice, NULL);
1115         if (name != NULL)
1116                 string_set(lp_ctx->ServicePtrs[i], &lp_ctx->ServicePtrs[i]->szService, name);
1117         return lp_ctx->ServicePtrs[i];
1118 }
1119
1120 /***************************************************************************
1121  Add a new home service, with the specified home directory, defaults coming 
1122  from service ifrom.
1123 ***************************************************************************/
1124
1125 bool lp_add_home(struct loadparm_context *lp_ctx, 
1126                  const char *pszHomename, 
1127                  struct loadparm_service *default_service,
1128                  const char *user, const char *pszHomedir)
1129 {
1130         struct loadparm_service *service;
1131
1132         service = add_a_service(lp_ctx, default_service, pszHomename);
1133
1134         if (service == NULL)
1135                 return false;
1136
1137         if (!(*(default_service->szPath))
1138             || strequal(default_service->szPath, sDefault.szPath)) {
1139                 service->szPath = talloc_strdup(service, pszHomedir);
1140         } else {
1141                 service->szPath = string_sub_talloc(service, lp_pathname(default_service),"%H", pszHomedir); 
1142         }
1143
1144         if (!(*(service->comment))) {
1145                 service->comment = talloc_asprintf(service, "Home directory of %s", user);
1146         }
1147         service->bAvailable = default_service->bAvailable;
1148         service->bBrowseable = default_service->bBrowseable;
1149
1150         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", 
1151                   pszHomename, user, service->szPath));
1152         
1153         return true;
1154 }
1155
1156 /***************************************************************************
1157  Add a new service, based on an old one.
1158 ***************************************************************************/
1159
1160 struct loadparm_service *lp_add_service(struct loadparm_context *lp_ctx, 
1161                                const char *pszService, 
1162                                struct loadparm_service *default_service)
1163 {
1164         return add_a_service(lp_ctx, default_service, pszService);
1165 }
1166
1167 /***************************************************************************
1168  Add the IPC service.
1169 ***************************************************************************/
1170
1171 static bool lp_add_hidden(struct loadparm_context *lp_ctx, const char *name, 
1172                           const char *fstype)
1173 {
1174         struct loadparm_service *service = add_a_service(lp_ctx, &sDefault, name);
1175
1176         if (service == NULL)
1177                 return false;
1178
1179         string_set(service, &service->szPath, tmpdir());
1180
1181         service->comment = talloc_asprintf(service, "%s Service (%s)", 
1182                                 fstype, lp_ctx->Globals.szServerString);
1183         string_set(service, &service->fstype, fstype);
1184         service->iMaxConnections = -1;
1185         service->bAvailable = true;
1186         service->bRead_only = true;
1187         service->bPrint_ok = false;
1188         service->bBrowseable = false;
1189
1190         if (strcasecmp(fstype, "IPC") == 0) {
1191                 lp_do_service_parameter(lp_ctx, service, "ntvfs handler", 
1192                                         "default");
1193         }
1194
1195         DEBUG(3, ("adding hidden service %s\n", name));
1196
1197         return true;
1198 }
1199
1200 /***************************************************************************
1201  Add a new printer service, with defaults coming from service iFrom.
1202 ***************************************************************************/
1203
1204 bool lp_add_printer(struct loadparm_context *lp_ctx,
1205                     const char *pszPrintername, 
1206                     struct loadparm_service *default_service)
1207 {
1208         const char *comment = "From Printcap";
1209         struct loadparm_service *service;
1210         service = add_a_service(lp_ctx, default_service, pszPrintername);
1211
1212         if (service == NULL)
1213                 return false;
1214
1215         /* note that we do NOT default the availability flag to True - */
1216         /* we take it from the default service passed. This allows all */
1217         /* dynamic printers to be disabled by disabling the [printers] */
1218         /* entry (if/when the 'available' keyword is implemented!).    */
1219
1220         /* the printer name is set to the service name. */
1221         string_set(service, &service->szPrintername, pszPrintername);
1222         string_set(service, &service->comment, comment);
1223         service->bBrowseable = sDefault.bBrowseable;
1224         /* Printers cannot be read_only. */
1225         service->bRead_only = false;
1226         /* Printer services must be printable. */
1227         service->bPrint_ok = true;
1228
1229         DEBUG(3, ("adding printer service %s\n", pszPrintername));
1230
1231         return true;
1232 }
1233
1234 /***************************************************************************
1235  Map a parameter's string representation to something we can use. 
1236  Returns False if the parameter string is not recognised, else TRUE.
1237 ***************************************************************************/
1238
1239 static int map_parameter(const char *pszParmName)
1240 {
1241         int iIndex;
1242
1243         if (*pszParmName == '-')
1244                 return -1;
1245
1246         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1247                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1248                         return iIndex;
1249
1250         /* Warn only if it isn't parametric option */
1251         if (strchr(pszParmName, ':') == NULL)
1252                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1253         /* We do return 'fail' for parametric options as well because they are
1254            stored in different storage
1255          */
1256         return -1;
1257 }
1258
1259
1260 /*
1261   return the parameter structure for a parameter
1262 */
1263 struct parm_struct *lp_parm_struct(const char *name)
1264 {
1265         int parmnum = map_parameter(name);
1266         if (parmnum == -1) return NULL;
1267         return &parm_table[parmnum];
1268 }
1269
1270 /*
1271   return the parameter pointer for a parameter
1272 */
1273 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
1274 {
1275         if (service == NULL)
1276                 return parm->ptr;
1277
1278         return ((char *)service) + PTR_DIFF(parm->ptr, &sDefault);
1279 }
1280
1281 /***************************************************************************
1282 Find a service by name. Otherwise works like get_service.
1283 ***************************************************************************/
1284
1285 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx, 
1286                                         const char *pszServiceName)
1287 {
1288         int iService;
1289
1290         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
1291                 if (lp_ctx->ServicePtrs[iService] != NULL &&
1292                     strwicmp(lp_ctx->ServicePtrs[iService]->szService, pszServiceName) == 0) {
1293                         return lp_ctx->ServicePtrs[iService];
1294                 }
1295
1296         return NULL;
1297 }
1298
1299 /***************************************************************************
1300  Copy a service structure to another.
1301  If pcopymapDest is NULL then copy all fields
1302 ***************************************************************************/
1303
1304 static void copy_service(struct loadparm_service *pserviceDest, 
1305                          struct loadparm_service *pserviceSource, 
1306                          int *pcopymapDest)
1307 {
1308         int i;
1309         bool bcopyall = (pcopymapDest == NULL);
1310         struct param_opt *data, *pdata, *paramo;
1311         bool not_added;
1312
1313         for (i = 0; parm_table[i].label; i++)
1314                 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1315                     (bcopyall || pcopymapDest[i])) {
1316                         void *def_ptr = parm_table[i].ptr;
1317                         void *src_ptr =
1318                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1319                                                                     &sDefault);
1320                         void *dest_ptr =
1321                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1322                                                                   &sDefault);
1323
1324                         switch (parm_table[i].type) {
1325                                 case P_BOOL:
1326                                         *(int *)dest_ptr = *(int *)src_ptr;
1327                                         break;
1328
1329                                 case P_INTEGER:
1330                                 case P_OCTAL:
1331                                 case P_ENUM:
1332                                         *(int *)dest_ptr = *(int *)src_ptr;
1333                                         break;
1334
1335                                 case P_STRING:
1336                                         string_set(pserviceDest, 
1337                                                    (char **)dest_ptr,
1338                                                    *(char **)src_ptr);
1339                                         break;
1340
1341                                 case P_USTRING:
1342                                         string_set(pserviceDest, 
1343                                                    (char **)dest_ptr,
1344                                                    *(char **)src_ptr);
1345                                         strupper(*(char **)dest_ptr);
1346                                         break;
1347                                 case P_LIST:
1348                                         *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(), 
1349                                                                                   *(const char ***)src_ptr);
1350                                         break;
1351                                 default:
1352                                         break;
1353                         }
1354                 }
1355
1356         if (bcopyall) {
1357                 init_copymap(pserviceDest);
1358                 if (pserviceSource->copymap)
1359                         memcpy((void *)pserviceDest->copymap,
1360                                (void *)pserviceSource->copymap,
1361                                sizeof(int) * NUMPARAMETERS);
1362         }
1363         
1364         data = pserviceSource->param_opt;
1365         while (data) {
1366                 not_added = true;
1367                 pdata = pserviceDest->param_opt;
1368                 /* Traverse destination */
1369                 while (pdata) {
1370                         /* If we already have same option, override it */
1371                         if (strcmp(pdata->key, data->key) == 0) {
1372                                 talloc_free(pdata->value);
1373                                 pdata->value = talloc_reference(pdata, 
1374                                                              data->value);
1375                                 not_added = false;
1376                                 break;
1377                         }
1378                         pdata = pdata->next;
1379                 }
1380                 if (not_added) {
1381                         paramo = talloc(pserviceDest, struct param_opt);
1382                         if (paramo == NULL)
1383                                 smb_panic("OOM");
1384                         paramo->key = talloc_reference(paramo, data->key);
1385                         paramo->value = talloc_reference(paramo, data->value);
1386                         DLIST_ADD(pserviceDest->param_opt, paramo);
1387                 }
1388                 data = data->next;
1389         }
1390 }
1391
1392 /***************************************************************************
1393 Check a service for consistency. Return False if the service is in any way
1394 incomplete or faulty, else True.
1395 ***************************************************************************/
1396
1397 static bool service_ok(struct loadparm_service *service)
1398 {
1399         bool bRetval;
1400
1401         bRetval = true;
1402         if (service->szService[0] == '\0') {
1403                 DEBUG(0, ("The following message indicates an internal error:\n"));
1404                 DEBUG(0, ("No service name in service entry.\n"));
1405                 bRetval = false;
1406         }
1407
1408         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1409         /* I can't see why you'd want a non-printable printer service...        */
1410         if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
1411                 if (!service->bPrint_ok) {
1412                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1413                                service->szService));
1414                         service->bPrint_ok = true;
1415                 }
1416                 /* [printers] service must also be non-browsable. */
1417                 if (service->bBrowseable)
1418                         service->bBrowseable = false;
1419         }
1420
1421         /* If a service is flagged unavailable, log the fact at level 0. */
1422         if (!service->bAvailable)
1423                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1424                           service->szService));
1425
1426         return bRetval;
1427 }
1428
1429
1430 /*******************************************************************
1431  Keep a linked list of all config files so we know when one has changed 
1432  it's date and needs to be reloaded.
1433 ********************************************************************/
1434
1435 static void add_to_file_list(struct loadparm_context *lp_ctx, 
1436                              const char *fname, const char *subfname)
1437 {
1438         struct file_lists *f = lp_ctx->file_lists;
1439
1440         while (f) {
1441                 if (f->name && !strcmp(f->name, fname))
1442                         break;
1443                 f = f->next;
1444         }
1445
1446         if (!f) {
1447                 f = talloc(talloc_autofree_context(), struct file_lists);
1448                 if (!f)
1449                         return;
1450                 f->next = lp_ctx->file_lists;
1451                 f->name = talloc_strdup(f, fname);
1452                 if (!f->name) {
1453                         talloc_free(f);
1454                         return;
1455                 }
1456                 f->subfname = talloc_strdup(f, subfname);
1457                 if (!f->subfname) {
1458                         talloc_free(f);
1459                         return;
1460                 }
1461                 lp_ctx->file_lists = f;
1462                 f->modtime = file_modtime(subfname);
1463         } else {
1464                 time_t t = file_modtime(subfname);
1465                 if (t)
1466                         f->modtime = t;
1467         }
1468 }
1469
1470 /*******************************************************************
1471  Check if a config file has changed date.
1472 ********************************************************************/
1473
1474 bool lp_file_list_changed(struct loadparm_context *lp_ctx)
1475 {
1476         struct file_lists *f;
1477         DEBUG(6, ("lp_file_list_changed()\n"));
1478
1479         for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
1480                 char *n2;
1481                 time_t mod_time;
1482
1483                 n2 = standard_sub_basic(talloc_autofree_context(), f->name);
1484
1485                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
1486                              f->name, n2, ctime(&f->modtime)));
1487
1488                 mod_time = file_modtime(n2);
1489
1490                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1491                         DEBUGADD(6, ("file %s modified: %s\n", n2,
1492                                   ctime(&mod_time)));
1493                         f->modtime = mod_time;
1494                         talloc_free(f->subfname);
1495                         f->subfname = talloc_strdup(f, n2);
1496                         return true;
1497                 }
1498         }
1499         return false;
1500 }
1501
1502 /***************************************************************************
1503  Handle the include operation.
1504 ***************************************************************************/
1505
1506 static bool handle_include(struct loadparm_context *lp_ctx, 
1507                            const char *pszParmValue, char **ptr)
1508 {
1509         char *fname = standard_sub_basic(talloc_autofree_context(), 
1510                                          pszParmValue);
1511
1512         add_to_file_list(lp_ctx, pszParmValue, fname);
1513
1514         string_set(talloc_autofree_context(), ptr, fname);
1515
1516         if (file_exist(fname))
1517                 return pm_process(fname, do_section, do_parameter, lp_ctx);
1518
1519         DEBUG(2, ("Can't find include file %s\n", fname));
1520
1521         return false;
1522 }
1523
1524 /***************************************************************************
1525  Handle the interpretation of the copy parameter.
1526 ***************************************************************************/
1527
1528 static bool handle_copy(struct loadparm_context *lp_ctx, 
1529                         const char *pszParmValue, char **ptr)
1530 {
1531         bool bRetval;
1532         struct loadparm_service *serviceTemp;
1533
1534         string_set(talloc_autofree_context(), ptr, pszParmValue);
1535
1536         bRetval = false;
1537
1538         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1539
1540         if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) {
1541                 if (serviceTemp == lp_ctx->currentService) {
1542                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1543                 } else {
1544                         copy_service(lp_ctx->currentService,
1545                                      serviceTemp,
1546                                      lp_ctx->currentService->copymap);
1547                         bRetval = true;
1548                 }
1549         } else {
1550                 DEBUG(0, ("Unable to copy service - source not found: %s\n", 
1551                           pszParmValue));
1552                 bRetval = false;
1553         }
1554
1555         return bRetval;
1556 }
1557
1558 /***************************************************************************
1559  Initialise a copymap.
1560 ***************************************************************************/
1561
1562 static void init_copymap(struct loadparm_service *pservice)
1563 {
1564         int i;
1565         talloc_free(pservice->copymap);
1566         pservice->copymap = talloc_array(pservice, int, NUMPARAMETERS);
1567         if (pservice->copymap == NULL) {
1568                 DEBUG(0,
1569                       ("Couldn't allocate copymap!! (size %d)\n",
1570                        (int)NUMPARAMETERS));
1571                 return;
1572         }
1573         for (i = 0; i < NUMPARAMETERS; i++)
1574                 pservice->copymap[i] = true;
1575 }
1576
1577 /***************************************************************************
1578  Process a parametric option
1579 ***************************************************************************/
1580 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx, 
1581                                        struct loadparm_service *service, 
1582                                        const char *pszParmName, 
1583                                        const char *pszParmValue, int flags)
1584 {
1585         struct param_opt *paramo, *data;
1586         char *name;
1587         TALLOC_CTX *mem_ctx;
1588
1589         while (isspace((unsigned char)*pszParmName)) {
1590                 pszParmName++;
1591         }
1592
1593         name = strdup(pszParmName);
1594         if (!name) return false;
1595
1596         strlower(name);
1597
1598         if (service == NULL) {
1599                 data = lp_ctx->Globals.param_opt;
1600                 mem_ctx = talloc_autofree_context();
1601         } else {
1602                 data = service->param_opt;
1603                 mem_ctx = service;
1604         }
1605
1606         /* Traverse destination */
1607         for (paramo=data; paramo; paramo=paramo->next) {
1608                 /* If we already have the option set, override it unless
1609                    it was a command line option and the new one isn't */
1610                 if (strcmp(paramo->key, name) == 0) {
1611                         if ((paramo->flags & FLAG_CMDLINE) &&
1612                             !(flags & FLAG_CMDLINE)) {
1613                                 return true;
1614                         }
1615
1616                         talloc_free(paramo->value);
1617                         paramo->value = talloc_strdup(paramo, pszParmValue);
1618                         paramo->flags = flags;
1619                         free(name);
1620                         return true;
1621                 }
1622         }
1623
1624         paramo = talloc(mem_ctx, struct param_opt);
1625         if (!paramo)
1626                 smb_panic("OOM");
1627         paramo->key = talloc_strdup(paramo, name);
1628         paramo->value = talloc_strdup(paramo, pszParmValue);
1629         paramo->flags = flags;
1630         if (service == NULL) {
1631                 DLIST_ADD(lp_ctx->Globals.param_opt, paramo);
1632         } else {
1633                 DLIST_ADD(service->param_opt, paramo);
1634         }
1635
1636         free(name);
1637         
1638         return true;
1639 }
1640
1641 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr, 
1642                          const char *pszParmName, const char *pszParmValue,
1643                          struct loadparm_context *lp_ctx)
1644 {
1645         int i;
1646         /* if it is a special case then go ahead */
1647         if (parm_table[parmnum].special) {
1648                 parm_table[parmnum].special(lp_ctx, pszParmValue, 
1649                                             (char **)parm_ptr);
1650                 return true;
1651         }
1652
1653         /* now switch on the type of variable it is */
1654         switch (parm_table[parmnum].type)
1655         {
1656                 case P_BOOL: {
1657                         bool b;
1658                         if (!set_boolean(pszParmValue, &b)) {
1659                                 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1660                                 return false;
1661                         }
1662                         *(int *)parm_ptr = b;
1663                         }
1664                         break;
1665
1666                 case P_INTEGER:
1667                         *(int *)parm_ptr = atoi(pszParmValue);
1668                         break;
1669
1670                 case P_OCTAL:
1671                         *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1672                         break;
1673
1674                 case P_BYTES:
1675                 {
1676                         uint64_t val;
1677                         if (conv_str_size(pszParmValue, &val)) {
1678                                 if (val <= INT_MAX) {
1679                                         *(int *)parm_ptr = (int)val;
1680                                         break;
1681                                 }
1682                         }
1683
1684                         DEBUG(0,("lp_do_parameter(%s): value is not "
1685                             "a valid size specifier!\n", pszParmValue));
1686                         return false;
1687                 }
1688
1689                 case P_LIST:
1690                         *(const char ***)parm_ptr = str_list_make(mem_ctx, 
1691                                                                   pszParmValue, NULL);
1692                         break;
1693
1694                 case P_STRING:
1695                         string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1696                         break;
1697
1698                 case P_USTRING:
1699                         string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1700                         strupper(*(char **)parm_ptr);
1701                         break;
1702
1703                 case P_ENUM:
1704                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1705                                 if (strequal
1706                                     (pszParmValue,
1707                                      parm_table[parmnum].enum_list[i].name)) {
1708                                         *(int *)parm_ptr =
1709                                                 parm_table[parmnum].
1710                                                 enum_list[i].value;
1711                                         break;
1712                                 }
1713                         }
1714                         if (!parm_table[parmnum].enum_list[i].name) {
1715                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
1716                                          pszParmValue, pszParmName));
1717                                 return false;
1718                         }
1719                         break;
1720                 case P_SEP:
1721                         break;
1722         }
1723
1724         if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1725                 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1726                 /* we have to also unset FLAG_DEFAULT on aliases */
1727                 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1728                         parm_table[i].flags &= ~FLAG_DEFAULT;
1729                 }
1730                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1731                         parm_table[i].flags &= ~FLAG_DEFAULT;
1732                 }
1733         }
1734         return true;
1735 }
1736
1737
1738 bool lp_do_global_parameter(struct loadparm_context *lp_ctx, 
1739                             const char *pszParmName, const char *pszParmValue)
1740 {
1741         int parmnum = map_parameter(pszParmName);
1742         void *parm_ptr;
1743
1744         if (parmnum < 0) {
1745                 if (strchr(pszParmName, ':')) {
1746                         return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, pszParmValue, 0);
1747                 }
1748                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1749                 return true;
1750         }
1751
1752         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1753                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1754                           pszParmName));
1755         }
1756
1757         /* if the flag has been set on the command line, then don't allow override,
1758            but don't report an error */
1759         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1760                 return true;
1761         }
1762
1763         parm_ptr = parm_table[parmnum].ptr;
1764
1765         return set_variable(talloc_autofree_context(), parmnum, parm_ptr, 
1766                             pszParmName, pszParmValue, lp_ctx);
1767 }
1768
1769 bool lp_do_service_parameter(struct loadparm_context *lp_ctx, 
1770                              struct loadparm_service *service, 
1771                              const char *pszParmName, const char *pszParmValue)
1772 {
1773         void *def_ptr = NULL;
1774         void *parm_ptr;
1775         int i;
1776         int parmnum = map_parameter(pszParmName);
1777
1778         if (parmnum < 0) {
1779                 if (strchr(pszParmName, ':')) {
1780                         return lp_do_parameter_parametric(lp_ctx, service, pszParmName, pszParmValue, 0);
1781                 }
1782                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1783                 return true;
1784         }
1785
1786         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1787                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1788                           pszParmName));
1789         }
1790
1791         /* if the flag has been set on the command line, then don't allow override,
1792            but don't report an error */
1793         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1794                 return true;
1795         }
1796
1797         def_ptr = parm_table[parmnum].ptr;
1798
1799         if (parm_table[parmnum].class == P_GLOBAL) {
1800                 DEBUG(0,
1801                       ("Global parameter %s found in service section!\n",
1802                        pszParmName));
1803                 return true;
1804         }
1805         parm_ptr = ((char *)service) + PTR_DIFF(def_ptr, &sDefault);
1806
1807         if (!service->copymap)
1808                 init_copymap(service);
1809
1810         /* this handles the aliases - set the copymap for other 
1811          * entries with the same data pointer */
1812         for (i = 0; parm_table[i].label; i++)
1813                 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1814                         service->copymap[i] = false;
1815
1816         return set_variable(service, parmnum, parm_ptr, pszParmName, 
1817                             pszParmValue, lp_ctx);
1818 }
1819
1820 /***************************************************************************
1821  Process a parameter.
1822 ***************************************************************************/
1823
1824 static bool do_parameter(const char *pszParmName, const char *pszParmValue, 
1825                          void *userdata)
1826 {
1827         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1828
1829         if (lp_ctx->bInGlobalSection) 
1830                 return lp_do_global_parameter(lp_ctx, pszParmName, 
1831                                               pszParmValue);
1832         else 
1833                 return lp_do_service_parameter(lp_ctx, lp_ctx->currentService,
1834                                                pszParmName, pszParmValue);
1835 }
1836
1837 /*
1838   variable argument do parameter
1839 */
1840 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
1841 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx, 
1842                                 const char *pszParmName, const char *fmt, ...) 
1843 {
1844         char *s;
1845         bool ret;
1846         va_list ap;
1847
1848         va_start(ap, fmt);      
1849         s = talloc_vasprintf(NULL, fmt, ap);
1850         va_end(ap);
1851         ret = lp_do_global_parameter(lp_ctx, pszParmName, s);
1852         talloc_free(s);
1853         return ret;
1854 }
1855
1856
1857 /*
1858   set a parameter from the commandline - this is called from command line parameter
1859   parsing code. It sets the parameter then marks the parameter as unable to be modified
1860   by smb.conf processing
1861 */
1862 bool lp_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName, 
1863                     const char *pszParmValue)
1864 {
1865         int parmnum = map_parameter(pszParmName);
1866         int i;
1867
1868         while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1869
1870
1871         if (parmnum < 0 && strchr(pszParmName, ':')) {
1872                 /* set a parametric option */
1873                 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, 
1874                                                   pszParmValue, FLAG_CMDLINE);
1875         }
1876
1877         if (parmnum < 0) {
1878                 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1879                 return false;
1880         }
1881
1882         /* reset the CMDLINE flag in case this has been called before */
1883         parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1884
1885         if (!lp_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
1886                 return false;
1887         }
1888
1889         parm_table[parmnum].flags |= FLAG_CMDLINE;
1890
1891         /* we have to also set FLAG_CMDLINE on aliases */
1892         for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1893                 parm_table[i].flags |= FLAG_CMDLINE;
1894         }
1895         for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1896                 parm_table[i].flags |= FLAG_CMDLINE;
1897         }
1898
1899         return true;
1900 }
1901
1902 /*
1903   set a option from the commandline in 'a=b' format. Use to support --option
1904 */
1905 bool lp_set_option(struct loadparm_context *lp_ctx, const char *option)
1906 {
1907         char *p, *s;
1908         bool ret;
1909
1910         s = strdup(option);
1911         if (!s) {
1912                 return false;
1913         }
1914
1915         p = strchr(s, '=');
1916         if (!p) {
1917                 free(s);
1918                 return false;
1919         }
1920
1921         *p = 0;
1922
1923         ret = lp_set_cmdline(lp_ctx, s, p+1);
1924         free(s);
1925         return ret;
1926 }
1927
1928
1929 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1930
1931 /***************************************************************************
1932  Print a parameter of the specified type.
1933 ***************************************************************************/
1934
1935 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1936 {
1937         int i;
1938         switch (p->type)
1939         {
1940                 case P_ENUM:
1941                         for (i = 0; p->enum_list[i].name; i++) {
1942                                 if (*(int *)ptr == p->enum_list[i].value) {
1943                                         fprintf(f, "%s",
1944                                                 p->enum_list[i].name);
1945                                         break;
1946                                 }
1947                         }
1948                         break;
1949
1950                 case P_BOOL:
1951                         fprintf(f, "%s", BOOLSTR((bool)*(int *)ptr));
1952                         break;
1953
1954                 case P_INTEGER:
1955                 case P_BYTES:
1956                         fprintf(f, "%d", *(int *)ptr);
1957                         break;
1958
1959                 case P_OCTAL:
1960                         fprintf(f, "0%o", *(int *)ptr);
1961                         break;
1962
1963                 case P_LIST:
1964                         if ((char ***)ptr && *(char ***)ptr) {
1965                                 char **list = *(char ***)ptr;
1966                                 
1967                                 for (; *list; list++)
1968                                         fprintf(f, "%s%s", *list,
1969                                                 ((*(list+1))?", ":""));
1970                         }
1971                         break;
1972
1973                 case P_STRING:
1974                 case P_USTRING:
1975                         if (*(char **)ptr) {
1976                                 fprintf(f, "%s", *(char **)ptr);
1977                         }
1978                         break;
1979                 case P_SEP:
1980                         break;
1981         }
1982 }
1983
1984 /***************************************************************************
1985  Check if two parameters are equal.
1986 ***************************************************************************/
1987
1988 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
1989 {
1990         switch (type) {
1991                 case P_BOOL:
1992                         return (*((int *)ptr1) == *((int *)ptr2));
1993
1994                 case P_INTEGER:
1995                 case P_OCTAL:
1996                 case P_BYTES:
1997                 case P_ENUM:
1998                         return (*((int *)ptr1) == *((int *)ptr2));
1999
2000                 case P_LIST:
2001                         return str_list_equal((const char **)(*(char ***)ptr1), 
2002                                               (const char **)(*(char ***)ptr2));
2003
2004                 case P_STRING:
2005                 case P_USTRING:
2006                 {
2007                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2008                         if (p1 && !*p1)
2009                                 p1 = NULL;
2010                         if (p2 && !*p2)
2011                                 p2 = NULL;
2012                         return (p1 == p2 || strequal(p1, p2));
2013                 }
2014                 case P_SEP:
2015                         break;
2016         }
2017         return false;
2018 }
2019
2020 /***************************************************************************
2021  Process a new section (service). At this stage all sections are services.
2022  Later we'll have special sections that permit server parameters to be set.
2023  Returns True on success, False on failure. 
2024 ***************************************************************************/
2025
2026 static bool do_section(const char *pszSectionName, void *userdata)
2027 {
2028         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
2029         bool bRetval;
2030         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2031                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2032         bRetval = false;
2033
2034         /* if we've just struck a global section, note the fact. */
2035         lp_ctx->bInGlobalSection = isglobal;
2036
2037         /* check for multiple global sections */
2038         if (lp_ctx->bInGlobalSection) {
2039                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2040                 return true;
2041         }
2042
2043         /* if we have a current service, tidy it up before moving on */
2044         bRetval = true;
2045
2046         if (lp_ctx->currentService != NULL)
2047                 bRetval = service_ok(lp_ctx->currentService);
2048
2049         /* if all is still well, move to the next record in the services array */
2050         if (bRetval) {
2051                 /* We put this here to avoid an odd message order if messages are */
2052                 /* issued by the post-processing of a previous section. */
2053                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2054
2055                 if ((lp_ctx->currentService = add_a_service(lp_ctx, &sDefault, 
2056                                                              pszSectionName))
2057                     == NULL) {
2058                         DEBUG(0, ("Failed to add a new service\n"));
2059                         return false;
2060                 }
2061         }
2062
2063         return bRetval;
2064 }
2065
2066
2067 /***************************************************************************
2068  Determine if a partcular base parameter is currentl set to the default value.
2069 ***************************************************************************/
2070
2071 static bool is_default(int i)
2072 {
2073         if (!defaults_saved)
2074                 return false;
2075         switch (parm_table[i].type) {
2076                 case P_LIST:
2077                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
2078                                               (const char **)(*(char ***)parm_table[i].ptr));
2079                 case P_STRING:
2080                 case P_USTRING:
2081                         return strequal(parm_table[i].def.svalue,
2082                                         *(char **)parm_table[i].ptr);
2083                 case P_BOOL:
2084                         return parm_table[i].def.bvalue ==
2085                                 *(int *)parm_table[i].ptr;
2086                 case P_INTEGER:
2087                 case P_OCTAL:
2088                 case P_BYTES:
2089                 case P_ENUM:
2090                         return parm_table[i].def.ivalue ==
2091                                 *(int *)parm_table[i].ptr;
2092                 case P_SEP:
2093                         break;
2094         }
2095         return false;
2096 }
2097
2098 /***************************************************************************
2099 Display the contents of the global structure.
2100 ***************************************************************************/
2101
2102 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults)
2103 {
2104         int i;
2105         struct param_opt *data;
2106         
2107         fprintf(f, "# Global parameters\n[global]\n");
2108
2109         for (i = 0; parm_table[i].label; i++)
2110                 if (parm_table[i].class == P_GLOBAL &&
2111                     parm_table[i].ptr &&
2112                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2113                         if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT)) 
2114                                 continue;
2115                         fprintf(f, "\t%s = ", parm_table[i].label);
2116                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
2117                         fprintf(f, "\n");
2118         }
2119         if (lp_ctx->Globals.param_opt != NULL) {
2120                 for (data = lp_ctx->Globals.param_opt; data; 
2121                      data = data->next) {
2122                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2123                 }
2124         }
2125
2126 }
2127
2128 /***************************************************************************
2129  Display the contents of a single services record.
2130 ***************************************************************************/
2131
2132 static void dump_a_service(struct loadparm_service * pService, FILE * f)
2133 {
2134         int i;
2135         struct param_opt *data;
2136         
2137         if (pService != &sDefault)
2138                 fprintf(f, "\n[%s]\n", pService->szService);
2139
2140         for (i = 0; parm_table[i].label; i++)
2141                 if (parm_table[i].class == P_LOCAL &&
2142                     parm_table[i].ptr &&
2143                     (*parm_table[i].label != '-') &&
2144                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2145                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2146
2147                         if (pService == &sDefault) {
2148                                 if (defaults_saved && is_default(i))
2149                                         continue;
2150                         } else {
2151                                 if (equal_parameter(parm_table[i].type,
2152                                                     ((char *)pService) +
2153                                                     pdiff,
2154                                                     ((char *)&sDefault) +
2155                                                     pdiff))
2156                                         continue;
2157                         }
2158
2159                         fprintf(f, "\t%s = ", parm_table[i].label);
2160                         print_parameter(&parm_table[i],
2161                                         ((char *)pService) + pdiff, f);
2162                         fprintf(f, "\n");
2163         }
2164         if (pService->param_opt != NULL) {
2165                 for (data = pService->param_opt; data; data = data->next) {
2166                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2167                 }
2168         }
2169 }
2170
2171 bool lp_dump_a_parameter(struct loadparm_context *lp_ctx, int snum, char *parm_name, FILE * f, 
2172                          bool isGlobal)
2173 {
2174         struct loadparm_service * pService = lp_ctx->ServicePtrs[snum];
2175         struct parm_struct *parm;
2176         void *ptr;
2177         
2178         parm = lp_parm_struct(parm_name);
2179         if (!parm) {
2180                 return false;
2181         }
2182         
2183         if (isGlobal)
2184                 ptr = parm->ptr;
2185         else
2186                 ptr = ((char *)pService) +
2187                         PTR_DIFF(parm->ptr, &sDefault);
2188         
2189         print_parameter(parm,
2190                         ptr, f);
2191         fprintf(f, "\n");
2192         return true;
2193 }
2194
2195 /***************************************************************************
2196  Return info about the next service  in a service. snum==-1 gives the globals.
2197  Return NULL when out of parameters.
2198 ***************************************************************************/
2199
2200 struct parm_struct *lp_next_parameter(struct loadparm_context *lp_ctx, int snum, int *i, 
2201                                       int allparameters)
2202 {
2203         if (snum == -1) {
2204                 /* do the globals */
2205                 for (; parm_table[*i].label; (*i)++) {
2206                         if (parm_table[*i].class == P_SEPARATOR)
2207                                 return &parm_table[(*i)++];
2208
2209                         if (!parm_table[*i].ptr
2210                             || (*parm_table[*i].label == '-'))
2211                                 continue;
2212
2213                         if ((*i) > 0
2214                             && (parm_table[*i].ptr ==
2215                                 parm_table[(*i) - 1].ptr))
2216                                 continue;
2217
2218                         return &parm_table[(*i)++];
2219                 }
2220         } else {
2221                 struct loadparm_service *pService = lp_ctx->ServicePtrs[snum];
2222
2223                 for (; parm_table[*i].label; (*i)++) {
2224                         if (parm_table[*i].class == P_SEPARATOR)
2225                                 return &parm_table[(*i)++];
2226
2227                         if (parm_table[*i].class == P_LOCAL &&
2228                             parm_table[*i].ptr &&
2229                             (*parm_table[*i].label != '-') &&
2230                             ((*i) == 0 ||
2231                              (parm_table[*i].ptr !=
2232                               parm_table[(*i) - 1].ptr)))
2233                         {
2234                                 int pdiff =
2235                                         PTR_DIFF(parm_table[*i].ptr,
2236                                                  &sDefault);
2237
2238                                 if (allparameters ||
2239                                     !equal_parameter(parm_table[*i].type,
2240                                                      ((char *)pService) +
2241                                                      pdiff,
2242                                                      ((char *)&sDefault) +
2243                                                      pdiff))
2244                                 {
2245                                         return &parm_table[(*i)++];
2246                                 }
2247                         }
2248                 }
2249         }
2250
2251         return NULL;
2252 }
2253
2254
2255 /***************************************************************************
2256  Auto-load some home services.
2257 ***************************************************************************/
2258
2259 static void lp_add_auto_services(struct loadparm_context *lp_ctx, 
2260                                  const char *str)
2261 {
2262         return;
2263 }
2264
2265 /***************************************************************************
2266  Have we loaded a services file yet?
2267 ***************************************************************************/
2268
2269 bool lp_loaded(void)
2270 {
2271         return bLoaded;
2272 }
2273
2274 /***************************************************************************
2275  Unload unused services.
2276 ***************************************************************************/
2277
2278 void lp_killunused(struct loadparm_context *lp_ctx, 
2279                    struct smbsrv_connection *smb, 
2280                    bool (*snumused) (struct smbsrv_connection *, int))
2281 {
2282         int i;
2283         for (i = 0; i < lp_ctx->iNumServices; i++) {
2284                 if (lp_ctx->ServicePtrs[i] == NULL)
2285                         continue;
2286
2287                 if (!snumused || !snumused(smb, i)) {
2288                         talloc_free(lp_ctx->ServicePtrs[i]);
2289                         lp_ctx->ServicePtrs[i] = NULL;
2290                 }
2291         }
2292 }
2293
2294 /***************************************************************************
2295  Initialise the global parameter structure.
2296 ***************************************************************************/
2297 bool loadparm_init(struct loadparm_context *lp_ctx)
2298 {
2299         int i;
2300         char *myname;
2301
2302         lp_ctx->bInGlobalSection = true;
2303
2304         DEBUG(3, ("Initialising global parameters\n"));
2305
2306         for (i = 0; parm_table[i].label; i++) {
2307                 if ((parm_table[i].type == P_STRING ||
2308                      parm_table[i].type == P_USTRING) &&
2309                     parm_table[i].ptr &&
2310                     !(parm_table[i].flags & FLAG_CMDLINE)) {
2311                         string_set(talloc_autofree_context(), 
2312                                    (char **)parm_table[i].ptr, "");
2313                 }
2314         }
2315
2316         lp_do_global_parameter(lp_ctx, "share backend", "classic");
2317         
2318         lp_do_global_parameter(lp_ctx, "server role", "standalone");
2319
2320         /* options that can be set on the command line must be initialised via
2321            the slower lp_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
2322 #ifdef TCP_NODELAY
2323         lp_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
2324 #endif
2325         lp_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
2326         myname = get_myname();
2327         lp_do_global_parameter(lp_ctx, "netbios name", myname);
2328         SAFE_FREE(myname);
2329         lp_do_global_parameter(lp_ctx, "name resolve order", "lmhosts wins host bcast");
2330
2331         lp_do_global_parameter(lp_ctx, "fstype", FSTYPE_STRING);
2332         lp_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
2333         lp_do_global_parameter(lp_ctx, "max connections", "-1");
2334
2335         lp_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo");
2336         lp_do_global_parameter(lp_ctx, "server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind");
2337         lp_do_global_parameter(lp_ctx, "ntptr providor", "simple_ldb");
2338         lp_do_global_parameter(lp_ctx, "auth methods:domain controller", "anonymous sam_ignoredomain");
2339         lp_do_global_parameter(lp_ctx, "auth methods:member server", "anonymous sam winbind");
2340         lp_do_global_parameter(lp_ctx, "auth methods:standalone", "anonymous sam_ignoredomain");
2341         lp_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
2342         lp_do_global_parameter(lp_ctx, "sam database", "sam.ldb");
2343         lp_do_global_parameter(lp_ctx, "secrets database", "secrets.ldb");
2344         lp_do_global_parameter(lp_ctx, "spoolss database", "spoolss.ldb");
2345         lp_do_global_parameter(lp_ctx, "wins config database", "wins_config.ldb");
2346         lp_do_global_parameter(lp_ctx, "wins database", "wins.ldb");
2347         lp_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
2348
2349         /* This hive should be dynamically generated by Samba using
2350            data from the sam, but for the moment leave it in a tdb to
2351            keep regedt32 from popping up an annoying dialog. */
2352         lp_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
2353         
2354         /* using UTF8 by default allows us to support all chars */
2355         lp_do_global_parameter(lp_ctx, "unix charset", "UTF8");
2356
2357         /* Use codepage 850 as a default for the dos character set */
2358         lp_do_global_parameter(lp_ctx, "dos charset", "CP850");
2359
2360         /*
2361          * Allow the default PASSWD_CHAT to be overridden in local.h.
2362          */
2363         lp_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
2364
2365         lp_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
2366         lp_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
2367         lp_do_global_parameter(lp_ctx, "modules dir", dyn_MODULESDIR);
2368         lp_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
2369
2370         lp_do_global_parameter(lp_ctx, "socket address", "0.0.0.0");
2371         lp_do_global_parameter_var(lp_ctx, "server string", 
2372                                    "Samba %s", SAMBA_VERSION_STRING);
2373
2374         lp_do_global_parameter_var(lp_ctx, "announce version", "%d.%d", 
2375                          DEFAULT_MAJOR_VERSION,
2376                          DEFAULT_MINOR_VERSION);
2377
2378         lp_do_global_parameter(lp_ctx, "password server", "*");
2379
2380         lp_do_global_parameter(lp_ctx, "max mux", "50");
2381         lp_do_global_parameter(lp_ctx, "max xmit", "12288");
2382         lp_do_global_parameter(lp_ctx, "password level", "0");
2383         lp_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
2384         lp_do_global_parameter(lp_ctx, "server min protocol", "CORE");
2385         lp_do_global_parameter(lp_ctx, "server max protocol", "NT1");
2386         lp_do_global_parameter(lp_ctx, "client min protocol", "CORE");
2387         lp_do_global_parameter(lp_ctx, "client max protocol", "NT1");
2388         lp_do_global_parameter(lp_ctx, "security", "USER");
2389         lp_do_global_parameter(lp_ctx, "paranoid server security", "True");
2390         lp_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
2391         lp_do_global_parameter(lp_ctx, "ReadRaw", "True");
2392         lp_do_global_parameter(lp_ctx, "WriteRaw", "True");
2393         lp_do_global_parameter(lp_ctx, "NullPasswords", "False");
2394         lp_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
2395         lp_do_global_parameter(lp_ctx, "announce as", "NT SERVER");
2396
2397         lp_do_global_parameter(lp_ctx, "TimeServer", "False");
2398         lp_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
2399         lp_do_global_parameter(lp_ctx, "Unicode", "True");
2400         lp_do_global_parameter(lp_ctx, "ClientLanManAuth", "True");
2401         lp_do_global_parameter(lp_ctx, "LanmanAuth", "True");
2402         lp_do_global_parameter(lp_ctx, "NTLMAuth", "True");
2403         lp_do_global_parameter(lp_ctx, "client use spnego principal", "False");
2404         
2405         lp_do_global_parameter(lp_ctx, "UnixExtensions", "False");
2406
2407         lp_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
2408         lp_do_global_parameter(lp_ctx, "LocalMaster", "True");
2409
2410         lp_do_global_parameter(lp_ctx, "wins support", "False");
2411         lp_do_global_parameter(lp_ctx, "dns proxy", "True");
2412
2413         lp_do_global_parameter(lp_ctx, "winbind separator", "\\");
2414         lp_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
2415         lp_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
2416         lp_do_global_parameter(lp_ctx, "template shell", "/bin/false");
2417         lp_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
2418
2419         lp_do_global_parameter(lp_ctx, "client signing", "Yes");
2420         lp_do_global_parameter(lp_ctx, "server signing", "auto");
2421
2422         lp_do_global_parameter(lp_ctx, "use spnego", "True");
2423
2424         lp_do_global_parameter(lp_ctx, "smb ports", "445 139");
2425         lp_do_global_parameter(lp_ctx, "nbt port", "137");
2426         lp_do_global_parameter(lp_ctx, "dgram port", "138");
2427         lp_do_global_parameter(lp_ctx, "cldap port", "389");
2428         lp_do_global_parameter(lp_ctx, "krb5 port", "88");
2429         lp_do_global_parameter(lp_ctx, "kpasswd port", "464");
2430         lp_do_global_parameter(lp_ctx, "web port", "901");
2431         lp_do_global_parameter(lp_ctx, "swat directory", dyn_SWATDIR);
2432
2433         lp_do_global_parameter(lp_ctx, "nt status support", "True");
2434
2435         lp_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
2436         lp_do_global_parameter(lp_ctx, "min wins ttl", "10");
2437
2438         lp_do_global_parameter(lp_ctx, "tls enabled", "True");
2439         lp_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
2440         lp_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
2441         lp_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
2442         lp_do_global_parameter_var(lp_ctx, "js include", "%s", dyn_JSDIR);
2443         lp_do_global_parameter_var(lp_ctx, "setup directory", "%s", 
2444                                    dyn_SETUPDIR);
2445
2446         for (i = 0; parm_table[i].label; i++) {
2447                 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
2448                         parm_table[i].flags |= FLAG_DEFAULT;
2449                 }
2450         }
2451
2452         return true;
2453 }
2454
2455 /***************************************************************************
2456  Load the services array from the services file. Return True on success, 
2457  False on failure.
2458 ***************************************************************************/
2459
2460 bool lp_load(const char *filename)
2461 {
2462         char *n2;
2463         bool bRetval;
2464         struct param_opt *data;
2465         struct loadparm_context *lp_ctx = &loadparm;
2466
2467         filename = talloc_strdup(talloc_autofree_context(), filename);
2468
2469         global_loadparm = lp_ctx;
2470
2471         if (lp_ctx->Globals.param_opt != NULL) {
2472                 struct param_opt *next;
2473                 for (data = lp_ctx->Globals.param_opt; data; data=next) {
2474                         next = data->next;
2475                         if (data->flags & FLAG_CMDLINE) continue;
2476                         DLIST_REMOVE(lp_ctx->Globals.param_opt, data);
2477                         talloc_free(data);
2478                 }
2479         }
2480
2481         if (!loadparm_init(lp_ctx))
2482                 return false;
2483
2484         lp_ctx->Globals.szConfigFile = filename;
2485         
2486         lp_ctx->bInGlobalSection = true;
2487         n2 = standard_sub_basic(talloc_autofree_context(), lp_ctx->Globals.szConfigFile);
2488         DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2489         
2490         add_to_file_list(lp_ctx, lp_ctx->Globals.szConfigFile, n2);
2491
2492         /* We get sections first, so have to start 'behind' to make up */
2493         lp_ctx->currentService = NULL;
2494         bRetval = pm_process(n2, do_section, do_parameter, lp_ctx);
2495
2496         /* finish up the last section */
2497         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2498         if (bRetval)
2499                 if (lp_ctx->currentService != NULL)
2500                         bRetval = service_ok(lp_ctx->currentService);
2501
2502         lp_add_auto_services(lp_ctx, lp_auto_services(lp_ctx));
2503
2504         lp_add_hidden(lp_ctx, "IPC$", "IPC");
2505         lp_add_hidden(lp_ctx, "ADMIN$", "DISK");
2506
2507         bLoaded = true;
2508
2509         if (!lp_ctx->Globals.szWINSservers && lp_ctx->Globals.bWINSsupport) {
2510                 lp_do_global_parameter(lp_ctx, "wins server", "127.0.0.1");
2511         }
2512
2513         init_iconv();
2514
2515         return bRetval;
2516 }
2517
2518 /***************************************************************************
2519  Return the max number of services.
2520 ***************************************************************************/
2521
2522 int lp_numservices(struct loadparm_context *lp_ctx)
2523 {
2524         return lp_ctx->iNumServices;
2525 }
2526
2527 /***************************************************************************
2528 Display the contents of the services array in human-readable form.
2529 ***************************************************************************/
2530
2531 void lp_dump(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults, 
2532              int maxtoprint)
2533 {
2534         int iService;
2535
2536         if (show_defaults)
2537                 defaults_saved = false;
2538
2539         dump_globals(lp_ctx, f, show_defaults);
2540
2541         dump_a_service(&sDefault, f);
2542
2543         for (iService = 0; iService < maxtoprint; iService++)
2544                 lp_dump_one(f, show_defaults, lp_ctx->ServicePtrs[iService]);
2545 }
2546
2547 /***************************************************************************
2548 Display the contents of one service in human-readable form.
2549 ***************************************************************************/
2550
2551 void lp_dump_one(FILE *f, bool show_defaults, struct loadparm_service *service)
2552 {
2553         if (service != NULL) {
2554                 if (service->szService[0] == '\0')
2555                         return;
2556                 dump_a_service(service, f);
2557         }
2558 }
2559
2560 struct loadparm_service *lp_servicebynum(struct loadparm_context *lp_ctx,
2561                                          int snum)
2562 {
2563         return lp_ctx->ServicePtrs[snum];
2564 }
2565
2566 struct loadparm_service *lp_service(struct loadparm_context *lp_ctx, 
2567                                     const char *service_name)
2568 {
2569         int iService;
2570         char *serviceName;
2571  
2572         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) {
2573                 if (lp_ctx->ServicePtrs[iService] && 
2574                     lp_ctx->ServicePtrs[iService]->szService) {
2575                         /*
2576                          * The substitution here is used to support %U is
2577                          * service names
2578                          */
2579                         serviceName = standard_sub_basic(
2580                                         lp_ctx->ServicePtrs[iService],
2581                                         lp_ctx->ServicePtrs[iService]->szService);
2582                         if (strequal(serviceName, service_name))
2583                                 return lp_ctx->ServicePtrs[iService];
2584                 }
2585         }
2586
2587         DEBUG(7,("lp_servicenumber: couldn't find %s\n", service_name));
2588         return NULL;
2589 }
2590
2591
2592 /*******************************************************************
2593  A useful volume label function. 
2594 ********************************************************************/
2595 const char *volume_label(struct loadparm_service *service)
2596 {
2597         const char *ret = lp_volume(service);
2598         if (!*ret)
2599                 return lp_servicename(service);
2600         return ret;
2601 }
2602
2603
2604 /***********************************************************
2605  If we are PDC then prefer us as DMB
2606 ************************************************************/
2607
2608 bool lp_domain_logons(struct loadparm_context *lp_ctx)
2609 {
2610         return (lp_server_role(lp_ctx) == ROLE_DOMAIN_CONTROLLER);
2611 }
2612
2613 const char *lp_printername(struct loadparm_service *service)
2614 {
2615         const char *ret = _lp_printername(service);
2616         if (ret == NULL || (ret != NULL && *ret == '\0'))
2617                 ret = lp_const_servicename(service);
2618
2619         return ret;
2620 }
2621
2622
2623 /*******************************************************************
2624  Return the max print jobs per queue.
2625 ********************************************************************/
2626
2627 int lp_maxprintjobs(struct loadparm_service *service)
2628 {
2629         int maxjobs = (service != NULL) ? service->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2630         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2631                 maxjobs = PRINT_MAX_JOBID - 1;
2632
2633         return maxjobs;
2634 }