edd3cec82ab8a3b3a8f2e7fd98d67f97ec07d861
[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_service *service, 
802                               const char *type, const char *option)
803 {
804         char *vfskey;
805         struct param_opt *data;
806         
807         data = (service == NULL ? loadparm.Globals.param_opt : service->param_opt);
808     
809         asprintf(&vfskey, "%s:%s", type, option);
810         strlower(vfskey);
811
812         while (data) {
813                 if (strcmp(data->key, vfskey) == 0) {
814                         free(vfskey);
815                         return data->value;
816                 }
817                 data = data->next;
818         }
819
820         if (service != NULL) {
821                 /* Try to fetch the same option but from globals */
822                 /* but only if we are not already working with Globals */
823                 for (data = loadparm.Globals.param_opt; data; 
824                      data = data->next) {
825                         if (strcmp(data->key, vfskey) == 0) {
826                                 free(vfskey);
827                                 return data->value;
828                         }
829                 }
830         }
831
832         free(vfskey);
833         
834         return NULL;
835 }
836
837
838 /*******************************************************************
839 convenience routine to return int parameters.
840 ********************************************************************/
841 static int lp_int(const char *s)
842 {
843
844         if (!s) {
845                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
846                 return -1;
847         }
848
849         return strtol(s, NULL, 0); 
850 }
851
852 /*******************************************************************
853 convenience routine to return unsigned long parameters.
854 ********************************************************************/
855 static int lp_ulong(const char *s)
856 {
857
858         if (!s) {
859                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
860                 return -1;
861         }
862
863         return strtoul(s, NULL, 0);
864 }
865
866 /*******************************************************************
867 convenience routine to return unsigned long parameters.
868 ********************************************************************/
869 static double lp_double(const char *s)
870 {
871
872         if (!s) {
873                 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
874                 return -1;
875         }
876
877         return strtod(s, NULL);
878 }
879
880 /*******************************************************************
881 convenience routine to return boolean parameters.
882 ********************************************************************/
883 static bool lp_bool(const char *s)
884 {
885         bool ret = false;
886
887         if (!s) {
888                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
889                 return false;
890         }
891         
892         if (!set_boolean(s, &ret)) {
893                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
894                 return false;
895         }
896
897         return ret;
898 }
899
900
901 /* Return parametric option from a given service. Type is a part of option before ':' */
902 /* Parametric option has following syntax: 'Type: option = value' */
903 /* Returned value is allocated in 'lp_talloc' context */
904
905 const char *lp_parm_string(struct loadparm_service *service, const char *type, 
906                            const char *option)
907 {
908         const char *value = lp_get_parametric(service, type, option);
909
910         if (value)
911                 return lp_string(value);
912
913         return NULL;
914 }
915
916 /* Return parametric option from a given service. Type is a part of option before ':' */
917 /* Parametric option has following syntax: 'Type: option = value' */
918 /* Returned value is allocated in 'lp_talloc' context */
919
920 const char **lp_parm_string_list(struct loadparm_service *service, 
921                                  const char *type, 
922                                  const char *option, const char *separator)
923 {
924         const char *value = lp_get_parametric(service, type, option);
925         
926         if (value)
927                 return str_list_make(talloc_autofree_context(), value, 
928                                      separator);
929
930         return NULL;
931 }
932
933 /* Return parametric option from a given service. Type is a part of option before ':' */
934 /* Parametric option has following syntax: 'Type: option = value' */
935
936 int lp_parm_int(struct loadparm_service *service, const char *type, 
937                 const char *option, int default_v)
938 {
939         const char *value = lp_get_parametric(service, type, option);
940         
941         if (value)
942                 return lp_int(value);
943
944         return default_v;
945 }
946
947 /* Return parametric option from a given service. Type is a part of
948  * option before ':'.
949  * Parametric option has following syntax: 'Type: option = value'.
950  */
951
952 int lp_parm_bytes(struct loadparm_service *service, const char *type, 
953                   const char *option, int default_v)
954 {
955         uint64_t bval;
956
957         const char *value = lp_get_parametric(service, type, option);
958
959         if (value && conv_str_size(value, &bval)) {
960                 if (bval <= INT_MAX) {
961                         return (int)bval;
962                 }
963         }
964
965         return default_v;
966 }
967
968 /* Return parametric option from a given service. Type is a part of option before ':' */
969 /* Parametric option has following syntax: 'Type: option = value' */
970
971 unsigned long lp_parm_ulong(struct loadparm_service *service, const char *type, 
972                             const char *option, unsigned long default_v)
973 {
974         const char *value = lp_get_parametric(service, type, option);
975         
976         if (value)
977                 return lp_ulong(value);
978
979         return default_v;
980 }
981
982
983 double lp_parm_double(struct loadparm_service *service, const char *type, 
984                       const char *option, double default_v)
985 {
986         const char *value = lp_get_parametric(service, type, option);
987         
988         if (value)
989                 return lp_double(value);
990
991         return default_v;
992 }
993
994 /* Return parametric option from a given service. Type is a part of option before ':' */
995 /* Parametric option has following syntax: 'Type: option = value' */
996
997 bool lp_parm_bool(struct loadparm_service *service, const char *type, 
998                   const char *option, bool default_v)
999 {
1000         const char *value = lp_get_parametric(service, type, option);
1001         
1002         if (value)
1003                 return lp_bool(value);
1004
1005         return default_v;
1006 }
1007
1008
1009 /***************************************************************************
1010  Initialise a service to the defaults.
1011 ***************************************************************************/
1012
1013 static struct loadparm_service *init_service(TALLOC_CTX *mem_ctx)
1014 {
1015         struct loadparm_service *pservice = 
1016                 talloc_zero(mem_ctx, struct loadparm_service);
1017         copy_service(pservice, &sDefault, NULL);
1018         return pservice;
1019 }
1020
1021 /**
1022  Set a string value, deallocating any existing space, and allocing the space
1023  for the string
1024 **/
1025 static bool string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
1026 {
1027         talloc_free(*dest);
1028
1029         if (src == NULL) 
1030                 src = "";
1031
1032         *dest = talloc_strdup(mem_ctx, src);
1033         if ((*dest) == NULL) {
1034                 DEBUG(0,("Out of memory in string_init\n"));
1035                 return false;
1036         }
1037
1038         return true;
1039 }
1040
1041
1042
1043 /***************************************************************************
1044  Add a new service to the services array initialising it with the given 
1045  service. 
1046 ***************************************************************************/
1047
1048 static struct loadparm_service *add_a_service(struct loadparm_context *lp_ctx, 
1049                                      const struct loadparm_service *pservice, 
1050                                      const char *name)
1051 {
1052         int i;
1053         struct loadparm_service tservice;
1054         int num_to_alloc = lp_ctx->iNumServices + 1;
1055         struct param_opt *data, *pdata;
1056
1057         tservice = *pservice;
1058
1059         /* it might already exist */
1060         if (name) {
1061                 struct loadparm_service *service = getservicebyname(lp_ctx, 
1062                                                                     name);
1063                 if (service != NULL) {
1064                         /* Clean all parametric options for service */
1065                         /* They will be added during parsing again */
1066                         data = service->param_opt;
1067                         while (data) {
1068                                 pdata = data->next;
1069                                 talloc_free(data);
1070                                 data = pdata;
1071                         }
1072                         service->param_opt = NULL;
1073                         return service;
1074                 }
1075         }
1076
1077         /* find an invalid one */
1078         for (i = 0; i < lp_ctx->iNumServices; i++)
1079                 if (lp_ctx->ServicePtrs[i] == NULL)
1080                         break;
1081
1082         /* if not, then create one */
1083         if (i == lp_ctx->iNumServices) {
1084                 struct loadparm_service **tsp;
1085                 
1086                 tsp = realloc_p(lp_ctx->ServicePtrs, struct loadparm_service *, 
1087                                 num_to_alloc);
1088                                            
1089                 if (!tsp) {
1090                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1091                         return NULL;
1092                 }
1093                 else {
1094                         lp_ctx->ServicePtrs = tsp;
1095                         lp_ctx->ServicePtrs[lp_ctx->iNumServices] = NULL;
1096                 }
1097
1098                 lp_ctx->iNumServices++;
1099         } 
1100
1101         lp_ctx->ServicePtrs[i] = init_service(talloc_autofree_context());
1102         if (lp_ctx->ServicePtrs[i] == NULL) {
1103                 DEBUG(0,("add_a_service: out of memory!\n"));
1104                 return NULL;
1105         }
1106         copy_service(lp_ctx->ServicePtrs[i], &tservice, NULL);
1107         if (name != NULL)
1108                 string_set(lp_ctx->ServicePtrs[i], &lp_ctx->ServicePtrs[i]->szService, name);
1109         return lp_ctx->ServicePtrs[i];
1110 }
1111
1112 /***************************************************************************
1113  Add a new home service, with the specified home directory, defaults coming 
1114  from service ifrom.
1115 ***************************************************************************/
1116
1117 bool lp_add_home(struct loadparm_context *lp_ctx, 
1118                  const char *pszHomename, 
1119                  struct loadparm_service *default_service,
1120                  const char *user, const char *pszHomedir)
1121 {
1122         struct loadparm_service *service;
1123
1124         service = add_a_service(lp_ctx, default_service, pszHomename);
1125
1126         if (service == NULL)
1127                 return false;
1128
1129         if (!(*(default_service->szPath))
1130             || strequal(default_service->szPath, sDefault.szPath)) {
1131                 service->szPath = talloc_strdup(service, pszHomedir);
1132         } else {
1133                 service->szPath = string_sub_talloc(service, lp_pathname(default_service),"%H", pszHomedir); 
1134         }
1135
1136         if (!(*(service->comment))) {
1137                 service->comment = talloc_asprintf(service, "Home directory of %s", user);
1138         }
1139         service->bAvailable = default_service->bAvailable;
1140         service->bBrowseable = default_service->bBrowseable;
1141
1142         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", 
1143                   pszHomename, user, service->szPath));
1144         
1145         return true;
1146 }
1147
1148 /***************************************************************************
1149  Add a new service, based on an old one.
1150 ***************************************************************************/
1151
1152 struct loadparm_service *lp_add_service(struct loadparm_context *lp_ctx, 
1153                                const char *pszService, 
1154                                struct loadparm_service *default_service)
1155 {
1156         return add_a_service(lp_ctx, default_service, pszService);
1157 }
1158
1159 /***************************************************************************
1160  Add the IPC service.
1161 ***************************************************************************/
1162
1163 static bool lp_add_hidden(struct loadparm_context *lp_ctx, const char *name, 
1164                           const char *fstype)
1165 {
1166         struct loadparm_service *service = add_a_service(lp_ctx, &sDefault, name);
1167
1168         if (service == NULL)
1169                 return false;
1170
1171         string_set(service, &service->szPath, tmpdir());
1172
1173         service->comment = talloc_asprintf(service, "%s Service (%s)", 
1174                                 fstype, lp_ctx->Globals.szServerString);
1175         string_set(service, &service->fstype, fstype);
1176         service->iMaxConnections = -1;
1177         service->bAvailable = true;
1178         service->bRead_only = true;
1179         service->bPrint_ok = false;
1180         service->bBrowseable = false;
1181
1182         if (strcasecmp(fstype, "IPC") == 0) {
1183                 lp_do_service_parameter(lp_ctx, service, "ntvfs handler", 
1184                                         "default");
1185         }
1186
1187         DEBUG(3, ("adding hidden service %s\n", name));
1188
1189         return true;
1190 }
1191
1192 /***************************************************************************
1193  Add a new printer service, with defaults coming from service iFrom.
1194 ***************************************************************************/
1195
1196 bool lp_add_printer(struct loadparm_context *lp_ctx,
1197                     const char *pszPrintername, 
1198                     struct loadparm_service *default_service)
1199 {
1200         const char *comment = "From Printcap";
1201         struct loadparm_service *service;
1202         service = add_a_service(lp_ctx, default_service, pszPrintername);
1203
1204         if (service == NULL)
1205                 return false;
1206
1207         /* note that we do NOT default the availability flag to True - */
1208         /* we take it from the default service passed. This allows all */
1209         /* dynamic printers to be disabled by disabling the [printers] */
1210         /* entry (if/when the 'available' keyword is implemented!).    */
1211
1212         /* the printer name is set to the service name. */
1213         string_set(service, &service->szPrintername, pszPrintername);
1214         string_set(service, &service->comment, comment);
1215         service->bBrowseable = sDefault.bBrowseable;
1216         /* Printers cannot be read_only. */
1217         service->bRead_only = false;
1218         /* Printer services must be printable. */
1219         service->bPrint_ok = true;
1220
1221         DEBUG(3, ("adding printer service %s\n", pszPrintername));
1222
1223         return true;
1224 }
1225
1226 /***************************************************************************
1227  Map a parameter's string representation to something we can use. 
1228  Returns False if the parameter string is not recognised, else TRUE.
1229 ***************************************************************************/
1230
1231 static int map_parameter(const char *pszParmName)
1232 {
1233         int iIndex;
1234
1235         if (*pszParmName == '-')
1236                 return -1;
1237
1238         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1239                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1240                         return iIndex;
1241
1242         /* Warn only if it isn't parametric option */
1243         if (strchr(pszParmName, ':') == NULL)
1244                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1245         /* We do return 'fail' for parametric options as well because they are
1246            stored in different storage
1247          */
1248         return -1;
1249 }
1250
1251
1252 /*
1253   return the parameter structure for a parameter
1254 */
1255 struct parm_struct *lp_parm_struct(const char *name)
1256 {
1257         int parmnum = map_parameter(name);
1258         if (parmnum == -1) return NULL;
1259         return &parm_table[parmnum];
1260 }
1261
1262 /*
1263   return the parameter pointer for a parameter
1264 */
1265 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
1266 {
1267         if (service == NULL)
1268                 return parm->ptr;
1269
1270         return ((char *)service) + PTR_DIFF(parm->ptr, &sDefault);
1271 }
1272
1273 /***************************************************************************
1274 Find a service by name. Otherwise works like get_service.
1275 ***************************************************************************/
1276
1277 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx, 
1278                                         const char *pszServiceName)
1279 {
1280         int iService;
1281
1282         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
1283                 if (lp_ctx->ServicePtrs[iService] != NULL &&
1284                     strwicmp(lp_ctx->ServicePtrs[iService]->szService, pszServiceName) == 0) {
1285                         return lp_ctx->ServicePtrs[iService];
1286                 }
1287
1288         return NULL;
1289 }
1290
1291 /***************************************************************************
1292  Copy a service structure to another.
1293  If pcopymapDest is NULL then copy all fields
1294 ***************************************************************************/
1295
1296 static void copy_service(struct loadparm_service *pserviceDest, 
1297                          struct loadparm_service *pserviceSource, 
1298                          int *pcopymapDest)
1299 {
1300         int i;
1301         bool bcopyall = (pcopymapDest == NULL);
1302         struct param_opt *data, *pdata, *paramo;
1303         bool not_added;
1304
1305         for (i = 0; parm_table[i].label; i++)
1306                 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1307                     (bcopyall || pcopymapDest[i])) {
1308                         void *def_ptr = parm_table[i].ptr;
1309                         void *src_ptr =
1310                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1311                                                                     &sDefault);
1312                         void *dest_ptr =
1313                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1314                                                                   &sDefault);
1315
1316                         switch (parm_table[i].type) {
1317                                 case P_BOOL:
1318                                         *(int *)dest_ptr = *(int *)src_ptr;
1319                                         break;
1320
1321                                 case P_INTEGER:
1322                                 case P_OCTAL:
1323                                 case P_ENUM:
1324                                         *(int *)dest_ptr = *(int *)src_ptr;
1325                                         break;
1326
1327                                 case P_STRING:
1328                                         string_set(pserviceDest, 
1329                                                    (char **)dest_ptr,
1330                                                    *(char **)src_ptr);
1331                                         break;
1332
1333                                 case P_USTRING:
1334                                         string_set(pserviceDest, 
1335                                                    (char **)dest_ptr,
1336                                                    *(char **)src_ptr);
1337                                         strupper(*(char **)dest_ptr);
1338                                         break;
1339                                 case P_LIST:
1340                                         *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(), 
1341                                                                                   *(const char ***)src_ptr);
1342                                         break;
1343                                 default:
1344                                         break;
1345                         }
1346                 }
1347
1348         if (bcopyall) {
1349                 init_copymap(pserviceDest);
1350                 if (pserviceSource->copymap)
1351                         memcpy((void *)pserviceDest->copymap,
1352                                (void *)pserviceSource->copymap,
1353                                sizeof(int) * NUMPARAMETERS);
1354         }
1355         
1356         data = pserviceSource->param_opt;
1357         while (data) {
1358                 not_added = true;
1359                 pdata = pserviceDest->param_opt;
1360                 /* Traverse destination */
1361                 while (pdata) {
1362                         /* If we already have same option, override it */
1363                         if (strcmp(pdata->key, data->key) == 0) {
1364                                 talloc_free(pdata->value);
1365                                 pdata->value = talloc_reference(pdata, 
1366                                                              data->value);
1367                                 not_added = false;
1368                                 break;
1369                         }
1370                         pdata = pdata->next;
1371                 }
1372                 if (not_added) {
1373                         paramo = talloc(pserviceDest, struct param_opt);
1374                         if (paramo == NULL)
1375                                 smb_panic("OOM");
1376                         paramo->key = talloc_reference(paramo, data->key);
1377                         paramo->value = talloc_reference(paramo, data->value);
1378                         DLIST_ADD(pserviceDest->param_opt, paramo);
1379                 }
1380                 data = data->next;
1381         }
1382 }
1383
1384 /***************************************************************************
1385 Check a service for consistency. Return False if the service is in any way
1386 incomplete or faulty, else True.
1387 ***************************************************************************/
1388
1389 static bool service_ok(struct loadparm_service *service)
1390 {
1391         bool bRetval;
1392
1393         bRetval = true;
1394         if (service->szService[0] == '\0') {
1395                 DEBUG(0, ("The following message indicates an internal error:\n"));
1396                 DEBUG(0, ("No service name in service entry.\n"));
1397                 bRetval = false;
1398         }
1399
1400         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1401         /* I can't see why you'd want a non-printable printer service...        */
1402         if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
1403                 if (!service->bPrint_ok) {
1404                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1405                                service->szService));
1406                         service->bPrint_ok = true;
1407                 }
1408                 /* [printers] service must also be non-browsable. */
1409                 if (service->bBrowseable)
1410                         service->bBrowseable = false;
1411         }
1412
1413         /* If a service is flagged unavailable, log the fact at level 0. */
1414         if (!service->bAvailable)
1415                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1416                           service->szService));
1417
1418         return bRetval;
1419 }
1420
1421
1422 /*******************************************************************
1423  Keep a linked list of all config files so we know when one has changed 
1424  it's date and needs to be reloaded.
1425 ********************************************************************/
1426
1427 static void add_to_file_list(struct loadparm_context *lp_ctx, 
1428                              const char *fname, const char *subfname)
1429 {
1430         struct file_lists *f = lp_ctx->file_lists;
1431
1432         while (f) {
1433                 if (f->name && !strcmp(f->name, fname))
1434                         break;
1435                 f = f->next;
1436         }
1437
1438         if (!f) {
1439                 f = talloc(talloc_autofree_context(), struct file_lists);
1440                 if (!f)
1441                         return;
1442                 f->next = lp_ctx->file_lists;
1443                 f->name = talloc_strdup(f, fname);
1444                 if (!f->name) {
1445                         talloc_free(f);
1446                         return;
1447                 }
1448                 f->subfname = talloc_strdup(f, subfname);
1449                 if (!f->subfname) {
1450                         talloc_free(f);
1451                         return;
1452                 }
1453                 lp_ctx->file_lists = f;
1454                 f->modtime = file_modtime(subfname);
1455         } else {
1456                 time_t t = file_modtime(subfname);
1457                 if (t)
1458                         f->modtime = t;
1459         }
1460 }
1461
1462 /*******************************************************************
1463  Check if a config file has changed date.
1464 ********************************************************************/
1465
1466 bool lp_file_list_changed(struct loadparm_context *lp_ctx)
1467 {
1468         struct file_lists *f;
1469         DEBUG(6, ("lp_file_list_changed()\n"));
1470
1471         for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
1472                 char *n2;
1473                 time_t mod_time;
1474
1475                 n2 = standard_sub_basic(talloc_autofree_context(), f->name);
1476
1477                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
1478                              f->name, n2, ctime(&f->modtime)));
1479
1480                 mod_time = file_modtime(n2);
1481
1482                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1483                         DEBUGADD(6, ("file %s modified: %s\n", n2,
1484                                   ctime(&mod_time)));
1485                         f->modtime = mod_time;
1486                         talloc_free(f->subfname);
1487                         f->subfname = talloc_strdup(f, n2);
1488                         return true;
1489                 }
1490         }
1491         return false;
1492 }
1493
1494 /***************************************************************************
1495  Handle the include operation.
1496 ***************************************************************************/
1497
1498 static bool handle_include(struct loadparm_context *lp_ctx, 
1499                            const char *pszParmValue, char **ptr)
1500 {
1501         char *fname = standard_sub_basic(talloc_autofree_context(), 
1502                                          pszParmValue);
1503
1504         add_to_file_list(lp_ctx, pszParmValue, fname);
1505
1506         string_set(talloc_autofree_context(), ptr, fname);
1507
1508         if (file_exist(fname))
1509                 return pm_process(fname, do_section, do_parameter, lp_ctx);
1510
1511         DEBUG(2, ("Can't find include file %s\n", fname));
1512
1513         return false;
1514 }
1515
1516 /***************************************************************************
1517  Handle the interpretation of the copy parameter.
1518 ***************************************************************************/
1519
1520 static bool handle_copy(struct loadparm_context *lp_ctx, 
1521                         const char *pszParmValue, char **ptr)
1522 {
1523         bool bRetval;
1524         struct loadparm_service *serviceTemp;
1525
1526         string_set(talloc_autofree_context(), ptr, pszParmValue);
1527
1528         bRetval = false;
1529
1530         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1531
1532         if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) {
1533                 if (serviceTemp == lp_ctx->currentService) {
1534                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1535                 } else {
1536                         copy_service(lp_ctx->currentService,
1537                                      serviceTemp,
1538                                      lp_ctx->currentService->copymap);
1539                         bRetval = true;
1540                 }
1541         } else {
1542                 DEBUG(0, ("Unable to copy service - source not found: %s\n", 
1543                           pszParmValue));
1544                 bRetval = false;
1545         }
1546
1547         return bRetval;
1548 }
1549
1550 /***************************************************************************
1551  Initialise a copymap.
1552 ***************************************************************************/
1553
1554 static void init_copymap(struct loadparm_service *pservice)
1555 {
1556         int i;
1557         talloc_free(pservice->copymap);
1558         pservice->copymap = talloc_array(pservice, int, NUMPARAMETERS);
1559         if (pservice->copymap == NULL) {
1560                 DEBUG(0,
1561                       ("Couldn't allocate copymap!! (size %d)\n",
1562                        (int)NUMPARAMETERS));
1563                 return;
1564         }
1565         for (i = 0; i < NUMPARAMETERS; i++)
1566                 pservice->copymap[i] = true;
1567 }
1568
1569 /***************************************************************************
1570  Process a parametric option
1571 ***************************************************************************/
1572 static bool lp_do_parameter_parametric(struct loadparm_service *service, 
1573                                        const char *pszParmName, 
1574                                        const char *pszParmValue, int flags)
1575 {
1576         struct param_opt *paramo, *data;
1577         char *name;
1578         TALLOC_CTX *mem_ctx;
1579
1580         while (isspace((unsigned char)*pszParmName)) {
1581                 pszParmName++;
1582         }
1583
1584         name = strdup(pszParmName);
1585         if (!name) return false;
1586
1587         strlower(name);
1588
1589         if (service == NULL) {
1590                 data = loadparm.Globals.param_opt;
1591                 mem_ctx = talloc_autofree_context();
1592         } else {
1593                 data = service->param_opt;
1594                 mem_ctx = service;
1595         }
1596
1597         /* Traverse destination */
1598         for (paramo=data; paramo; paramo=paramo->next) {
1599                 /* If we already have the option set, override it unless
1600                    it was a command line option and the new one isn't */
1601                 if (strcmp(paramo->key, name) == 0) {
1602                         if ((paramo->flags & FLAG_CMDLINE) &&
1603                             !(flags & FLAG_CMDLINE)) {
1604                                 return true;
1605                         }
1606
1607                         talloc_free(paramo->value);
1608                         paramo->value = talloc_strdup(paramo, pszParmValue);
1609                         paramo->flags = flags;
1610                         free(name);
1611                         return true;
1612                 }
1613         }
1614
1615         paramo = talloc(mem_ctx, struct param_opt);
1616         if (!paramo)
1617                 smb_panic("OOM");
1618         paramo->key = talloc_strdup(paramo, name);
1619         paramo->value = talloc_strdup(paramo, pszParmValue);
1620         paramo->flags = flags;
1621         if (service == NULL) {
1622                 DLIST_ADD(loadparm.Globals.param_opt, paramo);
1623         } else {
1624                 DLIST_ADD(service->param_opt, paramo);
1625         }
1626
1627         free(name);
1628         
1629         return true;
1630 }
1631
1632 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr, 
1633                          const char *pszParmName, const char *pszParmValue,
1634                          struct loadparm_context *lp_ctx)
1635 {
1636         int i;
1637         /* if it is a special case then go ahead */
1638         if (parm_table[parmnum].special) {
1639                 parm_table[parmnum].special(lp_ctx, pszParmValue, 
1640                                             (char **)parm_ptr);
1641                 return true;
1642         }
1643
1644         /* now switch on the type of variable it is */
1645         switch (parm_table[parmnum].type)
1646         {
1647                 case P_BOOL: {
1648                         bool b;
1649                         if (!set_boolean(pszParmValue, &b)) {
1650                                 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1651                                 return false;
1652                         }
1653                         *(int *)parm_ptr = b;
1654                         }
1655                         break;
1656
1657                 case P_INTEGER:
1658                         *(int *)parm_ptr = atoi(pszParmValue);
1659                         break;
1660
1661                 case P_OCTAL:
1662                         *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1663                         break;
1664
1665                 case P_BYTES:
1666                 {
1667                         uint64_t val;
1668                         if (conv_str_size(pszParmValue, &val)) {
1669                                 if (val <= INT_MAX) {
1670                                         *(int *)parm_ptr = (int)val;
1671                                         break;
1672                                 }
1673                         }
1674
1675                         DEBUG(0,("lp_do_parameter(%s): value is not "
1676                             "a valid size specifier!\n", pszParmValue));
1677                         return false;
1678                 }
1679
1680                 case P_LIST:
1681                         *(const char ***)parm_ptr = str_list_make(mem_ctx, 
1682                                                                   pszParmValue, NULL);
1683                         break;
1684
1685                 case P_STRING:
1686                         string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1687                         break;
1688
1689                 case P_USTRING:
1690                         string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1691                         strupper(*(char **)parm_ptr);
1692                         break;
1693
1694                 case P_ENUM:
1695                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1696                                 if (strequal
1697                                     (pszParmValue,
1698                                      parm_table[parmnum].enum_list[i].name)) {
1699                                         *(int *)parm_ptr =
1700                                                 parm_table[parmnum].
1701                                                 enum_list[i].value;
1702                                         break;
1703                                 }
1704                         }
1705                         if (!parm_table[parmnum].enum_list[i].name) {
1706                                 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 
1707                                          pszParmValue, pszParmName));
1708                                 return false;
1709                         }
1710                         break;
1711                 case P_SEP:
1712                         break;
1713         }
1714
1715         if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1716                 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1717                 /* we have to also unset FLAG_DEFAULT on aliases */
1718                 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1719                         parm_table[i].flags &= ~FLAG_DEFAULT;
1720                 }
1721                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1722                         parm_table[i].flags &= ~FLAG_DEFAULT;
1723                 }
1724         }
1725         return true;
1726 }
1727
1728
1729 bool lp_do_global_parameter(struct loadparm_context *lp_ctx, 
1730                             const char *pszParmName, const char *pszParmValue)
1731 {
1732         int parmnum = map_parameter(pszParmName);
1733         void *parm_ptr;
1734
1735         if (parmnum < 0) {
1736                 if (strchr(pszParmName, ':')) {
1737                         return lp_do_parameter_parametric(NULL, pszParmName, pszParmValue, 0);
1738                 }
1739                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1740                 return true;
1741         }
1742
1743         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1744                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1745                           pszParmName));
1746         }
1747
1748         /* if the flag has been set on the command line, then don't allow override,
1749            but don't report an error */
1750         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1751                 return true;
1752         }
1753
1754         parm_ptr = parm_table[parmnum].ptr;
1755
1756         return set_variable(talloc_autofree_context(), parmnum, parm_ptr, 
1757                             pszParmName, pszParmValue, lp_ctx);
1758 }
1759
1760 bool lp_do_service_parameter(struct loadparm_context *lp_ctx, 
1761                              struct loadparm_service *service, 
1762                              const char *pszParmName, const char *pszParmValue)
1763 {
1764         void *def_ptr = NULL;
1765         void *parm_ptr;
1766         int i;
1767         int parmnum = map_parameter(pszParmName);
1768
1769         if (parmnum < 0) {
1770                 if (strchr(pszParmName, ':')) {
1771                         return lp_do_parameter_parametric(service, pszParmName, pszParmValue, 0);
1772                 }
1773                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1774                 return true;
1775         }
1776
1777         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1778                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1779                           pszParmName));
1780         }
1781
1782         /* if the flag has been set on the command line, then don't allow override,
1783            but don't report an error */
1784         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1785                 return true;
1786         }
1787
1788         def_ptr = parm_table[parmnum].ptr;
1789
1790         if (parm_table[parmnum].class == P_GLOBAL) {
1791                 DEBUG(0,
1792                       ("Global parameter %s found in service section!\n",
1793                        pszParmName));
1794                 return true;
1795         }
1796         parm_ptr = ((char *)service) + PTR_DIFF(def_ptr, &sDefault);
1797
1798         if (!service->copymap)
1799                 init_copymap(service);
1800
1801         /* this handles the aliases - set the copymap for other 
1802          * entries with the same data pointer */
1803         for (i = 0; parm_table[i].label; i++)
1804                 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1805                         service->copymap[i] = false;
1806
1807         return set_variable(service, parmnum, parm_ptr, pszParmName, 
1808                             pszParmValue, lp_ctx);
1809 }
1810
1811 /***************************************************************************
1812  Process a parameter.
1813 ***************************************************************************/
1814
1815 static bool do_parameter(const char *pszParmName, const char *pszParmValue, 
1816                          void *userdata)
1817 {
1818         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1819
1820         if (lp_ctx->bInGlobalSection) 
1821                 return lp_do_global_parameter(lp_ctx, pszParmName, 
1822                                               pszParmValue);
1823         else 
1824                 return lp_do_service_parameter(lp_ctx, lp_ctx->currentService,
1825                                                pszParmName, pszParmValue);
1826 }
1827
1828 /*
1829   variable argument do parameter
1830 */
1831 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
1832 bool lp_do_global_parameter_var(struct loadparm_context *lp_ctx, 
1833                                 const char *pszParmName, const char *fmt, ...) 
1834 {
1835         char *s;
1836         bool ret;
1837         va_list ap;
1838
1839         va_start(ap, fmt);      
1840         s = talloc_vasprintf(NULL, fmt, ap);
1841         va_end(ap);
1842         ret = lp_do_global_parameter(lp_ctx, pszParmName, s);
1843         talloc_free(s);
1844         return ret;
1845 }
1846
1847
1848 /*
1849   set a parameter from the commandline - this is called from command line parameter
1850   parsing code. It sets the parameter then marks the parameter as unable to be modified
1851   by smb.conf processing
1852 */
1853 bool lp_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName, 
1854                     const char *pszParmValue)
1855 {
1856         int parmnum = map_parameter(pszParmName);
1857         int i;
1858
1859         while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1860
1861
1862         if (parmnum < 0 && strchr(pszParmName, ':')) {
1863                 /* set a parametric option */
1864                 return lp_do_parameter_parametric(NULL, pszParmName, pszParmValue, FLAG_CMDLINE);
1865         }
1866
1867         if (parmnum < 0) {
1868                 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1869                 return false;
1870         }
1871
1872         /* reset the CMDLINE flag in case this has been called before */
1873         parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1874
1875         if (!lp_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
1876                 return false;
1877         }
1878
1879         parm_table[parmnum].flags |= FLAG_CMDLINE;
1880
1881         /* we have to also set FLAG_CMDLINE on aliases */
1882         for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1883                 parm_table[i].flags |= FLAG_CMDLINE;
1884         }
1885         for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1886                 parm_table[i].flags |= FLAG_CMDLINE;
1887         }
1888
1889         return true;
1890 }
1891
1892 /*
1893   set a option from the commandline in 'a=b' format. Use to support --option
1894 */
1895 bool lp_set_option(struct loadparm_context *lp_ctx, const char *option)
1896 {
1897         char *p, *s;
1898         bool ret;
1899
1900         s = strdup(option);
1901         if (!s) {
1902                 return false;
1903         }
1904
1905         p = strchr(s, '=');
1906         if (!p) {
1907                 free(s);
1908                 return false;
1909         }
1910
1911         *p = 0;
1912
1913         ret = lp_set_cmdline(lp_ctx, s, p+1);
1914         free(s);
1915         return ret;
1916 }
1917
1918
1919 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1920
1921 /***************************************************************************
1922  Print a parameter of the specified type.
1923 ***************************************************************************/
1924
1925 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1926 {
1927         int i;
1928         switch (p->type)
1929         {
1930                 case P_ENUM:
1931                         for (i = 0; p->enum_list[i].name; i++) {
1932                                 if (*(int *)ptr == p->enum_list[i].value) {
1933                                         fprintf(f, "%s",
1934                                                 p->enum_list[i].name);
1935                                         break;
1936                                 }
1937                         }
1938                         break;
1939
1940                 case P_BOOL:
1941                         fprintf(f, "%s", BOOLSTR((bool)*(int *)ptr));
1942                         break;
1943
1944                 case P_INTEGER:
1945                 case P_BYTES:
1946                         fprintf(f, "%d", *(int *)ptr);
1947                         break;
1948
1949                 case P_OCTAL:
1950                         fprintf(f, "0%o", *(int *)ptr);
1951                         break;
1952
1953                 case P_LIST:
1954                         if ((char ***)ptr && *(char ***)ptr) {
1955                                 char **list = *(char ***)ptr;
1956                                 
1957                                 for (; *list; list++)
1958                                         fprintf(f, "%s%s", *list,
1959                                                 ((*(list+1))?", ":""));
1960                         }
1961                         break;
1962
1963                 case P_STRING:
1964                 case P_USTRING:
1965                         if (*(char **)ptr) {
1966                                 fprintf(f, "%s", *(char **)ptr);
1967                         }
1968                         break;
1969                 case P_SEP:
1970                         break;
1971         }
1972 }
1973
1974 /***************************************************************************
1975  Check if two parameters are equal.
1976 ***************************************************************************/
1977
1978 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
1979 {
1980         switch (type) {
1981                 case P_BOOL:
1982                         return (*((int *)ptr1) == *((int *)ptr2));
1983
1984                 case P_INTEGER:
1985                 case P_OCTAL:
1986                 case P_BYTES:
1987                 case P_ENUM:
1988                         return (*((int *)ptr1) == *((int *)ptr2));
1989
1990                 case P_LIST:
1991                         return str_list_equal((const char **)(*(char ***)ptr1), 
1992                                               (const char **)(*(char ***)ptr2));
1993
1994                 case P_STRING:
1995                 case P_USTRING:
1996                 {
1997                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1998                         if (p1 && !*p1)
1999                                 p1 = NULL;
2000                         if (p2 && !*p2)
2001                                 p2 = NULL;
2002                         return (p1 == p2 || strequal(p1, p2));
2003                 }
2004                 case P_SEP:
2005                         break;
2006         }
2007         return false;
2008 }
2009
2010 /***************************************************************************
2011  Process a new section (service). At this stage all sections are services.
2012  Later we'll have special sections that permit server parameters to be set.
2013  Returns True on success, False on failure. 
2014 ***************************************************************************/
2015
2016 static bool do_section(const char *pszSectionName, void *userdata)
2017 {
2018         struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
2019         bool bRetval;
2020         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2021                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2022         bRetval = false;
2023
2024         /* if we've just struck a global section, note the fact. */
2025         lp_ctx->bInGlobalSection = isglobal;
2026
2027         /* check for multiple global sections */
2028         if (lp_ctx->bInGlobalSection) {
2029                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2030                 return true;
2031         }
2032
2033         /* if we have a current service, tidy it up before moving on */
2034         bRetval = true;
2035
2036         if (lp_ctx->currentService != NULL)
2037                 bRetval = service_ok(lp_ctx->currentService);
2038
2039         /* if all is still well, move to the next record in the services array */
2040         if (bRetval) {
2041                 /* We put this here to avoid an odd message order if messages are */
2042                 /* issued by the post-processing of a previous section. */
2043                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2044
2045                 if ((lp_ctx->currentService = add_a_service(lp_ctx, &sDefault, 
2046                                                              pszSectionName))
2047                     == NULL) {
2048                         DEBUG(0, ("Failed to add a new service\n"));
2049                         return false;
2050                 }
2051         }
2052
2053         return bRetval;
2054 }
2055
2056
2057 /***************************************************************************
2058  Determine if a partcular base parameter is currentl set to the default value.
2059 ***************************************************************************/
2060
2061 static bool is_default(int i)
2062 {
2063         if (!defaults_saved)
2064                 return false;
2065         switch (parm_table[i].type) {
2066                 case P_LIST:
2067                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
2068                                               (const char **)(*(char ***)parm_table[i].ptr));
2069                 case P_STRING:
2070                 case P_USTRING:
2071                         return strequal(parm_table[i].def.svalue,
2072                                         *(char **)parm_table[i].ptr);
2073                 case P_BOOL:
2074                         return parm_table[i].def.bvalue ==
2075                                 *(int *)parm_table[i].ptr;
2076                 case P_INTEGER:
2077                 case P_OCTAL:
2078                 case P_BYTES:
2079                 case P_ENUM:
2080                         return parm_table[i].def.ivalue ==
2081                                 *(int *)parm_table[i].ptr;
2082                 case P_SEP:
2083                         break;
2084         }
2085         return false;
2086 }
2087
2088 /***************************************************************************
2089 Display the contents of the global structure.
2090 ***************************************************************************/
2091
2092 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults)
2093 {
2094         int i;
2095         struct param_opt *data;
2096         
2097         fprintf(f, "# Global parameters\n[global]\n");
2098
2099         for (i = 0; parm_table[i].label; i++)
2100                 if (parm_table[i].class == P_GLOBAL &&
2101                     parm_table[i].ptr &&
2102                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2103                         if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT)) 
2104                                 continue;
2105                         fprintf(f, "\t%s = ", parm_table[i].label);
2106                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
2107                         fprintf(f, "\n");
2108         }
2109         if (lp_ctx->Globals.param_opt != NULL) {
2110                 for (data = lp_ctx->Globals.param_opt; data; 
2111                      data = data->next) {
2112                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2113                 }
2114         }
2115
2116 }
2117
2118 /***************************************************************************
2119  Display the contents of a single services record.
2120 ***************************************************************************/
2121
2122 static void dump_a_service(struct loadparm_service * pService, FILE * f)
2123 {
2124         int i;
2125         struct param_opt *data;
2126         
2127         if (pService != &sDefault)
2128                 fprintf(f, "\n[%s]\n", pService->szService);
2129
2130         for (i = 0; parm_table[i].label; i++)
2131                 if (parm_table[i].class == P_LOCAL &&
2132                     parm_table[i].ptr &&
2133                     (*parm_table[i].label != '-') &&
2134                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2135                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2136
2137                         if (pService == &sDefault) {
2138                                 if (defaults_saved && is_default(i))
2139                                         continue;
2140                         } else {
2141                                 if (equal_parameter(parm_table[i].type,
2142                                                     ((char *)pService) +
2143                                                     pdiff,
2144                                                     ((char *)&sDefault) +
2145                                                     pdiff))
2146                                         continue;
2147                         }
2148
2149                         fprintf(f, "\t%s = ", parm_table[i].label);
2150                         print_parameter(&parm_table[i],
2151                                         ((char *)pService) + pdiff, f);
2152                         fprintf(f, "\n");
2153         }
2154         if (pService->param_opt != NULL) {
2155                 for (data = pService->param_opt; data; data = data->next) {
2156                         fprintf(f, "\t%s = %s\n", data->key, data->value);
2157                 }
2158         }
2159 }
2160
2161 bool lp_dump_a_parameter(struct loadparm_context *lp_ctx, int snum, char *parm_name, FILE * f, 
2162                          bool isGlobal)
2163 {
2164         struct loadparm_service * pService = lp_ctx->ServicePtrs[snum];
2165         struct parm_struct *parm;
2166         void *ptr;
2167         
2168         parm = lp_parm_struct(parm_name);
2169         if (!parm) {
2170                 return false;
2171         }
2172         
2173         if (isGlobal)
2174                 ptr = parm->ptr;
2175         else
2176                 ptr = ((char *)pService) +
2177                         PTR_DIFF(parm->ptr, &sDefault);
2178         
2179         print_parameter(parm,
2180                         ptr, f);
2181         fprintf(f, "\n");
2182         return true;
2183 }
2184
2185 /***************************************************************************
2186  Return info about the next service  in a service. snum==-1 gives the globals.
2187  Return NULL when out of parameters.
2188 ***************************************************************************/
2189
2190 struct parm_struct *lp_next_parameter(struct loadparm_context *lp_ctx, int snum, int *i, 
2191                                       int allparameters)
2192 {
2193         if (snum == -1) {
2194                 /* do the globals */
2195                 for (; parm_table[*i].label; (*i)++) {
2196                         if (parm_table[*i].class == P_SEPARATOR)
2197                                 return &parm_table[(*i)++];
2198
2199                         if (!parm_table[*i].ptr
2200                             || (*parm_table[*i].label == '-'))
2201                                 continue;
2202
2203                         if ((*i) > 0
2204                             && (parm_table[*i].ptr ==
2205                                 parm_table[(*i) - 1].ptr))
2206                                 continue;
2207
2208                         return &parm_table[(*i)++];
2209                 }
2210         } else {
2211                 struct loadparm_service *pService = lp_ctx->ServicePtrs[snum];
2212
2213                 for (; parm_table[*i].label; (*i)++) {
2214                         if (parm_table[*i].class == P_SEPARATOR)
2215                                 return &parm_table[(*i)++];
2216
2217                         if (parm_table[*i].class == P_LOCAL &&
2218                             parm_table[*i].ptr &&
2219                             (*parm_table[*i].label != '-') &&
2220                             ((*i) == 0 ||
2221                              (parm_table[*i].ptr !=
2222                               parm_table[(*i) - 1].ptr)))
2223                         {
2224                                 int pdiff =
2225                                         PTR_DIFF(parm_table[*i].ptr,
2226                                                  &sDefault);
2227
2228                                 if (allparameters ||
2229                                     !equal_parameter(parm_table[*i].type,
2230                                                      ((char *)pService) +
2231                                                      pdiff,
2232                                                      ((char *)&sDefault) +
2233                                                      pdiff))
2234                                 {
2235                                         return &parm_table[(*i)++];
2236                                 }
2237                         }
2238                 }
2239         }
2240
2241         return NULL;
2242 }
2243
2244
2245 /***************************************************************************
2246  Auto-load some home services.
2247 ***************************************************************************/
2248
2249 static void lp_add_auto_services(struct loadparm_context *lp_ctx, 
2250                                  const char *str)
2251 {
2252         return;
2253 }
2254
2255 /***************************************************************************
2256  Have we loaded a services file yet?
2257 ***************************************************************************/
2258
2259 bool lp_loaded(void)
2260 {
2261         return bLoaded;
2262 }
2263
2264 /***************************************************************************
2265  Unload unused services.
2266 ***************************************************************************/
2267
2268 void lp_killunused(struct loadparm_context *lp_ctx, 
2269                    struct smbsrv_connection *smb, 
2270                    bool (*snumused) (struct smbsrv_connection *, int))
2271 {
2272         int i;
2273         for (i = 0; i < lp_ctx->iNumServices; i++) {
2274                 if (lp_ctx->ServicePtrs[i] == NULL)
2275                         continue;
2276
2277                 if (!snumused || !snumused(smb, i)) {
2278                         talloc_free(lp_ctx->ServicePtrs[i]);
2279                         lp_ctx->ServicePtrs[i] = NULL;
2280                 }
2281         }
2282 }
2283
2284 /***************************************************************************
2285  Initialise the global parameter structure.
2286 ***************************************************************************/
2287 bool loadparm_init(struct loadparm_context *lp_ctx)
2288 {
2289         int i;
2290         char *myname;
2291
2292         lp_ctx->bInGlobalSection = true;
2293
2294         DEBUG(3, ("Initialising global parameters\n"));
2295
2296         for (i = 0; parm_table[i].label; i++) {
2297                 if ((parm_table[i].type == P_STRING ||
2298                      parm_table[i].type == P_USTRING) &&
2299                     parm_table[i].ptr &&
2300                     !(parm_table[i].flags & FLAG_CMDLINE)) {
2301                         string_set(talloc_autofree_context(), 
2302                                    (char **)parm_table[i].ptr, "");
2303                 }
2304         }
2305
2306         lp_do_global_parameter(lp_ctx, "share backend", "classic");
2307         
2308         lp_do_global_parameter(lp_ctx, "server role", "standalone");
2309
2310         /* options that can be set on the command line must be initialised via
2311            the slower lp_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
2312 #ifdef TCP_NODELAY
2313         lp_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
2314 #endif
2315         lp_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
2316         myname = get_myname();
2317         lp_do_global_parameter(lp_ctx, "netbios name", myname);
2318         SAFE_FREE(myname);
2319         lp_do_global_parameter(lp_ctx, "name resolve order", "lmhosts wins host bcast");
2320
2321         lp_do_global_parameter(lp_ctx, "fstype", FSTYPE_STRING);
2322         lp_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
2323         lp_do_global_parameter(lp_ctx, "max connections", "-1");
2324
2325         lp_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo");
2326         lp_do_global_parameter(lp_ctx, "server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind");
2327         lp_do_global_parameter(lp_ctx, "ntptr providor", "simple_ldb");
2328         lp_do_global_parameter(lp_ctx, "auth methods:domain controller", "anonymous sam_ignoredomain");
2329         lp_do_global_parameter(lp_ctx, "auth methods:member server", "anonymous sam winbind");
2330         lp_do_global_parameter(lp_ctx, "auth methods:standalone", "anonymous sam_ignoredomain");
2331         lp_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
2332         lp_do_global_parameter(lp_ctx, "sam database", "sam.ldb");
2333         lp_do_global_parameter(lp_ctx, "secrets database", "secrets.ldb");
2334         lp_do_global_parameter(lp_ctx, "spoolss database", "spoolss.ldb");
2335         lp_do_global_parameter(lp_ctx, "wins config database", "wins_config.ldb");
2336         lp_do_global_parameter(lp_ctx, "wins database", "wins.ldb");
2337         lp_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
2338
2339         /* This hive should be dynamically generated by Samba using
2340            data from the sam, but for the moment leave it in a tdb to
2341            keep regedt32 from popping up an annoying dialog. */
2342         lp_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
2343         
2344         /* using UTF8 by default allows us to support all chars */
2345         lp_do_global_parameter(lp_ctx, "unix charset", "UTF8");
2346
2347         /* Use codepage 850 as a default for the dos character set */
2348         lp_do_global_parameter(lp_ctx, "dos charset", "CP850");
2349
2350         /*
2351          * Allow the default PASSWD_CHAT to be overridden in local.h.
2352          */
2353         lp_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
2354
2355         lp_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
2356         lp_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
2357         lp_do_global_parameter(lp_ctx, "modules dir", dyn_MODULESDIR);
2358         lp_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
2359
2360         lp_do_global_parameter(lp_ctx, "socket address", "0.0.0.0");
2361         lp_do_global_parameter_var(lp_ctx, "server string", 
2362                                    "Samba %s", SAMBA_VERSION_STRING);
2363
2364         lp_do_global_parameter_var(lp_ctx, "announce version", "%d.%d", 
2365                          DEFAULT_MAJOR_VERSION,
2366                          DEFAULT_MINOR_VERSION);
2367
2368         lp_do_global_parameter(lp_ctx, "password server", "*");
2369
2370         lp_do_global_parameter(lp_ctx, "max mux", "50");
2371         lp_do_global_parameter(lp_ctx, "max xmit", "12288");
2372         lp_do_global_parameter(lp_ctx, "password level", "0");
2373         lp_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
2374         lp_do_global_parameter(lp_ctx, "server min protocol", "CORE");
2375         lp_do_global_parameter(lp_ctx, "server max protocol", "NT1");
2376         lp_do_global_parameter(lp_ctx, "client min protocol", "CORE");
2377         lp_do_global_parameter(lp_ctx, "client max protocol", "NT1");
2378         lp_do_global_parameter(lp_ctx, "security", "USER");
2379         lp_do_global_parameter(lp_ctx, "paranoid server security", "True");
2380         lp_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
2381         lp_do_global_parameter(lp_ctx, "ReadRaw", "True");
2382         lp_do_global_parameter(lp_ctx, "WriteRaw", "True");
2383         lp_do_global_parameter(lp_ctx, "NullPasswords", "False");
2384         lp_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
2385         lp_do_global_parameter(lp_ctx, "announce as", "NT SERVER");
2386
2387         lp_do_global_parameter(lp_ctx, "TimeServer", "False");
2388         lp_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
2389         lp_do_global_parameter(lp_ctx, "Unicode", "True");
2390         lp_do_global_parameter(lp_ctx, "ClientLanManAuth", "True");
2391         lp_do_global_parameter(lp_ctx, "LanmanAuth", "True");
2392         lp_do_global_parameter(lp_ctx, "NTLMAuth", "True");
2393         lp_do_global_parameter(lp_ctx, "client use spnego principal", "False");
2394         
2395         lp_do_global_parameter(lp_ctx, "UnixExtensions", "False");
2396
2397         lp_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
2398         lp_do_global_parameter(lp_ctx, "LocalMaster", "True");
2399
2400         lp_do_global_parameter(lp_ctx, "wins support", "False");
2401         lp_do_global_parameter(lp_ctx, "dns proxy", "True");
2402
2403         lp_do_global_parameter(lp_ctx, "winbind separator", "\\");
2404         lp_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
2405         lp_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
2406         lp_do_global_parameter(lp_ctx, "template shell", "/bin/false");
2407         lp_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
2408
2409         lp_do_global_parameter(lp_ctx, "client signing", "Yes");
2410         lp_do_global_parameter(lp_ctx, "server signing", "auto");
2411
2412         lp_do_global_parameter(lp_ctx, "use spnego", "True");
2413
2414         lp_do_global_parameter(lp_ctx, "smb ports", "445 139");
2415         lp_do_global_parameter(lp_ctx, "nbt port", "137");
2416         lp_do_global_parameter(lp_ctx, "dgram port", "138");
2417         lp_do_global_parameter(lp_ctx, "cldap port", "389");
2418         lp_do_global_parameter(lp_ctx, "krb5 port", "88");
2419         lp_do_global_parameter(lp_ctx, "kpasswd port", "464");
2420         lp_do_global_parameter(lp_ctx, "web port", "901");
2421         lp_do_global_parameter(lp_ctx, "swat directory", dyn_SWATDIR);
2422
2423         lp_do_global_parameter(lp_ctx, "nt status support", "True");
2424
2425         lp_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
2426         lp_do_global_parameter(lp_ctx, "min wins ttl", "10");
2427
2428         lp_do_global_parameter(lp_ctx, "tls enabled", "True");
2429         lp_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
2430         lp_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
2431         lp_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
2432         lp_do_global_parameter_var(lp_ctx, "js include", "%s", dyn_JSDIR);
2433         lp_do_global_parameter_var(lp_ctx, "setup directory", "%s", 
2434                                    dyn_SETUPDIR);
2435
2436         for (i = 0; parm_table[i].label; i++) {
2437                 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
2438                         parm_table[i].flags |= FLAG_DEFAULT;
2439                 }
2440         }
2441
2442         return true;
2443 }
2444
2445 /***************************************************************************
2446  Load the services array from the services file. Return True on success, 
2447  False on failure.
2448 ***************************************************************************/
2449
2450 bool lp_load(const char *filename)
2451 {
2452         char *n2;
2453         bool bRetval;
2454         struct param_opt *data;
2455         struct loadparm_context *lp_ctx = &loadparm;
2456
2457         filename = talloc_strdup(talloc_autofree_context(), filename);
2458
2459         global_loadparm = lp_ctx;
2460
2461         if (lp_ctx->Globals.param_opt != NULL) {
2462                 struct param_opt *next;
2463                 for (data = lp_ctx->Globals.param_opt; data; data=next) {
2464                         next = data->next;
2465                         if (data->flags & FLAG_CMDLINE) continue;
2466                         DLIST_REMOVE(lp_ctx->Globals.param_opt, data);
2467                         talloc_free(data);
2468                 }
2469         }
2470
2471         if (!loadparm_init(lp_ctx))
2472                 return false;
2473
2474         lp_ctx->Globals.szConfigFile = filename;
2475         
2476         lp_ctx->bInGlobalSection = true;
2477         n2 = standard_sub_basic(talloc_autofree_context(), lp_ctx->Globals.szConfigFile);
2478         DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2479         
2480         add_to_file_list(lp_ctx, lp_ctx->Globals.szConfigFile, n2);
2481
2482         /* We get sections first, so have to start 'behind' to make up */
2483         lp_ctx->currentService = NULL;
2484         bRetval = pm_process(n2, do_section, do_parameter, lp_ctx);
2485
2486         /* finish up the last section */
2487         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2488         if (bRetval)
2489                 if (lp_ctx->currentService != NULL)
2490                         bRetval = service_ok(lp_ctx->currentService);
2491
2492         lp_add_auto_services(lp_ctx, lp_auto_services(lp_ctx));
2493
2494         lp_add_hidden(lp_ctx, "IPC$", "IPC");
2495         lp_add_hidden(lp_ctx, "ADMIN$", "DISK");
2496
2497         bLoaded = true;
2498
2499         if (!lp_ctx->Globals.szWINSservers && lp_ctx->Globals.bWINSsupport) {
2500                 lp_do_global_parameter(lp_ctx, "wins server", "127.0.0.1");
2501         }
2502
2503         init_iconv();
2504
2505         return bRetval;
2506 }
2507
2508 /***************************************************************************
2509  Return the max number of services.
2510 ***************************************************************************/
2511
2512 int lp_numservices(struct loadparm_context *lp_ctx)
2513 {
2514         return lp_ctx->iNumServices;
2515 }
2516
2517 /***************************************************************************
2518 Display the contents of the services array in human-readable form.
2519 ***************************************************************************/
2520
2521 void lp_dump(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults, 
2522              int maxtoprint)
2523 {
2524         int iService;
2525
2526         if (show_defaults)
2527                 defaults_saved = false;
2528
2529         dump_globals(lp_ctx, f, show_defaults);
2530
2531         dump_a_service(&sDefault, f);
2532
2533         for (iService = 0; iService < maxtoprint; iService++)
2534                 lp_dump_one(f, show_defaults, lp_ctx->ServicePtrs[iService]);
2535 }
2536
2537 /***************************************************************************
2538 Display the contents of one service in human-readable form.
2539 ***************************************************************************/
2540
2541 void lp_dump_one(FILE *f, bool show_defaults, struct loadparm_service *service)
2542 {
2543         if (service != NULL) {
2544                 if (service->szService[0] == '\0')
2545                         return;
2546                 dump_a_service(service, f);
2547         }
2548 }
2549
2550 struct loadparm_service *lp_servicebynum(struct loadparm_context *lp_ctx,
2551                                          int snum)
2552 {
2553         return lp_ctx->ServicePtrs[snum];
2554 }
2555
2556 struct loadparm_service *lp_service(struct loadparm_context *lp_ctx, 
2557                                     const char *service_name)
2558 {
2559         int iService;
2560         char *serviceName;
2561  
2562         for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) {
2563                 if (lp_ctx->ServicePtrs[iService] && 
2564                     lp_ctx->ServicePtrs[iService]->szService) {
2565                         /*
2566                          * The substitution here is used to support %U is
2567                          * service names
2568                          */
2569                         serviceName = standard_sub_basic(
2570                                         lp_ctx->ServicePtrs[iService],
2571                                         lp_ctx->ServicePtrs[iService]->szService);
2572                         if (strequal(serviceName, service_name))
2573                                 return lp_ctx->ServicePtrs[iService];
2574                 }
2575         }
2576
2577         DEBUG(7,("lp_servicenumber: couldn't find %s\n", service_name));
2578         return NULL;
2579 }
2580
2581
2582 /*******************************************************************
2583  A useful volume label function. 
2584 ********************************************************************/
2585 const char *volume_label(struct loadparm_service *service)
2586 {
2587         const char *ret = lp_volume(service);
2588         if (!*ret)
2589                 return lp_servicename(service);
2590         return ret;
2591 }
2592
2593
2594 /***********************************************************
2595  If we are PDC then prefer us as DMB
2596 ************************************************************/
2597
2598 bool lp_domain_logons(struct loadparm_context *lp_ctx)
2599 {
2600         return (lp_server_role(lp_ctx) == ROLE_DOMAIN_CONTROLLER);
2601 }
2602
2603 const char *lp_printername(struct loadparm_service *service)
2604 {
2605         const char *ret = _lp_printername(service);
2606         if (ret == NULL || (ret != NULL && *ret == '\0'))
2607                 ret = lp_const_servicename(service);
2608
2609         return ret;
2610 }
2611
2612
2613 /*******************************************************************
2614  Return the max print jobs per queue.
2615 ********************************************************************/
2616
2617 int lp_maxprintjobs(struct loadparm_service *service)
2618 {
2619         int maxjobs = (service != NULL) ? service->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2620         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2621                 maxjobs = PRINT_MAX_JOBID - 1;
2622
2623         return maxjobs;
2624 }