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