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>
13 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 3 of the License, or
18 (at your option) any later version.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program. If not, see <http://www.gnu.org/licenses/>.
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"
58 #include "system/time.h"
59 #include "system/locale.h"
60 #include "system/network.h" /* needed for TCP_NODELAY */
61 #include "smb_server/smb_server.h"
62 #include "libcli/raw/signing.h"
63 #include "lib/util/dlinklist.h"
64 #include "param/loadparm.h"
67 static bool bLoaded = false;
69 #define standard_sub_basic strdup
71 /* some helpful bits */
72 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && VALID(i))
73 #define VALID(i) (ServicePtrs[i] != NULL)
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;
81 struct param_opt *prev, *next;
88 * This structure describes global (ie., server-wide) parameters.
92 enum server_role server_role;
100 char *szServerString;
101 char *szAutoServices;
104 char *szShareBackend;
108 char *szWINS_CONFIG_URL;
112 char *jsonrpcServicesDir;
113 char **szPasswordServers;
114 char *szSocketOptions;
116 char **szWINSservers;
118 char *szSocketAddress;
119 char *szAnnounceVersion; /* This is initialised in init_globals */
122 char **szNetbiosAliases;
123 char *szNetbiosScope;
124 char *szDomainOtherSIDs;
125 char **szNameResolveOrder;
126 char **dcerpc_ep_servers;
127 char **server_services;
128 char *ntptr_providor;
129 char *szWinbindSeparator;
130 char *szWinbinddSocketDirectory;
131 char *szTemplateShell;
132 char *szTemplateHomedir;
133 int bWinbindSealedPipes;
134 char *webapps_directory;
149 int paranoid_server_security;
152 int announce_as; /* This is initialised in init_globals */
159 char *socket_options;
164 int bPreferredMaster;
165 int bEncryptPasswords;
167 int bObeyPamRestrictions;
172 int bBindInterfacesOnly;
174 int bNTStatusSupport;
180 int bClientPlaintextAuth;
181 int bClientLanManAuth;
182 int bClientNTLMv2Auth;
183 int client_use_spnego_principal;
189 struct param_opt *param_opt;
193 static global Globals;
196 * This structure describes a single service.
210 char **ntvfs_handler;
223 int iCreate_force_mode;
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 = {
239 NULL, /* szService */
242 NULL, /* szInclude */
243 NULL, /* szPrintername */
244 NULL, /* szHostsallow */
245 NULL, /* szHostsdeny */
249 NULL, /* ntvfs_handler */
250 1000, /* iMaxPrintJobs */
251 0, /* iMaxConnections */
253 True, /* bAvailable */
254 True, /* bBrowseable */
255 True, /* bRead_only */
256 False, /* bPrint_ok */
257 False, /* bMap_system */
258 False, /* bMap_hidden */
259 True, /* bMap_archive */
260 True, /* bStrictLocking */
261 0744, /* iCreate_mask */
262 0000, /* iCreate_force_mode */
263 0755, /* iDir_mask */
264 0000, /* iDir_force_mode */
266 False, /* bMSDfsRoot */
267 False, /* bStrictSync */
268 False, /* bCIFileSystem */
269 NULL, /* Parametric options */
274 /* local variables */
275 static service **ServicePtrs = NULL;
276 static int iNumServices = 0;
277 static int iServiceIndex = 0;
278 static bool bInGlobalSection = True;
280 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
282 /* prototypes for the special type handlers */
283 static bool handle_include(const char *pszParmValue, char **ptr);
284 static bool handle_copy(const char *pszParmValue, char **ptr);
286 static const struct enum_list enum_protocol[] = {
287 {PROTOCOL_SMB2, "SMB2"},
288 {PROTOCOL_NT1, "NT1"},
289 {PROTOCOL_LANMAN2, "LANMAN2"},
290 {PROTOCOL_LANMAN1, "LANMAN1"},
291 {PROTOCOL_CORE, "CORE"},
292 {PROTOCOL_COREPLUS, "COREPLUS"},
293 {PROTOCOL_COREPLUS, "CORE+"},
297 static const struct enum_list enum_security[] = {
298 {SEC_SHARE, "SHARE"},
303 static const struct enum_list enum_announce_as[] = {
304 {ANNOUNCE_AS_NT_SERVER, "NT"},
305 {ANNOUNCE_AS_NT_SERVER, "NT Server"},
306 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
307 {ANNOUNCE_AS_WIN95, "win95"},
308 {ANNOUNCE_AS_WFW, "WfW"},
312 static const struct enum_list enum_bool_auto[] = {
323 /* Client-side offline caching policy types */
324 #define CSC_POLICY_MANUAL 0
325 #define CSC_POLICY_DOCUMENTS 1
326 #define CSC_POLICY_PROGRAMS 2
327 #define CSC_POLICY_DISABLE 3
329 static const struct enum_list enum_csc_policy[] = {
330 {CSC_POLICY_MANUAL, "manual"},
331 {CSC_POLICY_DOCUMENTS, "documents"},
332 {CSC_POLICY_PROGRAMS, "programs"},
333 {CSC_POLICY_DISABLE, "disable"},
337 /* SMB signing types. */
338 static const struct enum_list enum_smb_signing_vals[] = {
339 {SMB_SIGNING_OFF, "No"},
340 {SMB_SIGNING_OFF, "False"},
341 {SMB_SIGNING_OFF, "0"},
342 {SMB_SIGNING_OFF, "Off"},
343 {SMB_SIGNING_OFF, "disabled"},
344 {SMB_SIGNING_SUPPORTED, "Yes"},
345 {SMB_SIGNING_SUPPORTED, "True"},
346 {SMB_SIGNING_SUPPORTED, "1"},
347 {SMB_SIGNING_SUPPORTED, "On"},
348 {SMB_SIGNING_SUPPORTED, "enabled"},
349 {SMB_SIGNING_REQUIRED, "required"},
350 {SMB_SIGNING_REQUIRED, "mandatory"},
351 {SMB_SIGNING_REQUIRED, "force"},
352 {SMB_SIGNING_REQUIRED, "forced"},
353 {SMB_SIGNING_REQUIRED, "enforced"},
354 {SMB_SIGNING_AUTO, "auto"},
358 static const struct enum_list enum_server_role[] = {
359 {ROLE_STANDALONE, "standalone"},
360 {ROLE_DOMAIN_MEMBER, "member server"},
361 {ROLE_DOMAIN_CONTROLLER, "domain controller"},
366 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
368 * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
369 * is implied in current control logic. This may change at some later time. A
370 * flag value of 0 means - show as development option only.
372 * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
373 * screen in SWAT. This is used to exclude parameters as well as to squash all
374 * parameters that have been duplicated by pseudonyms.
376 static struct parm_struct parm_table[] = {
377 {"Base Options", P_SEP, P_SEPARATOR},
379 {"server role", P_ENUM, P_GLOBAL, &Globals.server_role, NULL, enum_server_role, FLAG_BASIC},
381 {"dos charset", P_STRING, P_GLOBAL, &dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
382 {"unix charset", P_STRING, P_GLOBAL, &unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
383 {"ncalrpc dir", P_STRING, P_GLOBAL, &Globals.ncalrpc_dir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
384 {"display charset", P_STRING, P_GLOBAL, &display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
385 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
386 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
387 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
388 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
389 {"realm", P_STRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
390 {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
391 {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
392 {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
393 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
394 {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
395 {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
396 {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
397 {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
398 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
399 {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
401 {"Security Options", P_SEP, P_SEPARATOR},
403 {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
404 {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
405 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
406 {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
407 {"password server", P_LIST, P_GLOBAL, &Globals.szPasswordServers, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
408 {"sam database", P_STRING, P_GLOBAL, &Globals.szSAM_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
409 {"secrets database", P_STRING, P_GLOBAL, &Globals.szSECRETS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
410 {"spoolss database", P_STRING, P_GLOBAL, &Globals.szSPOOLSS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
411 {"wins config database", P_STRING, P_GLOBAL, &Globals.szWINS_CONFIG_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
412 {"wins database", P_STRING, P_GLOBAL, &Globals.szWINS_URL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
413 {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
414 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
415 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
416 {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
417 {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
418 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
419 {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
420 {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
421 {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
423 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
425 {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
426 {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
427 {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
428 {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
430 {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
431 {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
433 {"Logging Options", P_SEP, P_SEPARATOR},
435 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
436 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL, FLAG_HIDE},
437 {"log file", P_STRING, P_GLOBAL, &logfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
439 {"Protocol Options", P_SEP, P_SEPARATOR},
441 {"smb ports", P_LIST, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
442 {"nbt port", P_INTEGER, P_GLOBAL, &Globals.nbt_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
443 {"dgram port", P_INTEGER, P_GLOBAL, &Globals.dgram_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
444 {"cldap port", P_INTEGER, P_GLOBAL, &Globals.cldap_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
445 {"krb5 port", P_INTEGER, P_GLOBAL, &Globals.krb5_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
446 {"kpasswd port", P_INTEGER, P_GLOBAL, &Globals.kpasswd_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
447 {"web port", P_INTEGER, P_GLOBAL, &Globals.web_port, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
448 {"tls enabled", P_BOOL, P_GLOBAL, &Globals.tls_enabled, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
449 {"tls keyfile", P_STRING, P_GLOBAL, &Globals.tls_keyfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
450 {"tls certfile", P_STRING, P_GLOBAL, &Globals.tls_certfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
451 {"tls cafile", P_STRING, P_GLOBAL, &Globals.tls_cafile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
452 {"tls crlfile", P_STRING, P_GLOBAL, &Globals.tls_crlfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
453 {"tls dh params file", P_STRING, P_GLOBAL, &Globals.tls_dhpfile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
454 {"web application directory", P_STRING, P_GLOBAL, &Globals.webapps_directory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
455 {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
456 {"server max protocol", P_ENUM, P_GLOBAL, &Globals.srv_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
457 {"server min protocol", P_ENUM, P_GLOBAL, &Globals.srv_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
458 {"client max protocol", P_ENUM, P_GLOBAL, &Globals.cli_maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
459 {"client min protocol", P_ENUM, P_GLOBAL, &Globals.cli_minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
460 {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
461 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
462 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
463 {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
465 {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
467 {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
468 {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
469 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
470 {"max xmit", P_BYTES, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
472 {"name resolve order", P_LIST, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
473 {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
474 {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
475 {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
476 {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
477 {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
478 {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
479 {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
480 {"rpc big endian", P_BOOL, P_GLOBAL, &Globals.bRpcBigEndian, NULL, NULL, FLAG_DEVELOPER},
482 {"Tuning Options", P_SEP, P_SEPARATOR},
484 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
485 {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
486 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options, NULL, NULL, FLAG_DEVELOPER},
488 {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
489 {"case insensitive filesystem", P_BOOL, P_LOCAL, &sDefault.bCIFileSystem, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
491 {"Printing Options", P_SEP, P_SEPARATOR},
493 {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
494 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
495 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
497 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
498 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
500 {"Filename Handling", P_SEP, P_SEPARATOR},
502 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
503 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
504 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
506 {"Domain Options", P_SEP, P_SEPARATOR},
508 {"Logon Options", P_SEP, P_SEPARATOR},
511 {"Browse Options", P_SEP, P_SEPARATOR},
513 {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
514 {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
515 {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
516 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
517 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
519 {"WINS Options", P_SEP, P_SEPARATOR},
521 {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
522 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
523 {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bWINSdnsProxy, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
524 {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
526 {"Locking Options", P_SEP, P_SEPARATOR},
528 {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
530 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
532 {"Miscellaneous Options", P_SEP, P_SEPARATOR},
534 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
535 {"share backend", P_STRING, P_GLOBAL, &Globals.szShareBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
536 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
537 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
538 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE},
539 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
540 {"modules dir", P_STRING, P_GLOBAL, &Globals.szModulesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
541 {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
542 {"js include", P_LIST, P_GLOBAL, &Globals.jsInclude, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
543 {"jsonrpc services directory", P_STRING, P_GLOBAL, &Globals.jsonrpcServicesDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
544 {"setup directory", P_STRING, P_GLOBAL, &Globals.szSetupDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
546 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
547 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
548 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
550 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
551 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
552 {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
554 {"panic action", P_STRING, P_GLOBAL, &panic_action, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
556 {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
557 {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
558 {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
559 {"winbindd socket directory", P_STRING, P_GLOBAL, &Globals.szWinbinddSocketDirectory, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
560 {"winbind sealed pipes", P_BOOL, P_GLOBAL, &Globals.bWinbindSealedPipes, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
561 {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
562 {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
564 {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
569 return the parameter table
571 struct parm_struct *lp_parm_table(void)
576 /***************************************************************************
577 Initialise the global parameter structure.
578 ***************************************************************************/
579 static void init_globals(void)
584 DEBUG(3, ("Initialising global parameters\n"));
586 for (i = 0; parm_table[i].label; i++) {
587 if ((parm_table[i].type == P_STRING ||
588 parm_table[i].type == P_USTRING) &&
590 !(parm_table[i].flags & FLAG_CMDLINE)) {
591 string_set(parm_table[i].ptr, "");
595 do_parameter("config file", dyn_CONFIGFILE, NULL);
597 do_parameter("share backend", "classic", NULL);
599 do_parameter("server role", "standalone", NULL);
601 /* options that can be set on the command line must be initialised via
602 the slower do_parameter() to ensure that FLAG_CMDLINE is obeyed */
604 do_parameter("socket options", "TCP_NODELAY", NULL);
606 do_parameter("workgroup", DEFAULT_WORKGROUP, NULL);
607 myname = get_myname();
608 do_parameter("netbios name", myname, NULL);
610 do_parameter("name resolve order", "lmhosts wins host bcast", NULL);
612 do_parameter("fstype", FSTYPE_STRING, NULL);
613 do_parameter("ntvfs handler", "unixuid default", NULL);
614 do_parameter("max connections", "-1", NULL);
616 do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo", NULL);
617 do_parameter("server services", "smb rpc nbt wrepl ldap cldap web kdc drepl winbind", NULL);
618 do_parameter("ntptr providor", "simple_ldb", NULL);
619 do_parameter("auth methods:domain controller", "anonymous sam_ignoredomain", NULL);
620 do_parameter("auth methods:member server", "anonymous sam winbind", NULL);
621 do_parameter("auth methods:standalone", "anonymous sam_ignoredomain", NULL);
622 do_parameter("private dir", dyn_PRIVATE_DIR, NULL);
623 do_parameter("sam database", "sam.ldb", NULL);
624 do_parameter("secrets database", "secrets.ldb", NULL);
625 do_parameter("spoolss database", "spoolss.ldb", NULL);
626 do_parameter("wins config database", "wins_config.ldb", NULL);
627 do_parameter("wins database", "wins.ldb", NULL);
628 do_parameter("registry:HKEY_LOCAL_MACHINE", "hklm.ldb", NULL);
630 /* This hive should be dynamically generated by Samba using
631 data from the sam, but for the moment leave it in a tdb to
632 keep regedt32 from popping up an annoying dialog. */
633 do_parameter("registry:HKEY_USERS", "hku.ldb", NULL);
635 /* using UTF8 by default allows us to support all chars */
636 do_parameter("unix charset", "UTF8", NULL);
638 /* Use codepage 850 as a default for the dos character set */
639 do_parameter("dos charset", "CP850", NULL);
642 * Allow the default PASSWD_CHAT to be overridden in local.h.
644 do_parameter("passwd chat", DEFAULT_PASSWD_CHAT, NULL);
646 do_parameter("pid directory", dyn_PIDDIR, NULL);
647 do_parameter("lock dir", dyn_LOCKDIR, NULL);
648 do_parameter("modules dir", dyn_MODULESDIR, NULL);
649 do_parameter("ncalrpc dir", dyn_NCALRPCDIR, NULL);
651 do_parameter("socket address", "0.0.0.0", NULL);
652 do_parameter_var("server string", "Samba %s", SAMBA_VERSION_STRING);
654 do_parameter_var("announce version", "%d.%d",
655 DEFAULT_MAJOR_VERSION,
656 DEFAULT_MINOR_VERSION);
658 do_parameter("password server", "*", NULL);
660 do_parameter("max mux", "50", NULL);
661 do_parameter("max xmit", "12288", NULL);
662 do_parameter("password level", "0", NULL);
663 do_parameter("LargeReadwrite", "True", NULL);
664 do_parameter("server min protocol", "CORE", NULL);
665 do_parameter("server max protocol", "NT1", NULL);
666 do_parameter("client min protocol", "CORE", NULL);
667 do_parameter("client max protocol", "NT1", NULL);
668 do_parameter("security", "USER", NULL);
669 do_parameter("paranoid server security", "True", NULL);
670 do_parameter("EncryptPasswords", "True", NULL);
671 do_parameter("ReadRaw", "True", NULL);
672 do_parameter("WriteRaw", "True", NULL);
673 do_parameter("NullPasswords", "False", NULL);
674 do_parameter("ObeyPamRestrictions", "False", NULL);
675 do_parameter("announce as", "NT SERVER", NULL);
677 do_parameter("TimeServer", "False", NULL);
678 do_parameter("BindInterfacesOnly", "False", NULL);
679 do_parameter("Unicode", "True", NULL);
680 do_parameter("ClientLanManAuth", "True", NULL);
681 do_parameter("LanmanAuth", "True", NULL);
682 do_parameter("NTLMAuth", "True", NULL);
683 do_parameter("client use spnego principal", "False", NULL);
685 do_parameter("UnixExtensions", "False", NULL);
687 do_parameter("PreferredMaster", "Auto", NULL);
688 do_parameter("LocalMaster", "True", NULL);
690 do_parameter("wins support", "False", NULL);
691 do_parameter("dns proxy", "True", NULL);
693 do_parameter("winbind separator", "\\", NULL);
694 do_parameter("winbind sealed pipes", "True", NULL);
695 do_parameter("winbindd socket directory", dyn_WINBINDD_SOCKET_DIR, NULL);
696 do_parameter("template shell", "/bin/false", NULL);
697 do_parameter("template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%", NULL);
699 do_parameter("client signing", "Yes", NULL);
700 do_parameter("server signing", "auto", NULL);
702 do_parameter("use spnego", "True", NULL);
704 do_parameter("smb ports", "445 139", NULL);
705 do_parameter("nbt port", "137", NULL);
706 do_parameter("dgram port", "138", NULL);
707 do_parameter("cldap port", "389", NULL);
708 do_parameter("krb5 port", "88", NULL);
709 do_parameter("kpasswd port", "464", NULL);
710 do_parameter("web port", "901", NULL);
711 do_parameter("web application directory", dyn_WEBAPPSDIR, NULL);
712 do_parameter("jsonrpc services directory", dyn_SERVICESDIR, NULL);
714 do_parameter("nt status support", "True", NULL);
716 do_parameter("max wins ttl", "518400", NULL); /* 6 days */
717 do_parameter("min wins ttl", "10", NULL);
719 do_parameter("tls enabled", "True", NULL);
720 do_parameter("tls keyfile", "tls/key.pem", NULL);
721 do_parameter("tls certfile", "tls/cert.pem", NULL);
722 do_parameter("tls cafile", "tls/ca.pem", NULL);
723 do_parameter_var("js include", "%s", dyn_JSDIR);
724 do_parameter_var("setup directory", "%s", dyn_SETUPDIR);
726 for (i = 0; parm_table[i].label; i++) {
727 if (!(parm_table[i].flags & FLAG_CMDLINE)) {
728 parm_table[i].flags |= FLAG_DEFAULT;
733 static TALLOC_CTX *lp_talloc;
735 /******************************************************************* a
736 Free up temporary memory - called from the main loop.
737 ********************************************************************/
739 void lp_talloc_free(void)
743 talloc_free(lp_talloc);
747 /*******************************************************************
748 Convenience routine to grab string parameters into temporary memory
749 and run standard_sub_basic on them. The buffers can be written to by
750 callers without affecting the source string.
751 ********************************************************************/
753 static const char *lp_string(const char *s)
755 #if 0 /* until REWRITE done to make thread-safe */
756 size_t len = s ? strlen(s) : 0;
760 /* The follow debug is useful for tracking down memory problems
761 especially if you have an inner loop that is calling a lp_*()
762 function that returns a string. Perhaps this debug should be
763 present all the time? */
766 DEBUG(10, ("lp_string(%s)\n", s));
769 #if 0 /* until REWRITE done to make thread-safe */
771 lp_talloc = talloc_init("lp_talloc");
773 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */
781 strlcpy(ret, s, len);
783 if (trim_string(ret, "\"", "\"")) {
784 if (strchr(ret,'"') != NULL)
785 strlcpy(ret, s, len);
788 standard_sub_basic(ret,len+100);
795 In this section all the functions that are used to access the
796 parameters from the rest of the program are defined
799 #define FN_GLOBAL_STRING(fn_name,ptr) \
800 const char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
801 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
802 const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
803 #define FN_GLOBAL_LIST(fn_name,ptr) \
804 const char **fn_name(void) {return(*(const char ***)(ptr));}
805 #define FN_GLOBAL_BOOL(fn_name,ptr) \
806 BOOL fn_name(void) {return((BOOL)*(int *)(ptr));}
808 #define FN_GLOBAL_CHAR(fn_name,ptr) \
809 char fn_name(void) {return(*(char *)(ptr));}
811 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
812 int fn_name(void) {return(*(int *)(ptr));}
814 #define FN_LOCAL_STRING(fn_name,val) \
815 const char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
816 #define FN_LOCAL_CONST_STRING(fn_name,val) \
817 const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
818 #define FN_LOCAL_LIST(fn_name,val) \
819 const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
820 #define FN_LOCAL_BOOL(fn_name,val) \
821 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
823 #define FN_LOCAL_CHAR(fn_name,val) \
824 char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
826 #define FN_LOCAL_INTEGER(fn_name,val) \
827 int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
829 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_role, &Globals.server_role)
830 _PUBLIC_ FN_GLOBAL_LIST(lp_smb_ports, &Globals.smb_ports)
831 _PUBLIC_ FN_GLOBAL_INTEGER(lp_nbt_port, &Globals.nbt_port)
832 _PUBLIC_ FN_GLOBAL_INTEGER(lp_dgram_port, &Globals.dgram_port)
833 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cldap_port, &Globals.cldap_port)
834 _PUBLIC_ FN_GLOBAL_INTEGER(lp_krb5_port, &Globals.krb5_port)
835 _PUBLIC_ FN_GLOBAL_INTEGER(lp_kpasswd_port, &Globals.kpasswd_port)
836 _PUBLIC_ FN_GLOBAL_INTEGER(lp_web_port, &Globals.web_port)
837 _PUBLIC_ FN_GLOBAL_STRING(lp_dos_charset, &dos_charset)
838 _PUBLIC_ FN_GLOBAL_STRING(lp_webapps_directory, &Globals.webapps_directory)
839 _PUBLIC_ FN_GLOBAL_BOOL(lp_tls_enabled, &Globals.tls_enabled)
840 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_keyfile, &Globals.tls_keyfile)
841 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_certfile, &Globals.tls_certfile)
842 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_cafile, &Globals.tls_cafile)
843 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_crlfile, &Globals.tls_crlfile)
844 _PUBLIC_ FN_GLOBAL_STRING(lp_tls_dhpfile, &Globals.tls_dhpfile)
845 _PUBLIC_ FN_GLOBAL_STRING(lp_unix_charset, &unix_charset)
846 _PUBLIC_ FN_GLOBAL_STRING(lp_display_charset, &display_charset)
847 _PUBLIC_ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
848 _PUBLIC_ FN_GLOBAL_STRING(lp_share_backend, &Globals.szShareBackend)
849 _PUBLIC_ FN_GLOBAL_STRING(lp_sam_url, &Globals.szSAM_URL)
850 _PUBLIC_ FN_GLOBAL_STRING(lp_secrets_url, &Globals.szSECRETS_URL)
851 _PUBLIC_ FN_GLOBAL_STRING(lp_spoolss_url, &Globals.szSPOOLSS_URL)
852 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_config_url, &Globals.szWINS_CONFIG_URL)
853 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_url, &Globals.szWINS_URL)
854 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
855 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_winbindd_socket_directory, &Globals.szWinbinddSocketDirectory)
856 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
857 _PUBLIC_ FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
858 _PUBLIC_ FN_GLOBAL_BOOL(lp_winbind_sealed_pipes, &Globals.bWinbindSealedPipes)
859 _PUBLIC_ FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
860 _PUBLIC_ FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
861 _PUBLIC_ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
862 _PUBLIC_ FN_GLOBAL_STRING(lp_modulesdir, &Globals.szModulesDir)
863 _PUBLIC_ FN_GLOBAL_STRING(lp_setupdir, &Globals.szSetupDir)
864 _PUBLIC_ FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
865 _PUBLIC_ FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
866 _PUBLIC_ FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
867 _PUBLIC_ FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
868 _PUBLIC_ FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
869 _PUBLIC_ FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
870 _PUBLIC_ FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
871 _PUBLIC_ FN_GLOBAL_LIST(lp_passwordserver, &Globals.szPasswordServers)
872 _PUBLIC_ FN_GLOBAL_LIST(lp_name_resolve_order, &Globals.szNameResolveOrder)
873 _PUBLIC_ FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
874 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
875 _PUBLIC_ FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkgroup)
876 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_name, &Globals.szNetbiosName)
877 _PUBLIC_ FN_GLOBAL_STRING(lp_netbios_scope, &Globals.szNetbiosScope)
878 _PUBLIC_ FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
879 _PUBLIC_ FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
880 _PUBLIC_ FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
881 _PUBLIC_ FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
883 _PUBLIC_ FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
884 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
885 _PUBLIC_ FN_GLOBAL_BOOL(lp_wins_dns_proxy, &Globals.bWINSdnsProxy)
886 _PUBLIC_ FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
887 _PUBLIC_ FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
888 _PUBLIC_ FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
889 _PUBLIC_ FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
890 _PUBLIC_ FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
891 _PUBLIC_ FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
892 _PUBLIC_ FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
893 _PUBLIC_ FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
894 _PUBLIC_ FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
895 _PUBLIC_ FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
896 _PUBLIC_ FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
897 _PUBLIC_ FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
898 _PUBLIC_ FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
899 _PUBLIC_ FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
900 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
901 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
902 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
903 _PUBLIC_ FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
904 _PUBLIC_ FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
905 _PUBLIC_ FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
906 _PUBLIC_ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
907 _PUBLIC_ FN_GLOBAL_BOOL(lp_rpc_big_endian, &Globals.bRpcBigEndian)
908 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
909 _PUBLIC_ FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
910 _PUBLIC_ FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
911 _PUBLIC_ FN_GLOBAL_INTEGER(lp_max_xmit, &Globals.max_xmit)
912 _PUBLIC_ FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
913 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_maxprotocol, &Globals.srv_maxprotocol)
914 _PUBLIC_ FN_GLOBAL_INTEGER(lp_srv_minprotocol, &Globals.srv_minprotocol)
915 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_maxprotocol, &Globals.cli_maxprotocol)
916 _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, &Globals.cli_minprotocol)
917 _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, &Globals.security)
918 _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
919 _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
920 _PUBLIC_ FN_GLOBAL_LIST(lp_js_include, &Globals.jsInclude)
921 _PUBLIC_ FN_GLOBAL_STRING(lp_jsonrpc_services_dir, &Globals.jsonrpcServicesDir)
924 _PUBLIC_ FN_LOCAL_STRING(lp_servicename, szService)
925 _PUBLIC_ FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
926 _PUBLIC_ FN_LOCAL_STRING(lp_pathname, szPath)
927 static FN_LOCAL_STRING(_lp_printername, szPrintername)
928 _PUBLIC_ FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
929 _PUBLIC_ FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
930 _PUBLIC_ FN_LOCAL_STRING(lp_comment, comment)
931 _PUBLIC_ FN_LOCAL_STRING(lp_fstype, fstype)
932 static FN_LOCAL_STRING(lp_volume, volume)
933 _PUBLIC_ FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
934 _PUBLIC_ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
935 _PUBLIC_ FN_LOCAL_BOOL(lp_browseable, bBrowseable)
936 _PUBLIC_ FN_LOCAL_BOOL(lp_readonly, bRead_only)
937 _PUBLIC_ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
938 _PUBLIC_ FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
939 _PUBLIC_ FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
940 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
941 _PUBLIC_ FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
942 _PUBLIC_ FN_LOCAL_BOOL(lp_ci_filesystem, bCIFileSystem)
943 _PUBLIC_ FN_LOCAL_BOOL(lp_map_system, bMap_system)
944 _PUBLIC_ FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
945 _PUBLIC_ FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
946 _PUBLIC_ FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
947 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
948 _PUBLIC_ FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
949 _PUBLIC_ FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
950 _PUBLIC_ FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
951 _PUBLIC_ FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
953 /* local prototypes */
955 static int map_parameter(const char *pszParmName);
956 static int getservicebyname(const char *pszServiceName,
957 service * pserviceDest);
958 static void copy_service(service * pserviceDest,
959 service * pserviceSource, int *pcopymapDest);
960 static bool service_ok(int iService);
961 static bool do_section(const char *pszSectionName, void *);
962 static void init_copymap(service * pservice);
964 /* This is a helper function for parametrical options support. */
965 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
966 /* Actual parametrical functions are quite simple */
967 const char *lp_get_parametric(int lookup_service, const char *type, const char *option)
970 struct param_opt *data;
972 if (lookup_service >= 0 && !LP_SNUM_OK(lookup_service))
975 data = (lookup_service < 0) ?
976 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
978 asprintf(&vfskey, "%s:%s", type, option);
982 if (strcmp(data->key, vfskey) == 0) {
989 if (lookup_service >= 0) {
990 /* Try to fetch the same option but from globals */
991 /* but only if we are not already working with Globals */
992 data = Globals.param_opt;
994 if (strcmp(data->key, vfskey) == 0) {
1008 /*******************************************************************
1009 convenience routine to return int parameters.
1010 ********************************************************************/
1011 static int lp_int(const char *s)
1015 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1019 return strtol(s, NULL, 0);
1022 /*******************************************************************
1023 convenience routine to return unsigned long parameters.
1024 ********************************************************************/
1025 static int lp_ulong(const char *s)
1029 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1033 return strtoul(s, NULL, 0);
1036 /*******************************************************************
1037 convenience routine to return unsigned long parameters.
1038 ********************************************************************/
1039 static double lp_double(const char *s)
1043 DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
1047 return strtod(s, NULL);
1050 /*******************************************************************
1051 convenience routine to return boolean parameters.
1052 ********************************************************************/
1053 static BOOL lp_bool(const char *s)
1058 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1062 if (!set_boolean(s, &ret)) {
1063 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1071 /* Return parametric option from a given service. Type is a part of option before ':' */
1072 /* Parametric option has following syntax: 'Type: option = value' */
1073 /* Returned value is allocated in 'lp_talloc' context */
1075 const char *lp_parm_string(int lookup_service, const char *type, const char *option)
1077 const char *value = lp_get_parametric(lookup_service, type, option);
1080 return lp_string(value);
1085 /* Return parametric option from a given service. Type is a part of option before ':' */
1086 /* Parametric option has following syntax: 'Type: option = value' */
1087 /* Returned value is allocated in 'lp_talloc' context */
1089 const char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
1090 const char *separator)
1092 const char *value = lp_get_parametric(lookup_service, type, option);
1095 return str_list_make(talloc_autofree_context(), value, separator);
1100 /* Return parametric option from a given service. Type is a part of option before ':' */
1101 /* Parametric option has following syntax: 'Type: option = value' */
1103 int lp_parm_int(int lookup_service, const char *type, const char *option, int default_v)
1105 const char *value = lp_get_parametric(lookup_service, type, option);
1108 return lp_int(value);
1113 /* Return parametric option from a given service. Type is a part of
1114 * option before ':'.
1115 * Parametric option has following syntax: 'Type: option = value'.
1118 int lp_parm_bytes(int lookup_service, const char *type, const char *option, int default_v)
1122 const char *value = lp_get_parametric(lookup_service, type, option);
1124 if (value && conv_str_size(value, &bval)) {
1125 if (bval <= INT_MAX) {
1133 /* Return parametric option from a given service. Type is a part of option before ':' */
1134 /* Parametric option has following syntax: 'Type: option = value' */
1136 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option, unsigned long default_v)
1138 const char *value = lp_get_parametric(lookup_service, type, option);
1141 return lp_ulong(value);
1147 double lp_parm_double(int lookup_service, const char *type, const char *option, double default_v)
1149 const char *value = lp_get_parametric(lookup_service, type, option);
1152 return lp_double(value);
1157 /* Return parametric option from a given service. Type is a part of option before ':' */
1158 /* Parametric option has following syntax: 'Type: option = value' */
1160 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option, BOOL default_v)
1162 const char *value = lp_get_parametric(lookup_service, type, option);
1165 return lp_bool(value);
1171 /***************************************************************************
1172 Initialise a service to the defaults.
1173 ***************************************************************************/
1175 static service *init_service(TALLOC_CTX *mem_ctx)
1177 service *pservice = talloc(mem_ctx, service);
1178 memset((char *)pservice, '\0', sizeof(service));
1179 copy_service(pservice, &sDefault, NULL);
1183 /***************************************************************************
1184 Free the dynamically allocated parts of a service struct.
1185 ***************************************************************************/
1187 static void free_service(service *pservice)
1190 struct param_opt *data, *pdata;
1194 if (pservice->szService)
1195 DEBUG(5, ("free_service: Freeing service %s\n",
1196 pservice->szService));
1198 string_free(&pservice->szService);
1199 SAFE_FREE(pservice->copymap);
1201 for (i = 0; parm_table[i].label; i++) {
1202 if ((parm_table[i].type == P_STRING ||
1203 parm_table[i].type == P_USTRING) &&
1204 parm_table[i].class == P_LOCAL) {
1205 string_free((char **)
1206 (((char *)pservice) +
1207 PTR_DIFF(parm_table[i].ptr, &sDefault)));
1208 } else if (parm_table[i].type == P_LIST &&
1209 parm_table[i].class == P_LOCAL) {
1210 char ***listp = (char ***)(((char *)pservice) +
1211 PTR_DIFF(parm_table[i].ptr, &sDefault));
1212 talloc_free(*listp);
1217 DEBUG(5,("Freeing parametrics:\n"));
1218 data = pservice->param_opt;
1220 DEBUG(5,("[%s = %s]\n", data->key, data->value));
1221 string_free(&data->key);
1222 string_free(&data->value);
1228 ZERO_STRUCTP(pservice);
1231 /***************************************************************************
1232 Add a new service to the services array initialising it with the given
1234 ***************************************************************************/
1236 static int add_a_service(const service *pservice, const char *name)
1240 int num_to_alloc = iNumServices + 1;
1241 struct param_opt *data, *pdata;
1243 tservice = *pservice;
1245 /* it might already exist */
1247 i = getservicebyname(name, NULL);
1249 /* Clean all parametric options for service */
1250 /* They will be added during parsing again */
1251 data = ServicePtrs[i]->param_opt;
1253 string_free(&data->key);
1254 string_free(&data->value);
1259 ServicePtrs[i]->param_opt = NULL;
1264 /* find an invalid one */
1265 for (i = 0; i < iNumServices; i++)
1266 if (ServicePtrs[i] == NULL)
1269 /* if not, then create one */
1270 if (i == iNumServices) {
1273 tsp = realloc_p(ServicePtrs, service *, num_to_alloc);
1276 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1281 ServicePtrs[iNumServices] = NULL;
1287 ServicePtrs[i] = init_service(talloc_autofree_context());
1288 if (ServicePtrs[i] == NULL) {
1289 DEBUG(0,("add_a_service: out of memory!\n"));
1292 copy_service(ServicePtrs[i], &tservice, NULL);
1294 string_set(&ServicePtrs[i]->szService, name);
1298 /***************************************************************************
1299 Add a new home service, with the specified home directory, defaults coming
1301 ***************************************************************************/
1303 BOOL lp_add_home(const char *pszHomename, int iDefaultService,
1304 const char *user, const char *pszHomedir)
1309 i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1314 if (!(*(ServicePtrs[iDefaultService]->szPath))
1315 || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
1316 pstrcpy(newHomedir, pszHomedir);
1318 pstrcpy(newHomedir, lp_pathname(iDefaultService));
1319 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir));
1322 string_set(&ServicePtrs[i]->szPath, newHomedir);
1324 if (!(*(ServicePtrs[i]->comment))) {
1326 slprintf(comment, sizeof(comment) - 1,
1327 "Home directory of %s", user);
1328 string_set(&ServicePtrs[i]->comment, comment);
1330 ServicePtrs[i]->bAvailable = sDefault.bAvailable;
1331 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1333 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
1339 /***************************************************************************
1340 Add a new service, based on an old one.
1341 ***************************************************************************/
1343 int lp_add_service(const char *pszService, int iDefaultService)
1345 return add_a_service(ServicePtrs[iDefaultService], pszService);
1348 /***************************************************************************
1349 Add the IPC service.
1350 ***************************************************************************/
1352 static bool lp_add_hidden(const char *name, const char *fstype)
1354 char *comment = NULL;
1355 int i = add_a_service(&sDefault, name);
1360 string_set(&ServicePtrs[i]->szPath, tmpdir());
1362 asprintf(&comment, "%s Service (%s)", fstype, Globals.szServerString);
1363 if (comment == NULL)
1366 string_set(&ServicePtrs[i]->comment, comment);
1368 string_set(&ServicePtrs[i]->fstype, fstype);
1369 ServicePtrs[i]->iMaxConnections = -1;
1370 ServicePtrs[i]->bAvailable = true;
1371 ServicePtrs[i]->bRead_only = true;
1372 ServicePtrs[i]->bPrint_ok = false;
1373 ServicePtrs[i]->bBrowseable = false;
1375 if (strcasecmp(fstype, "IPC") == 0) {
1376 lp_do_parameter(i, "ntvfs handler", "default");
1379 DEBUG(3, ("adding hidden service %s\n", name));
1384 /***************************************************************************
1385 Add a new printer service, with defaults coming from service iFrom.
1386 ***************************************************************************/
1388 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1390 const char *comment = "From Printcap";
1391 int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1396 /* note that we do NOT default the availability flag to True - */
1397 /* we take it from the default service passed. This allows all */
1398 /* dynamic printers to be disabled by disabling the [printers] */
1399 /* entry (if/when the 'available' keyword is implemented!). */
1401 /* the printer name is set to the service name. */
1402 string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1403 string_set(&ServicePtrs[i]->comment, comment);
1404 ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1405 /* Printers cannot be read_only. */
1406 ServicePtrs[i]->bRead_only = False;
1407 /* Printer services must be printable. */
1408 ServicePtrs[i]->bPrint_ok = True;
1410 DEBUG(3, ("adding printer service %s\n", pszPrintername));
1415 /***************************************************************************
1416 Map a parameter's string representation to something we can use.
1417 Returns False if the parameter string is not recognised, else TRUE.
1418 ***************************************************************************/
1420 static int map_parameter(const char *pszParmName)
1424 if (*pszParmName == '-')
1427 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1428 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1431 /* Warn only if it isn't parametric option */
1432 if (strchr(pszParmName, ':') == NULL)
1433 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1434 /* We do return 'fail' for parametric options as well because they are
1435 stored in different storage
1442 return the parameter structure for a parameter
1444 struct parm_struct *lp_parm_struct(const char *name)
1446 int parmnum = map_parameter(name);
1447 if (parmnum == -1) return NULL;
1448 return &parm_table[parmnum];
1452 return the parameter pointer for a parameter
1454 void *lp_parm_ptr(int snum, struct parm_struct *parm)
1459 return ((char *)ServicePtrs[snum]) + PTR_DIFF(parm->ptr, &sDefault);
1462 /***************************************************************************
1463 Find a service by name. Otherwise works like get_service.
1464 ***************************************************************************/
1466 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
1470 for (iService = iNumServices - 1; iService >= 0; iService--)
1471 if (VALID(iService) &&
1472 strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
1473 if (pserviceDest != NULL)
1474 copy_service(pserviceDest, ServicePtrs[iService], NULL);
1481 /***************************************************************************
1482 Copy a service structure to another.
1483 If pcopymapDest is NULL then copy all fields
1484 ***************************************************************************/
1486 static void copy_service(service *pserviceDest, service *pserviceSource,
1490 bool bcopyall = (pcopymapDest == NULL);
1491 struct param_opt *data, *pdata, *paramo;
1494 for (i = 0; parm_table[i].label; i++)
1495 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1496 (bcopyall || pcopymapDest[i])) {
1497 void *def_ptr = parm_table[i].ptr;
1499 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
1502 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
1505 switch (parm_table[i].type) {
1507 *(int *)dest_ptr = *(int *)src_ptr;
1513 *(int *)dest_ptr = *(int *)src_ptr;
1517 string_set(dest_ptr,
1522 string_set(dest_ptr,
1524 strupper(*(char **)dest_ptr);
1527 *(const char ***)dest_ptr = str_list_copy(talloc_autofree_context(),
1528 *(const char ***)src_ptr);
1536 init_copymap(pserviceDest);
1537 if (pserviceSource->copymap)
1538 memcpy((void *)pserviceDest->copymap,
1539 (void *)pserviceSource->copymap,
1540 sizeof(int) * NUMPARAMETERS);
1543 data = pserviceSource->param_opt;
1546 pdata = pserviceDest->param_opt;
1547 /* Traverse destination */
1549 /* If we already have same option, override it */
1550 if (strcmp(pdata->key, data->key) == 0) {
1551 string_free(&pdata->value);
1552 pdata->value = strdup(data->value);
1556 pdata = pdata->next;
1559 paramo = malloc_p(struct param_opt);
1562 paramo->key = strdup(data->key);
1563 paramo->value = strdup(data->value);
1564 DLIST_ADD(pserviceDest->param_opt, paramo);
1570 /***************************************************************************
1571 Check a service for consistency. Return False if the service is in any way
1572 incomplete or faulty, else True.
1573 ***************************************************************************/
1575 static BOOL service_ok(int iService)
1580 if (ServicePtrs[iService]->szService[0] == '\0') {
1581 DEBUG(0, ("The following message indicates an internal error:\n"));
1582 DEBUG(0, ("No service name in service entry.\n"));
1586 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1587 /* I can't see why you'd want a non-printable printer service... */
1588 if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
1589 if (!ServicePtrs[iService]->bPrint_ok) {
1590 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1591 ServicePtrs[iService]->szService));
1592 ServicePtrs[iService]->bPrint_ok = True;
1594 /* [printers] service must also be non-browsable. */
1595 if (ServicePtrs[iService]->bBrowseable)
1596 ServicePtrs[iService]->bBrowseable = False;
1599 /* If a service is flagged unavailable, log the fact at level 0. */
1600 if (!ServicePtrs[iService]->bAvailable)
1601 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1602 ServicePtrs[iService]->szService));
1607 static struct file_lists {
1608 struct file_lists *next;
1612 } *file_lists = NULL;
1614 /*******************************************************************
1615 Keep a linked list of all config files so we know when one has changed
1616 it's date and needs to be reloaded.
1617 ********************************************************************/
1619 static void add_to_file_list(const char *fname, const char *subfname)
1621 struct file_lists *f = file_lists;
1624 if (f->name && !strcmp(f->name, fname))
1630 f = malloc_p(struct file_lists);
1633 f->next = file_lists;
1634 f->name = strdup(fname);
1639 f->subfname = strdup(subfname);
1645 f->modtime = file_modtime(subfname);
1647 time_t t = file_modtime(subfname);
1653 /*******************************************************************
1654 Check if a config file has changed date.
1655 ********************************************************************/
1657 BOOL lp_file_list_changed(void)
1659 struct file_lists *f = file_lists;
1660 DEBUG(6, ("lp_file_list_changed()\n"));
1666 n2 = standard_sub_basic(f->name);
1668 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
1669 f->name, n2, ctime(&f->modtime)));
1671 mod_time = file_modtime(n2);
1673 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1675 ("file %s modified: %s\n", n2,
1677 f->modtime = mod_time;
1678 SAFE_FREE(f->subfname);
1679 f->subfname = strdup(n2);
1687 /***************************************************************************
1688 Handle the include operation.
1689 ***************************************************************************/
1691 static bool handle_include(const char *pszParmValue, char **ptr)
1693 char *fname = standard_sub_basic(pszParmValue);
1695 add_to_file_list(pszParmValue, fname);
1697 string_set(ptr, fname);
1699 if (file_exist(fname))
1700 return pm_process(fname, do_section, do_parameter, NULL);
1702 DEBUG(2, ("Can't find include file %s\n", fname));
1707 /***************************************************************************
1708 Handle the interpretation of the copy parameter.
1709 ***************************************************************************/
1711 static bool handle_copy(const char *pszParmValue, char **ptr)
1715 service *serviceTemp;
1717 string_set(ptr, pszParmValue);
1719 serviceTemp = init_service(talloc_autofree_context());
1723 DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1725 if ((iTemp = getservicebyname(pszParmValue, serviceTemp)) >= 0) {
1726 if (iTemp == iServiceIndex) {
1727 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1729 copy_service(ServicePtrs[iServiceIndex],
1731 ServicePtrs[iServiceIndex]->copymap);
1735 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
1739 free_service(serviceTemp);
1743 /***************************************************************************
1744 Initialise a copymap.
1745 ***************************************************************************/
1747 static void init_copymap(service * pservice)
1750 SAFE_FREE(pservice->copymap);
1751 pservice->copymap = malloc_array_p(int, NUMPARAMETERS);
1752 if (!pservice->copymap)
1754 ("Couldn't allocate copymap!! (size %d)\n",
1755 (int)NUMPARAMETERS));
1757 for (i = 0; i < NUMPARAMETERS; i++)
1758 pservice->copymap[i] = True;
1761 #if 0 /* not used anywhere */
1762 /***************************************************************************
1763 Return the local pointer to a parameter given the service number and the
1764 pointer into the default structure.
1765 ***************************************************************************/
1767 void *lp_local_ptr(int snum, void *ptr)
1769 return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
1773 /***************************************************************************
1774 Process a parametric option
1775 ***************************************************************************/
1776 static bool lp_do_parameter_parametric(int snum, const char *pszParmName,
1777 const char *pszParmValue, int flags)
1779 struct param_opt *paramo, *data;
1782 while (isspace((unsigned char)*pszParmName)) {
1786 name = strdup(pszParmName);
1787 if (!name) return False;
1792 data = Globals.param_opt;
1794 data = ServicePtrs[snum]->param_opt;
1797 /* Traverse destination */
1798 for (paramo=data; paramo; paramo=paramo->next) {
1799 /* If we already have the option set, override it unless
1800 it was a command line option and the new one isn't */
1801 if (strcmp(paramo->key, name) == 0) {
1802 if ((paramo->flags & FLAG_CMDLINE) &&
1803 !(flags & FLAG_CMDLINE)) {
1807 free(paramo->value);
1808 paramo->value = strdup(pszParmValue);
1809 paramo->flags = flags;
1815 paramo = malloc_p(struct param_opt);
1818 paramo->key = strdup(name);
1819 paramo->value = strdup(pszParmValue);
1820 paramo->flags = flags;
1822 DLIST_ADD(Globals.param_opt, paramo);
1824 DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
1832 /***************************************************************************
1833 Process a parameter for a particular service number. If snum < 0
1834 then assume we are in the globals.
1835 ***************************************************************************/
1836 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
1839 void *parm_ptr = NULL; /* where we are going to store the result */
1840 void *def_ptr = NULL;
1842 parmnum = map_parameter(pszParmName);
1845 if (strchr(pszParmName, ':')) {
1846 return lp_do_parameter_parametric(snum, pszParmName, pszParmValue, 0);
1848 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1852 if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1853 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1857 /* if the flag has been set on the command line, then don't allow override,
1858 but don't report an error */
1859 if (parm_table[parmnum].flags & FLAG_CMDLINE) {
1863 def_ptr = parm_table[parmnum].ptr;
1865 /* we might point at a service, the default service or a global */
1869 if (parm_table[parmnum].class == P_GLOBAL) {
1871 ("Global parameter %s found in service section!\n",
1876 ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
1881 if (!ServicePtrs[snum]->copymap)
1882 init_copymap(ServicePtrs[snum]);
1884 /* this handles the aliases - set the copymap for other entries with
1885 the same data pointer */
1886 for (i = 0; parm_table[i].label; i++)
1887 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1888 ServicePtrs[snum]->copymap[i] = False;
1891 /* if it is a special case then go ahead */
1892 if (parm_table[parmnum].special) {
1893 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
1897 /* now switch on the type of variable it is */
1898 switch (parm_table[parmnum].type)
1902 if (!set_boolean(pszParmValue, &b)) {
1903 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue));
1906 *(int *)parm_ptr = b;
1911 *(int *)parm_ptr = atoi(pszParmValue);
1915 *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
1921 if (conv_str_size(pszParmValue, &val)) {
1922 if (val <= INT_MAX) {
1923 *(int *)parm_ptr = (int)val;
1928 DEBUG(0,("lp_do_parameter(%s): value is not "
1929 "a valid size specifier!\n", pszParmValue));
1934 *(const char ***)parm_ptr = str_list_make(talloc_autofree_context(),
1935 pszParmValue, NULL);
1939 string_set(parm_ptr, pszParmValue);
1943 string_set(parm_ptr, pszParmValue);
1944 strupper(*(char **)parm_ptr);
1948 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
1951 parm_table[parmnum].enum_list[i].name)) {
1953 parm_table[parmnum].
1958 if (!parm_table[parmnum].enum_list[i].name) {
1959 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n",
1960 pszParmValue, pszParmName));
1968 if (parm_table[parmnum].flags & FLAG_DEFAULT) {
1969 parm_table[parmnum].flags &= ~FLAG_DEFAULT;
1970 /* we have to also unset FLAG_DEFAULT on aliases */
1971 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
1972 parm_table[i].flags &= ~FLAG_DEFAULT;
1974 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
1975 parm_table[i].flags &= ~FLAG_DEFAULT;
1982 /***************************************************************************
1983 Process a parameter.
1984 ***************************************************************************/
1986 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue, void *userdata)
1988 return lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
1989 pszParmName, pszParmValue);
1993 variable argument do parameter
1995 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
1997 static BOOL do_parameter_var(const char *pszParmName, const char *fmt, ...)
2004 s = talloc_vasprintf(NULL, fmt, ap);
2006 ret = do_parameter(pszParmName, s, NULL);
2013 set a parameter from the commandline - this is called from command line parameter
2014 parsing code. It sets the parameter then marks the parameter as unable to be modified
2015 by smb.conf processing
2017 BOOL lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
2019 int parmnum = map_parameter(pszParmName);
2022 while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
2025 if (parmnum < 0 && strchr(pszParmName, ':')) {
2026 /* set a parametric option */
2027 return lp_do_parameter_parametric(-1, pszParmName, pszParmValue, FLAG_CMDLINE);
2031 DEBUG(0,("Unknown option '%s'\n", pszParmName));
2035 /* reset the CMDLINE flag in case this has been called before */
2036 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
2038 if (!lp_do_parameter(-2, pszParmName, pszParmValue)) {
2042 parm_table[parmnum].flags |= FLAG_CMDLINE;
2044 /* we have to also set FLAG_CMDLINE on aliases */
2045 for (i=parmnum-1;i>=0 && parm_table[i].ptr == parm_table[parmnum].ptr;i--) {
2046 parm_table[i].flags |= FLAG_CMDLINE;
2048 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].ptr == parm_table[parmnum].ptr;i++) {
2049 parm_table[i].flags |= FLAG_CMDLINE;
2056 set a option from the commandline in 'a=b' format. Use to support --option
2058 BOOL lp_set_option(const char *option)
2076 ret = lp_set_cmdline(s, p+1);
2082 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2084 /***************************************************************************
2085 Print a parameter of the specified type.
2086 ***************************************************************************/
2088 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2094 for (i = 0; p->enum_list[i].name; i++) {
2095 if (*(int *)ptr == p->enum_list[i].value) {
2097 p->enum_list[i].name);
2104 fprintf(f, "%s", BOOLSTR((BOOL)*(int *)ptr));
2109 fprintf(f, "%d", *(int *)ptr);
2113 fprintf(f, "0%o", *(int *)ptr);
2117 if ((char ***)ptr && *(char ***)ptr) {
2118 char **list = *(char ***)ptr;
2120 for (; *list; list++)
2121 fprintf(f, "%s%s", *list,
2122 ((*(list+1))?", ":""));
2128 if (*(char **)ptr) {
2129 fprintf(f, "%s", *(char **)ptr);
2137 /***************************************************************************
2138 Check if two parameters are equal.
2139 ***************************************************************************/
2141 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
2145 return (*((int *)ptr1) == *((int *)ptr2));
2151 return (*((int *)ptr1) == *((int *)ptr2));
2154 return str_list_equal((const char **)(*(char ***)ptr1),
2155 (const char **)(*(char ***)ptr2));
2160 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2165 return (p1 == p2 || strequal(p1, p2));
2173 /***************************************************************************
2174 Process a new section (service). At this stage all sections are services.
2175 Later we'll have special sections that permit server parameters to be set.
2176 Returns True on success, False on failure.
2177 ***************************************************************************/
2179 static BOOL do_section(const char *pszSectionName, void *userdata)
2182 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2183 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2186 /* if we've just struck a global section, note the fact. */
2187 bInGlobalSection = isglobal;
2189 /* check for multiple global sections */
2190 if (bInGlobalSection) {
2191 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
2195 /* if we have a current service, tidy it up before moving on */
2198 if (iServiceIndex >= 0)
2199 bRetval = service_ok(iServiceIndex);
2201 /* if all is still well, move to the next record in the services array */
2203 /* We put this here to avoid an odd message order if messages are */
2204 /* issued by the post-processing of a previous section. */
2205 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
2207 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
2209 DEBUG(0, ("Failed to add a new service\n"));
2218 /***************************************************************************
2219 Determine if a partcular base parameter is currentl set to the default value.
2220 ***************************************************************************/
2222 static BOOL is_default(int i)
2224 if (!defaults_saved)
2226 switch (parm_table[i].type) {
2228 return str_list_equal((const char **)parm_table[i].def.lvalue,
2229 (const char **)(*(char ***)parm_table[i].ptr));
2232 return strequal(parm_table[i].def.svalue,
2233 *(char **)parm_table[i].ptr);
2235 return parm_table[i].def.bvalue ==
2236 *(int *)parm_table[i].ptr;
2241 return parm_table[i].def.ivalue ==
2242 *(int *)parm_table[i].ptr;
2249 /***************************************************************************
2250 Display the contents of the global structure.
2251 ***************************************************************************/
2253 static void dump_globals(FILE *f, BOOL show_defaults)
2256 struct param_opt *data;
2258 fprintf(f, "# Global parameters\n[global]\n");
2260 for (i = 0; parm_table[i].label; i++)
2261 if (parm_table[i].class == P_GLOBAL &&
2262 parm_table[i].ptr &&
2263 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2264 if (!show_defaults && (parm_table[i].flags & FLAG_DEFAULT))
2266 fprintf(f, "\t%s = ", parm_table[i].label);
2267 print_parameter(&parm_table[i], parm_table[i].ptr, f);
2270 if (Globals.param_opt != NULL) {
2271 data = Globals.param_opt;
2273 fprintf(f, "\t%s = %s\n", data->key, data->value);
2280 /***************************************************************************
2281 Display the contents of a single services record.
2282 ***************************************************************************/
2284 static void dump_a_service(service * pService, FILE * f)
2287 struct param_opt *data;
2289 if (pService != &sDefault)
2290 fprintf(f, "\n[%s]\n", pService->szService);
2292 for (i = 0; parm_table[i].label; i++)
2293 if (parm_table[i].class == P_LOCAL &&
2294 parm_table[i].ptr &&
2295 (*parm_table[i].label != '-') &&
2296 (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
2297 int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
2299 if (pService == &sDefault) {
2300 if (defaults_saved && is_default(i))
2303 if (equal_parameter(parm_table[i].type,
2304 ((char *)pService) +
2306 ((char *)&sDefault) +
2311 fprintf(f, "\t%s = ", parm_table[i].label);
2312 print_parameter(&parm_table[i],
2313 ((char *)pService) + pdiff, f);
2316 if (pService->param_opt != NULL) {
2317 data = pService->param_opt;
2319 fprintf(f, "\t%s = %s\n", data->key, data->value);
2325 BOOL lp_dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
2327 service * pService = ServicePtrs[snum];
2328 struct parm_struct *parm;
2331 parm = lp_parm_struct(parm_name);
2339 ptr = ((char *)pService) +
2340 PTR_DIFF(parm->ptr, &sDefault);
2342 print_parameter(parm,
2348 /***************************************************************************
2349 Return info about the next service in a service. snum==-1 gives the globals.
2350 Return NULL when out of parameters.
2351 ***************************************************************************/
2353 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2356 /* do the globals */
2357 for (; parm_table[*i].label; (*i)++) {
2358 if (parm_table[*i].class == P_SEPARATOR)
2359 return &parm_table[(*i)++];
2361 if (!parm_table[*i].ptr
2362 || (*parm_table[*i].label == '-'))
2366 && (parm_table[*i].ptr ==
2367 parm_table[(*i) - 1].ptr))
2370 return &parm_table[(*i)++];
2373 service *pService = ServicePtrs[snum];
2375 for (; parm_table[*i].label; (*i)++) {
2376 if (parm_table[*i].class == P_SEPARATOR)
2377 return &parm_table[(*i)++];
2379 if (parm_table[*i].class == P_LOCAL &&
2380 parm_table[*i].ptr &&
2381 (*parm_table[*i].label != '-') &&
2383 (parm_table[*i].ptr !=
2384 parm_table[(*i) - 1].ptr)))
2387 PTR_DIFF(parm_table[*i].ptr,
2390 if (allparameters ||
2391 !equal_parameter(parm_table[*i].type,
2392 ((char *)pService) +
2394 ((char *)&sDefault) +
2397 return &parm_table[(*i)++];
2407 /***************************************************************************
2408 Return TRUE if the passed service number is within range.
2409 ***************************************************************************/
2411 bool lp_snum_ok(int iService)
2413 return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
2416 /***************************************************************************
2417 Auto-load some home services.
2418 ***************************************************************************/
2420 static void lp_add_auto_services(const char *str)
2425 /***************************************************************************
2426 Have we loaded a services file yet?
2427 ***************************************************************************/
2429 BOOL lp_loaded(void)
2434 /***************************************************************************
2435 Unload unused services.
2436 ***************************************************************************/
2438 void lp_killunused(struct smbsrv_connection *smb, BOOL (*snumused) (struct smbsrv_connection *, int))
2441 for (i = 0; i < iNumServices; i++) {
2445 if (!snumused || !snumused(smb, i)) {
2446 free_service(ServicePtrs[i]);
2447 ServicePtrs[i] = NULL;
2452 /***************************************************************************
2454 ***************************************************************************/
2456 void lp_killservice(int iServiceIn)
2458 if (VALID(iServiceIn)) {
2459 free_service(ServicePtrs[iServiceIn]);
2460 ServicePtrs[iServiceIn] = NULL;
2464 /***************************************************************************
2465 Load the services array from the services file. Return True on success,
2467 ***************************************************************************/
2473 struct param_opt *data;
2477 bInGlobalSection = true;
2479 if (Globals.param_opt != NULL) {
2480 struct param_opt *next;
2481 for (data=Globals.param_opt; data; data=next) {
2483 if (data->flags & FLAG_CMDLINE) continue;
2486 DLIST_REMOVE(Globals.param_opt, data);
2493 n2 = standard_sub_basic(lp_configfile());
2494 DEBUG(2, ("lp_load: refreshing parameters from %s\n", n2));
2496 add_to_file_list(lp_configfile(), n2);
2498 /* We get sections first, so have to start 'behind' to make up */
2500 bRetval = pm_process(n2, do_section, do_parameter, NULL);
2502 /* finish up the last section */
2503 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
2505 if (iServiceIndex >= 0)
2506 bRetval = service_ok(iServiceIndex);
2508 lp_add_auto_services(lp_auto_services());
2510 lp_add_hidden("IPC$", "IPC");
2511 lp_add_hidden("ADMIN$", "DISK");
2515 if (!Globals.szWINSservers && Globals.bWINSsupport) {
2516 lp_do_parameter(-1, "wins server", "127.0.0.1");
2524 /***************************************************************************
2525 Reset the max number of services.
2526 ***************************************************************************/
2528 void lp_resetnumservices(void)
2533 /***************************************************************************
2534 Return the max number of services.
2535 ***************************************************************************/
2537 int lp_numservices(void)
2539 return iNumServices;
2542 /***************************************************************************
2543 Display the contents of the services array in human-readable form.
2544 ***************************************************************************/
2546 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2551 defaults_saved = False;
2553 dump_globals(f, show_defaults);
2555 dump_a_service(&sDefault, f);
2557 for (iService = 0; iService < maxtoprint; iService++)
2558 lp_dump_one(f, show_defaults, iService);
2561 /***************************************************************************
2562 Display the contents of one service in human-readable form.
2563 ***************************************************************************/
2565 void lp_dump_one(FILE *f, bool show_defaults, int snum)
2568 if (ServicePtrs[snum]->szService[0] == '\0')
2570 dump_a_service(ServicePtrs[snum], f);
2574 /***************************************************************************
2575 Return the number of the service with the given name, or -1 if it doesn't
2576 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2577 getservicebyname()! This works ONLY if all services have been loaded, and
2578 does not copy the found service.
2579 ***************************************************************************/
2581 int lp_servicenumber(const char *pszServiceName)
2587 for (iService = iNumServices - 1; iService >= 0; iService--) {
2588 if (VALID(iService) && ServicePtrs[iService]->szService) {
2590 * The substitution here is used to support %U is
2593 serviceName = standard_sub_basic(ServicePtrs[iService]->szService);
2594 if (strequal(serviceName, pszServiceName))
2600 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
2605 int lp_find_valid_service(const char *pszServiceName)
2609 iService = lp_servicenumber(pszServiceName);
2611 if (iService >= 0 && !lp_snum_ok(iService)) {
2612 DEBUG(0,("lp_find_valid_service: Invalid snum %d for '%s'\n",iService, pszServiceName));
2616 if (iService == -1) {
2617 DEBUG(3,("lp_find_valid_service: failed to find service '%s'\n", pszServiceName));
2623 /*******************************************************************
2624 A useful volume label function.
2625 ********************************************************************/
2626 const char *volume_label(int snum)
2628 const char *ret = lp_volume(snum);
2630 return lp_servicename(snum);
2635 /***********************************************************
2636 If we are PDC then prefer us as DMB
2637 ************************************************************/
2639 bool lp_domain_logons(void)
2641 return (lp_server_role() == ROLE_DOMAIN_CONTROLLER);
2644 /*******************************************************************
2646 ********************************************************************/
2648 void lp_remove_service(int snum)
2650 ServicePtrs[snum] = NULL;
2653 /*******************************************************************
2655 ********************************************************************/
2657 void lp_copy_service(int snum, const char *new_name)
2659 const char *oldname = lp_servicename(snum);
2660 do_section(new_name, NULL);
2662 snum = lp_servicenumber(new_name);
2664 lp_do_parameter(snum, "copy", oldname);
2668 const char *lp_printername(int snum)
2670 const char *ret = _lp_printername(snum);
2671 if (ret == NULL || (ret != NULL && *ret == '\0'))
2672 ret = lp_const_servicename(snum);
2678 /*******************************************************************
2679 Return the max print jobs per queue.
2680 ********************************************************************/
2682 int lp_maxprintjobs(int snum)
2684 int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
2685 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
2686 maxjobs = PRINT_MAX_JOBID - 1;