Changeset 988 for vendor/current/source4/param/loadparm.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source4/param/loadparm.c
r740 r988 27 27 */ 28 28 29 /*30 * Load parameters.31 *32 * This module provides suitable callback functions for the params33 * module. It builds the internal table of service details which is34 * then used by the rest of the server.35 *36 * To add a parameter:37 *38 * 1) add it to the global or service structure definition39 * 2) add it to the parm_table40 * 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 local42 * (ie. service) parameter then initialise it in the sDefault structure43 *44 *45 * Notes:46 * The configuration file is processed sequentially for speed. It is NOT47 * accessed randomly as happens in 'real' Windows. For this reason, there48 * is a fair bit of sequence-dependent code here - ie., code which assumes49 * that certain things happen before others. In particular, the code which50 * happens at the boundary between sections is delicately poised, so be51 * careful!52 *53 */54 55 29 #include "includes.h" 56 #include "version.h" 57 #include "dynconfig/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 "../lib/util/parmlist.h" 65 #include "param/param.h" 66 #include "param/loadparm.h" 30 #include "lib/param/param.h" 67 31 #include "libcli/raw/libcliraw.h" 68 #include "rpc_server/common/common.h" 69 #include "lib/socket/socket.h" 70 #include "auth/gensec/gensec.h" 71 72 #define standard_sub_basic talloc_strdup 73 74 static bool do_parameter(const char *, const char *, void *); 75 static bool defaults_saved = false; 76 77 /** 78 * This structure describes global (ie., server-wide) parameters. 79 */ 80 struct loadparm_global 81 { 82 enum server_role server_role; 83 enum sid_generator sid_generator; 84 85 const char **smb_ports; 86 char *ncalrpc_dir; 87 char *dos_charset; 88 char *unix_charset; 89 char *display_charset; 90 char *szLockDir; 91 char *szModulesDir; 92 char *szPidDir; 93 char *szServerString; 94 char *szAutoServices; 95 char *szPasswdChat; 96 char *szShareBackend; 97 char *szSAM_URL; 98 char *szIDMAP_URL; 99 char *szSECRETS_URL; 100 char *szSPOOLSS_URL; 101 char *szWINS_CONFIG_URL; 102 char *szWINS_URL; 103 char *szPrivateDir; 104 const char **szPasswordServers; 105 char *szSocketOptions; 106 char *szRealm; 107 char *szRealm_upper; 108 char *szRealm_lower; 109 const char **szWINSservers; 110 const char **szInterfaces; 111 char *szSocketAddress; 112 char *szAnnounceVersion; /* This is initialised in init_globals */ 113 char *szWorkgroup; 114 char *szNetbiosName; 115 const char **szNetbiosAliases; 116 char *szNetbiosScope; 117 char *szDomainOtherSIDs; 118 const char **szNameResolveOrder; 119 const char **dcerpc_ep_servers; 120 const char **server_services; 121 char *ntptr_providor; 122 char *szWinbindSeparator; 123 char *szWinbinddPrivilegedSocketDirectory; 124 char *szWinbinddSocketDirectory; 125 char *szTemplateShell; 126 char *szTemplateHomedir; 127 int bWinbindSealedPipes; 128 int bIdmapTrustedOnly; 129 int tls_enabled; 130 char *tls_keyfile; 131 char *tls_certfile; 132 char *tls_cafile; 133 char *tls_crlfile; 134 char *tls_dhpfile; 135 char *logfile; 136 char *loglevel; 137 char *panic_action; 138 int max_mux; 139 int debuglevel; 140 int max_xmit; 141 int pwordlevel; 142 int srv_maxprotocol; 143 int srv_minprotocol; 144 int cli_maxprotocol; 145 int cli_minprotocol; 146 int security; 147 int paranoid_server_security; 148 int max_wins_ttl; 149 int min_wins_ttl; 150 int announce_as; /* This is initialised in init_globals */ 151 int nbt_port; 152 int dgram_port; 153 int cldap_port; 154 int krb5_port; 155 int kpasswd_port; 156 int web_port; 157 char *socket_options; 158 int bWINSsupport; 159 int bWINSdnsProxy; 160 char *szWINSHook; 161 int bLocalMaster; 162 int bPreferredMaster; 163 int bEncryptPasswords; 164 int bNullPasswords; 165 int bObeyPamRestrictions; 166 int bLargeReadwrite; 167 int bReadRaw; 168 int bWriteRaw; 169 int bTimeServer; 170 int bBindInterfacesOnly; 171 int bNTSmbSupport; 172 int bNTStatusSupport; 173 int bLanmanAuth; 174 int bNTLMAuth; 175 int bUseSpnego; 176 int server_signing; 177 int client_signing; 178 int bClientPlaintextAuth; 179 int bClientLanManAuth; 180 int bClientNTLMv2Auth; 181 int client_use_spnego_principal; 182 int bHostMSDfs; 183 int bUnicode; 184 int bUnixExtensions; 185 int bDisableNetbios; 186 int bRpcBigEndian; 187 char *szNTPSignDSocketDirectory; 188 const char **szRNDCCommand; 189 const char **szDNSUpdateCommand; 190 const char **szSPNUpdateCommand; 191 const char **szNSUpdateCommand; 192 struct parmlist_entry *param_opt; 193 }; 194 195 196 /** 197 * This structure describes a single service. 198 */ 199 struct loadparm_service 200 { 201 char *szService; 202 char *szPath; 203 char *szCopy; 204 char *szInclude; 205 char *szPrintername; 206 char **szHostsallow; 207 char **szHostsdeny; 208 char *comment; 209 char *volume; 210 char *fstype; 211 char **ntvfs_handler; 212 int iMaxPrintJobs; 213 int iMaxConnections; 214 int iCSCPolicy; 215 int bAvailable; 216 int bBrowseable; 217 int bRead_only; 218 int bPrint_ok; 219 int bMap_system; 220 int bMap_hidden; 221 int bMap_archive; 222 int bStrictLocking; 223 int bOplocks; 224 int iCreate_mask; 225 int iCreate_force_mode; 226 int iDir_mask; 227 int iDir_force_mode; 228 int *copymap; 229 int bMSDfsRoot; 230 int bStrictSync; 231 int bCIFileSystem; 232 struct parmlist_entry *param_opt; 233 234 char dummy[3]; /* for alignment */ 235 }; 236 237 238 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct)) 239 240 241 /* prototypes for the special type handlers */ 242 static bool handle_include(struct loadparm_context *lp_ctx, 243 const char *pszParmValue, char **ptr); 244 static bool handle_realm(struct loadparm_context *lp_ctx, 245 const char *pszParmValue, char **ptr); 246 static bool handle_copy(struct loadparm_context *lp_ctx, 247 const char *pszParmValue, char **ptr); 248 static bool handle_debuglevel(struct loadparm_context *lp_ctx, 249 const char *pszParmValue, char **ptr); 250 static bool handle_logfile(struct loadparm_context *lp_ctx, 251 const char *pszParmValue, char **ptr); 252 253 static const struct enum_list enum_protocol[] = { 254 {PROTOCOL_SMB2, "SMB2"}, 255 {PROTOCOL_NT1, "NT1"}, 256 {PROTOCOL_LANMAN2, "LANMAN2"}, 257 {PROTOCOL_LANMAN1, "LANMAN1"}, 258 {PROTOCOL_CORE, "CORE"}, 259 {PROTOCOL_COREPLUS, "COREPLUS"}, 260 {PROTOCOL_COREPLUS, "CORE+"}, 261 {-1, NULL} 262 }; 263 264 static const struct enum_list enum_security[] = { 265 {SEC_SHARE, "SHARE"}, 266 {SEC_USER, "USER"}, 267 {-1, NULL} 268 }; 269 270 static const struct enum_list enum_announce_as[] = { 271 {ANNOUNCE_AS_NT_SERVER, "NT"}, 272 {ANNOUNCE_AS_NT_SERVER, "NT Server"}, 273 {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"}, 274 {ANNOUNCE_AS_WIN95, "win95"}, 275 {ANNOUNCE_AS_WFW, "WfW"}, 276 {-1, NULL} 277 }; 278 279 static const struct enum_list enum_bool_auto[] = { 280 {false, "No"}, 281 {false, "False"}, 282 {false, "0"}, 283 {true, "Yes"}, 284 {true, "True"}, 285 {true, "1"}, 286 {Auto, "Auto"}, 287 {-1, NULL} 288 }; 289 290 /* Client-side offline caching policy types */ 291 enum csc_policy { 292 CSC_POLICY_MANUAL=0, 293 CSC_POLICY_DOCUMENTS=1, 294 CSC_POLICY_PROGRAMS=2, 295 CSC_POLICY_DISABLE=3 296 }; 297 298 static const struct enum_list enum_csc_policy[] = { 299 {CSC_POLICY_MANUAL, "manual"}, 300 {CSC_POLICY_DOCUMENTS, "documents"}, 301 {CSC_POLICY_PROGRAMS, "programs"}, 302 {CSC_POLICY_DISABLE, "disable"}, 303 {-1, NULL} 304 }; 305 306 /* SMB signing types. */ 307 static const struct enum_list enum_smb_signing_vals[] = { 308 {SMB_SIGNING_OFF, "No"}, 309 {SMB_SIGNING_OFF, "False"}, 310 {SMB_SIGNING_OFF, "0"}, 311 {SMB_SIGNING_OFF, "Off"}, 312 {SMB_SIGNING_OFF, "disabled"}, 313 {SMB_SIGNING_SUPPORTED, "Yes"}, 314 {SMB_SIGNING_SUPPORTED, "True"}, 315 {SMB_SIGNING_SUPPORTED, "1"}, 316 {SMB_SIGNING_SUPPORTED, "On"}, 317 {SMB_SIGNING_SUPPORTED, "enabled"}, 318 {SMB_SIGNING_REQUIRED, "required"}, 319 {SMB_SIGNING_REQUIRED, "mandatory"}, 320 {SMB_SIGNING_REQUIRED, "force"}, 321 {SMB_SIGNING_REQUIRED, "forced"}, 322 {SMB_SIGNING_REQUIRED, "enforced"}, 323 {SMB_SIGNING_AUTO, "auto"}, 324 {-1, NULL} 325 }; 326 327 static const struct enum_list enum_server_role[] = { 328 {ROLE_STANDALONE, "standalone"}, 329 {ROLE_DOMAIN_MEMBER, "member server"}, 330 {ROLE_DOMAIN_MEMBER, "member"}, 331 {ROLE_DOMAIN_CONTROLLER, "domain controller"}, 332 {ROLE_DOMAIN_CONTROLLER, "dc"}, 333 {-1, NULL} 334 }; 335 336 static const struct enum_list enum_sid_generator[] = { 337 {SID_GENERATOR_INTERNAL, "internal"}, 338 {SID_GENERATOR_BACKEND, "backend"}, 339 {-1, NULL} 340 }; 341 342 #define GLOBAL_VAR(name) offsetof(struct loadparm_global, name) 343 #define LOCAL_VAR(name) offsetof(struct loadparm_service, name) 344 345 static struct parm_struct parm_table[] = { 346 {"server role", P_ENUM, P_GLOBAL, GLOBAL_VAR(server_role), NULL, enum_server_role}, 347 {"sid generator", P_ENUM, P_GLOBAL, GLOBAL_VAR(sid_generator), NULL, enum_sid_generator}, 348 349 {"dos charset", P_STRING, P_GLOBAL, GLOBAL_VAR(dos_charset), NULL, NULL}, 350 {"unix charset", P_STRING, P_GLOBAL, GLOBAL_VAR(unix_charset), NULL, NULL}, 351 {"ncalrpc dir", P_STRING, P_GLOBAL, GLOBAL_VAR(ncalrpc_dir), NULL, NULL}, 352 {"display charset", P_STRING, P_GLOBAL, GLOBAL_VAR(display_charset), NULL, NULL}, 353 {"comment", P_STRING, P_LOCAL, LOCAL_VAR(comment), NULL, NULL}, 354 {"path", P_STRING, P_LOCAL, LOCAL_VAR(szPath), NULL, NULL}, 355 {"directory", P_STRING, P_LOCAL, LOCAL_VAR(szPath), NULL, NULL}, 356 {"workgroup", P_USTRING, P_GLOBAL, GLOBAL_VAR(szWorkgroup), NULL, NULL}, 357 {"realm", P_STRING, P_GLOBAL, GLOBAL_VAR(szRealm), handle_realm, NULL}, 358 {"netbios name", P_USTRING, P_GLOBAL, GLOBAL_VAR(szNetbiosName), NULL, NULL}, 359 {"netbios aliases", P_LIST, P_GLOBAL, GLOBAL_VAR(szNetbiosAliases), NULL, NULL}, 360 {"netbios scope", P_USTRING, P_GLOBAL, GLOBAL_VAR(szNetbiosScope), NULL, NULL}, 361 {"server string", P_STRING, P_GLOBAL, GLOBAL_VAR(szServerString), NULL, NULL}, 362 {"interfaces", P_LIST, P_GLOBAL, GLOBAL_VAR(szInterfaces), NULL, NULL}, 363 {"bind interfaces only", P_BOOL, P_GLOBAL, GLOBAL_VAR(bBindInterfacesOnly), NULL, NULL}, 364 {"ntvfs handler", P_LIST, P_LOCAL, LOCAL_VAR(ntvfs_handler), NULL, NULL}, 365 {"ntptr providor", P_STRING, P_GLOBAL, GLOBAL_VAR(ntptr_providor), NULL, NULL}, 366 {"dcerpc endpoint servers", P_LIST, P_GLOBAL, GLOBAL_VAR(dcerpc_ep_servers), NULL, NULL}, 367 {"server services", P_LIST, P_GLOBAL, GLOBAL_VAR(server_services), NULL, NULL}, 368 369 {"security", P_ENUM, P_GLOBAL, GLOBAL_VAR(security), NULL, enum_security}, 370 {"encrypt passwords", P_BOOL, P_GLOBAL, GLOBAL_VAR(bEncryptPasswords), NULL, NULL}, 371 {"null passwords", P_BOOL, P_GLOBAL, GLOBAL_VAR(bNullPasswords), NULL, NULL}, 372 {"obey pam restrictions", P_BOOL, P_GLOBAL, GLOBAL_VAR(bObeyPamRestrictions), NULL, NULL}, 373 {"password server", P_LIST, P_GLOBAL, GLOBAL_VAR(szPasswordServers), NULL, NULL}, 374 {"sam database", P_STRING, P_GLOBAL, GLOBAL_VAR(szSAM_URL), NULL, NULL}, 375 {"idmap database", P_STRING, P_GLOBAL, GLOBAL_VAR(szIDMAP_URL), NULL, NULL}, 376 {"secrets database", P_STRING, P_GLOBAL, GLOBAL_VAR(szSECRETS_URL), NULL, NULL}, 377 {"spoolss database", P_STRING, P_GLOBAL, GLOBAL_VAR(szSPOOLSS_URL), NULL, NULL}, 378 {"wins config database", P_STRING, P_GLOBAL, GLOBAL_VAR(szWINS_CONFIG_URL), NULL, NULL}, 379 {"wins database", P_STRING, P_GLOBAL, GLOBAL_VAR(szWINS_URL), NULL, NULL}, 380 {"private dir", P_STRING, P_GLOBAL, GLOBAL_VAR(szPrivateDir), NULL, NULL}, 381 {"passwd chat", P_STRING, P_GLOBAL, GLOBAL_VAR(szPasswdChat), NULL, NULL}, 382 {"password level", P_INTEGER, P_GLOBAL, GLOBAL_VAR(pwordlevel), NULL, NULL}, 383 {"lanman auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bLanmanAuth), NULL, NULL}, 384 {"ntlm auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bNTLMAuth), NULL, NULL}, 385 {"client NTLMv2 auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bClientNTLMv2Auth), NULL, NULL}, 386 {"client lanman auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bClientLanManAuth), NULL, NULL}, 387 {"client plaintext auth", P_BOOL, P_GLOBAL, GLOBAL_VAR(bClientPlaintextAuth), NULL, NULL}, 388 {"client use spnego principal", P_BOOL, P_GLOBAL, GLOBAL_VAR(client_use_spnego_principal), NULL, NULL}, 389 390 {"read only", P_BOOL, P_LOCAL, LOCAL_VAR(bRead_only), NULL, NULL}, 391 392 {"create mask", P_OCTAL, P_LOCAL, LOCAL_VAR(iCreate_mask), NULL, NULL}, 393 {"force create mode", P_OCTAL, P_LOCAL, LOCAL_VAR(iCreate_force_mode), NULL, NULL}, 394 {"directory mask", P_OCTAL, P_LOCAL, LOCAL_VAR(iDir_mask), NULL, NULL}, 395 {"force directory mode", P_OCTAL, P_LOCAL, LOCAL_VAR(iDir_force_mode), NULL, NULL}, 396 397 {"hosts allow", P_LIST, P_LOCAL, LOCAL_VAR(szHostsallow), NULL, NULL}, 398 {"hosts deny", P_LIST, P_LOCAL, LOCAL_VAR(szHostsdeny), NULL, NULL}, 399 400 {"log level", P_STRING, P_GLOBAL, GLOBAL_VAR(loglevel), handle_debuglevel, NULL}, 401 {"debuglevel", P_STRING, P_GLOBAL, GLOBAL_VAR(loglevel), handle_debuglevel, NULL}, 402 {"log file", P_STRING, P_GLOBAL, GLOBAL_VAR(logfile), handle_logfile, NULL}, 403 404 {"smb ports", P_LIST, P_GLOBAL, GLOBAL_VAR(smb_ports), NULL, NULL}, 405 {"nbt port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(nbt_port), NULL, NULL}, 406 {"dgram port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(dgram_port), NULL, NULL}, 407 {"cldap port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(cldap_port), NULL, NULL}, 408 {"krb5 port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(krb5_port), NULL, NULL}, 409 {"kpasswd port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(kpasswd_port), NULL, NULL}, 410 {"web port", P_INTEGER, P_GLOBAL, GLOBAL_VAR(web_port), NULL, NULL}, 411 {"tls enabled", P_BOOL, P_GLOBAL, GLOBAL_VAR(tls_enabled), NULL, NULL}, 412 {"tls keyfile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_keyfile), NULL, NULL}, 413 {"tls certfile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_certfile), NULL, NULL}, 414 {"tls cafile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_cafile), NULL, NULL}, 415 {"tls crlfile", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_crlfile), NULL, NULL}, 416 {"tls dh params file", P_STRING, P_GLOBAL, GLOBAL_VAR(tls_dhpfile), NULL, NULL}, 417 {"large readwrite", P_BOOL, P_GLOBAL, GLOBAL_VAR(bLargeReadwrite), NULL, NULL}, 418 {"server max protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(srv_maxprotocol), NULL, enum_protocol}, 419 {"server min protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(srv_minprotocol), NULL, enum_protocol}, 420 {"client max protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(cli_maxprotocol), NULL, enum_protocol}, 421 {"client min protocol", P_ENUM, P_GLOBAL, GLOBAL_VAR(cli_minprotocol), NULL, enum_protocol}, 422 {"unicode", P_BOOL, P_GLOBAL, GLOBAL_VAR(bUnicode), NULL, NULL}, 423 {"read raw", P_BOOL, P_GLOBAL, GLOBAL_VAR(bReadRaw), NULL, NULL}, 424 {"write raw", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWriteRaw), NULL, NULL}, 425 {"disable netbios", P_BOOL, P_GLOBAL, GLOBAL_VAR(bDisableNetbios), NULL, NULL}, 426 427 {"nt status support", P_BOOL, P_GLOBAL, GLOBAL_VAR(bNTStatusSupport), NULL, NULL}, 428 429 {"announce version", P_STRING, P_GLOBAL, GLOBAL_VAR(szAnnounceVersion), NULL, NULL}, 430 {"announce as", P_ENUM, P_GLOBAL, GLOBAL_VAR(announce_as), NULL, enum_announce_as}, 431 {"max mux", P_INTEGER, P_GLOBAL, GLOBAL_VAR(max_mux), NULL, NULL}, 432 {"max xmit", P_BYTES, P_GLOBAL, GLOBAL_VAR(max_xmit), NULL, NULL}, 433 434 {"name resolve order", P_LIST, P_GLOBAL, GLOBAL_VAR(szNameResolveOrder), NULL, NULL}, 435 {"max wins ttl", P_INTEGER, P_GLOBAL, GLOBAL_VAR(max_wins_ttl), NULL, NULL}, 436 {"min wins ttl", P_INTEGER, P_GLOBAL, GLOBAL_VAR(min_wins_ttl), NULL, NULL}, 437 {"time server", P_BOOL, P_GLOBAL, GLOBAL_VAR(bTimeServer), NULL, NULL}, 438 {"unix extensions", P_BOOL, P_GLOBAL, GLOBAL_VAR(bUnixExtensions), NULL, NULL}, 439 {"use spnego", P_BOOL, P_GLOBAL, GLOBAL_VAR(bUseSpnego), NULL, NULL}, 440 {"server signing", P_ENUM, P_GLOBAL, GLOBAL_VAR(server_signing), NULL, enum_smb_signing_vals}, 441 {"client signing", P_ENUM, P_GLOBAL, GLOBAL_VAR(client_signing), NULL, enum_smb_signing_vals}, 442 {"rpc big endian", P_BOOL, P_GLOBAL, GLOBAL_VAR(bRpcBigEndian), NULL, NULL}, 443 444 {"max connections", P_INTEGER, P_LOCAL, LOCAL_VAR(iMaxConnections), NULL, NULL}, 445 {"paranoid server security", P_BOOL, P_GLOBAL, GLOBAL_VAR(paranoid_server_security), NULL, NULL}, 446 {"socket options", P_STRING, P_GLOBAL, GLOBAL_VAR(socket_options), NULL, NULL}, 447 448 {"strict sync", P_BOOL, P_LOCAL, LOCAL_VAR(bStrictSync), NULL, NULL}, 449 {"case insensitive filesystem", P_BOOL, P_LOCAL, LOCAL_VAR(bCIFileSystem), NULL, NULL}, 450 451 {"max print jobs", P_INTEGER, P_LOCAL, LOCAL_VAR(iMaxPrintJobs), NULL, NULL}, 452 {"printable", P_BOOL, P_LOCAL, LOCAL_VAR(bPrint_ok), NULL, NULL}, 453 {"print ok", P_BOOL, P_LOCAL, LOCAL_VAR(bPrint_ok), NULL, NULL}, 454 455 {"printer name", P_STRING, P_LOCAL, LOCAL_VAR(szPrintername), NULL, NULL}, 456 {"printer", P_STRING, P_LOCAL, LOCAL_VAR(szPrintername), NULL, NULL}, 457 458 {"map system", P_BOOL, P_LOCAL, LOCAL_VAR(bMap_system), NULL, NULL}, 459 {"map hidden", P_BOOL, P_LOCAL, LOCAL_VAR(bMap_hidden), NULL, NULL}, 460 {"map archive", P_BOOL, P_LOCAL, LOCAL_VAR(bMap_archive), NULL, NULL}, 461 462 {"preferred master", P_ENUM, P_GLOBAL, GLOBAL_VAR(bPreferredMaster), NULL, enum_bool_auto}, 463 {"prefered master", P_ENUM, P_GLOBAL, GLOBAL_VAR(bPreferredMaster), NULL, enum_bool_auto}, 464 {"local master", P_BOOL, P_GLOBAL, GLOBAL_VAR(bLocalMaster), NULL, NULL}, 465 {"browseable", P_BOOL, P_LOCAL, LOCAL_VAR(bBrowseable), NULL, NULL}, 466 {"browsable", P_BOOL, P_LOCAL, LOCAL_VAR(bBrowseable), NULL, NULL}, 467 468 {"wins server", P_LIST, P_GLOBAL, GLOBAL_VAR(szWINSservers), NULL, NULL}, 469 {"wins support", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWINSsupport), NULL, NULL}, 470 {"dns proxy", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWINSdnsProxy), NULL, NULL}, 471 {"wins hook", P_STRING, P_GLOBAL, GLOBAL_VAR(szWINSHook), NULL, NULL}, 472 473 {"csc policy", P_ENUM, P_LOCAL, LOCAL_VAR(iCSCPolicy), NULL, enum_csc_policy}, 474 475 {"strict locking", P_BOOL, P_LOCAL, LOCAL_VAR(bStrictLocking), NULL, NULL}, 476 {"oplocks", P_BOOL, P_LOCAL, LOCAL_VAR(bOplocks), NULL, NULL}, 477 478 {"share backend", P_STRING, P_GLOBAL, GLOBAL_VAR(szShareBackend), NULL, NULL}, 479 {"preload", P_STRING, P_GLOBAL, GLOBAL_VAR(szAutoServices), NULL, NULL}, 480 {"auto services", P_STRING, P_GLOBAL, GLOBAL_VAR(szAutoServices), NULL, NULL}, 481 {"lock dir", P_STRING, P_GLOBAL, GLOBAL_VAR(szLockDir), NULL, NULL}, 482 {"lock directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szLockDir), NULL, NULL}, 483 {"modules dir", P_STRING, P_GLOBAL, GLOBAL_VAR(szModulesDir), NULL, NULL}, 484 {"pid directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szPidDir), NULL, NULL}, 485 486 {"socket address", P_STRING, P_GLOBAL, GLOBAL_VAR(szSocketAddress), NULL, NULL}, 487 {"copy", P_STRING, P_LOCAL, LOCAL_VAR(szCopy), handle_copy, NULL}, 488 {"include", P_STRING, P_LOCAL, LOCAL_VAR(szInclude), handle_include, NULL}, 489 490 {"available", P_BOOL, P_LOCAL, LOCAL_VAR(bAvailable), NULL, NULL}, 491 {"volume", P_STRING, P_LOCAL, LOCAL_VAR(volume), NULL, NULL }, 492 {"fstype", P_STRING, P_LOCAL, LOCAL_VAR(fstype), NULL, NULL}, 493 494 {"panic action", P_STRING, P_GLOBAL, GLOBAL_VAR(panic_action), NULL, NULL}, 495 496 {"msdfs root", P_BOOL, P_LOCAL, LOCAL_VAR(bMSDfsRoot), NULL, NULL}, 497 {"host msdfs", P_BOOL, P_GLOBAL, GLOBAL_VAR(bHostMSDfs), NULL, NULL}, 498 {"winbind separator", P_STRING, P_GLOBAL, GLOBAL_VAR(szWinbindSeparator), NULL, NULL }, 499 {"winbindd socket directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szWinbinddSocketDirectory), NULL, NULL }, 500 {"winbindd privileged socket directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szWinbinddPrivilegedSocketDirectory), NULL, NULL }, 501 {"winbind sealed pipes", P_BOOL, P_GLOBAL, GLOBAL_VAR(bWinbindSealedPipes), NULL, NULL }, 502 {"template shell", P_STRING, P_GLOBAL, GLOBAL_VAR(szTemplateShell), NULL, NULL }, 503 {"template homedir", P_STRING, P_GLOBAL, GLOBAL_VAR(szTemplateHomedir), NULL, NULL }, 504 {"idmap trusted only", P_BOOL, P_GLOBAL, GLOBAL_VAR(bIdmapTrustedOnly), NULL, NULL}, 505 506 {"ntp signd socket directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szNTPSignDSocketDirectory), NULL, NULL }, 507 {"rndc command", P_CMDLIST, P_GLOBAL, GLOBAL_VAR(szRNDCCommand), NULL, NULL }, 508 {"dns update command", P_CMDLIST, P_GLOBAL, GLOBAL_VAR(szDNSUpdateCommand), NULL, NULL }, 509 {"spn update command", P_CMDLIST, P_GLOBAL, GLOBAL_VAR(szSPNUpdateCommand), NULL, NULL }, 510 {"nsupdate command", P_CMDLIST, P_GLOBAL, GLOBAL_VAR(szNSUpdateCommand), NULL, NULL }, 511 512 {NULL, P_BOOL, P_NONE, 0, NULL, NULL} 513 }; 514 515 516 /* local variables */ 517 struct loadparm_context { 518 const char *szConfigFile; 519 struct loadparm_global *globals; 520 struct loadparm_service **services; 521 struct loadparm_service *sDefault; 522 struct smb_iconv_convenience *iconv_convenience; 523 int iNumServices; 524 struct loadparm_service *currentService; 525 bool bInGlobalSection; 526 struct file_lists { 527 struct file_lists *next; 528 char *name; 529 char *subfname; 530 time_t modtime; 531 } *file_lists; 532 unsigned int flags[NUMPARAMETERS]; 533 bool loaded; 534 bool refuse_free; 535 }; 536 537 538 struct loadparm_service *lpcfg_default_service(struct loadparm_context *lp_ctx) 539 { 540 return lp_ctx->sDefault; 541 } 542 543 /* 544 return the parameter table 545 */ 546 struct parm_struct *lpcfg_parm_table(void) 547 { 548 return parm_table; 549 } 550 551 /** 552 * Convenience routine to grab string parameters into temporary memory 553 * and run standard_sub_basic on them. 554 * 555 * The buffers can be written to by 556 * callers without affecting the source string. 557 */ 558 559 static const char *lp_string(const char *s) 560 { 561 #if 0 /* until REWRITE done to make thread-safe */ 562 size_t len = s ? strlen(s) : 0; 563 char *ret; 564 #endif 565 566 /* The follow debug is useful for tracking down memory problems 567 especially if you have an inner loop that is calling a lp_*() 568 function that returns a string. Perhaps this debug should be 569 present all the time? */ 570 571 #if 0 572 DEBUG(10, ("lp_string(%s)\n", s)); 573 #endif 574 575 #if 0 /* until REWRITE done to make thread-safe */ 576 if (!lp_talloc) 577 lp_talloc = talloc_init("lp_talloc"); 578 579 ret = talloc_array(lp_talloc, char, len + 100); /* leave room for substitution */ 580 581 if (!ret) 582 return NULL; 583 584 if (!s) 585 *ret = 0; 586 else 587 strlcpy(ret, s, len); 588 589 if (trim_string(ret, "\"", "\"")) { 590 if (strchr(ret,'"') != NULL) 591 strlcpy(ret, s, len); 592 } 593 594 standard_sub_basic(ret,len+100); 595 return (ret); 596 #endif 597 return s; 598 } 599 600 /* 601 In this section all the functions that are used to access the 602 parameters from the rest of the program are defined 603 */ 604 605 /* 606 * the creation of separate lpcfg_*() and lp_*() functions is to allow 607 * for code compatibility between existing Samba4 and Samba3 code. 608 */ 609 610 /* this global context supports the lp_*() function varients */ 611 static struct loadparm_context *global_loadparm_context; 612 613 #define lpcfg_default_service global_loadparm_context->sDefault 614 #define lpcfg_global_service(i) global_loadparm_context->services[i] 615 616 #define FN_GLOBAL_STRING(fn_name,var_name) \ 617 _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->globals->var_name ? lp_string(lp_ctx->globals->var_name) : "";} 618 619 #define FN_GLOBAL_CONST_STRING(fn_name,var_name) \ 620 _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->globals->var_name ? lp_ctx->globals->var_name : "";} 621 622 #define FN_GLOBAL_LIST(fn_name,var_name) \ 623 _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return NULL; return lp_ctx->globals->var_name;} 624 625 #define FN_GLOBAL_BOOL(fn_name,var_name) \ 626 _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {if (lp_ctx == NULL) return false; return lp_ctx->globals->var_name;} 627 628 #define FN_GLOBAL_INTEGER(fn_name,var_name) \ 629 _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {return lp_ctx->globals->var_name;} 630 631 #define FN_LOCAL_STRING(fn_name,val) \ 632 _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_service *service, struct loadparm_service *sDefault) {return(lp_string((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault->val)));} 633 634 #define FN_LOCAL_LIST(fn_name,val) \ 635 _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_service *service, struct loadparm_service *sDefault) {return(const char **)(service != NULL && service->val != NULL? service->val : sDefault->val);} 636 637 #define FN_LOCAL_BOOL(fn_name,val) \ 638 _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_service *service, struct loadparm_service *sDefault) {return((service != NULL)? service->val : sDefault->val);} 639 640 #define FN_LOCAL_INTEGER(fn_name,val) \ 641 _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_service *service, struct loadparm_service *sDefault) {return((service != NULL)? service->val : sDefault->val);} 642 643 FN_GLOBAL_INTEGER(server_role, server_role) 644 FN_GLOBAL_INTEGER(sid_generator, sid_generator) 645 FN_GLOBAL_LIST(smb_ports, smb_ports) 646 FN_GLOBAL_INTEGER(nbt_port, nbt_port) 647 FN_GLOBAL_INTEGER(dgram_port, dgram_port) 648 FN_GLOBAL_INTEGER(cldap_port, cldap_port) 649 FN_GLOBAL_INTEGER(krb5_port, krb5_port) 650 FN_GLOBAL_INTEGER(kpasswd_port, kpasswd_port) 651 FN_GLOBAL_INTEGER(web_port, web_port) 652 FN_GLOBAL_BOOL(tls_enabled, tls_enabled) 653 FN_GLOBAL_STRING(share_backend, szShareBackend) 654 FN_GLOBAL_STRING(sam_url, szSAM_URL) 655 FN_GLOBAL_STRING(idmap_url, szIDMAP_URL) 656 FN_GLOBAL_STRING(secrets_url, szSECRETS_URL) 657 FN_GLOBAL_STRING(spoolss_url, szSPOOLSS_URL) 658 FN_GLOBAL_STRING(wins_config_url, szWINS_CONFIG_URL) 659 FN_GLOBAL_STRING(wins_url, szWINS_URL) 660 FN_GLOBAL_CONST_STRING(winbind_separator, szWinbindSeparator) 661 FN_GLOBAL_CONST_STRING(winbindd_socket_directory, szWinbinddSocketDirectory) 662 FN_GLOBAL_CONST_STRING(winbindd_privileged_socket_directory, szWinbinddPrivilegedSocketDirectory) 663 FN_GLOBAL_CONST_STRING(template_shell, szTemplateShell) 664 FN_GLOBAL_CONST_STRING(template_homedir, szTemplateHomedir) 665 FN_GLOBAL_BOOL(winbind_sealed_pipes, bWinbindSealedPipes) 666 FN_GLOBAL_BOOL(idmap_trusted_only, bIdmapTrustedOnly) 667 FN_GLOBAL_STRING(private_dir, szPrivateDir) 668 FN_GLOBAL_STRING(serverstring, szServerString) 669 FN_GLOBAL_STRING(lockdir, szLockDir) 670 FN_GLOBAL_STRING(modulesdir, szModulesDir) 671 FN_GLOBAL_STRING(ncalrpc_dir, ncalrpc_dir) 672 FN_GLOBAL_STRING(dos_charset, dos_charset) 673 FN_GLOBAL_STRING(unix_charset, unix_charset) 674 FN_GLOBAL_STRING(display_charset, display_charset) 675 FN_GLOBAL_STRING(piddir, szPidDir) 676 FN_GLOBAL_LIST(rndc_command, szRNDCCommand) 677 FN_GLOBAL_LIST(dns_update_command, szDNSUpdateCommand) 678 FN_GLOBAL_LIST(spn_update_command, szSPNUpdateCommand) 679 FN_GLOBAL_LIST(nsupdate_command, szNSUpdateCommand) 680 FN_GLOBAL_LIST(dcerpc_endpoint_servers, dcerpc_ep_servers) 681 FN_GLOBAL_LIST(server_services, server_services) 682 FN_GLOBAL_STRING(ntptr_providor, ntptr_providor) 683 FN_GLOBAL_STRING(auto_services, szAutoServices) 684 FN_GLOBAL_STRING(passwd_chat, szPasswdChat) 685 FN_GLOBAL_LIST(passwordserver, szPasswordServers) 686 FN_GLOBAL_LIST(name_resolve_order, szNameResolveOrder) 687 FN_GLOBAL_STRING(realm, szRealm_upper) 688 FN_GLOBAL_STRING(dnsdomain, szRealm_lower) 689 FN_GLOBAL_STRING(socket_options, socket_options) 690 FN_GLOBAL_STRING(workgroup, szWorkgroup) 691 FN_GLOBAL_STRING(netbios_name, szNetbiosName) 692 FN_GLOBAL_STRING(netbios_scope, szNetbiosScope) 693 FN_GLOBAL_LIST(wins_server_list, szWINSservers) 694 FN_GLOBAL_LIST(interfaces, szInterfaces) 695 FN_GLOBAL_STRING(socket_address, szSocketAddress) 696 FN_GLOBAL_LIST(netbios_aliases, szNetbiosAliases) 697 FN_GLOBAL_BOOL(disable_netbios, bDisableNetbios) 698 FN_GLOBAL_BOOL(wins_support, bWINSsupport) 699 FN_GLOBAL_BOOL(wins_dns_proxy, bWINSdnsProxy) 700 FN_GLOBAL_STRING(wins_hook, szWINSHook) 701 FN_GLOBAL_BOOL(local_master, bLocalMaster) 702 FN_GLOBAL_BOOL(readraw, bReadRaw) 703 FN_GLOBAL_BOOL(large_readwrite, bLargeReadwrite) 704 FN_GLOBAL_BOOL(writeraw, bWriteRaw) 705 FN_GLOBAL_BOOL(null_passwords, bNullPasswords) 706 FN_GLOBAL_BOOL(obey_pam_restrictions, bObeyPamRestrictions) 707 FN_GLOBAL_BOOL(encrypted_passwords, bEncryptPasswords) 708 FN_GLOBAL_BOOL(time_server, bTimeServer) 709 FN_GLOBAL_BOOL(bind_interfaces_only, bBindInterfacesOnly) 710 FN_GLOBAL_BOOL(unicode, bUnicode) 711 FN_GLOBAL_BOOL(nt_status_support, bNTStatusSupport) 712 FN_GLOBAL_BOOL(lanman_auth, bLanmanAuth) 713 FN_GLOBAL_BOOL(ntlm_auth, bNTLMAuth) 714 FN_GLOBAL_BOOL(client_plaintext_auth, bClientPlaintextAuth) 715 FN_GLOBAL_BOOL(client_lanman_auth, bClientLanManAuth) 716 FN_GLOBAL_BOOL(client_ntlmv2_auth, bClientNTLMv2Auth) 717 FN_GLOBAL_BOOL(client_use_spnego_principal, client_use_spnego_principal) 718 FN_GLOBAL_BOOL(host_msdfs, bHostMSDfs) 719 FN_GLOBAL_BOOL(unix_extensions, bUnixExtensions) 720 FN_GLOBAL_BOOL(use_spnego, bUseSpnego) 721 FN_GLOBAL_BOOL(rpc_big_endian, bRpcBigEndian) 722 FN_GLOBAL_INTEGER(max_wins_ttl, max_wins_ttl) 723 FN_GLOBAL_INTEGER(min_wins_ttl, min_wins_ttl) 724 FN_GLOBAL_INTEGER(maxmux, max_mux) 725 FN_GLOBAL_INTEGER(max_xmit, max_xmit) 726 FN_GLOBAL_INTEGER(passwordlevel, pwordlevel) 727 FN_GLOBAL_INTEGER(srv_maxprotocol, srv_maxprotocol) 728 FN_GLOBAL_INTEGER(srv_minprotocol, srv_minprotocol) 729 FN_GLOBAL_INTEGER(cli_maxprotocol, cli_maxprotocol) 730 FN_GLOBAL_INTEGER(cli_minprotocol, cli_minprotocol) 731 FN_GLOBAL_INTEGER(security, security) 732 FN_GLOBAL_BOOL(paranoid_server_security, paranoid_server_security) 733 FN_GLOBAL_INTEGER(announce_as, announce_as) 734 735 FN_LOCAL_STRING(pathname, szPath) 736 FN_LOCAL_LIST(hostsallow, szHostsallow) 737 FN_LOCAL_LIST(hostsdeny, szHostsdeny) 738 FN_LOCAL_STRING(comment, comment) 739 FN_LOCAL_STRING(fstype, fstype) 740 FN_LOCAL_LIST(ntvfs_handler, ntvfs_handler) 741 FN_LOCAL_BOOL(msdfs_root, bMSDfsRoot) 742 FN_LOCAL_BOOL(browseable, bBrowseable) 743 FN_LOCAL_BOOL(readonly, bRead_only) 744 FN_LOCAL_BOOL(print_ok, bPrint_ok) 745 FN_LOCAL_BOOL(map_hidden, bMap_hidden) 746 FN_LOCAL_BOOL(map_archive, bMap_archive) 747 FN_LOCAL_BOOL(strict_locking, bStrictLocking) 748 FN_LOCAL_BOOL(oplocks, bOplocks) 749 FN_LOCAL_BOOL(strict_sync, bStrictSync) 750 FN_LOCAL_BOOL(ci_filesystem, bCIFileSystem) 751 FN_LOCAL_BOOL(map_system, bMap_system) 752 FN_LOCAL_INTEGER(max_connections, iMaxConnections) 753 FN_LOCAL_INTEGER(csc_policy, iCSCPolicy) 754 FN_LOCAL_INTEGER(create_mask, iCreate_mask) 755 FN_LOCAL_INTEGER(force_create_mode, iCreate_force_mode) 756 FN_LOCAL_INTEGER(dir_mask, iDir_mask) 757 FN_LOCAL_INTEGER(force_dir_mode, iDir_force_mode) 758 FN_GLOBAL_INTEGER(server_signing, server_signing) 759 FN_GLOBAL_INTEGER(client_signing, client_signing) 760 761 FN_GLOBAL_CONST_STRING(ntp_signd_socket_directory, szNTPSignDSocketDirectory) 762 763 /* local prototypes */ 764 static int map_parameter(const char *pszParmName); 765 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx, 766 const char *pszServiceName); 767 static void copy_service(struct loadparm_service *pserviceDest, 768 struct loadparm_service *pserviceSource, 769 int *pcopymapDest); 770 static bool service_ok(struct loadparm_service *service); 771 static bool do_section(const char *pszSectionName, void *); 772 static void init_copymap(struct loadparm_service *pservice); 773 774 /* This is a helper function for parametrical options support. */ 775 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */ 776 /* Actual parametrical functions are quite simple */ 777 const char *lpcfg_get_parametric(struct loadparm_context *lp_ctx, 778 struct loadparm_service *service, 779 const char *type, const char *option) 780 { 781 char *vfskey = NULL; 782 struct parmlist_entry *data; 783 784 if (lp_ctx == NULL) 785 return NULL; 786 787 data = (service == NULL ? lp_ctx->globals->param_opt : service->param_opt); 788 789 asprintf(&vfskey, "%s:%s", type, option); 790 if (vfskey == NULL) return NULL; 791 strlower(vfskey); 792 793 while (data) { 794 if (strcmp(data->key, vfskey) == 0) { 795 free(vfskey); 796 return data->value; 797 } 798 data = data->next; 799 } 800 801 if (service != NULL) { 802 /* Try to fetch the same option but from globals */ 803 /* but only if we are not already working with globals */ 804 for (data = lp_ctx->globals->param_opt; data; 805 data = data->next) { 806 if (strcmp(data->key, vfskey) == 0) { 807 free(vfskey); 808 return data->value; 809 } 810 } 811 } 812 813 free(vfskey); 814 815 return NULL; 816 } 817 818 819 /** 820 * convenience routine to return int parameters. 821 */ 822 static int lp_int(const char *s) 823 { 824 825 if (!s) { 826 DEBUG(0,("lp_int(%s): is called with NULL!\n",s)); 827 return -1; 828 } 829 830 return strtol(s, NULL, 0); 831 } 832 833 /** 834 * convenience routine to return unsigned long parameters. 835 */ 836 static int lp_ulong(const char *s) 837 { 838 839 if (!s) { 840 DEBUG(0,("lp_int(%s): is called with NULL!\n",s)); 841 return -1; 842 } 843 844 return strtoul(s, NULL, 0); 845 } 846 847 /** 848 * convenience routine to return unsigned long parameters. 849 */ 850 static double lp_double(const char *s) 851 { 852 853 if (!s) { 854 DEBUG(0,("lp_double(%s): is called with NULL!\n",s)); 855 return -1; 856 } 857 858 return strtod(s, NULL); 859 } 860 861 /** 862 * convenience routine to return boolean parameters. 863 */ 864 static bool lp_bool(const char *s) 865 { 866 bool ret = false; 867 868 if (!s) { 869 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s)); 870 return false; 871 } 872 873 if (!set_boolean(s, &ret)) { 874 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s)); 875 return false; 876 } 877 878 return ret; 879 } 880 881 882 /** 883 * Return parametric option from a given service. Type is a part of option before ':' 884 * Parametric option has following syntax: 'Type: option = value' 885 * Returned value is allocated in 'lp_talloc' context 886 */ 887 888 const char *lpcfg_parm_string(struct loadparm_context *lp_ctx, 889 struct loadparm_service *service, const char *type, 890 const char *option) 891 { 892 const char *value = lpcfg_get_parametric(lp_ctx, service, type, option); 893 894 if (value) 895 return lp_string(value); 896 897 return NULL; 898 } 899 900 /** 901 * Return parametric option from a given service. Type is a part of option before ':' 902 * Parametric option has following syntax: 'Type: option = value' 903 * Returned value is allocated in 'lp_talloc' context 904 */ 905 906 const char **lpcfg_parm_string_list(TALLOC_CTX *mem_ctx, 907 struct loadparm_context *lp_ctx, 908 struct loadparm_service *service, 909 const char *type, 910 const char *option, const char *separator) 911 { 912 const char *value = lpcfg_get_parametric(lp_ctx, service, type, option); 913 914 if (value != NULL) 915 return (const char **)str_list_make(mem_ctx, value, separator); 916 917 return NULL; 918 } 919 920 /** 921 * Return parametric option from a given service. Type is a part of option before ':' 922 * Parametric option has following syntax: 'Type: option = value' 923 */ 924 925 int lpcfg_parm_int(struct loadparm_context *lp_ctx, 926 struct loadparm_service *service, const char *type, 927 const char *option, int default_v) 928 { 929 const char *value = lpcfg_get_parametric(lp_ctx, service, type, option); 930 931 if (value) 932 return lp_int(value); 933 934 return default_v; 935 } 936 937 /** 938 * Return parametric option from a given service. Type is a part of 939 * option before ':'. 940 * Parametric option has following syntax: 'Type: option = value'. 941 */ 942 943 int lpcfg_parm_bytes(struct loadparm_context *lp_ctx, 944 struct loadparm_service *service, const char *type, 945 const char *option, int default_v) 946 { 947 uint64_t bval; 948 949 const char *value = lpcfg_get_parametric(lp_ctx, service, type, option); 950 951 if (value && conv_str_size(value, &bval)) { 952 if (bval <= INT_MAX) { 953 return (int)bval; 954 } 955 } 956 957 return default_v; 958 } 959 960 /** 961 * Return parametric option from a given service. 962 * Type is a part of option before ':' 963 * Parametric option has following syntax: 'Type: option = value' 964 */ 965 unsigned long lpcfg_parm_ulong(struct loadparm_context *lp_ctx, 966 struct loadparm_service *service, const char *type, 967 const char *option, unsigned long default_v) 968 { 969 const char *value = lpcfg_get_parametric(lp_ctx, service, type, option); 970 971 if (value) 972 return lp_ulong(value); 973 974 return default_v; 975 } 976 977 978 double lpcfg_parm_double(struct loadparm_context *lp_ctx, 979 struct loadparm_service *service, const char *type, 980 const char *option, double default_v) 981 { 982 const char *value = lpcfg_get_parametric(lp_ctx, service, type, option); 983 984 if (value != NULL) 985 return lp_double(value); 986 987 return default_v; 988 } 989 990 /** 991 * Return parametric option from a given service. Type is a part of option before ':' 992 * Parametric option has following syntax: 'Type: option = value' 993 */ 994 995 bool lpcfg_parm_bool(struct loadparm_context *lp_ctx, 996 struct loadparm_service *service, const char *type, 997 const char *option, bool default_v) 998 { 999 const char *value = lpcfg_get_parametric(lp_ctx, service, type, option); 1000 1001 if (value != NULL) 1002 return lp_bool(value); 1003 1004 return default_v; 1005 } 1006 1007 1008 /** 1009 * Initialise a service to the defaults. 1010 */ 1011 1012 static struct loadparm_service *init_service(TALLOC_CTX *mem_ctx, struct loadparm_service *sDefault) 1013 { 1014 struct loadparm_service *pservice = 1015 talloc_zero(mem_ctx, struct loadparm_service); 1016 copy_service(pservice, sDefault, NULL); 1017 return pservice; 1018 } 1019 1020 /** 1021 * Set a string value, deallocating any existing space, and allocing the space 1022 * for the string 1023 */ 1024 static bool string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src) 1025 { 1026 talloc_free(*dest); 1027 1028 if (src == NULL) 1029 src = ""; 1030 1031 *dest = talloc_strdup(mem_ctx, src); 1032 if ((*dest) == NULL) { 1033 DEBUG(0,("Out of memory in string_init\n")); 1034 return false; 1035 } 1036 1037 return true; 1038 } 1039 1040 1041 1042 /** 1043 * Add a new service to the services array initialising it with the given 1044 * service. 1045 */ 1046 1047 struct loadparm_service *lpcfg_add_service(struct loadparm_context *lp_ctx, 1048 const struct loadparm_service *pservice, 1049 const char *name) 1050 { 1051 int i; 1052 struct loadparm_service tservice; 1053 int num_to_alloc = lp_ctx->iNumServices + 1; 1054 struct parmlist_entry *data, *pdata; 1055 1056 if (pservice == NULL) { 1057 pservice = lp_ctx->sDefault; 1058 } 1059 1060 tservice = *pservice; 1061 1062 /* it might already exist */ 1063 if (name) { 1064 struct loadparm_service *service = getservicebyname(lp_ctx, 1065 name); 1066 if (service != NULL) { 1067 /* Clean all parametric options for service */ 1068 /* They will be added during parsing again */ 1069 data = service->param_opt; 1070 while (data) { 1071 pdata = data->next; 1072 talloc_free(data); 1073 data = pdata; 1074 } 1075 service->param_opt = NULL; 1076 return service; 1077 } 1078 } 1079 1080 /* find an invalid one */ 1081 for (i = 0; i < lp_ctx->iNumServices; i++) 1082 if (lp_ctx->services[i] == NULL) 1083 break; 1084 1085 /* if not, then create one */ 1086 if (i == lp_ctx->iNumServices) { 1087 struct loadparm_service **tsp; 1088 1089 tsp = talloc_realloc(lp_ctx, lp_ctx->services, struct loadparm_service *, num_to_alloc); 1090 1091 if (!tsp) { 1092 DEBUG(0,("lpcfg_add_service: failed to enlarge services!\n")); 1093 return NULL; 1094 } else { 1095 lp_ctx->services = tsp; 1096 lp_ctx->services[lp_ctx->iNumServices] = NULL; 1097 } 1098 1099 lp_ctx->iNumServices++; 1100 } 1101 1102 lp_ctx->services[i] = init_service(lp_ctx->services, lp_ctx->sDefault); 1103 if (lp_ctx->services[i] == NULL) { 1104 DEBUG(0,("lpcfg_add_service: out of memory!\n")); 1105 return NULL; 1106 } 1107 copy_service(lp_ctx->services[i], &tservice, NULL); 1108 if (name != NULL) 1109 string_set(lp_ctx->services[i], &lp_ctx->services[i]->szService, name); 1110 return lp_ctx->services[i]; 1111 } 1112 1113 /** 1114 * Add a new home service, with the specified home directory, defaults coming 1115 * from service ifrom. 1116 */ 1117 1118 bool lpcfg_add_home(struct loadparm_context *lp_ctx, 1119 const char *pszHomename, 1120 struct loadparm_service *default_service, 1121 const char *user, const char *pszHomedir) 1122 { 1123 struct loadparm_service *service; 1124 1125 service = lpcfg_add_service(lp_ctx, default_service, pszHomename); 1126 1127 if (service == NULL) 1128 return false; 1129 1130 if (!(*(default_service->szPath)) 1131 || strequal(default_service->szPath, lp_ctx->sDefault->szPath)) { 1132 service->szPath = talloc_strdup(service, pszHomedir); 1133 } else { 1134 service->szPath = string_sub_talloc(service, lpcfg_pathname(default_service, lp_ctx->sDefault), "%H", pszHomedir); 1135 } 1136 1137 if (!(*(service->comment))) { 1138 service->comment = talloc_asprintf(service, "Home directory of %s", user); 1139 } 1140 service->bAvailable = default_service->bAvailable; 1141 service->bBrowseable = default_service->bBrowseable; 1142 1143 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", 1144 pszHomename, user, service->szPath)); 1145 1146 return true; 1147 } 1148 1149 /** 1150 * Add a new printer service, with defaults coming from service iFrom. 1151 */ 1152 1153 bool lp_add_printer(struct loadparm_context *lp_ctx, 1154 const char *pszPrintername, 1155 struct loadparm_service *default_service) 1156 { 1157 const char *comment = "From Printcap"; 1158 struct loadparm_service *service; 1159 service = lpcfg_add_service(lp_ctx, default_service, pszPrintername); 1160 1161 if (service == NULL) 1162 return false; 1163 1164 /* note that we do NOT default the availability flag to True - */ 1165 /* we take it from the default service passed. This allows all */ 1166 /* dynamic printers to be disabled by disabling the [printers] */ 1167 /* entry (if/when the 'available' keyword is implemented!). */ 1168 1169 /* the printer name is set to the service name. */ 1170 string_set(service, &service->szPrintername, pszPrintername); 1171 string_set(service, &service->comment, comment); 1172 service->bBrowseable = default_service->bBrowseable; 1173 /* Printers cannot be read_only. */ 1174 service->bRead_only = false; 1175 /* Printer services must be printable. */ 1176 service->bPrint_ok = true; 1177 1178 DEBUG(3, ("adding printer service %s\n", pszPrintername)); 1179 1180 return true; 1181 } 1182 1183 /** 1184 * Map a parameter's string representation to something we can use. 1185 * Returns False if the parameter string is not recognised, else TRUE. 1186 */ 1187 1188 static int map_parameter(const char *pszParmName) 1189 { 1190 int iIndex; 1191 1192 if (*pszParmName == '-') 1193 return -1; 1194 1195 for (iIndex = 0; parm_table[iIndex].label; iIndex++) 1196 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0) 1197 return iIndex; 1198 1199 /* Warn only if it isn't parametric option */ 1200 if (strchr(pszParmName, ':') == NULL) 1201 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName)); 1202 /* We do return 'fail' for parametric options as well because they are 1203 stored in different storage 1204 */ 1205 return -1; 1206 } 1207 1208 1209 /** 1210 return the parameter structure for a parameter 1211 */ 1212 struct parm_struct *lpcfg_parm_struct(const char *name) 1213 { 1214 int parmnum = map_parameter(name); 1215 if (parmnum == -1) return NULL; 1216 return &parm_table[parmnum]; 1217 } 1218 1219 /** 1220 return the parameter pointer for a parameter 1221 */ 1222 void *lpcfg_parm_ptr(struct loadparm_context *lp_ctx, 1223 struct loadparm_service *service, struct parm_struct *parm) 1224 { 1225 if (service == NULL) { 1226 if (parm->pclass == P_LOCAL) 1227 return ((char *)lp_ctx->sDefault)+parm->offset; 1228 else if (parm->pclass == P_GLOBAL) 1229 return ((char *)lp_ctx->globals)+parm->offset; 1230 else return NULL; 1231 } else { 1232 return ((char *)service) + parm->offset; 1233 } 1234 } 1235 1236 /** 1237 * Find a service by name. Otherwise works like get_service. 1238 */ 1239 1240 static struct loadparm_service *getservicebyname(struct loadparm_context *lp_ctx, 1241 const char *pszServiceName) 1242 { 1243 int iService; 1244 1245 for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) 1246 if (lp_ctx->services[iService] != NULL && 1247 strwicmp(lp_ctx->services[iService]->szService, pszServiceName) == 0) { 1248 return lp_ctx->services[iService]; 1249 } 1250 1251 return NULL; 1252 } 1253 1254 /** 1255 * Copy a service structure to another. 1256 * If pcopymapDest is NULL then copy all fields 1257 */ 1258 1259 static void copy_service(struct loadparm_service *pserviceDest, 1260 struct loadparm_service *pserviceSource, 1261 int *pcopymapDest) 1262 { 1263 int i; 1264 bool bcopyall = (pcopymapDest == NULL); 1265 struct parmlist_entry *data, *pdata, *paramo; 1266 bool not_added; 1267 1268 for (i = 0; parm_table[i].label; i++) 1269 if (parm_table[i].offset != -1 && parm_table[i].pclass == P_LOCAL && 1270 (bcopyall || pcopymapDest[i])) { 1271 void *src_ptr = 1272 ((char *)pserviceSource) + parm_table[i].offset; 1273 void *dest_ptr = 1274 ((char *)pserviceDest) + parm_table[i].offset; 1275 1276 switch (parm_table[i].type) { 1277 case P_BOOL: 1278 *(int *)dest_ptr = *(int *)src_ptr; 1279 break; 1280 1281 case P_INTEGER: 1282 case P_OCTAL: 1283 case P_ENUM: 1284 *(int *)dest_ptr = *(int *)src_ptr; 1285 break; 1286 1287 case P_STRING: 1288 string_set(pserviceDest, 1289 (char **)dest_ptr, 1290 *(char **)src_ptr); 1291 break; 1292 1293 case P_USTRING: 1294 string_set(pserviceDest, 1295 (char **)dest_ptr, 1296 *(char **)src_ptr); 1297 strupper(*(char **)dest_ptr); 1298 break; 1299 case P_LIST: 1300 *(const char ***)dest_ptr = (const char **)str_list_copy(pserviceDest, 1301 *(const char ***)src_ptr); 1302 break; 1303 default: 1304 break; 1305 } 1306 } 1307 1308 if (bcopyall) { 1309 init_copymap(pserviceDest); 1310 if (pserviceSource->copymap) 1311 memcpy((void *)pserviceDest->copymap, 1312 (void *)pserviceSource->copymap, 1313 sizeof(int) * NUMPARAMETERS); 1314 } 1315 1316 data = pserviceSource->param_opt; 1317 while (data) { 1318 not_added = true; 1319 pdata = pserviceDest->param_opt; 1320 /* Traverse destination */ 1321 while (pdata) { 1322 /* If we already have same option, override it */ 1323 if (strcmp(pdata->key, data->key) == 0) { 1324 talloc_free(pdata->value); 1325 pdata->value = talloc_reference(pdata, 1326 data->value); 1327 not_added = false; 1328 break; 1329 } 1330 pdata = pdata->next; 1331 } 1332 if (not_added) { 1333 paramo = talloc_zero(pserviceDest, struct parmlist_entry); 1334 if (paramo == NULL) 1335 smb_panic("OOM"); 1336 paramo->key = talloc_reference(paramo, data->key); 1337 paramo->value = talloc_reference(paramo, data->value); 1338 DLIST_ADD(pserviceDest->param_opt, paramo); 1339 } 1340 data = data->next; 1341 } 1342 } 1343 1344 /** 1345 * Check a service for consistency. Return False if the service is in any way 1346 * incomplete or faulty, else True. 1347 */ 1348 static bool service_ok(struct loadparm_service *service) 1349 { 1350 bool bRetval; 1351 1352 bRetval = true; 1353 if (service->szService[0] == '\0') { 1354 DEBUG(0, ("The following message indicates an internal error:\n")); 1355 DEBUG(0, ("No service name in service entry.\n")); 1356 bRetval = false; 1357 } 1358 1359 /* The [printers] entry MUST be printable. I'm all for flexibility, but */ 1360 /* I can't see why you'd want a non-printable printer service... */ 1361 if (strwicmp(service->szService, PRINTERS_NAME) == 0) { 1362 if (!service->bPrint_ok) { 1363 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n", 1364 service->szService)); 1365 service->bPrint_ok = true; 1366 } 1367 /* [printers] service must also be non-browsable. */ 1368 if (service->bBrowseable) 1369 service->bBrowseable = false; 1370 } 1371 1372 /* If a service is flagged unavailable, log the fact at level 0. */ 1373 if (!service->bAvailable) 1374 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n", 1375 service->szService)); 1376 1377 return bRetval; 1378 } 1379 1380 1381 /******************************************************************* 1382 Keep a linked list of all config files so we know when one has changed 1383 it's date and needs to be reloaded. 1384 ********************************************************************/ 1385 1386 static void add_to_file_list(struct loadparm_context *lp_ctx, 1387 const char *fname, const char *subfname) 1388 { 1389 struct file_lists *f = lp_ctx->file_lists; 1390 1391 while (f) { 1392 if (f->name && !strcmp(f->name, fname)) 1393 break; 1394 f = f->next; 1395 } 1396 1397 if (!f) { 1398 f = talloc(lp_ctx, struct file_lists); 1399 if (!f) 1400 return; 1401 f->next = lp_ctx->file_lists; 1402 f->name = talloc_strdup(f, fname); 1403 if (!f->name) { 1404 talloc_free(f); 1405 return; 1406 } 1407 f->subfname = talloc_strdup(f, subfname); 1408 if (!f->subfname) { 1409 talloc_free(f); 1410 return; 1411 } 1412 lp_ctx->file_lists = f; 1413 f->modtime = file_modtime(subfname); 1414 } else { 1415 time_t t = file_modtime(subfname); 1416 if (t) 1417 f->modtime = t; 1418 } 1419 } 1420 1421 /******************************************************************* 1422 Check if a config file has changed date. 1423 ********************************************************************/ 1424 bool lp_file_list_changed(struct loadparm_context *lp_ctx) 1425 { 1426 struct file_lists *f; 1427 DEBUG(6, ("lp_file_list_changed()\n")); 1428 1429 for (f = lp_ctx->file_lists; f != NULL; f = f->next) { 1430 char *n2; 1431 time_t mod_time; 1432 1433 n2 = standard_sub_basic(lp_ctx, f->name); 1434 1435 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n", 1436 f->name, n2, ctime(&f->modtime))); 1437 1438 mod_time = file_modtime(n2); 1439 1440 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) { 1441 DEBUGADD(6, ("file %s modified: %s\n", n2, 1442 ctime(&mod_time))); 1443 f->modtime = mod_time; 1444 talloc_free(f->subfname); 1445 f->subfname = talloc_strdup(f, n2); 1446 return true; 1447 } 1448 } 1449 return false; 1450 } 1451 1452 /*************************************************************************** 1453 Handle the "realm" parameter 1454 ***************************************************************************/ 1455 1456 static bool handle_realm(struct loadparm_context *lp_ctx, 1457 const char *pszParmValue, char **ptr) 1458 { 1459 string_set(lp_ctx, ptr, pszParmValue); 1460 1461 talloc_free(lp_ctx->globals->szRealm_upper); 1462 talloc_free(lp_ctx->globals->szRealm_lower); 1463 1464 lp_ctx->globals->szRealm_upper = strupper_talloc(lp_ctx, pszParmValue); 1465 lp_ctx->globals->szRealm_lower = strlower_talloc(lp_ctx, pszParmValue); 1466 1467 return true; 1468 } 1469 1470 /*************************************************************************** 1471 Handle the include operation. 1472 ***************************************************************************/ 1473 1474 static bool handle_include(struct loadparm_context *lp_ctx, 1475 const char *pszParmValue, char **ptr) 1476 { 1477 char *fname = standard_sub_basic(lp_ctx, pszParmValue); 1478 1479 add_to_file_list(lp_ctx, pszParmValue, fname); 1480 1481 string_set(lp_ctx, ptr, fname); 1482 1483 if (file_exist(fname)) 1484 return pm_process(fname, do_section, do_parameter, lp_ctx); 1485 1486 DEBUG(2, ("Can't find include file %s\n", fname)); 1487 1488 return false; 1489 } 1490 1491 /*************************************************************************** 1492 Handle the interpretation of the copy parameter. 1493 ***************************************************************************/ 1494 1495 static bool handle_copy(struct loadparm_context *lp_ctx, 1496 const char *pszParmValue, char **ptr) 1497 { 1498 bool bRetval; 1499 struct loadparm_service *serviceTemp; 1500 1501 string_set(lp_ctx, ptr, pszParmValue); 1502 1503 bRetval = false; 1504 1505 DEBUG(3, ("Copying service from service %s\n", pszParmValue)); 1506 1507 if ((serviceTemp = getservicebyname(lp_ctx, pszParmValue)) != NULL) { 1508 if (serviceTemp == lp_ctx->currentService) { 1509 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue)); 1510 } else { 1511 copy_service(lp_ctx->currentService, 1512 serviceTemp, 1513 lp_ctx->currentService->copymap); 1514 bRetval = true; 1515 } 1516 } else { 1517 DEBUG(0, ("Unable to copy service - source not found: %s\n", 1518 pszParmValue)); 1519 bRetval = false; 1520 } 1521 1522 return bRetval; 1523 } 1524 1525 static bool handle_debuglevel(struct loadparm_context *lp_ctx, 1526 const char *pszParmValue, char **ptr) 1527 { 1528 1529 string_set(lp_ctx, ptr, pszParmValue); 1530 return debug_parse_levels(pszParmValue); 1531 } 1532 1533 static bool handle_logfile(struct loadparm_context *lp_ctx, 1534 const char *pszParmValue, char **ptr) 1535 { 1536 debug_set_logfile(pszParmValue); 1537 string_set(lp_ctx, ptr, pszParmValue); 1538 return true; 1539 } 1540 1541 /*************************************************************************** 1542 Initialise a copymap. 1543 ***************************************************************************/ 1544 1545 static void init_copymap(struct loadparm_service *pservice) 1546 { 1547 int i; 1548 talloc_free(pservice->copymap); 1549 pservice->copymap = talloc_array(pservice, int, NUMPARAMETERS); 1550 if (pservice->copymap == NULL) { 1551 DEBUG(0, 1552 ("Couldn't allocate copymap!! (size %d)\n", 1553 (int)NUMPARAMETERS)); 1554 return; 1555 } 1556 for (i = 0; i < NUMPARAMETERS; i++) 1557 pservice->copymap[i] = true; 1558 } 1559 1560 /** 1561 * Process a parametric option 1562 */ 1563 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx, 1564 struct loadparm_service *service, 1565 const char *pszParmName, 1566 const char *pszParmValue, int flags) 1567 { 1568 struct parmlist_entry *paramo, *data; 1569 char *name; 1570 TALLOC_CTX *mem_ctx; 1571 1572 while (isspace((unsigned char)*pszParmName)) { 1573 pszParmName++; 1574 } 1575 1576 name = strdup(pszParmName); 1577 if (!name) return false; 1578 1579 strlower(name); 1580 1581 if (service == NULL) { 1582 data = lp_ctx->globals->param_opt; 1583 mem_ctx = lp_ctx->globals; 1584 } else { 1585 data = service->param_opt; 1586 mem_ctx = service; 1587 } 1588 1589 /* Traverse destination */ 1590 for (paramo=data; paramo; paramo=paramo->next) { 1591 /* If we already have the option set, override it unless 1592 it was a command line option and the new one isn't */ 1593 if (strcmp(paramo->key, name) == 0) { 1594 if ((paramo->priority & FLAG_CMDLINE) && 1595 !(flags & FLAG_CMDLINE)) { 1596 return true; 1597 } 1598 1599 talloc_free(paramo->value); 1600 paramo->value = talloc_strdup(paramo, pszParmValue); 1601 paramo->priority = flags; 1602 free(name); 1603 return true; 1604 } 1605 } 1606 1607 paramo = talloc_zero(mem_ctx, struct parmlist_entry); 1608 if (!paramo) 1609 smb_panic("OOM"); 1610 paramo->key = talloc_strdup(paramo, name); 1611 paramo->value = talloc_strdup(paramo, pszParmValue); 1612 paramo->priority = flags; 1613 if (service == NULL) { 1614 DLIST_ADD(lp_ctx->globals->param_opt, paramo); 1615 } else { 1616 DLIST_ADD(service->param_opt, paramo); 1617 } 1618 1619 free(name); 1620 1621 return true; 1622 } 1623 1624 static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr, 1625 const char *pszParmName, const char *pszParmValue, 1626 struct loadparm_context *lp_ctx, bool on_globals) 1627 { 1628 int i; 1629 /* if it is a special case then go ahead */ 1630 if (parm_table[parmnum].special) { 1631 bool ret; 1632 ret = parm_table[parmnum].special(lp_ctx, pszParmValue, 1633 (char **)parm_ptr); 1634 if (!ret) { 1635 return false; 1636 } 1637 goto mark_non_default; 1638 } 1639 1640 /* now switch on the type of variable it is */ 1641 switch (parm_table[parmnum].type) 1642 { 1643 case P_BOOL: { 1644 bool b; 1645 if (!set_boolean(pszParmValue, &b)) { 1646 DEBUG(0,("lp_do_parameter(%s): value is not boolean!\n", pszParmValue)); 1647 return false; 1648 } 1649 *(int *)parm_ptr = b; 1650 } 1651 break; 1652 1653 case P_INTEGER: 1654 *(int *)parm_ptr = atoi(pszParmValue); 1655 break; 1656 1657 case P_OCTAL: 1658 *(int *)parm_ptr = strtol(pszParmValue, NULL, 8); 1659 break; 1660 1661 case P_BYTES: 1662 { 1663 uint64_t val; 1664 if (conv_str_size(pszParmValue, &val)) { 1665 if (val <= INT_MAX) { 1666 *(int *)parm_ptr = (int)val; 1667 break; 1668 } 1669 } 1670 1671 DEBUG(0,("lp_do_parameter(%s): value is not " 1672 "a valid size specifier!\n", pszParmValue)); 1673 return false; 1674 } 1675 1676 case P_CMDLIST: 1677 *(const char ***)parm_ptr = (const char **)str_list_make(mem_ctx, 1678 pszParmValue, NULL); 1679 break; 1680 case P_LIST: 1681 { 1682 char **new_list = str_list_make(mem_ctx, 1683 pszParmValue, NULL); 1684 for (i=0; new_list[i]; i++) { 1685 if (new_list[i][0] == '+' && new_list[i][1]) { 1686 *(const char ***)parm_ptr = str_list_add(*(const char ***)parm_ptr, 1687 &new_list[i][1]); 1688 } else if (new_list[i][0] == '-' && new_list[i][1]) { 1689 if (!str_list_check(*(const char ***)parm_ptr, 1690 &new_list[i][1])) { 1691 DEBUG(0, ("Unsupported value for: %s = %s, %s is not in the original list\n", 1692 pszParmName, pszParmValue, new_list[i])); 1693 return false; 1694 1695 } 1696 str_list_remove(*(const char ***)parm_ptr, 1697 &new_list[i][1]); 1698 } else { 1699 if (i != 0) { 1700 DEBUG(0, ("Unsupported list syntax for: %s = %s\n", 1701 pszParmName, pszParmValue)); 1702 return false; 1703 } 1704 *(const char ***)parm_ptr = (const char **) new_list; 1705 break; 1706 } 1707 } 1708 break; 1709 } 1710 case P_STRING: 1711 string_set(mem_ctx, (char **)parm_ptr, pszParmValue); 1712 break; 1713 1714 case P_USTRING: 1715 string_set(mem_ctx, (char **)parm_ptr, pszParmValue); 1716 strupper(*(char **)parm_ptr); 1717 break; 1718 1719 case P_ENUM: 1720 for (i = 0; parm_table[parmnum].enum_list[i].name; i++) { 1721 if (strequal 1722 (pszParmValue, 1723 parm_table[parmnum].enum_list[i].name)) { 1724 *(int *)parm_ptr = 1725 parm_table[parmnum]. 1726 enum_list[i].value; 1727 break; 1728 } 1729 } 1730 if (!parm_table[parmnum].enum_list[i].name) { 1731 DEBUG(0,("Unknown enumerated value '%s' for '%s'\n", 1732 pszParmValue, pszParmName)); 1733 return false; 1734 } 1735 break; 1736 } 1737 1738 mark_non_default: 1739 if (on_globals && (lp_ctx->flags[parmnum] & FLAG_DEFAULT)) { 1740 lp_ctx->flags[parmnum] &= ~FLAG_DEFAULT; 1741 /* we have to also unset FLAG_DEFAULT on aliases */ 1742 for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) { 1743 lp_ctx->flags[i] &= ~FLAG_DEFAULT; 1744 } 1745 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) { 1746 lp_ctx->flags[i] &= ~FLAG_DEFAULT; 1747 } 1748 } 1749 return true; 1750 } 1751 1752 1753 bool lpcfg_do_global_parameter(struct loadparm_context *lp_ctx, 1754 const char *pszParmName, const char *pszParmValue) 1755 { 1756 int parmnum = map_parameter(pszParmName); 1757 void *parm_ptr; 1758 1759 if (parmnum < 0) { 1760 if (strchr(pszParmName, ':')) { 1761 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, pszParmValue, 0); 1762 } 1763 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName)); 1764 return true; 1765 } 1766 1767 /* if the flag has been set on the command line, then don't allow override, 1768 but don't report an error */ 1769 if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) { 1770 return true; 1771 } 1772 1773 parm_ptr = lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[parmnum]); 1774 1775 return set_variable(lp_ctx->globals, parmnum, parm_ptr, 1776 pszParmName, pszParmValue, lp_ctx, true); 1777 } 1778 1779 bool lpcfg_do_service_parameter(struct loadparm_context *lp_ctx, 1780 struct loadparm_service *service, 1781 const char *pszParmName, const char *pszParmValue) 1782 { 1783 void *parm_ptr; 1784 int i; 1785 int parmnum = map_parameter(pszParmName); 1786 1787 if (parmnum < 0) { 1788 if (strchr(pszParmName, ':')) { 1789 return lp_do_parameter_parametric(lp_ctx, service, pszParmName, pszParmValue, 0); 1790 } 1791 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName)); 1792 return true; 1793 } 1794 1795 /* if the flag has been set on the command line, then don't allow override, 1796 but don't report an error */ 1797 if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) { 1798 return true; 1799 } 1800 1801 if (parm_table[parmnum].pclass == P_GLOBAL) { 1802 DEBUG(0, 1803 ("Global parameter %s found in service section!\n", 1804 pszParmName)); 1805 return true; 1806 } 1807 parm_ptr = ((char *)service) + parm_table[parmnum].offset; 1808 1809 if (!service->copymap) 1810 init_copymap(service); 1811 1812 /* this handles the aliases - set the copymap for other 1813 * entries with the same data pointer */ 1814 for (i = 0; parm_table[i].label; i++) 1815 if (parm_table[i].offset == parm_table[parmnum].offset && 1816 parm_table[i].pclass == parm_table[parmnum].pclass) 1817 service->copymap[i] = false; 1818 1819 return set_variable(service, parmnum, parm_ptr, pszParmName, 1820 pszParmValue, lp_ctx, false); 1821 } 1822 1823 /** 1824 * Process a parameter. 1825 */ 1826 1827 static bool do_parameter(const char *pszParmName, const char *pszParmValue, 1828 void *userdata) 1829 { 1830 struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata; 1831 1832 if (lp_ctx->bInGlobalSection) 1833 return lpcfg_do_global_parameter(lp_ctx, pszParmName, 1834 pszParmValue); 1835 else 1836 return lpcfg_do_service_parameter(lp_ctx, lp_ctx->currentService, 1837 pszParmName, pszParmValue); 1838 } 1839 1840 /* 1841 variable argument do parameter 1842 */ 1843 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); 1844 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx, 1845 const char *pszParmName, const char *fmt, ...) 1846 { 1847 char *s; 1848 bool ret; 1849 va_list ap; 1850 1851 va_start(ap, fmt); 1852 s = talloc_vasprintf(NULL, fmt, ap); 1853 va_end(ap); 1854 ret = lpcfg_do_global_parameter(lp_ctx, pszParmName, s); 1855 talloc_free(s); 1856 return ret; 1857 } 1858 1859 1860 /* 1861 set a parameter from the commandline - this is called from command line parameter 1862 parsing code. It sets the parameter then marks the parameter as unable to be modified 1863 by smb.conf processing 1864 */ 1865 bool lpcfg_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName, 1866 const char *pszParmValue) 1867 { 1868 int parmnum = map_parameter(pszParmName); 1869 int i; 1870 1871 while (isspace((unsigned char)*pszParmValue)) pszParmValue++; 1872 1873 1874 if (parmnum < 0 && strchr(pszParmName, ':')) { 1875 /* set a parametric option */ 1876 return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, 1877 pszParmValue, FLAG_CMDLINE); 1878 } 1879 1880 if (parmnum < 0) { 1881 DEBUG(0,("Unknown option '%s'\n", pszParmName)); 1882 return false; 1883 } 1884 1885 /* reset the CMDLINE flag in case this has been called before */ 1886 lp_ctx->flags[parmnum] &= ~FLAG_CMDLINE; 1887 1888 if (!lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) { 1889 return false; 1890 } 1891 1892 lp_ctx->flags[parmnum] |= FLAG_CMDLINE; 1893 1894 /* we have to also set FLAG_CMDLINE on aliases */ 1895 for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) { 1896 lp_ctx->flags[i] |= FLAG_CMDLINE; 1897 } 1898 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) { 1899 lp_ctx->flags[i] |= FLAG_CMDLINE; 1900 } 1901 1902 return true; 1903 } 1904 1905 /* 1906 set a option from the commandline in 'a=b' format. Use to support --option 1907 */ 1908 bool lpcfg_set_option(struct loadparm_context *lp_ctx, const char *option) 1909 { 1910 char *p, *s; 1911 bool ret; 1912 1913 s = strdup(option); 1914 if (!s) { 1915 return false; 1916 } 1917 1918 p = strchr(s, '='); 1919 if (!p) { 1920 free(s); 1921 return false; 1922 } 1923 1924 *p = 0; 1925 1926 ret = lpcfg_set_cmdline(lp_ctx, s, p+1); 1927 free(s); 1928 return ret; 1929 } 1930 1931 1932 #define BOOLSTR(b) ((b) ? "Yes" : "No") 1933 1934 /** 1935 * Print a parameter of the specified type. 1936 */ 1937 1938 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f) 1939 { 1940 int i; 1941 const char *list_sep = ", "; /* For the seperation of lists values that we print below */ 1942 switch (p->type) 1943 { 1944 case P_ENUM: 1945 for (i = 0; p->enum_list[i].name; i++) { 1946 if (*(int *)ptr == p->enum_list[i].value) { 1947 fprintf(f, "%s", 1948 p->enum_list[i].name); 1949 break; 1950 } 1951 } 1952 break; 1953 1954 case P_BOOL: 1955 fprintf(f, "%s", BOOLSTR((bool)*(int *)ptr)); 1956 break; 1957 1958 case P_INTEGER: 1959 case P_BYTES: 1960 fprintf(f, "%d", *(int *)ptr); 1961 break; 1962 1963 case P_OCTAL: 1964 fprintf(f, "0%o", *(int *)ptr); 1965 break; 1966 1967 case P_CMDLIST: 1968 list_sep = " "; 1969 /* fall through */ 1970 case P_LIST: 1971 if ((char ***)ptr && *(char ***)ptr) { 1972 char **list = *(char ***)ptr; 1973 1974 for (; *list; list++) { 1975 if (*(list+1) == NULL) { 1976 /* last item, print no extra seperator after */ 1977 list_sep = ""; 1978 } 1979 fprintf(f, "%s%s", *list, list_sep); 1980 } 1981 } 1982 break; 1983 1984 case P_STRING: 1985 case P_USTRING: 1986 if (*(char **)ptr) { 1987 fprintf(f, "%s", *(char **)ptr); 1988 } 1989 break; 1990 } 1991 } 1992 1993 /** 1994 * Check if two parameters are equal. 1995 */ 1996 1997 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2) 1998 { 1999 switch (type) { 2000 case P_BOOL: 2001 return (*((int *)ptr1) == *((int *)ptr2)); 2002 2003 case P_INTEGER: 2004 case P_OCTAL: 2005 case P_BYTES: 2006 case P_ENUM: 2007 return (*((int *)ptr1) == *((int *)ptr2)); 2008 2009 case P_CMDLIST: 2010 case P_LIST: 2011 return str_list_equal((const char **)(*(char ***)ptr1), 2012 (const char **)(*(char ***)ptr2)); 2013 2014 case P_STRING: 2015 case P_USTRING: 2016 { 2017 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2; 2018 if (p1 && !*p1) 2019 p1 = NULL; 2020 if (p2 && !*p2) 2021 p2 = NULL; 2022 return (p1 == p2 || strequal(p1, p2)); 2023 } 2024 } 2025 return false; 2026 } 2027 2028 /** 2029 * Process a new section (service). 2030 * 2031 * At this stage all sections are services. 2032 * Later we'll have special sections that permit server parameters to be set. 2033 * Returns True on success, False on failure. 2034 */ 2035 2036 static bool do_section(const char *pszSectionName, void *userdata) 2037 { 2038 struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata; 2039 bool bRetval; 2040 bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) || 2041 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0)); 2042 bRetval = false; 2043 2044 /* if we've just struck a global section, note the fact. */ 2045 lp_ctx->bInGlobalSection = isglobal; 2046 2047 /* check for multiple global sections */ 2048 if (lp_ctx->bInGlobalSection) { 2049 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName)); 2050 return true; 2051 } 2052 2053 /* if we have a current service, tidy it up before moving on */ 2054 bRetval = true; 2055 2056 if (lp_ctx->currentService != NULL) 2057 bRetval = service_ok(lp_ctx->currentService); 2058 2059 /* if all is still well, move to the next record in the services array */ 2060 if (bRetval) { 2061 /* We put this here to avoid an odd message order if messages are */ 2062 /* issued by the post-processing of a previous section. */ 2063 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName)); 2064 2065 if ((lp_ctx->currentService = lpcfg_add_service(lp_ctx, lp_ctx->sDefault, 2066 pszSectionName)) 2067 == NULL) { 2068 DEBUG(0, ("Failed to add a new service\n")); 2069 return false; 2070 } 2071 } 2072 2073 return bRetval; 2074 } 2075 2076 2077 /** 2078 * Determine if a particular base parameter is currently set to the default value. 2079 */ 2080 2081 static bool is_default(struct loadparm_service *sDefault, int i) 2082 { 2083 void *def_ptr = ((char *)sDefault) + parm_table[i].offset; 2084 if (!defaults_saved) 2085 return false; 2086 switch (parm_table[i].type) { 2087 case P_CMDLIST: 2088 case P_LIST: 2089 return str_list_equal((const char **)parm_table[i].def.lvalue, 2090 (const char **)def_ptr); 2091 case P_STRING: 2092 case P_USTRING: 2093 return strequal(parm_table[i].def.svalue, 2094 *(char **)def_ptr); 2095 case P_BOOL: 2096 return parm_table[i].def.bvalue == 2097 *(int *)def_ptr; 2098 case P_INTEGER: 2099 case P_OCTAL: 2100 case P_BYTES: 2101 case P_ENUM: 2102 return parm_table[i].def.ivalue == 2103 *(int *)def_ptr; 2104 } 2105 return false; 2106 } 2107 2108 /** 2109 *Display the contents of the global structure. 2110 */ 2111 2112 static void dump_globals(struct loadparm_context *lp_ctx, FILE *f, 2113 bool show_defaults) 2114 { 2115 int i; 2116 struct parmlist_entry *data; 2117 2118 fprintf(f, "# Global parameters\n[global]\n"); 2119 2120 for (i = 0; parm_table[i].label; i++) 2121 if (parm_table[i].pclass == P_GLOBAL && 2122 parm_table[i].offset != -1 && 2123 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) { 2124 if (!show_defaults && (lp_ctx->flags[i] & FLAG_DEFAULT)) 2125 continue; 2126 fprintf(f, "\t%s = ", parm_table[i].label); 2127 print_parameter(&parm_table[i], lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[i]), f); 2128 fprintf(f, "\n"); 2129 } 2130 if (lp_ctx->globals->param_opt != NULL) { 2131 for (data = lp_ctx->globals->param_opt; data; 2132 data = data->next) { 2133 if (!show_defaults && (data->priority & FLAG_DEFAULT)) { 2134 continue; 2135 } 2136 fprintf(f, "\t%s = %s\n", data->key, data->value); 2137 } 2138 } 2139 2140 } 2141 2142 /** 2143 * Display the contents of a single services record. 2144 */ 2145 2146 static void dump_a_service(struct loadparm_service * pService, struct loadparm_service *sDefault, FILE * f, 2147 unsigned int *flags) 2148 { 2149 int i; 2150 struct parmlist_entry *data; 2151 2152 if (pService != sDefault) 2153 fprintf(f, "\n[%s]\n", pService->szService); 2154 2155 for (i = 0; parm_table[i].label; i++) { 2156 if (parm_table[i].pclass == P_LOCAL && 2157 parm_table[i].offset != -1 && 2158 (*parm_table[i].label != '-') && 2159 (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 2160 { 2161 if (pService == sDefault) { 2162 if (flags && (flags[i] & FLAG_DEFAULT)) { 2163 continue; 2164 } 2165 if (defaults_saved) { 2166 if (is_default(sDefault, i)) { 2167 continue; 2168 } 2169 } 2170 } else { 2171 if (equal_parameter(parm_table[i].type, 2172 ((char *)pService) + 2173 parm_table[i].offset, 2174 ((char *)sDefault) + 2175 parm_table[i].offset)) 2176 continue; 2177 } 2178 2179 fprintf(f, "\t%s = ", parm_table[i].label); 2180 print_parameter(&parm_table[i], 2181 ((char *)pService) + parm_table[i].offset, f); 2182 fprintf(f, "\n"); 2183 } 2184 } 2185 if (pService->param_opt != NULL) { 2186 for (data = pService->param_opt; data; data = data->next) { 2187 fprintf(f, "\t%s = %s\n", data->key, data->value); 2188 } 2189 } 2190 } 2191 2192 bool lpcfg_dump_a_parameter(struct loadparm_context *lp_ctx, 2193 struct loadparm_service *service, 2194 const char *parm_name, FILE * f) 2195 { 2196 struct parm_struct *parm; 2197 void *ptr; 2198 2199 parm = lpcfg_parm_struct(parm_name); 2200 if (!parm) { 2201 return false; 2202 } 2203 2204 ptr = lpcfg_parm_ptr(lp_ctx, service,parm); 2205 2206 print_parameter(parm, ptr, f); 2207 fprintf(f, "\n"); 2208 return true; 2209 } 2210 2211 /** 2212 * Return info about the next parameter in a service. 2213 * snum==-1 gives the globals. 2214 * Return NULL when out of parameters. 2215 */ 2216 2217 2218 struct parm_struct *lpcfg_next_parameter(struct loadparm_context *lp_ctx, int snum, int *i, 2219 int allparameters) 2220 { 2221 if (snum == -1) { 2222 /* do the globals */ 2223 for (; parm_table[*i].label; (*i)++) { 2224 if (parm_table[*i].offset == -1 2225 || (*parm_table[*i].label == '-')) 2226 continue; 2227 2228 if ((*i) > 0 2229 && (parm_table[*i].offset == 2230 parm_table[(*i) - 1].offset)) 2231 continue; 2232 2233 return &parm_table[(*i)++]; 2234 } 2235 } else { 2236 struct loadparm_service *pService = lp_ctx->services[snum]; 2237 2238 for (; parm_table[*i].label; (*i)++) { 2239 if (parm_table[*i].pclass == P_LOCAL && 2240 parm_table[*i].offset != -1 && 2241 (*parm_table[*i].label != '-') && 2242 ((*i) == 0 || 2243 (parm_table[*i].offset != 2244 parm_table[(*i) - 1].offset))) 2245 { 2246 if (allparameters || 2247 !equal_parameter(parm_table[*i].type, 2248 ((char *)pService) + 2249 parm_table[*i].offset, 2250 ((char *)lp_ctx->sDefault) + 2251 parm_table[*i].offset)) 2252 { 2253 return &parm_table[(*i)++]; 2254 } 2255 } 2256 } 2257 } 2258 2259 return NULL; 2260 } 2261 2262 2263 /** 2264 * Auto-load some home services. 2265 */ 2266 static void lpcfg_add_auto_services(struct loadparm_context *lp_ctx, 2267 const char *str) 2268 { 2269 return; 2270 } 2271 2272 2273 /** 2274 * Unload unused services. 2275 */ 2276 2277 void lp_killunused(struct loadparm_context *lp_ctx, 2278 struct smbsrv_connection *smb, 2279 bool (*snumused) (struct smbsrv_connection *, int)) 2280 { 2281 int i; 2282 for (i = 0; i < lp_ctx->iNumServices; i++) { 2283 if (lp_ctx->services[i] == NULL) 2284 continue; 2285 2286 if (!snumused || !snumused(smb, i)) { 2287 talloc_free(lp_ctx->services[i]); 2288 lp_ctx->services[i] = NULL; 2289 } 2290 } 2291 } 2292 2293 2294 static int lp_destructor(struct loadparm_context *lp_ctx) 2295 { 2296 struct parmlist_entry *data; 2297 2298 if (lp_ctx->refuse_free) { 2299 /* someone is trying to free the 2300 global_loadparm_context. 2301 We can't allow that. */ 2302 return -1; 2303 } 2304 2305 if (lp_ctx->globals->param_opt != NULL) { 2306 struct parmlist_entry *next; 2307 for (data = lp_ctx->globals->param_opt; data; data=next) { 2308 next = data->next; 2309 if (data->priority & FLAG_CMDLINE) continue; 2310 DLIST_REMOVE(lp_ctx->globals->param_opt, data); 2311 talloc_free(data); 2312 } 2313 } 2314 2315 return 0; 2316 } 2317 2318 /** 2319 * Initialise the global parameter structure. 2320 * 2321 * Note that most callers should use loadparm_init_global() instead 2322 */ 2323 struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) 2324 { 2325 int i; 2326 char *myname; 2327 struct loadparm_context *lp_ctx; 2328 struct parmlist_entry *parm; 2329 2330 lp_ctx = talloc_zero(mem_ctx, struct loadparm_context); 2331 if (lp_ctx == NULL) 2332 return NULL; 2333 2334 talloc_set_destructor(lp_ctx, lp_destructor); 2335 lp_ctx->bInGlobalSection = true; 2336 lp_ctx->globals = talloc_zero(lp_ctx, struct loadparm_global); 2337 lp_ctx->sDefault = talloc_zero(lp_ctx, struct loadparm_service); 2338 2339 lp_ctx->sDefault->iMaxPrintJobs = 1000; 2340 lp_ctx->sDefault->bAvailable = true; 2341 lp_ctx->sDefault->bBrowseable = true; 2342 lp_ctx->sDefault->bRead_only = true; 2343 lp_ctx->sDefault->bMap_archive = true; 2344 lp_ctx->sDefault->bStrictLocking = true; 2345 lp_ctx->sDefault->bOplocks = true; 2346 lp_ctx->sDefault->iCreate_mask = 0744; 2347 lp_ctx->sDefault->iCreate_force_mode = 0000; 2348 lp_ctx->sDefault->iDir_mask = 0755; 2349 lp_ctx->sDefault->iDir_force_mode = 0000; 2350 2351 DEBUG(3, ("Initialising global parameters\n")); 2352 2353 for (i = 0; parm_table[i].label; i++) { 2354 if ((parm_table[i].type == P_STRING || 2355 parm_table[i].type == P_USTRING) && 2356 parm_table[i].offset != -1 && 2357 !(lp_ctx->flags[i] & FLAG_CMDLINE)) { 2358 char **r; 2359 if (parm_table[i].pclass == P_LOCAL) { 2360 r = (char **)(((char *)lp_ctx->sDefault) + parm_table[i].offset); 2361 } else { 2362 r = (char **)(((char *)lp_ctx->globals) + parm_table[i].offset); 2363 } 2364 *r = talloc_strdup(lp_ctx, ""); 2365 } 2366 } 2367 2368 2369 lpcfg_do_global_parameter(lp_ctx, "log level", "0"); 2370 2371 lpcfg_do_global_parameter(lp_ctx, "share backend", "classic"); 2372 2373 lpcfg_do_global_parameter(lp_ctx, "share backend", "classic"); 2374 2375 lpcfg_do_global_parameter(lp_ctx, "server role", "standalone"); 2376 2377 /* options that can be set on the command line must be initialised via 2378 the slower lpcfg_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */ 2379 #ifdef TCP_NODELAY 2380 lpcfg_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY"); 2381 #endif 2382 lpcfg_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP); 2383 myname = get_myname(lp_ctx); 2384 lpcfg_do_global_parameter(lp_ctx, "netbios name", myname); 2385 talloc_free(myname); 2386 lpcfg_do_global_parameter(lp_ctx, "name resolve order", "wins host bcast"); 2387 2388 lpcfg_do_global_parameter(lp_ctx, "fstype", "NTFS"); 2389 2390 lpcfg_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default"); 2391 lpcfg_do_global_parameter(lp_ctx, "max connections", "-1"); 2392 2393 lpcfg_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup unixinfo browser eventlog6 backupkey"); 2394 lpcfg_do_global_parameter(lp_ctx, "server services", "smb rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate web"); 2395 lpcfg_do_global_parameter(lp_ctx, "ntptr providor", "simple_ldb"); 2396 /* the winbind method for domain controllers is for both RODC 2397 auth forwarding and for trusted domains */ 2398 lpcfg_do_global_parameter(lp_ctx, "auth methods:domain controller", "anonymous sam_ignoredomain winbind"); 2399 lpcfg_do_global_parameter(lp_ctx, "auth methods:member server", "anonymous sam winbind"); 2400 lpcfg_do_global_parameter(lp_ctx, "auth methods:standalone", "anonymous sam_ignoredomain"); 2401 lpcfg_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR); 2402 lpcfg_do_global_parameter(lp_ctx, "sam database", "sam.ldb"); 2403 lpcfg_do_global_parameter(lp_ctx, "idmap database", "idmap.ldb"); 2404 lpcfg_do_global_parameter(lp_ctx, "secrets database", "secrets.ldb"); 2405 lpcfg_do_global_parameter(lp_ctx, "spoolss database", "spoolss.ldb"); 2406 lpcfg_do_global_parameter(lp_ctx, "wins config database", "wins_config.ldb"); 2407 lpcfg_do_global_parameter(lp_ctx, "wins database", "wins.ldb"); 2408 lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb"); 2409 2410 /* This hive should be dynamically generated by Samba using 2411 data from the sam, but for the moment leave it in a tdb to 2412 keep regedt32 from popping up an annoying dialog. */ 2413 lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb"); 2414 2415 /* using UTF8 by default allows us to support all chars */ 2416 lpcfg_do_global_parameter(lp_ctx, "unix charset", "UTF8"); 2417 2418 /* Use codepage 850 as a default for the dos character set */ 2419 lpcfg_do_global_parameter(lp_ctx, "dos charset", "CP850"); 2420 2421 /* 2422 * Allow the default PASSWD_CHAT to be overridden in local.h. 2423 */ 2424 lpcfg_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT); 2425 2426 lpcfg_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR); 2427 lpcfg_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR); 2428 lpcfg_do_global_parameter(lp_ctx, "modules dir", dyn_MODULESDIR); 2429 lpcfg_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR); 2430 2431 lpcfg_do_global_parameter(lp_ctx, "socket address", "0.0.0.0"); 2432 lpcfg_do_global_parameter_var(lp_ctx, "server string", 2433 "Samba %s", SAMBA_VERSION_STRING); 2434 2435 lpcfg_do_global_parameter_var(lp_ctx, "announce version", "%d.%d", 2436 DEFAULT_MAJOR_VERSION, 2437 DEFAULT_MINOR_VERSION); 2438 2439 lpcfg_do_global_parameter(lp_ctx, "password server", "*"); 2440 2441 lpcfg_do_global_parameter(lp_ctx, "max mux", "50"); 2442 lpcfg_do_global_parameter(lp_ctx, "max xmit", "12288"); 2443 lpcfg_do_global_parameter(lp_ctx, "password level", "0"); 2444 lpcfg_do_global_parameter(lp_ctx, "LargeReadwrite", "True"); 2445 lpcfg_do_global_parameter(lp_ctx, "server min protocol", "CORE"); 2446 lpcfg_do_global_parameter(lp_ctx, "server max protocol", "NT1"); 2447 lpcfg_do_global_parameter(lp_ctx, "client min protocol", "CORE"); 2448 lpcfg_do_global_parameter(lp_ctx, "client max protocol", "NT1"); 2449 lpcfg_do_global_parameter(lp_ctx, "security", "USER"); 2450 lpcfg_do_global_parameter(lp_ctx, "paranoid server security", "True"); 2451 lpcfg_do_global_parameter(lp_ctx, "EncryptPasswords", "True"); 2452 lpcfg_do_global_parameter(lp_ctx, "ReadRaw", "True"); 2453 lpcfg_do_global_parameter(lp_ctx, "WriteRaw", "True"); 2454 lpcfg_do_global_parameter(lp_ctx, "NullPasswords", "False"); 2455 lpcfg_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False"); 2456 lpcfg_do_global_parameter(lp_ctx, "announce as", "NT SERVER"); 2457 2458 lpcfg_do_global_parameter(lp_ctx, "TimeServer", "False"); 2459 lpcfg_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False"); 2460 lpcfg_do_global_parameter(lp_ctx, "Unicode", "True"); 2461 lpcfg_do_global_parameter(lp_ctx, "ClientLanManAuth", "False"); 2462 lpcfg_do_global_parameter(lp_ctx, "ClientNTLMv2Auth", "True"); 2463 lpcfg_do_global_parameter(lp_ctx, "LanmanAuth", "False"); 2464 lpcfg_do_global_parameter(lp_ctx, "NTLMAuth", "True"); 2465 lpcfg_do_global_parameter(lp_ctx, "client use spnego principal", "False"); 2466 2467 lpcfg_do_global_parameter(lp_ctx, "UnixExtensions", "False"); 2468 2469 lpcfg_do_global_parameter(lp_ctx, "PreferredMaster", "Auto"); 2470 lpcfg_do_global_parameter(lp_ctx, "LocalMaster", "True"); 2471 2472 lpcfg_do_global_parameter(lp_ctx, "wins support", "False"); 2473 lpcfg_do_global_parameter(lp_ctx, "dns proxy", "True"); 2474 2475 lpcfg_do_global_parameter(lp_ctx, "winbind separator", "\\"); 2476 lpcfg_do_global_parameter(lp_ctx, "winbind sealed pipes", "True"); 2477 lpcfg_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR); 2478 lpcfg_do_global_parameter(lp_ctx, "winbindd privileged socket directory", dyn_WINBINDD_PRIVILEGED_SOCKET_DIR); 2479 lpcfg_do_global_parameter(lp_ctx, "template shell", "/bin/false"); 2480 lpcfg_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%"); 2481 lpcfg_do_global_parameter(lp_ctx, "idmap trusted only", "False"); 2482 2483 lpcfg_do_global_parameter(lp_ctx, "client signing", "Yes"); 2484 lpcfg_do_global_parameter(lp_ctx, "server signing", "auto"); 2485 2486 lpcfg_do_global_parameter(lp_ctx, "use spnego", "True"); 2487 2488 lpcfg_do_global_parameter(lp_ctx, "smb ports", "445 139"); 2489 lpcfg_do_global_parameter(lp_ctx, "nbt port", "137"); 2490 lpcfg_do_global_parameter(lp_ctx, "dgram port", "138"); 2491 lpcfg_do_global_parameter(lp_ctx, "cldap port", "389"); 2492 lpcfg_do_global_parameter(lp_ctx, "krb5 port", "88"); 2493 lpcfg_do_global_parameter(lp_ctx, "kpasswd port", "464"); 2494 lpcfg_do_global_parameter(lp_ctx, "web port", "901"); 2495 2496 lpcfg_do_global_parameter(lp_ctx, "nt status support", "True"); 2497 2498 lpcfg_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */ 2499 lpcfg_do_global_parameter(lp_ctx, "min wins ttl", "10"); 2500 2501 lpcfg_do_global_parameter(lp_ctx, "tls enabled", "True"); 2502 lpcfg_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem"); 2503 lpcfg_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem"); 2504 lpcfg_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem"); 2505 lpcfg_do_global_parameter(lp_ctx, "prefork children:smb", "4"); 2506 2507 lpcfg_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR); 2508 lpcfg_do_global_parameter(lp_ctx, "rndc command", "/usr/sbin/rndc"); 2509 lpcfg_do_global_parameter_var(lp_ctx, "dns update command", "%s/samba_dnsupdate", dyn_SCRIPTSBINDIR); 2510 lpcfg_do_global_parameter_var(lp_ctx, "spn update command", "%s/samba_spnupdate", dyn_SCRIPTSBINDIR); 2511 lpcfg_do_global_parameter(lp_ctx, "nsupdate command", "/usr/bin/nsupdate -g"); 2512 2513 for (i = 0; parm_table[i].label; i++) { 2514 if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) { 2515 lp_ctx->flags[i] |= FLAG_DEFAULT; 2516 } 2517 } 2518 2519 for (parm=lp_ctx->globals->param_opt; parm; parm=parm->next) { 2520 if (!(parm->priority & FLAG_CMDLINE)) { 2521 parm->priority |= FLAG_DEFAULT; 2522 } 2523 } 2524 2525 return lp_ctx; 2526 } 2527 2528 /** 2529 * Initialise the global parameter structure. 2530 */ 2531 struct loadparm_context *loadparm_init_global(bool load_default) 2532 { 2533 if (global_loadparm_context == NULL) { 2534 global_loadparm_context = loadparm_init(NULL); 2535 } 2536 if (load_default && !global_loadparm_context->loaded) { 2537 lpcfg_load_default(global_loadparm_context); 2538 } 2539 global_loadparm_context->refuse_free = true; 2540 return global_loadparm_context; 2541 } 2542 2543 const char *lpcfg_configfile(struct loadparm_context *lp_ctx) 2544 { 2545 return lp_ctx->szConfigFile; 2546 } 2547 2548 const char *lp_default_path(void) 2549 { 2550 if (getenv("SMB_CONF_PATH")) 2551 return getenv("SMB_CONF_PATH"); 2552 else 2553 return dyn_CONFIGFILE; 2554 } 2555 2556 /** 2557 * Update the internal state of a loadparm context after settings 2558 * have changed. 2559 */ 2560 static bool lpcfg_update(struct loadparm_context *lp_ctx) 2561 { 2562 struct debug_settings settings; 2563 lpcfg_add_auto_services(lp_ctx, lpcfg_auto_services(lp_ctx)); 2564 2565 if (!lp_ctx->globals->szWINSservers && lp_ctx->globals->bWINSsupport) { 2566 lpcfg_do_global_parameter(lp_ctx, "wins server", "127.0.0.1"); 2567 } 2568 2569 panic_action = lp_ctx->globals->panic_action; 2570 2571 reload_charcnv(lp_ctx); 2572 2573 ZERO_STRUCT(settings); 2574 /* Add any more debug-related smb.conf parameters created in 2575 * future here */ 2576 settings.timestamp_logs = true; 2577 debug_set_settings(&settings); 2578 2579 /* FIXME: ntstatus_check_dos_mapping = lpcfg_nt_status_support(lp_ctx); */ 2580 2581 /* FIXME: This is a bit of a hack, but we can't use a global, since 2582 * not everything that uses lp also uses the socket library */ 2583 if (lpcfg_parm_bool(lp_ctx, NULL, "socket", "testnonblock", false)) { 2584 setenv("SOCKET_TESTNONBLOCK", "1", 1); 2585 } else { 2586 unsetenv("SOCKET_TESTNONBLOCK"); 2587 } 2588 2589 /* FIXME: Check locale in environment for this: */ 2590 if (strcmp(lpcfg_display_charset(lp_ctx), lpcfg_unix_charset(lp_ctx)) != 0) 2591 d_set_iconv(smb_iconv_open(lpcfg_display_charset(lp_ctx), lpcfg_unix_charset(lp_ctx))); 2592 else 2593 d_set_iconv((smb_iconv_t)-1); 2594 2595 return true; 2596 } 2597 2598 bool lpcfg_load_default(struct loadparm_context *lp_ctx) 2599 { 2600 const char *path; 2601 2602 path = lp_default_path(); 2603 2604 if (!file_exist(path)) { 2605 /* We allow the default smb.conf file to not exist, 2606 * basically the equivalent of an empty file. */ 2607 return lpcfg_update(lp_ctx); 2608 } 2609 2610 return lpcfg_load(lp_ctx, path); 2611 } 2612 2613 /** 2614 * Load the services array from the services file. 2615 * 2616 * Return True on success, False on failure. 2617 */ 2618 bool lpcfg_load(struct loadparm_context *lp_ctx, const char *filename) 2619 { 2620 char *n2; 2621 bool bRetval; 2622 2623 filename = talloc_strdup(lp_ctx, filename); 2624 2625 lp_ctx->szConfigFile = filename; 2626 2627 lp_ctx->bInGlobalSection = true; 2628 n2 = standard_sub_basic(lp_ctx, lp_ctx->szConfigFile); 2629 DEBUG(2, ("lpcfg_load: refreshing parameters from %s\n", n2)); 2630 2631 add_to_file_list(lp_ctx, lp_ctx->szConfigFile, n2); 2632 2633 /* We get sections first, so have to start 'behind' to make up */ 2634 lp_ctx->currentService = NULL; 2635 bRetval = pm_process(n2, do_section, do_parameter, lp_ctx); 2636 2637 /* finish up the last section */ 2638 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval))); 2639 if (bRetval) 2640 if (lp_ctx->currentService != NULL) 2641 bRetval = service_ok(lp_ctx->currentService); 2642 2643 bRetval = bRetval && lpcfg_update(lp_ctx); 2644 2645 /* we do this unconditionally, so that it happens even 2646 for a missing smb.conf */ 2647 reload_charcnv(lp_ctx); 2648 2649 if (bRetval == true) { 2650 /* set this up so that any child python tasks will 2651 find the right smb.conf */ 2652 setenv("SMB_CONF_PATH", filename, 1); 2653 2654 /* set the context used by the lp_*() function 2655 varients */ 2656 global_loadparm_context = lp_ctx; 2657 lp_ctx->loaded = true; 2658 } 2659 2660 return bRetval; 2661 } 2662 2663 /** 2664 * Return the max number of services. 2665 */ 2666 2667 int lpcfg_numservices(struct loadparm_context *lp_ctx) 2668 { 2669 return lp_ctx->iNumServices; 2670 } 2671 2672 /** 2673 * Display the contents of the services array in human-readable form. 2674 */ 2675 2676 void lpcfg_dump(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults, 2677 int maxtoprint) 2678 { 2679 int iService; 2680 2681 defaults_saved = !show_defaults; 2682 2683 dump_globals(lp_ctx, f, show_defaults); 2684 2685 dump_a_service(lp_ctx->sDefault, lp_ctx->sDefault, f, lp_ctx->flags); 2686 2687 for (iService = 0; iService < maxtoprint; iService++) 2688 lpcfg_dump_one(f, show_defaults, lp_ctx->services[iService], lp_ctx->sDefault); 2689 } 2690 2691 /** 2692 * Display the contents of one service in human-readable form. 2693 */ 2694 void lpcfg_dump_one(FILE *f, bool show_defaults, struct loadparm_service *service, struct loadparm_service *sDefault) 2695 { 2696 if (service != NULL) { 2697 if (service->szService[0] == '\0') 2698 return; 2699 dump_a_service(service, sDefault, f, NULL); 2700 } 2701 } 2702 2703 struct loadparm_service *lpcfg_servicebynum(struct loadparm_context *lp_ctx, 2704 int snum) 2705 { 2706 return lp_ctx->services[snum]; 2707 } 2708 2709 struct loadparm_service *lpcfg_service(struct loadparm_context *lp_ctx, 2710 const char *service_name) 2711 { 2712 int iService; 2713 char *serviceName; 2714 2715 for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) { 2716 if (lp_ctx->services[iService] && 2717 lp_ctx->services[iService]->szService) { 2718 /* 2719 * The substitution here is used to support %U is 2720 * service names 2721 */ 2722 serviceName = standard_sub_basic( 2723 lp_ctx->services[iService], 2724 lp_ctx->services[iService]->szService); 2725 if (strequal(serviceName, service_name)) { 2726 talloc_free(serviceName); 2727 return lp_ctx->services[iService]; 2728 } 2729 talloc_free(serviceName); 2730 } 2731 } 2732 2733 DEBUG(7,("lpcfg_servicenumber: couldn't find %s\n", service_name)); 2734 return NULL; 2735 } 2736 2737 const char *lpcfg_servicename(const struct loadparm_service *service) 2738 { 2739 return lp_string((const char *)service->szService); 2740 } 2741 2742 /** 2743 * A useful volume label function. 2744 */ 2745 const char *volume_label(struct loadparm_service *service, struct loadparm_service *sDefault) 2746 { 2747 const char *ret; 2748 ret = lp_string((const char *)((service != NULL && service->volume != NULL) ? 2749 service->volume : sDefault->volume)); 2750 if (!*ret) 2751 return lpcfg_servicename(service); 2752 return ret; 2753 } 2754 2755 /** 2756 * If we are PDC then prefer us as DMB 2757 */ 2758 const char *lpcfg_printername(struct loadparm_service *service, struct loadparm_service *sDefault) 2759 { 2760 const char *ret; 2761 ret = lp_string((const char *)((service != NULL && service->szPrintername != NULL) ? 2762 service->szPrintername : sDefault->szPrintername)); 2763 if (ret == NULL || (ret != NULL && *ret == '\0')) 2764 ret = lpcfg_servicename(service); 2765 2766 return ret; 2767 } 2768 2769 2770 /** 2771 * Return the max print jobs per queue. 2772 */ 2773 int lpcfg_maxprintjobs(struct loadparm_service *service, struct loadparm_service *sDefault) 2774 { 2775 int maxjobs = (service != NULL) ? service->iMaxPrintJobs : sDefault->iMaxPrintJobs; 2776 if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID) 2777 maxjobs = PRINT_MAX_JOBID - 1; 2778 2779 return maxjobs; 2780 } 2781 2782 struct smb_iconv_convenience *lpcfg_iconv_convenience(struct loadparm_context *lp_ctx) 2783 { 2784 if (lp_ctx == NULL) { 2785 return get_iconv_convenience(); 2786 } 2787 return lp_ctx->iconv_convenience; 2788 } 2789 2790 _PUBLIC_ void reload_charcnv(struct loadparm_context *lp_ctx) 2791 { 2792 struct smb_iconv_convenience *old_ic = lp_ctx->iconv_convenience; 2793 if (old_ic == NULL) { 2794 old_ic = global_iconv_convenience; 2795 } 2796 lp_ctx->iconv_convenience = smb_iconv_convenience_reinit_lp(lp_ctx, lp_ctx, old_ic); 2797 global_iconv_convenience = lp_ctx->iconv_convenience; 2798 } 32 #include "librpc/ndr/libndr.h" 2799 33 2800 34 void lpcfg_smbcli_options(struct loadparm_context *lp_ctx, … … 2802 36 { 2803 37 options->max_xmit = lpcfg_max_xmit(lp_ctx); 2804 options->max_mux = lpcfg_max mux(lp_ctx);2805 options->use_spnego = lpcfg_nt_status_support(lp_ctx) && lpcfg_ use_spnego(lp_ctx);38 options->max_mux = lpcfg_max_mux(lp_ctx); 39 options->use_spnego = lpcfg_nt_status_support(lp_ctx) && lpcfg_client_use_spnego(lp_ctx); 2806 40 options->signing = lpcfg_client_signing(lp_ctx); 2807 41 options->request_timeout = SMB_REQUEST_TIMEOUT; 2808 42 options->ntstatus_support = lpcfg_nt_status_support(lp_ctx); 2809 options->max_protocol = lpcfg_cli_maxprotocol(lp_ctx); 43 options->min_protocol = lpcfg_client_min_protocol(lp_ctx); 44 options->max_protocol = lpcfg__client_max_protocol(lp_ctx); 2810 45 options->unicode = lpcfg_unicode(lp_ctx); 2811 46 options->use_oplocks = true; 2812 47 options->use_level2_oplocks = true; 48 options->smb2_capabilities = SMB2_CAP_ALL; 49 options->client_guid = GUID_random(); 2813 50 } 2814 51 … … 2821 58 } 2822 59 2823 _PUBLIC_ char *lpcfg_tls_keyfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)2824 {2825 return private_path(mem_ctx, lp_ctx, lp_ctx->globals->tls_keyfile);2826 }2827 2828 _PUBLIC_ char *lpcfg_tls_certfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)2829 {2830 return private_path(mem_ctx, lp_ctx, lp_ctx->globals->tls_certfile);2831 }2832 2833 _PUBLIC_ char *lpcfg_tls_cafile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)2834 {2835 return private_path(mem_ctx, lp_ctx, lp_ctx->globals->tls_cafile);2836 }2837 2838 _PUBLIC_ char *lpcfg_tls_crlfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)2839 {2840 return private_path(mem_ctx, lp_ctx, lp_ctx->globals->tls_crlfile);2841 }2842 2843 _PUBLIC_ char *lpcfg_tls_dhpfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)2844 {2845 return private_path(mem_ctx, lp_ctx, lp_ctx->globals->tls_dhpfile);2846 }2847 2848 _PUBLIC_ struct dcerpc_server_info *lpcfg_dcerpc_server_info(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)2849 {2850 struct dcerpc_server_info *ret = talloc_zero(mem_ctx, struct dcerpc_server_info);2851 2852 ret->domain_name = talloc_reference(mem_ctx, lpcfg_workgroup(lp_ctx));2853 ret->version_major = lpcfg_parm_int(lp_ctx, NULL, "server_info", "version_major", 5);2854 ret->version_minor = lpcfg_parm_int(lp_ctx, NULL, "server_info", "version_minor", 2);2855 ret->version_build = lpcfg_parm_int(lp_ctx, NULL, "server_info", "version_build", 3790);2856 2857 return ret;2858 }2859 2860 struct gensec_settings *lpcfg_gensec_settings(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)2861 {2862 struct gensec_settings *settings = talloc(mem_ctx, struct gensec_settings);2863 if (settings == NULL)2864 return NULL;2865 SMB_ASSERT(lp_ctx != NULL);2866 settings->lp_ctx = talloc_reference(settings, lp_ctx);2867 settings->target_hostname = lpcfg_parm_string(lp_ctx, NULL, "gensec", "target_hostname");2868 return settings;2869 }2870
Note:
See TracChangeset
for help on using the changeset viewer.