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
57 #include "dynconfig.h"
59 #include "system/time.h"
60 #include "system/locale.h"
61 #include "system/network.h" /* needed for TCP_NODELAY */
62 #include "smb_server/smb_server.h"
63 #include "libcli/raw/signing.h"
64 #include "lib/util/dlinklist.h"
65 #include "param/loadparm.h"
67 static BOOL bLoaded = False;
69 #define standard_sub_basic(str,len)
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;
104 char *szServerString;
105 char *szAutoServices;
108 char *szShareBackend;
112 char *szWINS_CONFIG_URL;
116 char *jsonrpcServicesDir;
117 char **szPasswordServers;
118 char *szSocketOptions;
120 char **szWINSservers;
122 char *szSocketAddress;
123 char *szAnnounceVersion; /* This is initialised in init_globals */
126 char **szNetbiosAliases;
127 char *szNetbiosScope;
128 char *szDomainOtherSIDs;
129 char **szNameResolveOrder;
130 char **dcerpc_ep_servers;
131 char **server_services;
132 char *ntptr_providor;
133 char *szWinbindSeparator;
134 char *szWinbinddSocketDirectory;
135 int bWinbindSealedPipes;
136 char *webapps_directory;
152 int paranoid_server_security;
155 int announce_as; /* This is initialised in init_globals */
162 char *socket_options;
167 int bPreferredMaster;
168 int bEncryptPasswords;
170 int bObeyPamRestrictions;
175 int bBindInterfacesOnly;
177 int bNTStatusSupport;
183 int bClientPlaintextAuth;
184 int bClientLanManAuth;
185 int bClientNTLMv2Auth;
186 int client_use_spnego_principal;
192 struct param_opt *param_opt;
196 static global Globals;
199 * This structure describes a single service.
214 char **ntvfs_handler;
230 struct param_opt *param_opt;
232 char dummy[3]; /* for alignment */
237 /* This is a default service used to prime a services structure */
238 static service sDefault = {
240 NULL, /* szService */
243 NULL, /* szInclude */
244 NULL, /* szPrintername */
245 NULL, /* szHostsallow */
246 NULL, /* szHostsdeny */
250 NULL, /* ntvfs_handler */
251 1000, /* iMaxPrintJobs */
252 0, /* iMaxConnections */
254 True, /* bAvailable */
255 True, /* bBrowseable */
256 True, /* bRead_only */
257 False, /* bPrint_ok */
258 False, /* bMap_system */
259 False, /* bMap_hidden */
260 True, /* bMap_archive */
261 True, /* bStrictLocking */
263 False, /* bMSDfsRoot */
264 False, /* bStrictSync */
265 False, /* bCIFileSystem */
266 NULL, /* Parametric options */
271 /* local variables */
272 static service **ServicePtrs = NULL;
273 static int iNumServices = 0;
274 static int iServiceIndex = 0;
275 static BOOL bInGlobalSection = True;
277 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
279 /* prototypes for the special type handlers */
280 static BOOL handle_include(const char *pszParmValue, char **ptr);
281 static BOOL handle_copy(const char *pszParmValue, char **ptr);
283 static const struct enum_list enum_protocol[] = {
284 {PROTOCOL_SMB2, "SMB2"},
285 {PROTOCOL_NT1, "NT1"},
286 {PROTOCOL_LANMAN2, "LANMAN2"},
287 {PROTOCOL_LANMAN1, "LANMAN1"},
288 {PROTOCOL_CORE, "CORE"},
289 {PROTOCOL_COREPLUS, "COREPLUS"},
290 {PROTOCOL_COREPLUS, "CORE+"},
294 static const struct enum_list enum_security[] = {
295 {SEC_SHARE, "SHARE"},
300 static const struct enum_list enum_announce_as[] = {
301 {ANNOUNCE_AS_NT_SERVER, "NT"},
302 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
303 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
304 {ANNOUNCE_AS_WIN95, "win95"},
305 {ANNOUNCE_AS_WFW, "WfW"},
309 static const struct enum_list enum_bool_auto[] = {
320 /* Client-side offline caching policy types */
321 #define CSC_POLICY_MANUAL 0
322 #define CSC_POLICY_DOCUMENTS 1
323 #define CSC_POLICY_PROGRAMS 2
324 #define CSC_POLICY_DISABLE 3
326 static const struct enum_list enum_csc_policy[] = {
327 {CSC_POLICY_MANUAL, "manual"},
328 {CSC_POLICY_DOCUMENTS, "documents"},
329 {CSC_POLICY_PROGRAMS, "programs"},
330 {CSC_POLICY_DISABLE, "disable"},
334 /* SMB signing types. */
335 static const struct enum_list enum_smb_signing_vals[] = {
336 {SMB_SIGNING_OFF, "No"},
337 {SMB_SIGNING_OFF, "False"},
338 {SMB_SIGNING_OFF, "0"},
339 {SMB_SIGNING_OFF, "Off"},
340 {SMB_SIGNING_OFF, "disabled"},
341 {SMB_SIGNING_SUPPORTED, "Yes"},
342 {SMB_SIGNING_SUPPORTED, "True"},
343 {SMB_SIGNING_SUPPORTED, "1"},
344 {SMB_SIGNING_SUPPORTED, "On"},
345 {SMB_SIGNING_SUPPORTED, "enabled"},
346 {SMB_SIGNING_REQUIRED, "required"},
347 {SMB_SIGNING_REQUIRED, "mandatory"},
348 {SMB_SIGNING_REQUIRED, "force"},
349 {SMB_SIGNING_REQUIRED, "forced"},
350 {SMB_SIGNING_REQUIRED, "enforced"},
351 {SMB_SIGNING_AUTO, "auto"},
355 static const struct enum_list enum_server_role[] = {
356 {ROLE_STANDALONE, "standalone"},
357 {ROLE_DOMAIN_MEMBER, "member server"},
358 {ROLE_DOMAIN_CONTROLLER, "domain controller"},
363 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
365 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
366 * is implied in current control logic. This may change at some later time. A
367 * flag value of 0 means - show as development option only.
369 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
370 * screen in SWAT. This is used to exclude parameters as well as to squash all
371 * parameters that have been duplicated by pseudonyms.
373 static struct parm_struct parm_table[] = {
374 {"Base Options", P_SEP, P_SEPARATOR},
376 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
378 {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
379 {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
380 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
381 {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
382 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
383 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
384 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
385 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
386 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
387 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
388 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
389 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
390 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
391 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
393 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
394 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
395 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
396 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
398 {"Security Options", P_SEP, P_SEPARATOR},
400 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
401 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
402 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
403 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
404 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
405 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
406 {"secrets database", P_STRING, P_GLOBAL, &Globals.szSECRETS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
407 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
408 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
422 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
423 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
425 {"Logging Options", P_SEP, P_SEPARATOR},
427 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
428 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
429 {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
431 {"Protocol Options", P_SEP, P_SEPARATOR},
433 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
434 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
435 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
436 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
437 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
438 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
440 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
441 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"tls dh params file", P_STRING, P_GLOBAL, &Globals.tls_dhpfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"web application directory", P_STRING, P_GLOBAL, &Globals.webapps_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
448 {"server max protocol", P_ENUM, P_GLOBAL, &Globals.srv_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
449 {"server min protocol", P_ENUM, P_GLOBAL, &Globals.srv_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
450 {"client max protocol", P_ENUM, P_GLOBAL, &Globals.cli_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
451 {"client min protocol", P_ENUM, P_GLOBAL, &Globals.cli_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
452 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
453 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
454 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
455 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
457 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
459 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
460 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
461 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
462 {"max xmit", P_BYTES, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
464 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
465 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
466 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
468 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
469 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
470 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
471 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
472 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
474 {"Tuning Options", P_SEP, P_SEPARATOR},
476 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
477 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
478 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
480 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
481 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
483 {"Printing Options", P_SEP, P_SEPARATOR},
485 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
486 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
487 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
489 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
490 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
492 {"Filename Handling", P_SEP, P_SEPARATOR},
494 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
495 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
496 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
498 {"Domain Options", P_SEP, P_SEPARATOR},
500 {"Logon Options", P_SEP, P_SEPARATOR},
503 {"Browse Options", P_SEP, P_SEPARATOR},
505 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
506 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
507 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
508 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
509 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
511 {"WINS Options", P_SEP, P_SEPARATOR},
513 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
514 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
515 {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
516 {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
518 {"Locking Options", P_SEP, P_SEPARATOR},
520 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
522 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
524 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
526 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
527 {"share backend", P_STRING, P_GLOBAL, &Globals.szShareBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
528 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
529 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
530 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
531 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
532 {"modules dir", P_STRING, P_GLOBAL, &Globals.szModulesDir, 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 {"jsonrpc services directory", P_STRING, P_GLOBAL, &Globals.jsonrpcServicesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
536 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
538 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
539 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
541 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
542 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
544 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
545 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
546 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
548 {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
550 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
551 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
552 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
553 {"winbindd socket directory", P_STRING, P_GLOBAL, &Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
554 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
556 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
561 return the parameter table
563 struct parm_struct *lp_parm_table(void)
568 /***************************************************************************
569 Initialise the global parameter structure.
570 ***************************************************************************/
571 static void init_globals(void)
576 DEBUG(3, ("Initialising global parameters\n"));
578 for (i = 0; parm_table[i].label; i++) {
579 if ((parm_table[i].type == P_STRING ||
580 parm_table[i].type == P_USTRING) &&
582 !(parm_table[i].flags & FLAG_CMDLINE)) {
583 string_set(parm_table[i].ptr, "");
587 do_parameter("config file", dyn_CONFIGFILE, NULL);
589 do_parameter("share backend", "classic", NULL);
591 do_parameter("server role", "standalone", NULL);
593 /* options that can be set on the command line must be initialised via
594 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
596 do_parameter("socket options", "TCP_NODELAY", NULL);
598 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
599 myname = get_myname();
600 do_parameter("netbios name", myname, NULL);
602 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
604 do_parameter("fstype", FSTYPE_STRING, NULL);
605 do_parameter("ntvfs handler", "unixuid default", NULL);
606 do_parameter("max connections", "-1", NULL);
608 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo", NULL);
609 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind", NULL);
610 do_parameter("ntptr providor", "simple_ldb", NULL);
611 do_parameter("auth methods:domain controller", "anonymous sam_ignoredomain", NULL);
612 do_parameter("auth methods:member server", "anonymous sam winbind", NULL);
613 do_parameter("auth methods:standalone", "anonymous sam_ignoredomain", NULL);
614 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
615 do_parameter("sam database", "sam.ldb", NULL);
616 do_parameter("secrets database", "secrets.ldb", NULL);
617 do_parameter("spoolss database", "spoolss.ldb", NULL);
618 do_parameter("wins config database", "wins_config.ldb", NULL);
619 do_parameter("wins database", "wins.ldb", NULL);
620 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
622 /* This hive should be dynamically generated by Samba using
623 data from the sam, but for the moment leave it in a tdb to
624 keep regedt32 from popping up an annoying dialog. */
625 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
627 /* using UTF8 by default allows us to support all chars */
628 do_parameter("unix charset", "UTF8", NULL);
630 /* Use codepage 850 as a default for the dos character set */
631 do_parameter("dos charset", "CP850", NULL);
634 * Allow the default PASSWD_CHAT to be overridden in local.h.
636 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
638 do_parameter("pid directory", dyn_PIDDIR, NULL);
639 do_parameter("lock dir", dyn_LOCKDIR, NULL);
640 do_parameter("modules dir", dyn_MODULESDIR, NULL);
641 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
643 do_parameter("socket address", "0.0.0.0", NULL);
644 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
646 do_parameter_var("announce version", "%d.%d",
647 DEFAULT_MAJOR_VERSION,
648 DEFAULT_MINOR_VERSION);
650 do_parameter("password server", "*", NULL);
652 do_parameter("max mux", "50", NULL);
653 do_parameter("max xmit", "12288", NULL);
654 do_parameter("password level", "0", NULL);
655 do_parameter("LargeReadwrite", "True", NULL);
656 do_parameter("server min protocol", "CORE", NULL);
657 do_parameter("server max protocol", "NT1", NULL);
658 do_parameter("client min protocol", "CORE", NULL);
659 do_parameter("client max protocol", "NT1", NULL);
660 do_parameter("security", "USER", NULL);
661 do_parameter("paranoid server security", "True", NULL);
662 do_parameter("EncryptPasswords", "True", NULL);
663 do_parameter("ReadRaw", "True", NULL);
664 do_parameter("WriteRaw", "True", NULL);
665 do_parameter("NullPasswords", "False", NULL);
666 do_parameter("ObeyPamRestrictions", "False", NULL);
667 do_parameter("announce as", "NT SERVER", NULL);
669 do_parameter("TimeServer", "False", NULL);
670 do_parameter("BindInterfacesOnly", "False", NULL);
671 do_parameter("Unicode", "True", NULL);
672 do_parameter("ClientLanManAuth", "True", NULL);
673 do_parameter("LanmanAuth", "True", NULL);
674 do_parameter("NTLMAuth", "True", NULL);
675 do_parameter("client use spnego principal", "False", NULL);
677 do_parameter("UnixExtensions", "False", NULL);
679 do_parameter("PreferredMaster", "Auto", NULL);
680 do_parameter("LocalMaster", "True", NULL);
682 do_parameter("wins support", "False", NULL);
683 do_parameter("dns proxy", "True", NULL);
685 do_parameter("winbind separator", "\\", NULL);
686 do_parameter("winbind sealed pipes", "True", NULL);
687 do_parameter("winbindd socket directory", dyn_WINBINDD_SOCKET_DIR, NULL);
689 do_parameter("client signing", "Yes", NULL);
690 do_parameter("server signing", "auto", NULL);
692 do_parameter("use spnego", "True", NULL);
694 do_parameter("smb ports", "445 139", NULL);
695 do_parameter("nbt port", "137", NULL);
696 do_parameter("dgram port", "138", NULL);
697 do_parameter("cldap port", "389", NULL);
698 do_parameter("krb5 port", "88", NULL);
699 do_parameter("kpasswd port", "464", NULL);
700 do_parameter("web port", "901", NULL);
701 do_parameter("web application directory", dyn_WEBAPPSDIR, NULL);
702 do_parameter("jsonrpc services directory", dyn_SERVICESDIR, NULL);
704 do_parameter("nt status support", "True", NULL);
706 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
707 do_parameter("min wins ttl", "10", NULL);
709 do_parameter("tls enabled", "True", NULL);
710 do_parameter("tls keyfile", "tls/key.pem", NULL);
711 do_parameter("tls certfile", "tls/cert.pem", NULL);
712 do_parameter("tls cafile", "tls/ca.pem", NULL);
713 do_parameter_var("js include", "%s", dyn_JSDIR);
714 do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
716 for (i = 0; parm_table[i].label; i++) {
717 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
718 parm_table[i].flags |= FLAG_DEFAULT;
723 static TALLOC_CTX *lp_talloc;
725 /******************************************************************* a
726 Free up temporary memory - called from the main loop.
727 ********************************************************************/
729 void lp_talloc_free(void)
733 talloc_free(lp_talloc);
737 /*******************************************************************
738 Convenience routine to grab string parameters into temporary memory
739 and run standard_sub_basic on them. The buffers can be written to by
740 callers without affecting the source string.
741 ********************************************************************/
743 static const char *lp_string(const char *s)
745 #if 0 /* until REWRITE done to make thread-safe */
746 size_t len = s ? strlen(s) : 0;
750 /* The follow debug is useful for tracking down memory problems
751 especially if you have an inner loop that is calling a lp_*()
752 function that returns a string. Perhaps this debug should be
753 present all the time? */
756 DEBUG(10, ("lp_string(%s)\n", s));
759 #if 0 /* until REWRITE done to make thread-safe */
761 lp_talloc = talloc_init("lp_talloc");
763 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
771 strlcpy(ret, s, len);
773 if (trim_string(ret, "\"", "\"")) {
774 if (strchr(ret,'"') != NULL)
775 strlcpy(ret, s, len);
778 standard_sub_basic(ret,len+100);
785 In this section all the functions that are used to access the
786 parameters from the rest of the program are defined
789 #define FN_GLOBAL_STRING(fn_name,ptr) \
790 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
791 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
792 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
793 #define FN_GLOBAL_LIST(fn_name,ptr) \
794 const char **fn_name(void) {return(*(const char ***)(ptr));}
795 #define FN_GLOBAL_BOOL(fn_name,ptr) \
796 BOOL fn_name(void) {return((BOOL)*(int *)(ptr));}
798 #define FN_GLOBAL_CHAR(fn_name,ptr) \
799 char fn_name(void) {return(*(char *)(ptr));}
801 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
802 int fn_name(void) {return(*(int *)(ptr));}
804 #define FN_LOCAL_STRING(fn_name,val) \
805 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
806 #define FN_LOCAL_CONST_STRING(fn_name,val) \
807 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
808 #define FN_LOCAL_LIST(fn_name,val) \
809 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
810 #define FN_LOCAL_BOOL(fn_name,val) \
811 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
813 #define FN_LOCAL_CHAR(fn_name,val) \
814 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
816 #define FN_LOCAL_INTEGER(fn_name,val) \
817 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
819 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
820 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
821 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
822 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
823 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
824 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
825 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
826 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
827 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
828 _PUBLIC_ FN_GLOBAL_STRING(lp_webapps_directory, &Globals.webapps_directory)
829 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
830 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
831 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
832 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
833 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
834 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, &Globals.tls_dhpfile)
835 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
836 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
837 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
838 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, &Globals.szShareBackend)
839 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
840 _PUBLIC_ FN_GLOBAL_STRING(lp_secrets_url, &Globals.szSECRETS_URL)
841 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
842 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
843 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
844 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
845 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, &Globals.szWinbinddSocketDirectory)
846 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
847 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
848 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
849 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
850 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, &Globals.szModulesDir)
851 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
852 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
853 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
854 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
855 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
856 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
857 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
858 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
859 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
860 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
861 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
862 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
863 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
864 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
865 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
866 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
867 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
868 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
869 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
871 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
872 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
873 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
874 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
875 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
876 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
877 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
878 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
879 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
880 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
881 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
882 _PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
883 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
884 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
885 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
886 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
887 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
888 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
889 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
890 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
891 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
892 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
893 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
894 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
895 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
896 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
897 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
898 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
899 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
900 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
901 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, &Globals.srv_maxprotocol)
902 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, &Globals.srv_minprotocol)
903 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, &Globals.cli_maxprotocol)
904 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, &Globals.cli_minprotocol)
905 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, &Globals.security)
906 _PUBLIC_ FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
907 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
908 _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
909 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
910 _PUBLIC_ FN_GLOBAL_STRING(lp_jsonrpc_services_dir, &Globals.jsonrpcServicesDir)
913 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
914 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
915 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
916 static FN_LOCAL_STRING(_lp_printername, szPrintername)
917 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
918 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
919 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
920 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
921 static FN_LOCAL_STRING(lp_volume, volume)
922 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
923 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
924 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
925 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
926 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
927 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
928 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
929 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
930 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
931 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
932 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
933 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
934 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
935 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
936 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
938 /* local prototypes */
940 static int map_parameter(const char *pszParmName);
941 static int getservicebyname(const char *pszServiceName,
942 service * pserviceDest);
943 static void copy_service(service * pserviceDest,
944 service * pserviceSource, int *pcopymapDest);
945 static BOOL service_ok(int iService);
946 static BOOL do_section(const char *pszSectionName, void *);
947 static void init_copymap(service * pservice);
949 /* This is a helper function for parametrical options support. */
950 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
951 /* Actual parametrical functions are quite simple */
952 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
955 struct param_opt *data;
957 if (lookup_service >= iNumServices) return NULL;
959 data = (lookup_service < 0) ?
960 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
962 asprintf(&vfskey, "%s:%s", type, option);
966 if (strcmp(data->key, vfskey) == 0) {
973 if (lookup_service >= 0) {
974 /* Try to fetch the same option but from globals */
975 /* but only if we are not already working with Globals */
976 data = Globals.param_opt;
978 if (strcmp(data->key, vfskey) == 0) {
992 /*******************************************************************
993 convenience routine to return int parameters.
994 ********************************************************************/
995 static int lp_int(const char *s)
999 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1003 return strtol(s, NULL, 0);
1006 /*******************************************************************
1007 convenience routine to return unsigned long parameters.
1008 ********************************************************************/
1009 static int lp_ulong(const char *s)
1013 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1017 return strtoul(s, NULL, 0);
1020 /*******************************************************************
1021 convenience routine to return unsigned long parameters.
1022 ********************************************************************/
1023 static double lp_double(const char *s)
1027 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
1031 return strtod(s, NULL);
1034 /*******************************************************************
1035 convenience routine to return boolean parameters.
1036 ********************************************************************/
1037 static BOOL lp_bool(const char *s)
1042 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1046 if (!set_boolean(s, &ret)) {
1047 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1055 /* Return parametric option from a given service. Type is a part of option before ':' */
1056 /* Parametric option has following syntax: 'Type: option = value' */
1057 /* Returned value is allocated in 'lp_talloc' context */
1059 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1061 const char *value = lp_get_parametric(lookup_service, type, option);
1064 return lp_string(value);
1069 /* Return parametric option from a given service. Type is a part of option before ':' */
1070 /* Parametric option has following syntax: 'Type: option = value' */
1071 /* Returned value is allocated in 'lp_talloc' context */
1073 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1074 const char *separator)
1076 const char *value = lp_get_parametric(lookup_service, type, option);
1079 return str_list_make(talloc_autofree_context(), value, separator);
1084 /* Return parametric option from a given service. Type is a part of option before ':' */
1085 /* Parametric option has following syntax: 'Type: option = value' */
1087 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1089 const char *value = lp_get_parametric(lookup_service, type, option);
1092 return lp_int(value);
1097 /* Return parametric option from a given service. Type is a part of
1098 * option before ':'.
1099 * Parametric option has following syntax: 'Type: option = value'.
1102 int lp_parm_bytes(int lookup_service, const char *type, const char *option, int default_v)
1106 const char *value = lp_get_parametric(lookup_service, type, option);
1108 if (value && conv_str_size(value, &bval)) {
1109 if (bval <= INT_MAX) {
1117 /* Return parametric option from a given service. Type is a part of option before ':' */
1118 /* Parametric option has following syntax: 'Type: option = value' */
1120 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1122 const char *value = lp_get_parametric(lookup_service, type, option);
1125 return lp_ulong(value);
1131 double lp_parm_double(int lookup_service, const char *type, const char *option, double default_v)
1133 const char *value = lp_get_parametric(lookup_service, type, option);
1136 return lp_double(value);
1141 /* Return parametric option from a given service. Type is a part of option before ':' */
1142 /* Parametric option has following syntax: 'Type: option = value' */
1144 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1146 const char *value = lp_get_parametric(lookup_service, type, option);
1149 return lp_bool(value);
1155 /***************************************************************************
1156 Initialise a service to the defaults.
1157 ***************************************************************************/
1159 static void init_service(service * pservice)
1161 memset((char *)pservice, '\0', sizeof(service));
1162 copy_service(pservice, &sDefault, NULL);
1165 /***************************************************************************
1166 Free the dynamically allocated parts of a service struct.
1167 ***************************************************************************/
1169 static void free_service(service *pservice)
1172 struct param_opt *data, *pdata;
1176 if (pservice->szService)
1177 DEBUG(5, ("free_service: Freeing service %s\n",
1178 pservice->szService));
1180 string_free(&pservice->szService);
1181 SAFE_FREE(pservice->copymap);
1183 for (i = 0; parm_table[i].label; i++) {
1184 if ((parm_table[i].type == P_STRING ||
1185 parm_table[i].type == P_USTRING) &&
1186 parm_table[i].class == P_LOCAL) {
1187 string_free((char **)
1188 (((char *)pservice) +
1189 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1190 } else if (parm_table[i].type == P_LIST &&
1191 parm_table[i].class == P_LOCAL) {
1192 char ***listp = (char ***)(((char *)pservice) +
1193 PTR_DIFF(parm_table[i].ptr, &sDefault));
1194 talloc_free(*listp);
1199 DEBUG(5,("Freeing parametrics:\n"));
1200 data = pservice->param_opt;
1202 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1203 string_free(&data->key);
1204 string_free(&data->value);
1210 ZERO_STRUCTP(pservice);
1213 /***************************************************************************
1214 Add a new service to the services array initialising it with the given
1216 ***************************************************************************/
1218 static int add_a_service(const service *pservice, const char *name)
1222 int num_to_alloc = iNumServices + 1;
1223 struct param_opt *data, *pdata;
1225 tservice = *pservice;
1227 /* it might already exist */
1229 i = getservicebyname(name, NULL);
1231 /* Clean all parametric options for service */
1232 /* They will be added during parsing again */
1233 data = ServicePtrs[i]->param_opt;
1235 string_free(&data->key);
1236 string_free(&data->value);
1241 ServicePtrs[i]->param_opt = NULL;
1246 /* find an invalid one */
1247 for (i = 0; i < iNumServices; i++)
1248 if (!ServicePtrs[i]->valid)
1251 /* if not, then create one */
1252 if (i == iNumServices) {
1255 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1258 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1263 ServicePtrs[iNumServices] = malloc_p(service);
1265 if (!ServicePtrs[iNumServices]) {
1266 DEBUG(0,("add_a_service: out of memory!\n"));
1272 free_service(ServicePtrs[i]);
1274 ServicePtrs[i]->valid = True;
1276 init_service(ServicePtrs[i]);
1277 copy_service(ServicePtrs[i], &tservice, NULL);
1279 string_set(&ServicePtrs[i]->szService, name);
1283 /***************************************************************************
1284 Add a new home service, with the specified home directory, defaults coming
1286 ***************************************************************************/
1288 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1289 const char *user, const char *pszHomedir)
1294 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1299 if (!(*(ServicePtrs[iDefaultService]->szPath))
1300 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1301 pstrcpy(newHomedir, pszHomedir);
1303 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1304 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1307 string_set(&ServicePtrs[i]->szPath, newHomedir);
1309 if (!(*(ServicePtrs[i]->comment))) {
1311 slprintf(comment, sizeof(comment) - 1,
1312 "Home directory of %s", user);
1313 string_set(&ServicePtrs[i]->comment, comment);
1315 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1316 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1318 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1324 /***************************************************************************
1325 Add a new service, based on an old one.
1326 ***************************************************************************/
1328 int lp_add_service(const char *pszService, int iDefaultService)
1330 return (add_a_service(ServicePtrs[iDefaultService], pszService));
1333 /***************************************************************************
1334 Add the IPC service.
1335 ***************************************************************************/
1337 static BOOL lp_add_hidden(const char *name, const char *fstype)
1340 int i = add_a_service(&sDefault, name);
1345 slprintf(comment, sizeof(comment) - 1,
1346 "%s Service (%s)", fstype, Globals.szServerString);
1348 string_set(&ServicePtrs[i]->szPath, tmpdir());
1349 string_set(&ServicePtrs[i]->comment, comment);
1350 string_set(&ServicePtrs[i]->fstype, fstype);
1351 ServicePtrs[i]->iMaxConnections = -1;
1352 ServicePtrs[i]->bAvailable = True;
1353 ServicePtrs[i]->bRead_only = True;
1354 ServicePtrs[i]->bPrint_ok = False;
1355 ServicePtrs[i]->bBrowseable = False;
1357 if (strcasecmp(fstype, "IPC") == 0) {
1358 lp_do_parameter(i, "ntvfs handler", "default");
1361 DEBUG(3, ("adding hidden service %s\n", name));
1366 /***************************************************************************
1367 Add a new printer service, with defaults coming from service iFrom.
1368 ***************************************************************************/
1370 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
1372 const char *comment = "From Printcap";
1373 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1378 /* note that we do NOT default the availability flag to True - */
1379 /* we take it from the default service passed. This allows all */
1380 /* dynamic printers to be disabled by disabling the [printers] */
1381 /* entry (if/when the 'available' keyword is implemented!). */
1383 /* the printer name is set to the service name. */
1384 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1385 string_set(&ServicePtrs[i]->comment, comment);
1386 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1387 /* Printers cannot be read_only. */
1388 ServicePtrs[i]->bRead_only = False;
1389 /* Printer services must be printable. */
1390 ServicePtrs[i]->bPrint_ok = True;
1392 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1397 /***************************************************************************
1398 Map a parameter's string representation to something we can use.
1399 Returns False if the parameter string is not recognised, else TRUE.
1400 ***************************************************************************/
1402 static int map_parameter(const char *pszParmName)
1406 if (*pszParmName == '-')
1409 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1410 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1413 /* Warn only if it isn't parametric option */
1414 if (strchr(pszParmName, ':') == NULL)
1415 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1416 /* We do return 'fail' for parametric options as well because they are
1417 stored in different storage
1424 return the parameter structure for a parameter
1426 struct parm_struct *lp_parm_struct(const char *name)
1428 int parmnum = map_parameter(name);
1429 if (parmnum == -1) return NULL;
1430 return &parm_table[parmnum];
1434 return the parameter pointer for a parameter
1436 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1441 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1444 /***************************************************************************
1445 Find a service by name. Otherwise works like get_service.
1446 ***************************************************************************/
1448 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1452 for (iService = iNumServices - 1; iService >= 0; iService--)
1453 if (VALID(iService) &&
1454 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1455 if (pserviceDest != NULL)
1456 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1463 /***************************************************************************
1464 Copy a service structure to another.
1465 If pcopymapDest is NULL then copy all fields
1466 ***************************************************************************/
1468 static void copy_service(service * pserviceDest, service * pserviceSource, int *pcopymapDest)
1471 BOOL bcopyall = (pcopymapDest == NULL);
1472 struct param_opt *data, *pdata, *paramo;
1475 for (i = 0; parm_table[i].label; i++)
1476 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1477 (bcopyall || pcopymapDest[i])) {
1478 void *def_ptr = parm_table[i].ptr;
1480 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1483 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1486 switch (parm_table[i].type) {
1488 *(int *)dest_ptr = *(int *)src_ptr;
1493 *(int *)dest_ptr = *(int *)src_ptr;
1497 string_set(dest_ptr,
1502 string_set(dest_ptr,
1504 strupper(*(char **)dest_ptr);
1507 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1508 *(const char ***)src_ptr);
1516 init_copymap(pserviceDest);
1517 if (pserviceSource->copymap)
1518 memcpy((void *)pserviceDest->copymap,
1519 (void *)pserviceSource->copymap,
1520 sizeof(int) * NUMPARAMETERS);
1523 data = pserviceSource->param_opt;
1526 pdata = pserviceDest->param_opt;
1527 /* Traverse destination */
1529 /* If we already have same option, override it */
1530 if (strcmp(pdata->key, data->key) == 0) {
1531 string_free(&pdata->value);
1532 pdata->value = strdup(data->value);
1536 pdata = pdata->next;
1539 paramo = malloc_p(struct param_opt);
1542 paramo->key = strdup(data->key);
1543 paramo->value = strdup(data->value);
1544 DLIST_ADD(pserviceDest->param_opt, paramo);
1550 /***************************************************************************
1551 Check a service for consistency. Return False if the service is in any way
1552 incomplete or faulty, else True.
1553 ***************************************************************************/
1555 static BOOL service_ok(int iService)
1560 if (ServicePtrs[iService]->szService[0] == '\0') {
1561 DEBUG(0, ("The following message indicates an internal error:\n"));
1562 DEBUG(0, ("No service name in service entry.\n"));
1566 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1567 /* I can't see why you'd want a non-printable printer service... */
1568 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1569 if (!ServicePtrs[iService]->bPrint_ok) {
1570 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1571 ServicePtrs[iService]->szService));
1572 ServicePtrs[iService]->bPrint_ok = True;
1574 /* [printers] service must also be non-browsable. */
1575 if (ServicePtrs[iService]->bBrowseable)
1576 ServicePtrs[iService]->bBrowseable = False;
1579 /* If a service is flagged unavailable, log the fact at level 0. */
1580 if (!ServicePtrs[iService]->bAvailable)
1581 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1582 ServicePtrs[iService]->szService));
1587 static struct file_lists {
1588 struct file_lists *next;
1592 } *file_lists = NULL;
1594 /*******************************************************************
1595 Keep a linked list of all config files so we know when one has changed
1596 it's date and needs to be reloaded.
1597 ********************************************************************/
1599 static void add_to_file_list(const char *fname, const char *subfname)
1601 struct file_lists *f = file_lists;
1604 if (f->name && !strcmp(f->name, fname))
1610 f = malloc_p(struct file_lists);
1613 f->next = file_lists;
1614 f->name = strdup(fname);
1619 f->subfname = strdup(subfname);
1625 f->modtime = file_modtime(subfname);
1627 time_t t = file_modtime(subfname);
1633 /*******************************************************************
1634 Check if a config file has changed date.
1635 ********************************************************************/
1637 BOOL lp_file_list_changed(void)
1639 struct file_lists *f = file_lists;
1640 DEBUG(6, ("lp_file_list_changed()\n"));
1646 pstrcpy(n2, f->name);
1647 standard_sub_basic(n2,sizeof(n2));
1649 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1650 f->name, n2, ctime(&f->modtime)));
1652 mod_time = file_modtime(n2);
1654 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1656 ("file %s modified: %s\n", n2,
1658 f->modtime = mod_time;
1659 SAFE_FREE(f->subfname);
1660 f->subfname = strdup(n2);
1668 /***************************************************************************
1669 Handle the include operation.
1670 ***************************************************************************/
1672 static BOOL handle_include(const char *pszParmValue, char **ptr)
1675 pstrcpy(fname, pszParmValue);
1677 standard_sub_basic(fname,sizeof(fname));
1679 add_to_file_list(pszParmValue, fname);
1681 string_set(ptr, fname);
1683 if (file_exist(fname))
1684 return (pm_process(fname, do_section, do_parameter, NULL));
1686 DEBUG(2, ("Can't find include file %s\n", fname));
1691 /***************************************************************************
1692 Handle the interpretation of the copy parameter.
1693 ***************************************************************************/
1695 static BOOL handle_copy(const char *pszParmValue, char **ptr)
1699 service serviceTemp;
1701 string_set(ptr, pszParmValue);
1703 init_service(&serviceTemp);
1707 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1709 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
1710 if (iTemp == iServiceIndex) {
1711 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1713 copy_service(ServicePtrs[iServiceIndex],
1715 ServicePtrs[iServiceIndex]->copymap);
1719 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1723 free_service(&serviceTemp);
1727 /***************************************************************************
1728 Initialise a copymap.
1729 ***************************************************************************/
1731 static void init_copymap(service * pservice)
1734 SAFE_FREE(pservice->copymap);
1735 pservice->copymap = malloc_array_p(int, NUMPARAMETERS);
1736 if (!pservice->copymap)
1738 ("Couldn't allocate copymap!! (size %d)\n",
1739 (int)NUMPARAMETERS));
1741 for (i = 0; i < NUMPARAMETERS; i++)
1742 pservice->copymap[i] = True;
1745 #if 0 /* not used anywhere */
1746 /***************************************************************************
1747 Return the local pointer to a parameter given the service number and the
1748 pointer into the default structure.
1749 ***************************************************************************/
1751 void *lp_local_ptr(int snum, void *ptr)
1753 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1757 /***************************************************************************
1758 Process a parametric option
1759 ***************************************************************************/
1760 static BOOL lp_do_parameter_parametric(int snum, const char *pszParmName, const char *pszParmValue, int flags)
1762 struct param_opt *paramo, *data;
1765 while (isspace((unsigned char)*pszParmName)) {
1769 name = strdup(pszParmName);
1770 if (!name) return False;
1775 data = Globals.param_opt;
1777 data = ServicePtrs[snum]->param_opt;
1780 /* Traverse destination */
1781 for (paramo=data; paramo; paramo=paramo->next) {
1782 /* If we already have the option set, override it unless
1783 it was a command line option and the new one isn't */
1784 if (strcmp(paramo->key, name) == 0) {
1785 if ((paramo->flags & FLAG_CMDLINE) &&
1786 !(flags & FLAG_CMDLINE)) {
1790 free(paramo->value);
1791 paramo->value = strdup(pszParmValue);
1792 paramo->flags = flags;
1798 paramo = malloc_p(struct param_opt);
1801 paramo->key = strdup(name);
1802 paramo->value = strdup(pszParmValue);
1803 paramo->flags = flags;
1805 DLIST_ADD(Globals.param_opt, paramo);
1807 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1815 /***************************************************************************
1816 Process a parameter for a particular service number. If snum < 0
1817 then assume we are in the globals.
1818 ***************************************************************************/
1819 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1822 void *parm_ptr = NULL; /* where we are going to store the result */
1823 void *def_ptr = NULL;
1825 parmnum = map_parameter(pszParmName);
1828 if (strchr(pszParmName, ':')) {
1829 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1831 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1835 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1836 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1840 /* if the flag has been set on the command line, then don't allow override,
1841 but don't report an error */
1842 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1846 def_ptr = parm_table[parmnum].ptr;
1848 /* we might point at a service, the default service or a global */
1852 if (parm_table[parmnum].class == P_GLOBAL) {
1854 ("Global parameter %s found in service section!\n",
1859 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1864 if (!ServicePtrs[snum]->copymap)
1865 init_copymap(ServicePtrs[snum]);
1867 /* this handles the aliases - set the copymap for other entries with
1868 the same data pointer */
1869 for (i = 0; parm_table[i].label; i++)
1870 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1871 ServicePtrs[snum]->copymap[i] = False;
1874 /* if it is a special case then go ahead */
1875 if (parm_table[parmnum].special) {
1876 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1880 /* now switch on the type of variable it is */
1881 switch (parm_table[parmnum].type)
1885 if (!set_boolean(pszParmValue, &b)) {
1886 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1889 *(int *)parm_ptr = b;
1894 *(int *)parm_ptr = atoi(pszParmValue);
1900 if (conv_str_size(pszParmValue, &val)) {
1901 if (val <= INT_MAX) {
1902 *(int *)parm_ptr = (int)val;
1907 DEBUG(0,("lp_do_parameter(%s): value is not "
1908 "a valid size specifier!\n", pszParmValue));
1913 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1914 pszParmValue, NULL);
1918 string_set(parm_ptr, pszParmValue);
1922 string_set(parm_ptr, pszParmValue);
1923 strupper(*(char **)parm_ptr);
1927 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1930 parm_table[parmnum].enum_list[i].name)) {
1932 parm_table[parmnum].
1937 if (!parm_table[parmnum].enum_list[i].name) {
1938 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1939 pszParmValue, pszParmName));
1947 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1948 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1949 /* we have to also unset FLAG_DEFAULT on aliases */
1950 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1951 parm_table[i].flags &= ~FLAG_DEFAULT;
1953 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1954 parm_table[i].flags &= ~FLAG_DEFAULT;
1961 /***************************************************************************
1962 Process a parameter.
1963 ***************************************************************************/
1965 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1967 return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1968 pszParmName, pszParmValue));
1972 variable argument do parameter
1974 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1976 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
1983 s = talloc_vasprintf(NULL, fmt, ap);
1985 ret = do_parameter(pszParmName, s, NULL);
1992 set a parameter from the commandline - this is called from command line parameter
1993 parsing code. It sets the parameter then marks the parameter as unable to be modified
1994 by smb.conf processing
1996 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
1998 int parmnum = map_parameter(pszParmName);
2001 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
2004 if (parmnum < 0 && strchr(pszParmName, ':')) {
2005 /* set a parametric option */
2006 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
2010 DEBUG(0,("Unknown option '%s'\n", pszParmName));
2014 /* reset the CMDLINE flag in case this has been called before */
2015 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
2017 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
2021 parm_table[parmnum].flags |= FLAG_CMDLINE;
2023 /* we have to also set FLAG_CMDLINE on aliases */
2024 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
2025 parm_table[i].flags |= FLAG_CMDLINE;
2027 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
2028 parm_table[i].flags |= FLAG_CMDLINE;
2035 set a option from the commandline in 'a=b' format. Use to support --option
2037 BOOL lp_set_option(const char *option)
2055 ret = lp_set_cmdline(s, p+1);
2061 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2063 /***************************************************************************
2064 Print a parameter of the specified type.
2065 ***************************************************************************/
2067 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2073 for (i = 0; p->enum_list[i].name; i++) {
2074 if (*(int *)ptr == p->enum_list[i].value) {
2076 p->enum_list[i].name);
2083 fprintf(f, "%s", BOOLSTR((BOOL)*(int *)ptr));
2088 fprintf(f, "%d", *(int *)ptr);
2092 if ((char ***)ptr && *(char ***)ptr) {
2093 char **list = *(char ***)ptr;
2095 for (; *list; list++)
2096 fprintf(f, "%s%s", *list,
2097 ((*(list+1))?", ":""));
2103 if (*(char **)ptr) {
2104 fprintf(f, "%s", *(char **)ptr);
2112 /***************************************************************************
2113 Check if two parameters are equal.
2114 ***************************************************************************/
2116 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2120 return (*((int *)ptr1) == *((int *)ptr2));
2125 return (*((int *)ptr1) == *((int *)ptr2));
2128 return str_list_equal((const char **)(*(char ***)ptr1),
2129 (const char **)(*(char ***)ptr2));
2134 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2139 return (p1 == p2 || strequal(p1, p2));
2147 /***************************************************************************
2148 Process a new section (service). At this stage all sections are services.
2149 Later we'll have special sections that permit server parameters to be set.
2150 Returns True on success, False on failure.
2151 ***************************************************************************/
2153 static BOOL do_section(const char *pszSectionName, void *userdata)
2156 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2157 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2160 /* if we've just struck a global section, note the fact. */
2161 bInGlobalSection = isglobal;
2163 /* check for multiple global sections */
2164 if (bInGlobalSection) {
2165 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2169 /* if we have a current service, tidy it up before moving on */
2172 if (iServiceIndex >= 0)
2173 bRetval = service_ok(iServiceIndex);
2175 /* if all is still well, move to the next record in the services array */
2177 /* We put this here to avoid an odd message order if messages are */
2178 /* issued by the post-processing of a previous section. */
2179 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2181 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2183 DEBUG(0, ("Failed to add a new service\n"));
2192 /***************************************************************************
2193 Determine if a partcular base parameter is currentl set to the default value.
2194 ***************************************************************************/
2196 static BOOL is_default(int i)
2198 if (!defaults_saved)
2200 switch (parm_table[i].type) {
2202 return str_list_equal((const char **)parm_table[i].def.lvalue,
2203 (const char **)(*(char ***)parm_table[i].ptr));
2206 return strequal(parm_table[i].def.svalue,
2207 *(char **)parm_table[i].ptr);
2209 return parm_table[i].def.bvalue ==
2210 *(int *)parm_table[i].ptr;
2214 return parm_table[i].def.ivalue ==
2215 *(int *)parm_table[i].ptr;
2222 /***************************************************************************
2223 Display the contents of the global structure.
2224 ***************************************************************************/
2226 static void dump_globals(FILE *f, BOOL show_defaults)
2229 struct param_opt *data;
2231 fprintf(f, "# Global parameters\n[global]\n");
2233 for (i = 0; parm_table[i].label; i++)
2234 if (parm_table[i].class == P_GLOBAL &&
2235 parm_table[i].ptr &&
2236 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2237 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2239 fprintf(f, "\t%s = ", parm_table[i].label);
2240 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2243 if (Globals.param_opt != NULL) {
2244 data = Globals.param_opt;
2246 fprintf(f, "\t%s = %s\n", data->key, data->value);
2253 /***************************************************************************
2254 Display the contents of a single services record.
2255 ***************************************************************************/
2257 static void dump_a_service(service * pService, FILE * f)
2260 struct param_opt *data;
2262 if (pService != &sDefault)
2263 fprintf(f, "\n[%s]\n", pService->szService);
2265 for (i = 0; parm_table[i].label; i++)
2266 if (parm_table[i].class == P_LOCAL &&
2267 parm_table[i].ptr &&
2268 (*parm_table[i].label != '-') &&
2269 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2270 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2272 if (pService == &sDefault) {
2273 if (defaults_saved && is_default(i))
2276 if (equal_parameter(parm_table[i].type,
2277 ((char *)pService) +
2279 ((char *)&sDefault) +
2284 fprintf(f, "\t%s = ", parm_table[i].label);
2285 print_parameter(&parm_table[i],
2286 ((char *)pService) + pdiff, f);
2289 if (pService->param_opt != NULL) {
2290 data = pService->param_opt;
2292 fprintf(f, "\t%s = %s\n", data->key, data->value);
2298 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2300 service * pService = ServicePtrs[snum];
2301 struct parm_struct *parm;
2304 parm = lp_parm_struct(parm_name);
2312 ptr = ((char *)pService) +
2313 PTR_DIFF(parm->ptr, &sDefault);
2315 print_parameter(parm,
2321 /***************************************************************************
2322 Return info about the next service in a service. snum==-1 gives the globals.
2323 Return NULL when out of parameters.
2324 ***************************************************************************/
2326 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2329 /* do the globals */
2330 for (; parm_table[*i].label; (*i)++) {
2331 if (parm_table[*i].class == P_SEPARATOR)
2332 return &parm_table[(*i)++];
2334 if (!parm_table[*i].ptr
2335 || (*parm_table[*i].label == '-'))
2339 && (parm_table[*i].ptr ==
2340 parm_table[(*i) - 1].ptr))
2343 return &parm_table[(*i)++];
2346 service *pService = ServicePtrs[snum];
2348 for (; parm_table[*i].label; (*i)++) {
2349 if (parm_table[*i].class == P_SEPARATOR)
2350 return &parm_table[(*i)++];
2352 if (parm_table[*i].class == P_LOCAL &&
2353 parm_table[*i].ptr &&
2354 (*parm_table[*i].label != '-') &&
2356 (parm_table[*i].ptr !=
2357 parm_table[(*i) - 1].ptr)))
2360 PTR_DIFF(parm_table[*i].ptr,
2363 if (allparameters ||
2364 !equal_parameter(parm_table[*i].type,
2365 ((char *)pService) +
2367 ((char *)&sDefault) +
2370 return &parm_table[(*i)++];
2380 /***************************************************************************
2381 Return TRUE if the passed service number is within range.
2382 ***************************************************************************/
2384 BOOL lp_snum_ok(int iService)
2386 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2389 /***************************************************************************
2390 Auto-load some home services.
2391 ***************************************************************************/
2393 static void lp_add_auto_services(const char *str)
2398 /***************************************************************************
2399 Have we loaded a services file yet?
2400 ***************************************************************************/
2402 BOOL lp_loaded(void)
2407 /***************************************************************************
2408 Unload unused services.
2409 ***************************************************************************/
2411 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2414 for (i = 0; i < iNumServices; i++) {
2418 if (!snumused || !snumused(smb, i)) {
2419 ServicePtrs[i]->valid = False;
2420 free_service(ServicePtrs[i]);
2425 /***************************************************************************
2427 ***************************************************************************/
2429 void lp_killservice(int iServiceIn)
2431 if (VALID(iServiceIn)) {
2432 ServicePtrs[iServiceIn]->valid = False;
2433 free_service(ServicePtrs[iServiceIn]);
2437 /***************************************************************************
2438 Load the services array from the services file. Return True on success,
2440 ***************************************************************************/
2446 struct param_opt *data;
2450 bInGlobalSection = True;
2452 if (Globals.param_opt != NULL) {
2453 struct param_opt *next;
2454 for (data=Globals.param_opt; data; data=next) {
2456 if (data->flags & FLAG_CMDLINE) continue;
2459 DLIST_REMOVE(Globals.param_opt, data);
2466 pstrcpy(n2, lp_configfile());
2467 standard_sub_basic(n2,sizeof(n2));
2468 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2470 add_to_file_list(lp_configfile(), n2);
2472 /* We get sections first, so have to start 'behind' to make up */
2474 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2476 /* finish up the last section */
2477 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2479 if (iServiceIndex >= 0)
2480 bRetval = service_ok(iServiceIndex);
2482 lp_add_auto_services(lp_auto_services());
2484 lp_add_hidden("IPC$", "IPC");
2485 lp_add_hidden("ADMIN$", "DISK");
2489 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2490 lp_do_parameter(-1, "wins server", "127.0.0.1");
2498 /***************************************************************************
2499 Reset the max number of services.
2500 ***************************************************************************/
2502 void lp_resetnumservices(void)
2507 /***************************************************************************
2508 Return the max number of services.
2509 ***************************************************************************/
2511 int lp_numservices(void)
2513 return (iNumServices);
2516 /***************************************************************************
2517 Display the contents of the services array in human-readable form.
2518 ***************************************************************************/
2520 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2525 defaults_saved = False;
2527 dump_globals(f, show_defaults);
2529 dump_a_service(&sDefault, f);
2531 for (iService = 0; iService < maxtoprint; iService++)
2532 lp_dump_one(f, show_defaults, iService);
2535 /***************************************************************************
2536 Display the contents of one service in human-readable form.
2537 ***************************************************************************/
2539 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
2542 if (ServicePtrs[snum]->szService[0] == '\0')
2544 dump_a_service(ServicePtrs[snum], f);
2548 /***************************************************************************
2549 Return the number of the service with the given name, or -1 if it doesn't
2550 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2551 getservicebyname()! This works ONLY if all services have been loaded, and
2552 does not copy the found service.
2553 ***************************************************************************/
2555 int lp_servicenumber(const char *pszServiceName)
2558 fstring serviceName;
2561 for (iService = iNumServices - 1; iService >= 0; iService--) {
2562 if (VALID(iService) && ServicePtrs[iService]->szService) {
2564 * The substitution here is used to support %U is
2567 fstrcpy(serviceName, ServicePtrs[iService]->szService);
2568 standard_sub_basic(serviceName,sizeof(serviceName));
2569 if (strequal(serviceName, pszServiceName))
2575 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2580 int lp_find_valid_service(const char *pszServiceName)
2584 iService = lp_servicenumber(pszServiceName);
2586 if (iService >= 0 && !lp_snum_ok(iService)) {
2587 DEBUG(0,("lp_find_valid_service: Invalid snum %d for '%s'\n",iService, pszServiceName));
2591 if (iService == -1) {
2592 DEBUG(3,("lp_find_valid_service: failed to find service '%s'\n", pszServiceName));
2598 /*******************************************************************
2599 A useful volume label function.
2600 ********************************************************************/
2601 const char *volume_label(int snum)
2603 const char *ret = lp_volume(snum);
2605 return lp_servicename(snum);
2610 /***********************************************************
2611 If we are PDC then prefer us as DMB
2612 ************************************************************/
2614 BOOL lp_domain_logons(void)
2616 return (lp_server_role() == ROLE_DOMAIN_CONTROLLER);
2619 /*******************************************************************
2621 ********************************************************************/
2623 void lp_remove_service(int snum)
2625 ServicePtrs[snum]->valid = False;
2628 /*******************************************************************
2630 ********************************************************************/
2632 void lp_copy_service(int snum, const char *new_name)
2634 const char *oldname = lp_servicename(snum);
2635 do_section(new_name, NULL);
2637 snum = lp_servicenumber(new_name);
2639 lp_do_parameter(snum, "copy", oldname);
2643 const char *lp_printername(int snum)
2645 const char *ret = _lp_printername(snum);
2646 if (ret == NULL || (ret != NULL && *ret == '\0'))
2647 ret = lp_const_servicename(snum);
2653 /*******************************************************************
2654 Return the max print jobs per queue.
2655 ********************************************************************/
2657 int lp_maxprintjobs(int snum)
2659 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2660 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2661 maxjobs = PRINT_MAX_JOBID - 1;