2 Unix SMB/CIFS implementation.
3 Parameter loading functions
4 Copyright (C) Karl Auer 1993-1998
6 Largely re-written by Andrew Tridgell, September 1994
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>
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.
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.
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.
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.
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
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
58 #include "dynconfig.h"
60 #include "system/time.h"
61 #include "system/iconv.h"
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 "dlinklist.h"
67 #include "param/loadparm.h"
69 static BOOL bLoaded = False;
71 /* some helpful bits */
72 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
73 #define VALID(i) ServicePtrs[i]->valid
75 static BOOL do_parameter(const char *, const char *, void *);
76 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...);
78 static BOOL defaults_saved = False;
82 struct param_opt *prev, *next;
89 * This structure describes global (ie., server-wide) parameters.
99 char *display_charset;
103 char *szServerString;
104 char *szAutoServices;
110 char *szWINS_CONFIG_URL;
114 char **szPasswordServers;
115 char *szSocketOptions;
117 char **szWINSservers;
119 char *szSocketAddress;
120 char *szAnnounceVersion; /* This is initialised in init_globals */
123 char **szNetbiosAliases;
124 char *szNetbiosScope;
125 char *szDomainOtherSIDs;
126 char **szNameResolveOrder;
128 char **dcerpc_ep_servers;
129 char **server_services;
130 char *ntptr_providor;
131 char *szWinbindSeparator;
132 char *szWinbinddSocketDirectory;
133 BOOL bWinbindSealedPipes;
134 char *swat_directory;
147 BOOL paranoid_server_security;
150 int announce_as; /* This is initialised in init_globals */
157 char *socket_options;
162 BOOL bPreferredMaster;
163 BOOL bEncryptPasswords;
165 BOOL bObeyPamRestrictions;
166 BOOL bLargeReadwrite;
170 BOOL bBindInterfacesOnly;
172 BOOL bNTStatusSupport;
178 BOOL bClientPlaintextAuth;
179 BOOL bClientLanManAuth;
180 BOOL bClientNTLMv2Auth;
181 BOOL client_use_spnego_principal;
184 BOOL bUnixExtensions;
185 BOOL bDisableNetbios;
187 struct param_opt *param_opt;
191 static global Globals;
194 * This structure describes a single service.
209 char **ntvfs_handler;
225 struct param_opt *param_opt;
227 char dummy[3]; /* for alignment */
232 /* This is a default service used to prime a services structure */
233 static service sDefault = {
235 NULL, /* szService */
238 NULL, /* szInclude */
239 NULL, /* szPrintername */
240 NULL, /* szHostsallow */
241 NULL, /* szHostsdeny */
245 NULL, /* ntvfs_handler */
246 1000, /* iMaxPrintJobs */
247 0, /* iMaxConnections */
249 True, /* bAvailable */
250 True, /* bBrowseable */
251 True, /* bRead_only */
252 False, /* bPrint_ok */
253 False, /* bMap_system */
254 False, /* bMap_hidden */
255 True, /* bMap_archive */
256 True, /* bStrictLocking */
258 False, /* bMSDfsRoot */
259 False, /* bStrictSync */
260 False, /* bCIFileSystem */
261 NULL, /* Parametric options */
266 /* local variables */
267 static service **ServicePtrs = NULL;
268 static int iNumServices = 0;
269 static int iServiceIndex = 0;
270 static BOOL bInGlobalSection = True;
271 static int default_server_announce;
273 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
275 /* prototypes for the special type handlers */
276 static BOOL handle_include(const char *pszParmValue, char **ptr);
277 static BOOL handle_copy(const char *pszParmValue, char **ptr);
279 static void set_default_server_announce_type(void);
281 static const struct enum_list enum_protocol[] = {
282 {PROTOCOL_SMB2, "SMB2"},
283 {PROTOCOL_NT1, "NT1"},
284 {PROTOCOL_LANMAN2, "LANMAN2"},
285 {PROTOCOL_LANMAN1, "LANMAN1"},
286 {PROTOCOL_CORE, "CORE"},
287 {PROTOCOL_COREPLUS, "COREPLUS"},
288 {PROTOCOL_COREPLUS, "CORE+"},
292 static const struct enum_list enum_security[] = {
293 {SEC_SHARE, "SHARE"},
298 /* Types of machine we can announce as. */
299 #define ANNOUNCE_AS_NT_SERVER 1
300 #define ANNOUNCE_AS_WIN95 2
301 #define ANNOUNCE_AS_WFW 3
302 #define ANNOUNCE_AS_NT_WORKSTATION 4
304 static const struct enum_list enum_announce_as[] = {
305 {ANNOUNCE_AS_NT_SERVER, "NT"},
306 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
307 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
308 {ANNOUNCE_AS_WIN95, "win95"},
309 {ANNOUNCE_AS_WFW, "WfW"},
313 static const struct enum_list enum_bool_auto[] = {
324 /* Client-side offline caching policy types */
325 #define CSC_POLICY_MANUAL 0
326 #define CSC_POLICY_DOCUMENTS 1
327 #define CSC_POLICY_PROGRAMS 2
328 #define CSC_POLICY_DISABLE 3
330 static const struct enum_list enum_csc_policy[] = {
331 {CSC_POLICY_MANUAL, "manual"},
332 {CSC_POLICY_DOCUMENTS, "documents"},
333 {CSC_POLICY_PROGRAMS, "programs"},
334 {CSC_POLICY_DISABLE, "disable"},
338 /* SMB signing types. */
339 static const struct enum_list enum_smb_signing_vals[] = {
340 {SMB_SIGNING_OFF, "No"},
341 {SMB_SIGNING_OFF, "False"},
342 {SMB_SIGNING_OFF, "0"},
343 {SMB_SIGNING_OFF, "Off"},
344 {SMB_SIGNING_OFF, "disabled"},
345 {SMB_SIGNING_SUPPORTED, "Yes"},
346 {SMB_SIGNING_SUPPORTED, "True"},
347 {SMB_SIGNING_SUPPORTED, "1"},
348 {SMB_SIGNING_SUPPORTED, "On"},
349 {SMB_SIGNING_SUPPORTED, "enabled"},
350 {SMB_SIGNING_REQUIRED, "required"},
351 {SMB_SIGNING_REQUIRED, "mandatory"},
352 {SMB_SIGNING_REQUIRED, "force"},
353 {SMB_SIGNING_REQUIRED, "forced"},
354 {SMB_SIGNING_REQUIRED, "enforced"},
355 {SMB_SIGNING_AUTO, "auto"},
359 static const struct enum_list enum_server_role[] = {
360 {ROLE_STANDALONE, "standalone"},
361 {ROLE_DOMAIN_MEMBER, "member server"},
362 {ROLE_DOMAIN_BDC, "bdc"},
363 {ROLE_DOMAIN_PDC, "pdc"},
368 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
370 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
371 * is implied in current control logic. This may change at some later time. A
372 * flag value of 0 means - show as development option only.
374 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
375 * screen in SWAT. This is used to exclude parameters as well as to squash all
376 * parameters that have been duplicated by pseudonyms.
378 static struct parm_struct parm_table[] = {
379 {"Base Options", P_SEP, P_SEPARATOR},
381 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
383 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
384 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
385 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
386 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
387 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
388 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
389 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
390 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
391 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
394 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
395 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
396 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
397 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
398 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
399 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
400 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
401 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
403 {"Security Options", P_SEP, P_SEPARATOR},
405 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
406 {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
407 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
408 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
411 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
422 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
425 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
427 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
428 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
430 {"Logging Options", P_SEP, P_SEPARATOR},
432 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
433 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
434 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
436 {"Protocol Options", P_SEP, P_SEPARATOR},
438 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"swat directory", P_STRING, P_GLOBAL, &Globals.swat_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
452 {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
453 {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
454 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
455 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
456 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
457 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
459 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
461 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
462 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
463 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
464 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
466 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
467 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
468 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
470 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
471 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
472 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
473 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
474 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
476 {"Tuning Options", P_SEP, P_SEPARATOR},
478 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
479 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
480 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
482 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
483 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
485 {"Printing Options", P_SEP, P_SEPARATOR},
487 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
488 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
489 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
491 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
492 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
494 {"Filename Handling", P_SEP, P_SEPARATOR},
496 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
497 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
498 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
500 {"Domain Options", P_SEP, P_SEPARATOR},
502 {"Logon Options", P_SEP, P_SEPARATOR},
505 {"Browse Options", P_SEP, P_SEPARATOR},
507 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
508 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
509 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
510 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
511 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
513 {"WINS Options", P_SEP, P_SEPARATOR},
515 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
516 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
517 {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
518 {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
520 {"Locking Options", P_SEP, P_SEPARATOR},
522 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
524 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
526 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
528 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
529 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
530 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
531 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
532 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
533 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
534 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
535 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
537 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
538 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
540 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
541 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
543 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
544 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
545 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
547 {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
549 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
550 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
551 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
552 {"winbindd socket directory", P_STRING, P_GLOBAL, &Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
553 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
555 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
560 return the parameter table
562 struct parm_struct *lp_parm_table(void)
567 /***************************************************************************
568 Initialise the global parameter structure.
569 ***************************************************************************/
570 static void init_globals(void)
575 DEBUG(3, ("Initialising global parameters\n"));
577 for (i = 0; parm_table[i].label; i++) {
578 if ((parm_table[i].type == P_STRING ||
579 parm_table[i].type == P_USTRING) &&
581 !(parm_table[i].flags & FLAG_CMDLINE)) {
582 string_set(parm_table[i].ptr, "");
586 do_parameter("config file", dyn_CONFIGFILE, NULL);
588 do_parameter("server role", "standalone", NULL);
590 /* options that can be set on the command line must be initialised via
591 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
593 do_parameter("socket options", "TCP_NODELAY", NULL);
595 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
596 myname = get_myname();
597 do_parameter("netbios name", myname, NULL);
599 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
601 do_parameter("fstype", FSTYPE_STRING, NULL);
602 do_parameter("ntvfs handler", "unixuid default", NULL);
603 do_parameter("max connections", "-1", NULL);
605 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup", NULL);
606 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc winbind", NULL);
607 do_parameter("ntptr providor", "simple_ldb", NULL);
608 do_parameter("auth methods", "anonymous sam_ignoredomain", NULL);
609 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
610 do_parameter("sam database", "sam.ldb", NULL);
611 do_parameter("spoolss database", "spoolss.ldb", NULL);
612 do_parameter("wins config database", "wins_config.ldb", NULL);
613 do_parameter("wins database", "wins.ldb", NULL);
614 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
616 /* This hive should be dynamically generated by Samba using
617 data from the sam, but for the moment leave it in a tdb to
618 keep regedt32 from popping up an annoying dialog. */
619 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
621 /* using UTF8 by default allows us to support all chars */
622 do_parameter("unix charset", "UTF8", NULL);
624 /* Use codepage 850 as a default for the dos character set */
625 do_parameter("dos charset", "CP850", NULL);
628 * Allow the default PASSWD_CHAT to be overridden in local.h.
630 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
632 do_parameter("pid directory", dyn_PIDDIR, NULL);
633 do_parameter("lock dir", dyn_LOCKDIR, NULL);
634 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
636 do_parameter("socket address", "0.0.0.0", NULL);
637 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
639 do_parameter_var("announce version", "%d.%d",
640 DEFAULT_MAJOR_VERSION,
641 DEFAULT_MINOR_VERSION);
643 do_parameter("password server", "*", NULL);
645 do_parameter("max mux", "50", NULL);
646 do_parameter("max xmit", "12288", NULL);
647 do_parameter("password level", "0", NULL);
648 do_parameter("LargeReadwrite", "True", NULL);
649 do_parameter("min protocol", "CORE", NULL);
650 do_parameter("max protocol", "NT1", NULL);
651 do_parameter("security", "USER", NULL);
652 do_parameter("paranoid server security", "True", NULL);
653 do_parameter("EncryptPasswords", "True", NULL);
654 do_parameter("ReadRaw", "True", NULL);
655 do_parameter("WriteRaw", "True", NULL);
656 do_parameter("NullPasswords", "False", NULL);
657 do_parameter("ObeyPamRestrictions", "False", NULL);
658 do_parameter("announce as", "NT SERVER", NULL);
660 do_parameter("TimeServer", "False", NULL);
661 do_parameter("BindInterfacesOnly", "False", NULL);
662 do_parameter("Unicode", "True", NULL);
663 do_parameter("ClientLanManAuth", "True", NULL);
664 do_parameter("LanmanAuth", "True", NULL);
665 do_parameter("NTLMAuth", "True", NULL);
666 do_parameter("client use spnego principal", "False", NULL);
668 do_parameter("UnixExtensions", "False", NULL);
670 do_parameter("PreferredMaster", "Auto", NULL);
671 do_parameter("LocalMaster", "True", NULL);
673 do_parameter("wins support", "False", NULL);
674 do_parameter("dns proxy", "True", NULL);
676 do_parameter("winbind separator", "\\", NULL);
677 do_parameter("winbind sealed pipes", "True", NULL);
678 do_parameter("winbindd socket directory", dyn_WINBINDD_SOCKET_DIR, NULL);
680 do_parameter("client signing", "Yes", NULL);
681 do_parameter("server signing", "auto", NULL);
683 do_parameter("use spnego", "True", NULL);
685 do_parameter("smb ports", SMB_PORTS, NULL);
686 do_parameter("nbt port", "137", NULL);
687 do_parameter("dgram port", "138", NULL);
688 do_parameter("cldap port", "389", NULL);
689 do_parameter("krb5 port", "88", NULL);
690 do_parameter("kpasswd port", "464", NULL);
691 do_parameter("web port", "901", NULL);
692 do_parameter("swat directory", dyn_SWATDIR, NULL);
694 do_parameter("nt status support", "True", NULL);
696 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
697 do_parameter("min wins ttl", "10", NULL);
699 do_parameter("tls enabled", "True", NULL);
700 do_parameter("tls keyfile", "tls/key.pem", NULL);
701 do_parameter("tls certfile", "tls/cert.pem", NULL);
702 do_parameter("tls cafile", "tls/ca.pem", NULL);
703 do_parameter_var("js include", "%s", dyn_JSDIR);
704 do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
706 for (i = 0; parm_table[i].label; i++) {
707 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
708 parm_table[i].flags |= FLAG_DEFAULT;
713 static TALLOC_CTX *lp_talloc;
715 /******************************************************************* a
716 Free up temporary memory - called from the main loop.
717 ********************************************************************/
719 void lp_talloc_free(void)
723 talloc_free(lp_talloc);
727 /*******************************************************************
728 Convenience routine to grab string parameters into temporary memory
729 and run standard_sub_basic on them. The buffers can be written to by
730 callers without affecting the source string.
731 ********************************************************************/
733 static const char *lp_string(const char *s)
735 #if 0 /* until REWRITE done to make thread-safe */
736 size_t len = s ? strlen(s) : 0;
740 /* The follow debug is useful for tracking down memory problems
741 especially if you have an inner loop that is calling a lp_*()
742 function that returns a string. Perhaps this debug should be
743 present all the time? */
746 DEBUG(10, ("lp_string(%s)\n", s));
749 #if 0 /* until REWRITE done to make thread-safe */
751 lp_talloc = talloc_init("lp_talloc");
753 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
761 StrnCpy(ret, s, len);
763 if (trim_string(ret, "\"", "\"")) {
764 if (strchr(ret,'"') != NULL)
765 StrnCpy(ret, s, len);
768 standard_sub_basic(ret,len+100);
775 In this section all the functions that are used to access the
776 parameters from the rest of the program are defined
779 #define FN_GLOBAL_STRING(fn_name,ptr) \
780 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
781 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
782 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
783 #define FN_GLOBAL_LIST(fn_name,ptr) \
784 const char **fn_name(void) {return(*(const char ***)(ptr));}
785 #define FN_GLOBAL_BOOL(fn_name,ptr) \
786 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
787 #define FN_GLOBAL_CHAR(fn_name,ptr) \
788 char fn_name(void) {return(*(char *)(ptr));}
789 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
790 int fn_name(void) {return(*(int *)(ptr));}
792 #define FN_LOCAL_STRING(fn_name,val) \
793 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
794 #define FN_LOCAL_CONST_STRING(fn_name,val) \
795 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
796 #define FN_LOCAL_LIST(fn_name,val) \
797 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
798 #define FN_LOCAL_BOOL(fn_name,val) \
799 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
800 #define FN_LOCAL_CHAR(fn_name,val) \
801 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
802 #define FN_LOCAL_INTEGER(fn_name,val) \
803 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
805 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
806 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
807 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
808 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
809 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
810 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
811 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
812 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
813 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
814 _PUBLIC_ FN_GLOBAL_STRING(lp_swat_directory, &Globals.swat_directory)
815 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
816 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
817 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
818 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
819 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
820 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
821 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
822 _PUBLIC_ FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
823 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
824 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
825 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
826 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
827 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
828 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
829 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, &Globals.szWinbinddSocketDirectory)
830 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
831 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
832 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
833 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
834 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
835 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
836 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
837 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
838 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
839 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
840 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
841 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
842 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
843 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
844 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
845 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
846 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
847 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
848 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
849 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
850 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
851 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
852 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
853 _PUBLIC_ FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
855 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
856 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
857 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
858 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
859 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
860 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
861 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
862 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
863 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
864 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
865 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
866 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
867 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
868 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
869 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
870 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
871 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
872 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
873 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
874 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
875 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
876 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
877 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
878 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
879 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
880 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
881 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
882 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
883 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
884 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
885 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
886 _PUBLIC_ FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
887 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, &Globals.security)
888 _PUBLIC_ FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
889 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
890 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
891 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
894 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
895 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
896 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
897 static FN_LOCAL_STRING(_lp_printername, szPrintername)
898 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
899 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
900 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
901 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
902 static FN_LOCAL_STRING(lp_volume, volume)
903 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
904 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
905 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
906 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
907 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
908 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
909 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
910 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
911 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
912 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
913 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
914 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
915 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
916 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
917 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
919 /* local prototypes */
921 static int map_parameter(const char *pszParmName);
922 static int getservicebyname(const char *pszServiceName,
923 service * pserviceDest);
924 static void copy_service(service * pserviceDest,
925 service * pserviceSource, BOOL *pcopymapDest);
926 static BOOL service_ok(int iService);
927 static BOOL do_section(const char *pszSectionName, void *);
928 static void init_copymap(service * pservice);
930 /* This is a helper function for parametrical options support. */
931 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
932 /* Actual parametrical functions are quite simple */
933 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
936 struct param_opt *data;
938 if (lookup_service >= iNumServices) return NULL;
940 data = (lookup_service < 0) ?
941 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
943 asprintf(&vfskey, "%s:%s", type, option);
947 if (strcmp(data->key, vfskey) == 0) {
954 if (lookup_service >= 0) {
955 /* Try to fetch the same option but from globals */
956 /* but only if we are not already working with Globals */
957 data = Globals.param_opt;
959 if (strcmp(data->key, vfskey) == 0) {
973 /*******************************************************************
974 convenience routine to return int parameters.
975 ********************************************************************/
976 static int lp_int(const char *s)
980 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
984 return strtol(s, NULL, 0);
987 /*******************************************************************
988 convenience routine to return unsigned long parameters.
989 ********************************************************************/
990 static int lp_ulong(const char *s)
994 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
998 return strtoul(s, NULL, 0);
1001 /*******************************************************************
1002 convenience routine to return boolean parameters.
1003 ********************************************************************/
1004 static BOOL lp_bool(const char *s)
1009 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1013 if (!set_boolean(s, &ret)) {
1014 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1022 /* Return parametric option from a given service. Type is a part of option before ':' */
1023 /* Parametric option has following syntax: 'Type: option = value' */
1024 /* Returned value is allocated in 'lp_talloc' context */
1026 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1028 const char *value = lp_get_parametric(lookup_service, type, option);
1031 return lp_string(value);
1036 /* Return parametric option from a given service. Type is a part of option before ':' */
1037 /* Parametric option has following syntax: 'Type: option = value' */
1038 /* Returned value is allocated in 'lp_talloc' context */
1040 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1041 const char *separator)
1043 const char *value = lp_get_parametric(lookup_service, type, option);
1046 return str_list_make(talloc_autofree_context(), value, separator);
1051 /* Return parametric option from a given service. Type is a part of option before ':' */
1052 /* Parametric option has following syntax: 'Type: option = value' */
1054 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1056 const char *value = lp_get_parametric(lookup_service, type, option);
1059 return lp_int(value);
1064 /* Return parametric option from a given service. Type is a part of option before ':' */
1065 /* Parametric option has following syntax: 'Type: option = value' */
1067 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1069 const char *value = lp_get_parametric(lookup_service, type, option);
1072 return lp_ulong(value);
1077 /* Return parametric option from a given service. Type is a part of option before ':' */
1078 /* Parametric option has following syntax: 'Type: option = value' */
1080 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1082 const char *value = lp_get_parametric(lookup_service, type, option);
1085 return lp_bool(value);
1091 /***************************************************************************
1092 Initialise a service to the defaults.
1093 ***************************************************************************/
1095 static void init_service(service * pservice)
1097 memset((char *)pservice, '\0', sizeof(service));
1098 copy_service(pservice, &sDefault, NULL);
1101 /***************************************************************************
1102 Free the dynamically allocated parts of a service struct.
1103 ***************************************************************************/
1105 static void free_service(service *pservice)
1108 struct param_opt *data, *pdata;
1112 if (pservice->szService)
1113 DEBUG(5, ("free_service: Freeing service %s\n",
1114 pservice->szService));
1116 string_free(&pservice->szService);
1117 SAFE_FREE(pservice->copymap);
1119 for (i = 0; parm_table[i].label; i++) {
1120 if ((parm_table[i].type == P_STRING ||
1121 parm_table[i].type == P_USTRING) &&
1122 parm_table[i].class == P_LOCAL) {
1123 string_free((char **)
1124 (((char *)pservice) +
1125 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1126 } else if (parm_table[i].type == P_LIST &&
1127 parm_table[i].class == P_LOCAL) {
1128 char ***listp = (char ***)(((char *)pservice) +
1129 PTR_DIFF(parm_table[i].ptr, &sDefault));
1130 talloc_free(*listp);
1135 DEBUG(5,("Freeing parametrics:\n"));
1136 data = pservice->param_opt;
1138 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1139 string_free(&data->key);
1140 string_free(&data->value);
1146 ZERO_STRUCTP(pservice);
1149 /***************************************************************************
1150 Add a new service to the services array initialising it with the given
1152 ***************************************************************************/
1154 static int add_a_service(const service *pservice, const char *name)
1158 int num_to_alloc = iNumServices + 1;
1159 struct param_opt *data, *pdata;
1161 tservice = *pservice;
1163 /* it might already exist */
1165 i = getservicebyname(name, NULL);
1167 /* Clean all parametric options for service */
1168 /* They will be added during parsing again */
1169 data = ServicePtrs[i]->param_opt;
1171 string_free(&data->key);
1172 string_free(&data->value);
1177 ServicePtrs[i]->param_opt = NULL;
1182 /* find an invalid one */
1183 for (i = 0; i < iNumServices; i++)
1184 if (!ServicePtrs[i]->valid)
1187 /* if not, then create one */
1188 if (i == iNumServices) {
1191 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1194 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1199 ServicePtrs[iNumServices] = malloc_p(service);
1201 if (!ServicePtrs[iNumServices]) {
1202 DEBUG(0,("add_a_service: out of memory!\n"));
1208 free_service(ServicePtrs[i]);
1210 ServicePtrs[i]->valid = True;
1212 init_service(ServicePtrs[i]);
1213 copy_service(ServicePtrs[i], &tservice, NULL);
1215 string_set(&ServicePtrs[i]->szService, name);
1219 /***************************************************************************
1220 Add a new home service, with the specified home directory, defaults coming
1222 ***************************************************************************/
1224 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1225 const char *user, const char *pszHomedir)
1230 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1235 if (!(*(ServicePtrs[iDefaultService]->szPath))
1236 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1237 pstrcpy(newHomedir, pszHomedir);
1239 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1240 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1243 string_set(&ServicePtrs[i]->szPath, newHomedir);
1245 if (!(*(ServicePtrs[i]->comment))) {
1247 slprintf(comment, sizeof(comment) - 1,
1248 "Home directory of %s", user);
1249 string_set(&ServicePtrs[i]->comment, comment);
1251 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1252 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1254 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1260 /***************************************************************************
1261 Add a new service, based on an old one.
1262 ***************************************************************************/
1264 int lp_add_service(const char *pszService, int iDefaultService)
1266 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1269 /***************************************************************************
1270 Add the IPC service.
1271 ***************************************************************************/
1273 static BOOL lp_add_hidden(const char *name, const char *fstype)
1276 int i = add_a_service(&sDefault, name);
1281 slprintf(comment, sizeof(comment) - 1,
1282 "%s Service (%s)", fstype, Globals.szServerString);
1284 string_set(&ServicePtrs[i]->szPath, tmpdir());
1285 string_set(&ServicePtrs[i]->comment, comment);
1286 string_set(&ServicePtrs[i]->fstype, fstype);
1287 ServicePtrs[i]->iMaxConnections = -1;
1288 ServicePtrs[i]->bAvailable = True;
1289 ServicePtrs[i]->bRead_only = True;
1290 ServicePtrs[i]->bPrint_ok = False;
1291 ServicePtrs[i]->bBrowseable = False;
1293 if (strcasecmp(fstype, "IPC") == 0) {
1294 lp_do_parameter(i, "ntvfs handler", "default");
1297 DEBUG(3, ("adding hidden service %s\n", name));
1302 /***************************************************************************
1303 Add a new printer service, with defaults coming from service iFrom.
1304 ***************************************************************************/
1306 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1308 const char *comment = "From Printcap";
1309 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1314 /* note that we do NOT default the availability flag to True - */
1315 /* we take it from the default service passed. This allows all */
1316 /* dynamic printers to be disabled by disabling the [printers] */
1317 /* entry (if/when the 'available' keyword is implemented!). */
1319 /* the printer name is set to the service name. */
1320 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1321 string_set(&ServicePtrs[i]->comment, comment);
1322 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1323 /* Printers cannot be read_only. */
1324 ServicePtrs[i]->bRead_only = False;
1325 /* Printer services must be printable. */
1326 ServicePtrs[i]->bPrint_ok = True;
1328 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1330 update_server_announce_as_printserver();
1335 /***************************************************************************
1336 Map a parameter's string representation to something we can use.
1337 Returns False if the parameter string is not recognised, else TRUE.
1338 ***************************************************************************/
1340 static int map_parameter(const char *pszParmName)
1344 if (*pszParmName == '-')
1347 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1348 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1351 /* Warn only if it isn't parametric option */
1352 if (strchr(pszParmName, ':') == NULL)
1353 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1354 /* We do return 'fail' for parametric options as well because they are
1355 stored in different storage
1362 return the parameter structure for a parameter
1364 struct parm_struct *lp_parm_struct(const char *name)
1366 int parmnum = map_parameter(name);
1367 if (parmnum == -1) return NULL;
1368 return &parm_table[parmnum];
1372 return the parameter pointer for a parameter
1374 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1379 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1382 /***************************************************************************
1383 Find a service by name. Otherwise works like get_service.
1384 ***************************************************************************/
1386 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1390 for (iService = iNumServices - 1; iService >= 0; iService--)
1391 if (VALID(iService) &&
1392 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1393 if (pserviceDest != NULL)
1394 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1401 /***************************************************************************
1402 Copy a service structure to another.
1403 If pcopymapDest is NULL then copy all fields
1404 ***************************************************************************/
1406 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
1409 BOOL bcopyall = (pcopymapDest == NULL);
1410 struct param_opt *data, *pdata, *paramo;
1413 for (i = 0; parm_table[i].label; i++)
1414 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1415 (bcopyall || pcopymapDest[i])) {
1416 void *def_ptr = parm_table[i].ptr;
1418 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1421 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1424 switch (parm_table[i].type) {
1426 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1431 *(int *)dest_ptr = *(int *)src_ptr;
1435 string_set(dest_ptr,
1440 string_set(dest_ptr,
1442 strupper(*(char **)dest_ptr);
1445 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1446 *(const char ***)src_ptr);
1454 init_copymap(pserviceDest);
1455 if (pserviceSource->copymap)
1456 memcpy((void *)pserviceDest->copymap,
1457 (void *)pserviceSource->copymap,
1458 sizeof(BOOL) * NUMPARAMETERS);
1461 data = pserviceSource->param_opt;
1464 pdata = pserviceDest->param_opt;
1465 /* Traverse destination */
1467 /* If we already have same option, override it */
1468 if (strcmp(pdata->key, data->key) == 0) {
1469 string_free(&pdata->value);
1470 pdata->value = strdup(data->value);
1474 pdata = pdata->next;
1477 paramo = malloc_p(struct param_opt);
1480 paramo->key = strdup(data->key);
1481 paramo->value = strdup(data->value);
1482 DLIST_ADD(pserviceDest->param_opt, paramo);
1488 /***************************************************************************
1489 Check a service for consistency. Return False if the service is in any way
1490 incomplete or faulty, else True.
1491 ***************************************************************************/
1493 static BOOL service_ok(int iService)
1498 if (ServicePtrs[iService]->szService[0] == '\0') {
1499 DEBUG(0, ("The following message indicates an internal error:\n"));
1500 DEBUG(0, ("No service name in service entry.\n"));
1504 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1505 /* I can't see why you'd want a non-printable printer service... */
1506 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1507 if (!ServicePtrs[iService]->bPrint_ok) {
1508 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1509 ServicePtrs[iService]->szService));
1510 ServicePtrs[iService]->bPrint_ok = True;
1511 update_server_announce_as_printserver();
1513 /* [printers] service must also be non-browsable. */
1514 if (ServicePtrs[iService]->bBrowseable)
1515 ServicePtrs[iService]->bBrowseable = False;
1518 /* If a service is flagged unavailable, log the fact at level 0. */
1519 if (!ServicePtrs[iService]->bAvailable)
1520 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1521 ServicePtrs[iService]->szService));
1526 static struct file_lists {
1527 struct file_lists *next;
1531 } *file_lists = NULL;
1533 /*******************************************************************
1534 Keep a linked list of all config files so we know when one has changed
1535 it's date and needs to be reloaded.
1536 ********************************************************************/
1538 static void add_to_file_list(const char *fname, const char *subfname)
1540 struct file_lists *f = file_lists;
1543 if (f->name && !strcmp(f->name, fname))
1549 f = malloc_p(struct file_lists);
1552 f->next = file_lists;
1553 f->name = strdup(fname);
1558 f->subfname = strdup(subfname);
1564 f->modtime = file_modtime(subfname);
1566 time_t t = file_modtime(subfname);
1572 /*******************************************************************
1573 Check if a config file has changed date.
1574 ********************************************************************/
1576 BOOL lp_file_list_changed(void)
1578 struct file_lists *f = file_lists;
1579 DEBUG(6, ("lp_file_list_changed()\n"));
1585 pstrcpy(n2, f->name);
1586 standard_sub_basic(n2,sizeof(n2));
1588 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1589 f->name, n2, ctime(&f->modtime)));
1591 mod_time = file_modtime(n2);
1593 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1595 ("file %s modified: %s\n", n2,
1597 f->modtime = mod_time;
1598 SAFE_FREE(f->subfname);
1599 f->subfname = strdup(n2);
1607 /***************************************************************************
1608 Handle the include operation.
1609 ***************************************************************************/
1611 static BOOL handle_include(const char *pszParmValue, char **ptr)
1614 pstrcpy(fname, pszParmValue);
1616 standard_sub_basic(fname,sizeof(fname));
1618 add_to_file_list(pszParmValue, fname);
1620 string_set(ptr, fname);
1622 if (file_exist(fname))
1623 return (pm_process(fname, do_section, do_parameter, NULL));
1625 DEBUG(2, ("Can't find include file %s\n", fname));
1630 /***************************************************************************
1631 Handle the interpretation of the copy parameter.
1632 ***************************************************************************/
1634 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1638 service serviceTemp;
1640 string_set(ptr, pszParmValue);
1642 init_service(&serviceTemp);
1646 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1648 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1649 if (iTemp == iServiceIndex) {
1650 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1652 copy_service(ServicePtrs[iServiceIndex],
1654 ServicePtrs[iServiceIndex]->copymap);
1658 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1662 free_service(&serviceTemp);
1666 /***************************************************************************
1667 Initialise a copymap.
1668 ***************************************************************************/
1670 static void init_copymap(service * pservice)
1673 SAFE_FREE(pservice->copymap);
1674 pservice->copymap = malloc_array_p(BOOL, NUMPARAMETERS);
1675 if (!pservice->copymap)
1677 ("Couldn't allocate copymap!! (size %d)\n",
1678 (int)NUMPARAMETERS));
1680 for (i = 0; i < NUMPARAMETERS; i++)
1681 pservice->copymap[i] = True;
1684 /***************************************************************************
1685 Return the local pointer to a parameter given the service number and the
1686 pointer into the default structure.
1687 ***************************************************************************/
1689 void *lp_local_ptr(int snum, void *ptr)
1691 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1695 /***************************************************************************
1696 Process a parametric option
1697 ***************************************************************************/
1698 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1700 struct param_opt *paramo, *data;
1703 while (isspace((unsigned char)*pszParmName)) {
1707 name = strdup(pszParmName);
1708 if (!name) return False;
1713 data = Globals.param_opt;
1715 data = ServicePtrs[snum]->param_opt;
1718 /* Traverse destination */
1719 for (paramo=data; paramo; paramo=paramo->next) {
1720 /* If we already have the option set, override it unless
1721 it was a command line option and the new one isn't */
1722 if (strcmp(paramo->key, name) == 0) {
1723 if ((paramo->flags & FLAG_CMDLINE) &&
1724 !(flags & FLAG_CMDLINE)) {
1728 free(paramo->value);
1729 paramo->value = strdup(pszParmValue);
1730 paramo->flags = flags;
1736 paramo = malloc_p(struct param_opt);
1739 paramo->key = strdup(name);
1740 paramo->value = strdup(pszParmValue);
1741 paramo->flags = flags;
1743 DLIST_ADD(Globals.param_opt, paramo);
1745 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1753 /***************************************************************************
1754 Process a parameter for a particular service number. If snum < 0
1755 then assume we are in the globals.
1756 ***************************************************************************/
1757 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1760 void *parm_ptr = NULL; /* where we are going to store the result */
1761 void *def_ptr = NULL;
1763 parmnum = map_parameter(pszParmName);
1766 if (strchr(pszParmName, ':')) {
1767 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1769 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1773 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1774 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1778 /* if the flag has been set on the command line, then don't allow override,
1779 but don't report an error */
1780 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1784 def_ptr = parm_table[parmnum].ptr;
1786 /* we might point at a service, the default service or a global */
1790 if (parm_table[parmnum].class == P_GLOBAL) {
1792 ("Global parameter %s found in service section!\n",
1797 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1802 if (!ServicePtrs[snum]->copymap)
1803 init_copymap(ServicePtrs[snum]);
1805 /* this handles the aliases - set the copymap for other entries with
1806 the same data pointer */
1807 for (i = 0; parm_table[i].label; i++)
1808 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1809 ServicePtrs[snum]->copymap[i] = False;
1812 /* if it is a special case then go ahead */
1813 if (parm_table[parmnum].special) {
1814 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1818 /* now switch on the type of variable it is */
1819 switch (parm_table[parmnum].type)
1822 if (!set_boolean(pszParmValue, parm_ptr)) {
1823 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1829 *(int *)parm_ptr = atoi(pszParmValue);
1833 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1834 pszParmValue, NULL);
1838 string_set(parm_ptr, pszParmValue);
1842 string_set(parm_ptr, pszParmValue);
1843 strupper(*(char **)parm_ptr);
1847 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1850 parm_table[parmnum].enum_list[i].name)) {
1852 parm_table[parmnum].
1857 if (!parm_table[parmnum].enum_list[i].name) {
1858 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1859 pszParmValue, pszParmName));
1867 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1868 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1869 /* we have to also unset FLAG_DEFAULT on aliases */
1870 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1871 parm_table[i].flags &= ~FLAG_DEFAULT;
1873 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1874 parm_table[i].flags &= ~FLAG_DEFAULT;
1881 /***************************************************************************
1882 Process a parameter.
1883 ***************************************************************************/
1885 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1887 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1888 pszParmName, pszParmValue));
1892 variable argument do parameter
1894 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1896 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1903 s = talloc_vasprintf(NULL, fmt, ap);
1905 ret = do_parameter(pszParmName, s, NULL);
1912 set a parameter from the commandline - this is called from command line parameter
1913 parsing code. It sets the parameter then marks the parameter as unable to be modified
1914 by smb.conf processing
1916 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1918 int parmnum = map_parameter(pszParmName);
1921 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1924 if (parmnum < 0 && strchr(pszParmName, ':')) {
1925 /* set a parametric option */
1926 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
1930 DEBUG(0,("Unknown option '%s'\n", pszParmName));
1934 /* reset the CMDLINE flag in case this has been called before */
1935 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
1937 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
1941 parm_table[parmnum].flags |= FLAG_CMDLINE;
1943 /* we have to also set FLAG_CMDLINE on aliases */
1944 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1945 parm_table[i].flags |= FLAG_CMDLINE;
1947 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1948 parm_table[i].flags |= FLAG_CMDLINE;
1955 set a option from the commandline in 'a=b' format. Use to support --option
1957 BOOL lp_set_option(const char *option)
1975 ret = lp_set_cmdline(s, p+1);
1981 #define BOOLSTR(b) ((b) ? "Yes" : "No")
1983 /***************************************************************************
1984 Print a parameter of the specified type.
1985 ***************************************************************************/
1987 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
1993 for (i = 0; p->enum_list[i].name; i++) {
1994 if (*(int *)ptr == p->enum_list[i].value) {
1996 p->enum_list[i].name);
2003 fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
2007 fprintf(f, "%d", *(int *)ptr);
2011 if ((char ***)ptr && *(char ***)ptr) {
2012 char **list = *(char ***)ptr;
2014 for (; *list; list++)
2015 fprintf(f, "%s%s", *list,
2016 ((*(list+1))?", ":""));
2022 if (*(char **)ptr) {
2023 fprintf(f, "%s", *(char **)ptr);
2031 /***************************************************************************
2032 Check if two parameters are equal.
2033 ***************************************************************************/
2035 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2039 return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
2043 return (*((int *)ptr1) == *((int *)ptr2));
2046 return str_list_equal((const char **)(*(char ***)ptr1),
2047 (const char **)(*(char ***)ptr2));
2052 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2057 return (p1 == p2 || strequal(p1, p2));
2065 /***************************************************************************
2066 Process a new section (service). At this stage all sections are services.
2067 Later we'll have special sections that permit server parameters to be set.
2068 Returns True on success, False on failure.
2069 ***************************************************************************/
2071 static BOOL do_section(const char *pszSectionName, void *userdata)
2074 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2075 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2078 /* if we've just struck a global section, note the fact. */
2079 bInGlobalSection = isglobal;
2081 /* check for multiple global sections */
2082 if (bInGlobalSection) {
2083 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2087 /* if we have a current service, tidy it up before moving on */
2090 if (iServiceIndex >= 0)
2091 bRetval = service_ok(iServiceIndex);
2093 /* if all is still well, move to the next record in the services array */
2095 /* We put this here to avoid an odd message order if messages are */
2096 /* issued by the post-processing of a previous section. */
2097 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2099 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2101 DEBUG(0, ("Failed to add a new service\n"));
2110 /***************************************************************************
2111 Determine if a partcular base parameter is currentl set to the default value.
2112 ***************************************************************************/
2114 static BOOL is_default(int i)
2116 if (!defaults_saved)
2118 switch (parm_table[i].type) {
2120 return str_list_equal((const char **)parm_table[i].def.lvalue,
2121 (const char **)(*(char ***)parm_table[i].ptr));
2124 return strequal(parm_table[i].def.svalue,
2125 *(char **)parm_table[i].ptr);
2127 return parm_table[i].def.bvalue ==
2128 *(BOOL *)parm_table[i].ptr;
2131 return parm_table[i].def.ivalue ==
2132 *(int *)parm_table[i].ptr;
2139 /***************************************************************************
2140 Display the contents of the global structure.
2141 ***************************************************************************/
2143 static void dump_globals(FILE *f, BOOL show_defaults)
2146 struct param_opt *data;
2148 fprintf(f, "# Global parameters\n[global]\n");
2150 for (i = 0; parm_table[i].label; i++)
2151 if (parm_table[i].class == P_GLOBAL &&
2152 parm_table[i].ptr &&
2153 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2154 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2156 fprintf(f, "\t%s = ", parm_table[i].label);
2157 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2160 if (Globals.param_opt != NULL) {
2161 data = Globals.param_opt;
2163 fprintf(f, "\t%s = %s\n", data->key, data->value);
2170 /***************************************************************************
2171 Display the contents of a single services record.
2172 ***************************************************************************/
2174 static void dump_a_service(service * pService, FILE * f)
2177 struct param_opt *data;
2179 if (pService != &sDefault)
2180 fprintf(f, "\n[%s]\n", pService->szService);
2182 for (i = 0; parm_table[i].label; i++)
2183 if (parm_table[i].class == P_LOCAL &&
2184 parm_table[i].ptr &&
2185 (*parm_table[i].label != '-') &&
2186 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2187 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2189 if (pService == &sDefault) {
2190 if (defaults_saved && is_default(i))
2193 if (equal_parameter(parm_table[i].type,
2194 ((char *)pService) +
2196 ((char *)&sDefault) +
2201 fprintf(f, "\t%s = ", parm_table[i].label);
2202 print_parameter(&parm_table[i],
2203 ((char *)pService) + pdiff, f);
2206 if (pService->param_opt != NULL) {
2207 data = pService->param_opt;
2209 fprintf(f, "\t%s = %s\n", data->key, data->value);
2215 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2217 service * pService = ServicePtrs[snum];
2218 struct parm_struct *parm;
2221 parm = lp_parm_struct(parm_name);
2229 ptr = ((char *)pService) +
2230 PTR_DIFF(parm->ptr, &sDefault);
2232 print_parameter(parm,
2238 /***************************************************************************
2239 Return info about the next service in a service. snum==-1 gives the globals.
2240 Return NULL when out of parameters.
2241 ***************************************************************************/
2243 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2246 /* do the globals */
2247 for (; parm_table[*i].label; (*i)++) {
2248 if (parm_table[*i].class == P_SEPARATOR)
2249 return &parm_table[(*i)++];
2251 if (!parm_table[*i].ptr
2252 || (*parm_table[*i].label == '-'))
2256 && (parm_table[*i].ptr ==
2257 parm_table[(*i) - 1].ptr))
2260 return &parm_table[(*i)++];
2263 service *pService = ServicePtrs[snum];
2265 for (; parm_table[*i].label; (*i)++) {
2266 if (parm_table[*i].class == P_SEPARATOR)
2267 return &parm_table[(*i)++];
2269 if (parm_table[*i].class == P_LOCAL &&
2270 parm_table[*i].ptr &&
2271 (*parm_table[*i].label != '-') &&
2273 (parm_table[*i].ptr !=
2274 parm_table[(*i) - 1].ptr)))
2277 PTR_DIFF(parm_table[*i].ptr,
2280 if (allparameters ||
2281 !equal_parameter(parm_table[*i].type,
2282 ((char *)pService) +
2284 ((char *)&sDefault) +
2287 return &parm_table[(*i)++];
2297 /***************************************************************************
2298 Return TRUE if the passed service number is within range.
2299 ***************************************************************************/
2301 BOOL lp_snum_ok(int iService)
2303 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2306 /***************************************************************************
2307 Auto-load some home services.
2308 ***************************************************************************/
2310 static void lp_add_auto_services(const char *str)
2315 /***************************************************************************
2316 Announce ourselves as a print server.
2317 ***************************************************************************/
2319 void update_server_announce_as_printserver(void)
2321 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2324 /***************************************************************************
2325 Have we loaded a services file yet?
2326 ***************************************************************************/
2328 BOOL lp_loaded(void)
2333 /***************************************************************************
2334 Unload unused services.
2335 ***************************************************************************/
2337 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2340 for (i = 0; i < iNumServices; i++) {
2344 if (!snumused || !snumused(smb, i)) {
2345 ServicePtrs[i]->valid = False;
2346 free_service(ServicePtrs[i]);
2351 /***************************************************************************
2353 ***************************************************************************/
2355 void lp_killservice(int iServiceIn)
2357 if (VALID(iServiceIn)) {
2358 ServicePtrs[iServiceIn]->valid = False;
2359 free_service(ServicePtrs[iServiceIn]);
2363 /***************************************************************************
2364 Load the services array from the services file. Return True on success,
2366 ***************************************************************************/
2372 struct param_opt *data;
2376 bInGlobalSection = True;
2378 if (Globals.param_opt != NULL) {
2379 struct param_opt *next;
2380 for (data=Globals.param_opt; data; data=next) {
2382 if (data->flags & FLAG_CMDLINE) continue;
2385 DLIST_REMOVE(Globals.param_opt, data);
2392 pstrcpy(n2, lp_configfile());
2393 standard_sub_basic(n2,sizeof(n2));
2394 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2396 add_to_file_list(lp_configfile(), n2);
2398 /* We get sections first, so have to start 'behind' to make up */
2400 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2402 /* finish up the last section */
2403 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2405 if (iServiceIndex >= 0)
2406 bRetval = service_ok(iServiceIndex);
2408 lp_add_auto_services(lp_auto_services());
2410 lp_add_hidden("IPC$", "IPC");
2411 lp_add_hidden("ADMIN$", "DISK");
2413 set_default_server_announce_type();
2417 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2418 lp_do_parameter(-1, "wins server", "127.0.0.1");
2426 /***************************************************************************
2427 Reset the max number of services.
2428 ***************************************************************************/
2430 void lp_resetnumservices(void)
2435 /***************************************************************************
2436 Return the max number of services.
2437 ***************************************************************************/
2439 int lp_numservices(void)
2441 return (iNumServices);
2444 /***************************************************************************
2445 Display the contents of the services array in human-readable form.
2446 ***************************************************************************/
2448 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2453 defaults_saved = False;
2455 dump_globals(f, show_defaults);
2457 dump_a_service(&sDefault, f);
2459 for (iService = 0; iService < maxtoprint; iService++)
2460 lp_dump_one(f, show_defaults, iService);
2463 /***************************************************************************
2464 Display the contents of one service in human-readable form.
2465 ***************************************************************************/
2467 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2470 if (ServicePtrs[snum]->szService[0] == '\0')
2472 dump_a_service(ServicePtrs[snum], f);
2476 /***************************************************************************
2477 Return the number of the service with the given name, or -1 if it doesn't
2478 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2479 getservicebyname()! This works ONLY if all services have been loaded, and
2480 does not copy the found service.
2481 ***************************************************************************/
2483 int lp_servicenumber(const char *pszServiceName)
2486 fstring serviceName;
2489 for (iService = iNumServices - 1; iService >= 0; iService--) {
2490 if (VALID(iService) && ServicePtrs[iService]->szService) {
2492 * The substitution here is used to support %U is
2495 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2496 standard_sub_basic(serviceName,sizeof(serviceName));
2497 if (strequal(serviceName, pszServiceName))
2503 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2508 /*******************************************************************
2509 A useful volume label function.
2510 ********************************************************************/
2511 const char *volume_label(int snum)
2513 const char *ret = lp_volume(snum);
2515 return lp_servicename(snum);
2520 /*******************************************************************
2521 Set the server type we will announce as via nmbd.
2522 ********************************************************************/
2524 static void set_default_server_announce_type(void)
2526 default_server_announce = 0;
2527 default_server_announce |= SV_TYPE_WORKSTATION;
2528 default_server_announce |= SV_TYPE_SERVER;
2529 default_server_announce |= SV_TYPE_SERVER_UNIX;
2531 switch (lp_announce_as()) {
2532 case ANNOUNCE_AS_NT_SERVER:
2533 default_server_announce |= SV_TYPE_SERVER_NT;
2534 /* fall through... */
2535 case ANNOUNCE_AS_NT_WORKSTATION:
2536 default_server_announce |= SV_TYPE_NT;
2538 case ANNOUNCE_AS_WIN95:
2539 default_server_announce |= SV_TYPE_WIN95_PLUS;
2541 case ANNOUNCE_AS_WFW:
2542 default_server_announce |= SV_TYPE_WFW;
2548 switch (lp_server_role()) {
2549 case ROLE_DOMAIN_MEMBER:
2550 default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
2552 case ROLE_DOMAIN_PDC:
2553 default_server_announce |= SV_TYPE_DOMAIN_CTRL;
2555 case ROLE_DOMAIN_BDC:
2556 default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
2558 case ROLE_STANDALONE:
2562 if (lp_time_server())
2563 default_server_announce |= SV_TYPE_TIME_SOURCE;
2565 if (lp_host_msdfs())
2566 default_server_announce |= SV_TYPE_DFS_SERVER;
2568 /* TODO: only announce us as print server when we are a print server */
2569 default_server_announce |= SV_TYPE_PRINTQ_SERVER;
2572 /***********************************************************
2573 If we are PDC then prefer us as DMB
2574 ************************************************************/
2576 BOOL lp_domain_master(void)
2578 return (lp_server_role() == ROLE_DOMAIN_PDC);
2581 /***********************************************************
2582 If we are PDC then prefer us as DMB
2583 ************************************************************/
2585 BOOL lp_domain_logons(void)
2587 return (lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC);
2590 /***********************************************************
2591 If we are DMB then prefer us as LMB
2592 ************************************************************/
2594 BOOL lp_preferred_master(void)
2596 return (lp_local_master() && lp_domain_master());
2599 /*******************************************************************
2601 ********************************************************************/
2603 void lp_remove_service(int snum)
2605 ServicePtrs[snum]->valid = False;
2608 /*******************************************************************
2610 ********************************************************************/
2612 void lp_copy_service(int snum, const char *new_name)
2614 const char *oldname = lp_servicename(snum);
2615 do_section(new_name, NULL);
2617 snum = lp_servicenumber(new_name);
2619 lp_do_parameter(snum, "copy", oldname);
2624 /*******************************************************************
2625 Get the default server type we will announce as via nmbd.
2626 ********************************************************************/
2627 int lp_default_server_announce(void)
2629 return default_server_announce;
2632 const char *lp_printername(int snum)
2634 const char *ret = _lp_printername(snum);
2635 if (ret == NULL || (ret != NULL && *ret == '\0'))
2636 ret = lp_const_servicename(snum);
2642 /*******************************************************************
2643 Return the max print jobs per queue.
2644 ********************************************************************/
2646 int lp_maxprintjobs(int snum)
2648 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2649 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2650 maxjobs = PRINT_MAX_JOBID - 1;