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