1/* bconfig.c - the config backend */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 2005-2011 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16/* ACKNOWLEDGEMENTS: 17 * This work was originally developed by Howard Chu for inclusion 18 * in OpenLDAP Software. 19 */ 20 21#include "portable.h" 22 23#include <stdio.h> 24#include <ac/string.h> 25#include <ac/ctype.h> 26#include <ac/errno.h> 27#include <sys/stat.h> 28#include <ac/unistd.h> 29 30#include "slap.h" 31 32#ifdef LDAP_SLAPI 33#include "slapi/slapi.h" 34#endif 35 36#include <ldif.h> 37#include <lutil.h> 38 39#include "config.h" 40 41#define CONFIG_RDN "cn=config" 42#define SCHEMA_RDN "cn=schema" 43 44static struct berval config_rdn = BER_BVC(CONFIG_RDN); 45static struct berval schema_rdn = BER_BVC(SCHEMA_RDN); 46 47extern int slap_DN_strict; /* dn.c */ 48 49#ifdef SLAPD_MODULES 50typedef struct modpath_s { 51 struct modpath_s *mp_next; 52 struct berval mp_path; 53 BerVarray mp_loads; 54} ModPaths; 55 56static ModPaths modpaths, *modlast = &modpaths, *modcur = &modpaths; 57#endif 58 59typedef struct ConfigFile { 60 struct ConfigFile *c_sibs; 61 struct ConfigFile *c_kids; 62 struct berval c_file; 63 AttributeType *c_at_head, *c_at_tail; 64 ContentRule *c_cr_head, *c_cr_tail; 65 ObjectClass *c_oc_head, *c_oc_tail; 66 OidMacro *c_om_head, *c_om_tail; 67 Syntax *c_syn_head, *c_syn_tail; 68 BerVarray c_dseFiles; 69} ConfigFile; 70 71typedef struct { 72 ConfigFile *cb_config; 73 CfEntryInfo *cb_root; 74 BackendDB cb_db; /* underlying database */ 75 int cb_got_ldif; 76 int cb_use_ldif; 77} CfBackInfo; 78 79static CfBackInfo cfBackInfo; 80 81static char *passwd_salt; 82static FILE *logfile; 83static char *logfileName; 84static char *pws_replica_name; 85#ifdef SLAP_AUTH_REWRITE 86static BerVarray authz_rewrites; 87#endif 88static AccessControl *defacl_parsed = NULL; 89 90static struct berval cfdir; 91 92BerVarray cf_accountpolicy_override; 93 94/* Private state */ 95static AttributeDescription *cfAd_backend, *cfAd_database, *cfAd_overlay, 96 *cfAd_include, *cfAd_attr, *cfAd_oc, *cfAd_om, *cfAd_syntax; 97 98static ConfigFile *cfn; 99 100static Avlnode *CfOcTree; 101 102/* System schema state */ 103extern AttributeType *at_sys_tail; /* at.c */ 104extern ObjectClass *oc_sys_tail; /* oc.c */ 105extern OidMacro *om_sys_tail; /* oidm.c */ 106extern Syntax *syn_sys_tail; /* syntax.c */ 107static AttributeType *cf_at_tail; 108static ObjectClass *cf_oc_tail; 109static OidMacro *cf_om_tail; 110static Syntax *cf_syn_tail; 111 112static int config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, 113 SlapReply *rs, int *renumber, Operation *op ); 114 115static int config_check_schema( Operation *op, CfBackInfo *cfb ); 116 117static ConfigDriver config_fname; 118static ConfigDriver config_cfdir; 119static ConfigDriver config_generic; 120static ConfigDriver config_search_base; 121static ConfigDriver config_passwd_hash; 122static ConfigDriver config_schema_dn; 123static ConfigDriver config_sizelimit; 124static ConfigDriver config_timelimit; 125static ConfigDriver config_overlay; 126static ConfigDriver config_subordinate; 127static ConfigDriver config_suffix; 128#ifdef LDAP_TCP_BUFFER 129static ConfigDriver config_tcp_buffer; 130#endif /* LDAP_TCP_BUFFER */ 131static ConfigDriver config_rootdn; 132static ConfigDriver config_rootpw; 133static ConfigDriver config_restrict; 134static ConfigDriver config_allows; 135static ConfigDriver config_disallows; 136static ConfigDriver config_requires; 137static ConfigDriver config_security; 138static ConfigDriver config_referral; 139static ConfigDriver config_loglevel; 140static ConfigDriver config_updatedn; 141static ConfigDriver config_updateref; 142static ConfigDriver config_extra_attrs; 143static ConfigDriver config_include; 144static ConfigDriver config_obsolete; 145#ifdef HAVE_TLS 146static ConfigDriver config_tls_option; 147static ConfigDriver config_tls_config; 148#endif 149extern ConfigDriver syncrepl_config; 150static ConfigDriver config_accountpolicy; 151 152enum { 153 CFG_ACL = 1, 154 CFG_BACKEND, 155 CFG_DATABASE, 156 CFG_TLS_RAND, 157 CFG_TLS_CIPHER, 158 CFG_TLS_PROTOCOL_MIN, 159 CFG_TLS_CERT_FILE, 160 CFG_TLS_CERT_KEY, 161 CFG_TLS_CA_PATH, 162 CFG_TLS_CA_FILE, 163 CFG_TLS_DH_FILE, 164 CFG_TLS_VERIFY, 165 CFG_TLS_CRLCHECK, 166 CFG_TLS_CRL_FILE, 167 CFG_CONCUR, 168 CFG_THREADS, 169 CFG_SALT, 170 CFG_LIMITS, 171 CFG_RO, 172 CFG_REWRITE, 173 CFG_DEPTH, 174 CFG_OID, 175 CFG_OC, 176 CFG_DIT, 177 CFG_ATTR, 178 CFG_ATOPT, 179 CFG_ROOTDSE, 180 CFG_LOGFILE, 181 CFG_PLUGIN, 182 CFG_MODLOAD, 183 CFG_MODPATH, 184 CFG_LASTMOD, 185 CFG_AZPOLICY, 186 CFG_AZREGEXP, 187 CFG_SASLSECP, 188 CFG_SSTR_IF_MAX, 189 CFG_SSTR_IF_MIN, 190 CFG_TTHREADS, 191 CFG_MIRRORMODE, 192 CFG_HIDDEN, 193 CFG_MONITORING, 194 CFG_SERVERID, 195 CFG_SORTVALS, 196 CFG_IX_INTLEN, 197 CFG_SYNTAX, 198 CFG_ACL_ADD, 199 CFG_SYNC_SUBENTRY, 200 CFG_LTHREADS, 201 CFG_TLS_CERT_PASSPHRASE, 202 CFG_PWS_REPLICA_NAME, 203 CFG_TLS_IDENT_REF, 204 CFG_TLS_IDENTITY, 205 CFG_TLS_TRUSTED_CERTS, 206 CFG_ACCOUNTPOLICY_OVERRIDE, 207 208 CFG_LAST 209}; 210 211typedef struct { 212 char *name, *oid; 213} OidRec; 214 215static OidRec OidMacros[] = { 216 /* OpenLDAProot:1.12.2 */ 217 { "OLcfg", "1.3.6.1.4.1.4203.1.12.2" }, 218 { "OLcfgAt", "OLcfg:3" }, 219 { "OLcfgGlAt", "OLcfgAt:0" }, 220 { "OLcfgBkAt", "OLcfgAt:1" }, 221 { "OLcfgDbAt", "OLcfgAt:2" }, 222 { "OLcfgOvAt", "OLcfgAt:3" }, 223 { "OLcfgCtAt", "OLcfgAt:4" }, /* contrib modules */ 224 { "OLcfgOc", "OLcfg:4" }, 225 { "OLcfgGlOc", "OLcfgOc:0" }, 226 { "OLcfgBkOc", "OLcfgOc:1" }, 227 { "OLcfgDbOc", "OLcfgOc:2" }, 228 { "OLcfgOvOc", "OLcfgOc:3" }, 229 { "OLcfgCtOc", "OLcfgOc:4" }, /* contrib modules */ 230 231 /* Syntaxes. We should just start using the standard names and 232 * document that they are predefined and available for users 233 * to reference in their own schema. Defining schema without 234 * OID macros is for masochists... 235 */ 236 { "OMsyn", "1.3.6.1.4.1.1466.115.121.1" }, 237 { "OMsBoolean", "OMsyn:7" }, 238 { "OMsDN", "OMsyn:12" }, 239 { "OMsDirectoryString", "OMsyn:15" }, 240 { "OMsIA5String", "OMsyn:26" }, 241 { "OMsInteger", "OMsyn:27" }, 242 { "OMsOID", "OMsyn:38" }, 243 { "OMsOctetString", "OMsyn:40" }, 244 { NULL, NULL } 245}; 246 247/* 248 * Backend/Database registry 249 * 250 * OLcfg{Bk|Db}{Oc|At}:0 -> common 251 * OLcfg{Bk|Db}{Oc|At}:1 -> back-bdb(/back-hdb) 252 * OLcfg{Bk|Db}{Oc|At}:2 -> back-ldif 253 * OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap 254 * OLcfg{Bk|Db}{Oc|At}:4 -> back-monitor 255 * OLcfg{Bk|Db}{Oc|At}:5 -> back-relay 256 * OLcfg{Bk|Db}{Oc|At}:6 -> back-sql(/back-ndb) 257 * OLcfg{Bk|Db}{Oc|At}:7 -> back-sock 258 * OLcfg{Bk|Db}{Oc|At}:8 -> back-null 259 * OLcfg{Bk|Db}{Oc|At}:9 -> back-passwd 260 * OLcfg{Bk|Db}{Oc|At}:10 -> back-shell 261 * OLcfg{Bk|Db}{Oc|At}:11 -> back-perl 262 * OLcfg{Bk|Db}{Oc|At}:12 -> back-mdb 263 */ 264 265/* 266 * Overlay registry 267 * 268 * OLcfgOv{Oc|At}:1 -> syncprov 269 * OLcfgOv{Oc|At}:2 -> pcache 270 * OLcfgOv{Oc|At}:3 -> chain 271 * OLcfgOv{Oc|At}:4 -> accesslog 272 * OLcfgOv{Oc|At}:5 -> valsort 273 * OLcfgOv{Oc|At}:7 -> distproc 274 * OLcfgOv{Oc|At}:8 -> dynlist 275 * OLcfgOv{Oc|At}:9 -> dds 276 * OLcfgOv{Oc|At}:10 -> unique 277 * OLcfgOv{Oc|At}:11 -> refint 278 * OLcfgOv{Oc|At}:12 -> ppolicy 279 * OLcfgOv{Oc|At}:13 -> constraint 280 * OLcfgOv{Oc|At}:14 -> translucent 281 * OLcfgOv{Oc|At}:15 -> auditlog 282 * OLcfgOv{Oc|At}:16 -> rwm 283 * OLcfgOv{Oc|At}:17 -> dyngroup 284 * OLcfgOv{Oc|At}:18 -> memberof 285 * OLcfgOv{Oc|At}:19 -> collect 286 * OLcfgOv{Oc|At}:20 -> retcode 287 * OLcfgOv{Oc|At}:21 -> sssvlv 288 */ 289 290/* alphabetical ordering */ 291 292static ConfigTable config_back_cf_table[] = { 293 /* This attr is read-only */ 294 { "", "", 0, 0, 0, ARG_MAGIC, 295 &config_fname, "( OLcfgGlAt:78 NAME 'olcConfigFile' " 296 "DESC 'File for slapd configuration directives' " 297 "EQUALITY caseIgnoreMatch " 298 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 299 { "", "", 0, 0, 0, ARG_MAGIC, 300 &config_cfdir, "( OLcfgGlAt:79 NAME 'olcConfigDir' " 301 "DESC 'Directory for slapd configuration backend' " 302 "EQUALITY caseIgnoreMatch " 303 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 304 { "access", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC|CFG_ACL, 305 &config_generic, "( OLcfgGlAt:1 NAME 'olcAccess' " 306 "DESC 'Access Control List' " 307 "EQUALITY caseIgnoreMatch " 308 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL }, 309 { "add_content_acl", NULL, 0, 0, 0, ARG_MAY_DB|ARG_ON_OFF|ARG_MAGIC|CFG_ACL_ADD, 310 &config_generic, "( OLcfgGlAt:86 NAME 'olcAddContentAcl' " 311 "DESC 'Check ACLs against content of Add ops' " 312 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 313 { "allows", "features", 2, 0, 5, ARG_PRE_DB|ARG_MAGIC, 314 &config_allows, "( OLcfgGlAt:2 NAME 'olcAllows' " 315 "DESC 'Allowed set of deprecated features' " 316 "EQUALITY caseIgnoreMatch " 317 "SYNTAX OMsDirectoryString )", NULL, NULL }, 318 { "argsfile", "file", 2, 2, 0, ARG_STRING, 319 &slapd_args_file, "( OLcfgGlAt:3 NAME 'olcArgsFile' " 320 "DESC 'File for slapd command line options' " 321 "EQUALITY caseIgnoreMatch " 322 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 323 { "attributeoptions", NULL, 0, 0, 0, ARG_MAGIC|CFG_ATOPT, 324 &config_generic, "( OLcfgGlAt:5 NAME 'olcAttributeOptions' " 325 "EQUALITY caseIgnoreMatch " 326 "SYNTAX OMsDirectoryString )", NULL, NULL }, 327 { "attribute", "attribute", 2, 0, STRLENOF( "attribute" ), 328 ARG_PAREN|ARG_MAGIC|CFG_ATTR, 329 &config_generic, "( OLcfgGlAt:4 NAME 'olcAttributeTypes' " 330 "DESC 'OpenLDAP attributeTypes' " 331 "EQUALITY caseIgnoreMatch " 332 "SUBSTR caseIgnoreSubstringsMatch " 333 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", 334 NULL, NULL }, 335 { "authid-rewrite", NULL, 2, 0, STRLENOF( "authid-rewrite" ), 336#ifdef SLAP_AUTH_REWRITE 337 ARG_MAGIC|CFG_REWRITE|ARG_NO_INSERT, &config_generic, 338#else 339 ARG_IGNORED, NULL, 340#endif 341 "( OLcfgGlAt:6 NAME 'olcAuthIDRewrite' " 342 "EQUALITY caseIgnoreMatch " 343 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL }, 344 { "authz-policy", "policy", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_AZPOLICY, 345 &config_generic, "( OLcfgGlAt:7 NAME 'olcAuthzPolicy' " 346 "EQUALITY caseIgnoreMatch " 347 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 348 { "authz-regexp", "regexp> <DN", 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP|ARG_NO_INSERT, 349 &config_generic, "( OLcfgGlAt:8 NAME 'olcAuthzRegexp' " 350 "EQUALITY caseIgnoreMatch " 351 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL }, 352 { "backend", "type", 2, 2, 0, ARG_PRE_DB|ARG_MAGIC|CFG_BACKEND, 353 &config_generic, "( OLcfgGlAt:9 NAME 'olcBackend' " 354 "DESC 'A type of backend' " 355 "EQUALITY caseIgnoreMatch " 356 "SYNTAX OMsDirectoryString SINGLE-VALUE X-ORDERED 'SIBLINGS' )", 357 NULL, NULL }, 358 { "concurrency", "level", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_CONCUR, 359 &config_generic, "( OLcfgGlAt:10 NAME 'olcConcurrency' " 360 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 361 { "conn_max_pending", "max", 2, 2, 0, ARG_INT, 362 &slap_conn_max_pending, "( OLcfgGlAt:11 NAME 'olcConnMaxPending' " 363 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 364 { "conn_max_pending_auth", "max", 2, 2, 0, ARG_INT, 365 &slap_conn_max_pending_auth, "( OLcfgGlAt:12 NAME 'olcConnMaxPendingAuth' " 366 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 367 { "database", "type", 2, 2, 0, ARG_MAGIC|CFG_DATABASE, 368 &config_generic, "( OLcfgGlAt:13 NAME 'olcDatabase' " 369 "DESC 'The backend type for a database instance' " 370 "SUP olcBackend SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL }, 371 { "defaultSearchBase", "dn", 2, 2, 0, ARG_PRE_BI|ARG_PRE_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC, 372 &config_search_base, "( OLcfgGlAt:14 NAME 'olcDefaultSearchBase' " 373 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL }, 374 { "disallows", "features", 2, 0, 8, ARG_PRE_DB|ARG_MAGIC, 375 &config_disallows, "( OLcfgGlAt:15 NAME 'olcDisallows' " 376 "EQUALITY caseIgnoreMatch " 377 "SYNTAX OMsDirectoryString )", NULL, NULL }, 378 { "ditcontentrule", NULL, 0, 0, 0, ARG_MAGIC|CFG_DIT|ARG_NO_DELETE|ARG_NO_INSERT, 379 &config_generic, "( OLcfgGlAt:16 NAME 'olcDitContentRules' " 380 "DESC 'OpenLDAP DIT content rules' " 381 "EQUALITY caseIgnoreMatch " 382 "SUBSTR caseIgnoreSubstringsMatch " 383 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", 384 NULL, NULL }, 385 { "extra_attrs", "attrlist", 2, 2, 0, ARG_DB|ARG_MAGIC, 386 &config_extra_attrs, "( OLcfgDbAt:0.20 NAME 'olcExtraAttrs' " 387 "EQUALITY caseIgnoreMatch " 388 "SYNTAX OMsDirectoryString )", NULL, NULL }, 389 { "gentlehup", "on|off", 2, 2, 0, 390#ifdef SIGHUP 391 ARG_ON_OFF, &global_gentlehup, 392#else 393 ARG_IGNORED, NULL, 394#endif 395 "( OLcfgGlAt:17 NAME 'olcGentleHUP' " 396 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 397 { "hidden", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_HIDDEN, 398 &config_generic, "( OLcfgDbAt:0.17 NAME 'olcHidden' " 399 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 400 { "idletimeout", "timeout", 2, 2, 0, ARG_INT, 401 &global_idletimeout, "( OLcfgGlAt:18 NAME 'olcIdleTimeout' " 402 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 403 { "include", "file", 2, 2, 0, ARG_MAGIC, 404 &config_include, "( OLcfgGlAt:19 NAME 'olcInclude' " 405 "SUP labeledURI )", NULL, NULL }, 406 { "index_substr_if_minlen", "min", 2, 2, 0, ARG_UINT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MIN, 407 &config_generic, "( OLcfgGlAt:20 NAME 'olcIndexSubstrIfMinLen' " 408 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 409 { "index_substr_if_maxlen", "max", 2, 2, 0, ARG_UINT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MAX, 410 &config_generic, "( OLcfgGlAt:21 NAME 'olcIndexSubstrIfMaxLen' " 411 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 412 { "index_substr_any_len", "len", 2, 2, 0, ARG_INT|ARG_NONZERO, 413 &index_substr_any_len, "( OLcfgGlAt:22 NAME 'olcIndexSubstrAnyLen' " 414 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 415 { "index_substr_any_step", "step", 2, 2, 0, ARG_INT|ARG_NONZERO, 416 &index_substr_any_step, "( OLcfgGlAt:23 NAME 'olcIndexSubstrAnyStep' " 417 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 418 { "index_intlen", "len", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_IX_INTLEN, 419 &config_generic, "( OLcfgGlAt:84 NAME 'olcIndexIntLen' " 420 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 421 { "lastmod", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_LASTMOD, 422 &config_generic, "( OLcfgDbAt:0.4 NAME 'olcLastMod' " 423 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 424 { "ldapsyntax", "syntax", 2, 0, 0, 425 ARG_PAREN|ARG_MAGIC|CFG_SYNTAX, 426 &config_generic, "( OLcfgGlAt:85 NAME 'olcLdapSyntaxes' " 427 "DESC 'OpenLDAP ldapSyntax' " 428 "EQUALITY caseIgnoreMatch " 429 "SUBSTR caseIgnoreSubstringsMatch " 430 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", 431 NULL, NULL }, 432 { "limits", "limits", 2, 0, 0, ARG_DB|ARG_MAGIC|CFG_LIMITS, 433 &config_generic, "( OLcfgDbAt:0.5 NAME 'olcLimits' " 434 "EQUALITY caseIgnoreMatch " 435 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL }, 436 { "listener-threads", "count", 2, 0, 0, 437#ifdef NO_THREADS 438 ARG_IGNORED, NULL, 439#else 440 ARG_UINT|ARG_MAGIC|CFG_LTHREADS, &config_generic, 441#endif 442 "( OLcfgGlAt:93 NAME 'olcListenerThreads' " 443 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 444 { "localSSF", "ssf", 2, 2, 0, ARG_INT, 445 &local_ssf, "( OLcfgGlAt:26 NAME 'olcLocalSSF' " 446 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 447 { "logfile", "file", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_LOGFILE, 448 &config_generic, "( OLcfgGlAt:27 NAME 'olcLogFile' " 449 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 450 { "loglevel", "level", 2, 0, 0, ARG_MAGIC, 451 &config_loglevel, "( OLcfgGlAt:28 NAME 'olcLogLevel' " 452 "EQUALITY caseIgnoreMatch " 453 "SYNTAX OMsDirectoryString )", NULL, NULL }, 454 { "maxDerefDepth", "depth", 2, 2, 0, ARG_DB|ARG_INT|ARG_MAGIC|CFG_DEPTH, 455 &config_generic, "( OLcfgDbAt:0.6 NAME 'olcMaxDerefDepth' " 456 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 457 { "mirrormode", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_MIRRORMODE, 458 &config_generic, "( OLcfgDbAt:0.16 NAME 'olcMirrorMode' " 459 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 460 { "moduleload", "file", 2, 0, 0, 461#ifdef SLAPD_MODULES 462 ARG_MAGIC|CFG_MODLOAD|ARG_NO_DELETE, &config_generic, 463#else 464 ARG_IGNORED, NULL, 465#endif 466 "( OLcfgGlAt:30 NAME 'olcModuleLoad' " 467 "EQUALITY caseIgnoreMatch " 468 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL }, 469 { "modulepath", "path", 2, 2, 0, 470#ifdef SLAPD_MODULES 471 ARG_MAGIC|CFG_MODPATH|ARG_NO_DELETE|ARG_NO_INSERT, &config_generic, 472#else 473 ARG_IGNORED, NULL, 474#endif 475 "( OLcfgGlAt:31 NAME 'olcModulePath' " 476 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 477 { "monitoring", "TRUE|FALSE", 2, 2, 0, 478 ARG_MAGIC|CFG_MONITORING|ARG_DB|ARG_ON_OFF, &config_generic, 479 "( OLcfgDbAt:0.18 NAME 'olcMonitoring' " 480 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 481 { "objectclass", "objectclass", 2, 0, 0, ARG_PAREN|ARG_MAGIC|CFG_OC, 482 &config_generic, "( OLcfgGlAt:32 NAME 'olcObjectClasses' " 483 "DESC 'OpenLDAP object classes' " 484 "EQUALITY caseIgnoreMatch " 485 "SUBSTR caseIgnoreSubstringsMatch " 486 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", 487 NULL, NULL }, 488 { "objectidentifier", "name> <oid", 3, 3, 0, ARG_MAGIC|CFG_OID, 489 &config_generic, "( OLcfgGlAt:33 NAME 'olcObjectIdentifier' " 490 "EQUALITY caseIgnoreMatch " 491 "SUBSTR caseIgnoreSubstringsMatch " 492 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL }, 493 { "overlay", "overlay", 2, 2, 0, ARG_MAGIC, 494 &config_overlay, "( OLcfgGlAt:34 NAME 'olcOverlay' " 495 "SUP olcDatabase SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL }, 496 { "password-crypt-salt-format", "salt", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_SALT, 497 &config_generic, "( OLcfgGlAt:35 NAME 'olcPasswordCryptSaltFormat' " 498 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 499 { "password-hash", "hash", 2, 0, 0, ARG_MAGIC, 500 &config_passwd_hash, "( OLcfgGlAt:36 NAME 'olcPasswordHash' " 501 "EQUALITY caseIgnoreMatch " 502 "SYNTAX OMsDirectoryString )", NULL, NULL }, 503 { "pidfile", "file", 2, 2, 0, ARG_STRING, 504 &slapd_pid_file, "( OLcfgGlAt:37 NAME 'olcPidFile' " 505 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 506 { "plugin", NULL, 0, 0, 0, 507#ifdef LDAP_SLAPI 508 ARG_MAGIC|CFG_PLUGIN, &config_generic, 509#else 510 ARG_IGNORED, NULL, 511#endif 512 "( OLcfgGlAt:38 NAME 'olcPlugin' " 513 "EQUALITY caseIgnoreMatch " 514 "SYNTAX OMsDirectoryString )", NULL, NULL }, 515 { "pluginlog", "filename", 2, 2, 0, 516#ifdef LDAP_SLAPI 517 ARG_STRING, &slapi_log_file, 518#else 519 ARG_IGNORED, NULL, 520#endif 521 "( OLcfgGlAt:39 NAME 'olcPluginLogFile' " 522 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 523 { "readonly", "on|off", 2, 2, 0, ARG_MAY_DB|ARG_ON_OFF|ARG_MAGIC|CFG_RO, 524 &config_generic, "( OLcfgGlAt:40 NAME 'olcReadOnly' " 525 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 526 { "referral", "url", 2, 2, 0, ARG_MAGIC, 527 &config_referral, "( OLcfgGlAt:41 NAME 'olcReferral' " 528 "SUP labeledURI SINGLE-VALUE )", NULL, NULL }, 529 { "replica", "host or uri", 2, 0, 0, ARG_DB|ARG_MAGIC, 530 &config_obsolete, "( OLcfgDbAt:0.7 NAME 'olcReplica' " 531 "EQUALITY caseIgnoreMatch " 532 "SUP labeledURI X-ORDERED 'VALUES' )", NULL, NULL }, 533 { "replica-argsfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC, 534 &config_obsolete, "( OLcfgGlAt:43 NAME 'olcReplicaArgsFile' " 535 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 536 { "replica-pidfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC, 537 &config_obsolete, "( OLcfgGlAt:44 NAME 'olcReplicaPidFile' " 538 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 539 { "replicationInterval", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC, 540 &config_obsolete, "( OLcfgGlAt:45 NAME 'olcReplicationInterval' " 541 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 542 { "replogfile", "filename", 2, 2, 0, ARG_MAY_DB|ARG_MAGIC, 543 &config_obsolete, "( OLcfgGlAt:46 NAME 'olcReplogFile' " 544 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 545 { "require", "features", 2, 0, 7, ARG_MAY_DB|ARG_MAGIC, 546 &config_requires, "( OLcfgGlAt:47 NAME 'olcRequires' " 547 "EQUALITY caseIgnoreMatch " 548 "SYNTAX OMsDirectoryString )", NULL, NULL }, 549 { "restrict", "op_list", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC, 550 &config_restrict, "( OLcfgGlAt:48 NAME 'olcRestrict' " 551 "EQUALITY caseIgnoreMatch " 552 "SYNTAX OMsDirectoryString )", NULL, NULL }, 553 { "reverse-lookup", "on|off", 2, 2, 0, 554#ifdef SLAPD_RLOOKUPS 555 ARG_ON_OFF, &use_reverse_lookup, 556#else 557 ARG_IGNORED, NULL, 558#endif 559 "( OLcfgGlAt:49 NAME 'olcReverseLookup' " 560 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 561 { "rootdn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC, 562 &config_rootdn, "( OLcfgDbAt:0.8 NAME 'olcRootDN' " 563 "EQUALITY distinguishedNameMatch " 564 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL }, 565 { "rootDSE", "file", 2, 2, 0, ARG_MAGIC|CFG_ROOTDSE, 566 &config_generic, "( OLcfgGlAt:51 NAME 'olcRootDSE' " 567 "EQUALITY caseIgnoreMatch " 568 "SYNTAX OMsDirectoryString )", NULL, NULL }, 569 { "rootpw", "password", 2, 2, 0, ARG_BERVAL|ARG_DB|ARG_MAGIC, 570 &config_rootpw, "( OLcfgDbAt:0.9 NAME 'olcRootPW' " 571 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 572 { "sasl-authz-policy", NULL, 2, 2, 0, ARG_MAGIC|CFG_AZPOLICY, 573 &config_generic, NULL, NULL, NULL }, 574 { "sasl-auxprops", NULL, 2, 0, 0, 575#ifdef HAVE_CYRUS_SASL 576 ARG_STRING|ARG_UNIQUE, &slap_sasl_auxprops, 577#else 578 ARG_IGNORED, NULL, 579#endif 580 "( OLcfgGlAt:89 NAME 'olcSaslAuxprops' " 581 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 582 { "sasl-host", "host", 2, 2, 0, 583#ifdef HAVE_CYRUS_SASL 584 ARG_STRING|ARG_UNIQUE, &sasl_host, 585#else 586 ARG_IGNORED, NULL, 587#endif 588 "( OLcfgGlAt:53 NAME 'olcSaslHost' " 589 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 590 { "sasl-realm", "realm", 2, 2, 0, 591#ifdef HAVE_CYRUS_SASL 592 ARG_STRING|ARG_UNIQUE, &global_realm, 593#else 594 ARG_IGNORED, NULL, 595#endif 596 "( OLcfgGlAt:54 NAME 'olcSaslRealm' " 597 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 598 { "sasl-regexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP, 599 &config_generic, NULL, NULL, NULL }, 600 { "sasl-secprops", "properties", 2, 2, 0, 601#ifdef HAVE_CYRUS_SASL 602 ARG_MAGIC|CFG_SASLSECP, &config_generic, 603#else 604 ARG_IGNORED, NULL, 605#endif 606 "( OLcfgGlAt:56 NAME 'olcSaslSecProps' " 607 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 608 { "saslRegexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP, 609 &config_generic, NULL, NULL, NULL }, 610 { "schemadn", "dn", 2, 2, 0, ARG_MAY_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC, 611 &config_schema_dn, "( OLcfgGlAt:58 NAME 'olcSchemaDN' " 612 "EQUALITY distinguishedNameMatch " 613 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL }, 614 { "security", "factors", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC, 615 &config_security, "( OLcfgGlAt:59 NAME 'olcSecurity' " 616 "EQUALITY caseIgnoreMatch " 617 "SYNTAX OMsDirectoryString )", NULL, NULL }, 618 { "serverID", "number> <[URI]", 2, 3, 0, ARG_MAGIC|CFG_SERVERID, 619 &config_generic, "( OLcfgGlAt:81 NAME 'olcServerID' " 620 "EQUALITY caseIgnoreMatch " 621 "SYNTAX OMsDirectoryString )", NULL, NULL }, 622 { "sizelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC, 623 &config_sizelimit, "( OLcfgGlAt:60 NAME 'olcSizeLimit' " 624 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 625 { "sockbuf_max_incoming", "max", 2, 2, 0, ARG_BER_LEN_T, 626 &sockbuf_max_incoming, "( OLcfgGlAt:61 NAME 'olcSockbufMaxIncoming' " 627 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 628 { "sockbuf_max_incoming_auth", "max", 2, 2, 0, ARG_BER_LEN_T, 629 &sockbuf_max_incoming_auth, "( OLcfgGlAt:62 NAME 'olcSockbufMaxIncomingAuth' " 630 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 631 { "sortvals", "attr", 2, 0, 0, ARG_MAGIC|CFG_SORTVALS, 632 &config_generic, "( OLcfgGlAt:83 NAME 'olcSortVals' " 633 "DESC 'Attributes whose values will always be sorted' " 634 "EQUALITY caseIgnoreMatch " 635 "SYNTAX OMsDirectoryString )", NULL, NULL }, 636 { "subordinate", "[advertise]", 1, 2, 0, ARG_DB|ARG_MAGIC, 637 &config_subordinate, "( OLcfgDbAt:0.15 NAME 'olcSubordinate' " 638 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 639 { "suffix", "suffix", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC, 640 &config_suffix, "( OLcfgDbAt:0.10 NAME 'olcSuffix' " 641 "EQUALITY distinguishedNameMatch " 642 "SYNTAX OMsDN )", NULL, NULL }, 643 { "sync_use_subentry", NULL, 0, 0, 0, ARG_ON_OFF|ARG_DB|ARG_MAGIC|CFG_SYNC_SUBENTRY, 644 &config_generic, "( OLcfgDbAt:0.19 NAME 'olcSyncUseSubentry' " 645 "DESC 'Store sync context in a subentry' " 646 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, 647 { "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC, 648 &syncrepl_config, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' " 649 "EQUALITY caseIgnoreMatch " 650 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL }, 651 { "tcp-buffer", "[listener=<listener>] [{read|write}=]size", 0, 0, 0, 652#ifndef LDAP_TCP_BUFFER 653 ARG_IGNORED, NULL, 654#else /* LDAP_TCP_BUFFER */ 655 ARG_MAGIC, &config_tcp_buffer, 656#endif /* LDAP_TCP_BUFFER */ 657 "( OLcfgGlAt:90 NAME 'olcTCPBuffer' " 658 "DESC 'Custom TCP buffer size' " 659 "SYNTAX OMsDirectoryString )", NULL, NULL }, 660 { "threads", "count", 2, 2, 0, 661#ifdef NO_THREADS 662 ARG_IGNORED, NULL, 663#else 664 ARG_INT|ARG_MAGIC|CFG_THREADS, &config_generic, 665#endif 666 "( OLcfgGlAt:66 NAME 'olcThreads' " 667 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 668 { "timelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC, 669 &config_timelimit, "( OLcfgGlAt:67 NAME 'olcTimeLimit' " 670 "SYNTAX OMsDirectoryString )", NULL, NULL }, 671 { "TLSCACertificateFile", NULL, 2, 2, 0, 672#if defined(HAVE_TLS) && !defined(HAVE_SECURE_TRANSPORT) 673 CFG_TLS_CA_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option, 674#else 675 ARG_IGNORED, NULL, 676#endif 677 "( OLcfgGlAt:68 NAME 'olcTLSCACertificateFile' " 678 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 679 { "TLSCACertificatePath", NULL, 2, 2, 0, 680#if defined(HAVE_TLS) && !defined(HAVE_SECURE_TRANSPORT) 681 CFG_TLS_CA_PATH|ARG_STRING|ARG_MAGIC, &config_tls_option, 682#else 683 ARG_IGNORED, NULL, 684#endif 685 "( OLcfgGlAt:69 NAME 'olcTLSCACertificatePath' " 686 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 687 { "TLSCertificateFile", NULL, 2, 2, 0, 688#if defined(HAVE_TLS) && !defined(HAVE_SECURE_TRANSPORT) 689 CFG_TLS_CERT_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option, 690#else 691 ARG_IGNORED, NULL, 692#endif 693 "( OLcfgGlAt:70 NAME 'olcTLSCertificateFile' " 694 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 695 { "TLSCertificateKeyFile", NULL, 2, 2, 0, 696#if defined(HAVE_TLS) && !defined(HAVE_SECURE_TRANSPORT) 697 CFG_TLS_CERT_KEY|ARG_STRING|ARG_MAGIC, &config_tls_option, 698#else 699 ARG_IGNORED, NULL, 700#endif 701 "( OLcfgGlAt:71 NAME 'olcTLSCertificateKeyFile' " 702 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 703 { "TLSCipherSuite", NULL, 2, 2, 0, 704#ifdef HAVE_TLS 705 CFG_TLS_CIPHER|ARG_STRING|ARG_MAGIC, &config_tls_option, 706#else 707 ARG_IGNORED, NULL, 708#endif 709 "( OLcfgGlAt:72 NAME 'olcTLSCipherSuite' " 710 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 711 { "TLSCRLCheck", NULL, 2, 2, 0, 712#if defined(HAVE_TLS) && (defined(HAVE_OPENSSL_CRL) || defined(HAVE_SECURE_TRANSPORT)) 713 CFG_TLS_CRLCHECK|ARG_STRING|ARG_MAGIC, &config_tls_config, 714#else 715 ARG_IGNORED, NULL, 716#endif 717 "( OLcfgGlAt:73 NAME 'olcTLSCRLCheck' " 718 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 719 { "TLSCRLFile", NULL, 2, 2, 0, 720#if defined(HAVE_GNUTLS) 721 CFG_TLS_CRL_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option, 722#else 723 ARG_IGNORED, NULL, 724#endif 725 "( OLcfgGlAt:82 NAME 'olcTLSCRLFile' " 726 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 727 { "TLSRandFile", NULL, 2, 2, 0, 728#if defined(HAVE_TLS) && !defined(HAVE_SECURE_TRANSPORT) 729 CFG_TLS_RAND|ARG_STRING|ARG_MAGIC, &config_tls_option, 730#else 731 ARG_IGNORED, NULL, 732#endif 733 "( OLcfgGlAt:74 NAME 'olcTLSRandFile' " 734 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 735 { "TLSVerifyClient", NULL, 2, 2, 0, 736#ifdef HAVE_TLS 737 CFG_TLS_VERIFY|ARG_STRING|ARG_MAGIC, &config_tls_config, 738#else 739 ARG_IGNORED, NULL, 740#endif 741 "( OLcfgGlAt:75 NAME 'olcTLSVerifyClient' " 742 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 743 { "TLSDHParamFile", NULL, 2, 2, 0, 744#ifdef HAVE_TLS 745 CFG_TLS_DH_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option, 746#else 747 ARG_IGNORED, NULL, 748#endif 749 "( OLcfgGlAt:77 NAME 'olcTLSDHParamFile' " 750 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 751 { "TLSProtocolMin", NULL, 2, 2, 0, 752#ifdef HAVE_TLS 753 CFG_TLS_PROTOCOL_MIN|ARG_STRING|ARG_MAGIC, &config_tls_config, 754#else 755 ARG_IGNORED, NULL, 756#endif 757 "( OLcfgGlAt:87 NAME 'olcTLSProtocolMin' " 758 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 759 { "tool-threads", "count", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_TTHREADS, 760 &config_generic, "( OLcfgGlAt:80 NAME 'olcToolThreads' " 761 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 762 { "ucdata-path", "path", 2, 2, 0, ARG_IGNORED, 763 NULL, NULL, NULL, NULL }, 764 { "updatedn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC, 765 &config_updatedn, "( OLcfgDbAt:0.12 NAME 'olcUpdateDN' " 766 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL }, 767 { "updateref", "url", 2, 2, 0, ARG_DB|ARG_MAGIC, 768 &config_updateref, "( OLcfgDbAt:0.13 NAME 'olcUpdateRef' " 769 "EQUALITY caseIgnoreMatch " 770 "SUP labeledURI )", NULL, NULL }, 771 { "writetimeout", "timeout", 2, 2, 0, ARG_INT, 772 &global_writetimeout, "( OLcfgGlAt:88 NAME 'olcWriteTimeout' " 773 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, 774 { "olcTLSCertificatePassphrase", NULL, 0, 0, 0, 775#if defined(HAVE_TLS) && !defined(HAVE_SECURE_TRANSPORT) 776 CFG_TLS_CERT_PASSPHRASE|ARG_STRING|ARG_MAGIC, &config_tls_option, 777#else 778 ARG_IGNORED, NULL, 779#endif 780 "( OLcfgGlAt:700 NAME 'olcTLSCertificatePassphrase' " 781 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 782 { "PWSReplicaName", NULL, 0, 0, 0, 783 CFG_PWS_REPLICA_NAME|ARG_STRING|ARG_MAGIC, &config_generic, 784 "( OLcfgGlAt:703 NAME 'olcPWSReplicaName' " 785 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 786 { "olcTLSCertificateIdentityRef", NULL, 0, 0, 0, 787#if defined(HAVE_TLS) && !defined(HAVE_SECURE_TRANSPORT) 788 CFG_TLS_IDENT_REF|ARG_STRING|ARG_MAGIC, &config_tls_option, 789#else 790 ARG_IGNORED, NULL, 791#endif 792 "( OLcfgGlAt:701 NAME 'olcTLSCertificateIdentityRef' " 793 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 794 795 { "olcTLSIdentity", NULL, 0, 0, 0, 796#if defined(HAVE_TLS) && defined(HAVE_SECURE_TRANSPORT) 797 CFG_TLS_IDENTITY|ARG_STRING|ARG_MAGIC, &config_tls_option, 798#else 799 ARG_IGNORED, NULL, 800#endif 801 "( OLcfgGlAt:702 NAME 'olcTLSIdentity' " 802 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 803 { "olcTLSTrustedCerts", NULL, 0, 0, 0, 804#if defined(HAVE_TLS) && defined(HAVE_SECURE_TRANSPORT) 805 CFG_TLS_TRUSTED_CERTS|ARG_STRING|ARG_MAGIC, &config_tls_option, 806#else 807 ARG_IGNORED, NULL, 808#endif 809 "( OLcfgGlAt:704 NAME 'olcTLSTrustedCerts' " 810 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 811 812 { "accountpolicyoverride", NULL, 0, 0, 0, 813 CFG_ACCOUNTPOLICY_OVERRIDE|ARG_STRING|ARG_MAGIC, &config_accountpolicy, 814 "( OLcfgGlAt:710 NAME 'olcAccountPolicyOverride' " 815 "SYNTAX OMsDirectoryString)", NULL, NULL }, 816 817 { NULL, NULL, 0, 0, 0, ARG_IGNORED, 818 NULL, NULL, NULL, NULL } 819}; 820 821/* Need to no-op this keyword for dynamic config */ 822ConfigTable olcDatabaseDummy[] = { 823 { "", "", 0, 0, 0, ARG_IGNORED, 824 NULL, "( OLcfgGlAt:13 NAME 'olcDatabase' " 825 "DESC 'The backend type for a database instance' " 826 "SUP olcBackend SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL }, 827 { NULL, NULL, 0, 0, 0, ARG_IGNORED } 828}; 829 830/* Routines to check if a child can be added to this type */ 831static ConfigLDAPadd cfAddSchema, cfAddInclude, cfAddDatabase, 832 cfAddBackend, cfAddModule, cfAddOverlay; 833 834/* NOTE: be careful when defining array members 835 * that can be conditionally compiled */ 836#define CFOC_GLOBAL cf_ocs[1] 837#define CFOC_SCHEMA cf_ocs[2] 838#define CFOC_BACKEND cf_ocs[3] 839#define CFOC_DATABASE cf_ocs[4] 840#define CFOC_OVERLAY cf_ocs[5] 841#define CFOC_INCLUDE cf_ocs[6] 842#define CFOC_FRONTEND cf_ocs[7] 843#ifdef SLAPD_MODULES 844#define CFOC_MODULE cf_ocs[8] 845#endif /* SLAPD_MODULES */ 846 847static ConfigOCs cf_ocs[] = { 848 { "( OLcfgGlOc:0 " 849 "NAME 'olcConfig' " 850 "DESC 'OpenLDAP configuration object' " 851 "ABSTRACT SUP top )", Cft_Abstract, NULL }, 852 { "( OLcfgGlOc:1 " 853 "NAME 'olcGlobal' " 854 "DESC 'OpenLDAP Global configuration options' " 855 "SUP olcConfig STRUCTURAL " 856 "MAY ( cn $ olcConfigFile $ olcConfigDir $ olcAllows $ olcArgsFile $ " 857 "olcAttributeOptions $ olcAuthIDRewrite $ " 858 "olcAuthzPolicy $ olcAuthzRegexp $ olcConcurrency $ " 859 "olcConnMaxPending $ olcConnMaxPendingAuth $ " 860 "olcDisallows $ olcGentleHUP $ olcIdleTimeout $ " 861 "olcIndexSubstrIfMaxLen $ olcIndexSubstrIfMinLen $ " 862 "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcIndexIntLen $ " 863 "olcLocalSSF $ olcLogFile $ olcLogLevel $ " 864 "olcPasswordCryptSaltFormat $ olcPasswordHash $ olcPidFile $ " 865 "olcPluginLogFile $ olcReadOnly $ olcReferral $ " 866 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ " 867 "olcRootDSE $ " 868 "olcSaslAuxprops $ olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ " 869 "olcSecurity $ olcServerID $ olcSizeLimit $ " 870 "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ " 871 "olcTCPBuffer $ " 872 "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ " 873 "olcTLSCACertificatePath $ olcTLSCertificateFile $ " 874 "olcTLSCertificatePassphrase $ olcTLSCertificateIdentityRef $ " 875 "olcTLSIdentity $ olcTLSTrustedCerts $ " 876 "olcAccountPolicyOverride $ " 877 "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ " 878 "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ " 879 "olcTLSCRLFile $ olcToolThreads $ olcWriteTimeout $ " 880 "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ " 881 "olcDitContentRules $ olcPWSReplicaName $ olcLdapSyntaxes ) )", Cft_Global }, 882 { "( OLcfgGlOc:2 " 883 "NAME 'olcSchemaConfig' " 884 "DESC 'OpenLDAP schema object' " 885 "SUP olcConfig STRUCTURAL " 886 "MAY ( cn $ olcObjectIdentifier $ olcLdapSyntaxes $ " 887 "olcAttributeTypes $ olcObjectClasses $ olcDitContentRules ) )", 888 Cft_Schema, NULL, cfAddSchema }, 889 { "( OLcfgGlOc:3 " 890 "NAME 'olcBackendConfig' " 891 "DESC 'OpenLDAP Backend-specific options' " 892 "SUP olcConfig STRUCTURAL " 893 "MUST olcBackend )", Cft_Backend, NULL, cfAddBackend }, 894 { "( OLcfgGlOc:4 " 895 "NAME 'olcDatabaseConfig' " 896 "DESC 'OpenLDAP Database-specific options' " 897 "SUP olcConfig STRUCTURAL " 898 "MUST olcDatabase " 899 "MAY ( olcHidden $ olcSuffix $ olcSubordinate $ olcAccess $ " 900 "olcAddContentAcl $ olcLastMod $ olcLimits $ " 901 "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ " 902 "olcReplicaArgsFile $ olcReplicaPidFile $ olcReplicationInterval $ " 903 "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ " 904 "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncUseSubentry $ olcSyncrepl $ " 905 "olcTimeLimit $ olcUpdateDN $ olcUpdateRef $ olcMirrorMode $ " 906 "olcMonitoring $ olcExtraAttrs ) )", 907 Cft_Database, NULL, cfAddDatabase }, 908 { "( OLcfgGlOc:5 " 909 "NAME 'olcOverlayConfig' " 910 "DESC 'OpenLDAP Overlay-specific options' " 911 "SUP olcConfig STRUCTURAL " 912 "MUST olcOverlay )", Cft_Overlay, NULL, cfAddOverlay }, 913 { "( OLcfgGlOc:6 " 914 "NAME 'olcIncludeFile' " 915 "DESC 'OpenLDAP configuration include file' " 916 "SUP olcConfig STRUCTURAL " 917 "MUST olcInclude " 918 "MAY ( cn $ olcRootDSE ) )", 919 /* Used to be Cft_Include, that def has been removed */ 920 Cft_Abstract, NULL, cfAddInclude }, 921 /* This should be STRUCTURAL like all the other database classes, but 922 * that would mean inheriting all of the olcDatabaseConfig attributes, 923 * which causes them to be merged twice in config_build_entry. 924 */ 925 { "( OLcfgGlOc:7 " 926 "NAME 'olcFrontendConfig' " 927 "DESC 'OpenLDAP frontend configuration' " 928 "AUXILIARY " 929 "MAY ( olcDefaultSearchBase $ olcPasswordHash $ olcSortVals ) )", 930 Cft_Database, NULL, NULL }, 931#ifdef SLAPD_MODULES 932 { "( OLcfgGlOc:8 " 933 "NAME 'olcModuleList' " 934 "DESC 'OpenLDAP dynamic module info' " 935 "SUP olcConfig STRUCTURAL " 936 "MAY ( cn $ olcModulePath $ olcModuleLoad ) )", 937 Cft_Module, NULL, cfAddModule }, 938#endif 939 { NULL, 0, NULL } 940}; 941 942typedef struct ServerID { 943 struct ServerID *si_next; 944 struct berval si_url; 945 int si_num; 946} ServerID; 947 948static ServerID *sid_list; 949 950typedef struct voidList { 951 struct voidList *vl_next; 952 void *vl_ptr; 953} voidList; 954 955typedef struct ADlist { 956 struct ADlist *al_next; 957 AttributeDescription *al_desc; 958} ADlist; 959 960static ADlist *sortVals; 961 962static int 963config_generic(ConfigArgs *c) { 964 int i; 965 966 if ( c->op == SLAP_CONFIG_EMIT ) { 967 int rc = 0; 968 switch(c->type) { 969 case CFG_CONCUR: 970 c->value_int = ldap_pvt_thread_get_concurrency(); 971 break; 972 case CFG_THREADS: 973 c->value_int = connection_pool_max * 2; 974 break; 975 case CFG_TTHREADS: 976 c->value_int = slap_tool_thread_max; 977 break; 978 case CFG_LTHREADS: 979 c->value_uint = slapd_daemon_threads; 980 break; 981 case CFG_SALT: 982 if ( passwd_salt ) 983 c->value_string = ch_strdup( passwd_salt ); 984 else 985 rc = 1; 986 break; 987 case CFG_LIMITS: 988 if ( c->be->be_limits ) { 989 char buf[4096*3]; 990 struct berval bv; 991 992 for ( i=0; c->be->be_limits[i]; i++ ) { 993 bv.bv_len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i ); 994 if ( bv.bv_len >= sizeof( buf ) ) { 995 ber_bvarray_free_x( c->rvalue_vals, NULL ); 996 c->rvalue_vals = NULL; 997 rc = 1; 998 break; 999 } 1000 bv.bv_val = buf + bv.bv_len; 1001 limits_unparse( c->be->be_limits[i], &bv, 1002 sizeof( buf ) - ( bv.bv_val - buf ) ); 1003 bv.bv_len += bv.bv_val - buf; 1004 bv.bv_val = buf; 1005 value_add_one( &c->rvalue_vals, &bv ); 1006 } 1007 } 1008 if ( !c->rvalue_vals ) rc = 1; 1009 break; 1010 case CFG_RO: 1011 c->value_int = (c->be->be_restrictops & SLAP_RESTRICT_READONLY); 1012 break; 1013 case CFG_AZPOLICY: 1014 c->value_string = ch_strdup( slap_sasl_getpolicy()); 1015 break; 1016 case CFG_AZREGEXP: 1017 slap_sasl_regexp_unparse( &c->rvalue_vals ); 1018 if ( !c->rvalue_vals ) rc = 1; 1019 break; 1020#ifdef HAVE_CYRUS_SASL 1021 case CFG_SASLSECP: { 1022 struct berval bv = BER_BVNULL; 1023 slap_sasl_secprops_unparse( &bv ); 1024 if ( !BER_BVISNULL( &bv )) { 1025 ber_bvarray_add( &c->rvalue_vals, &bv ); 1026 } else { 1027 rc = 1; 1028 } 1029 } 1030 break; 1031#endif 1032 case CFG_DEPTH: 1033 c->value_int = c->be->be_max_deref_depth; 1034 break; 1035 case CFG_HIDDEN: 1036 if ( SLAP_DBHIDDEN( c->be )) { 1037 c->value_int = 1; 1038 } else { 1039 rc = 1; 1040 } 1041 break; 1042 case CFG_OID: { 1043 ConfigFile *cf = c->ca_private; 1044 if ( !cf ) 1045 oidm_unparse( &c->rvalue_vals, NULL, NULL, 1 ); 1046 else if ( cf->c_om_head ) 1047 oidm_unparse( &c->rvalue_vals, cf->c_om_head, 1048 cf->c_om_tail, 0 ); 1049 if ( !c->rvalue_vals ) 1050 rc = 1; 1051 } 1052 break; 1053 case CFG_ATOPT: 1054 ad_unparse_options( &c->rvalue_vals ); 1055 break; 1056 case CFG_OC: { 1057 ConfigFile *cf = c->ca_private; 1058 if ( !cf ) 1059 oc_unparse( &c->rvalue_vals, NULL, NULL, 1 ); 1060 else if ( cf->c_oc_head ) 1061 oc_unparse( &c->rvalue_vals, cf->c_oc_head, 1062 cf->c_oc_tail, 0 ); 1063 if ( !c->rvalue_vals ) 1064 rc = 1; 1065 } 1066 break; 1067 case CFG_ATTR: { 1068 ConfigFile *cf = c->ca_private; 1069 if ( !cf ) 1070 at_unparse( &c->rvalue_vals, NULL, NULL, 1 ); 1071 else if ( cf->c_at_head ) 1072 at_unparse( &c->rvalue_vals, cf->c_at_head, 1073 cf->c_at_tail, 0 ); 1074 if ( !c->rvalue_vals ) 1075 rc = 1; 1076 } 1077 break; 1078 case CFG_SYNTAX: { 1079 ConfigFile *cf = c->ca_private; 1080 if ( !cf ) 1081 syn_unparse( &c->rvalue_vals, NULL, NULL, 1 ); 1082 else if ( cf->c_syn_head ) 1083 syn_unparse( &c->rvalue_vals, cf->c_syn_head, 1084 cf->c_syn_tail, 0 ); 1085 if ( !c->rvalue_vals ) 1086 rc = 1; 1087 } 1088 break; 1089 case CFG_DIT: { 1090 ConfigFile *cf = c->ca_private; 1091 if ( !cf ) 1092 cr_unparse( &c->rvalue_vals, NULL, NULL, 1 ); 1093 else if ( cf->c_cr_head ) 1094 cr_unparse( &c->rvalue_vals, cf->c_cr_head, 1095 cf->c_cr_tail, 0 ); 1096 if ( !c->rvalue_vals ) 1097 rc = 1; 1098 } 1099 break; 1100 1101 case CFG_ACL: { 1102 AccessControl *a; 1103 char *src, *dst, ibuf[11]; 1104 struct berval bv, abv; 1105 for (i=0, a=c->be->be_acl; a; i++,a=a->acl_next) { 1106 abv.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, i ); 1107 if ( abv.bv_len >= sizeof( ibuf ) ) { 1108 ber_bvarray_free_x( c->rvalue_vals, NULL ); 1109 c->rvalue_vals = NULL; 1110 i = 0; 1111 break; 1112 } 1113 acl_unparse( a, &bv ); 1114 abv.bv_val = ch_malloc( abv.bv_len + bv.bv_len + 1 ); 1115 AC_MEMCPY( abv.bv_val, ibuf, abv.bv_len ); 1116 /* Turn TAB / EOL into plain space */ 1117 for (src=bv.bv_val,dst=abv.bv_val+abv.bv_len; *src; src++) { 1118 if (isspace((unsigned char)*src)) *dst++ = ' '; 1119 else *dst++ = *src; 1120 } 1121 *dst = '\0'; 1122 if (dst[-1] == ' ') { 1123 dst--; 1124 *dst = '\0'; 1125 } 1126 abv.bv_len = dst - abv.bv_val; 1127 ber_bvarray_add( &c->rvalue_vals, &abv ); 1128 } 1129 rc = (!i); 1130 break; 1131 } 1132 case CFG_ACL_ADD: 1133 c->value_int = (SLAP_DBACL_ADD(c->be) != 0); 1134 break; 1135 case CFG_ROOTDSE: { 1136 ConfigFile *cf = c->ca_private; 1137 if ( cf->c_dseFiles ) { 1138 value_add( &c->rvalue_vals, cf->c_dseFiles ); 1139 } else { 1140 rc = 1; 1141 } 1142 } 1143 break; 1144 case CFG_SERVERID: 1145 if ( sid_list ) { 1146 ServerID *si; 1147 struct berval bv; 1148 1149 for ( si = sid_list; si; si=si->si_next ) { 1150 assert( si->si_num >= 0 && si->si_num <= SLAP_SYNC_SID_MAX ); 1151 if ( !BER_BVISEMPTY( &si->si_url )) { 1152 bv.bv_len = si->si_url.bv_len + 6; 1153 bv.bv_val = ch_malloc( bv.bv_len ); 1154 bv.bv_len = sprintf( bv.bv_val, "%d %s", si->si_num, 1155 si->si_url.bv_val ); 1156 ber_bvarray_add( &c->rvalue_vals, &bv ); 1157 } else { 1158 char buf[5]; 1159 bv.bv_val = buf; 1160 bv.bv_len = sprintf( buf, "%d", si->si_num ); 1161 value_add_one( &c->rvalue_vals, &bv ); 1162 } 1163 } 1164 } else { 1165 rc = 1; 1166 } 1167 break; 1168 case CFG_LOGFILE: 1169 if ( logfileName ) 1170 c->value_string = ch_strdup( logfileName ); 1171 else 1172 rc = 1; 1173 break; 1174 case CFG_LASTMOD: 1175 c->value_int = (SLAP_NOLASTMOD(c->be) == 0); 1176 break; 1177 case CFG_SYNC_SUBENTRY: 1178 c->value_int = (SLAP_SYNC_SUBENTRY(c->be) != 0); 1179 break; 1180 case CFG_MIRRORMODE: 1181 if ( SLAP_SHADOW(c->be)) 1182 c->value_int = (SLAP_MULTIMASTER(c->be) != 0); 1183 else 1184 rc = 1; 1185 break; 1186 case CFG_MONITORING: 1187 c->value_int = (SLAP_DBMONITORING(c->be) != 0); 1188 break; 1189 case CFG_SSTR_IF_MAX: 1190 c->value_uint = index_substr_if_maxlen; 1191 break; 1192 case CFG_SSTR_IF_MIN: 1193 c->value_uint = index_substr_if_minlen; 1194 break; 1195 case CFG_IX_INTLEN: 1196 c->value_int = index_intlen; 1197 break; 1198 case CFG_SORTVALS: { 1199 ADlist *sv; 1200 rc = 1; 1201 for ( sv = sortVals; sv; sv = sv->al_next ) { 1202 value_add_one( &c->rvalue_vals, &sv->al_desc->ad_cname ); 1203 rc = 0; 1204 } 1205 } break; 1206#ifdef SLAPD_MODULES 1207 case CFG_MODLOAD: { 1208 ModPaths *mp = c->ca_private; 1209 if (mp->mp_loads) { 1210 int i; 1211 for (i=0; !BER_BVISNULL(&mp->mp_loads[i]); i++) { 1212 struct berval bv; 1213 bv.bv_val = c->log; 1214 bv.bv_len = snprintf( bv.bv_val, sizeof( c->log ), 1215 SLAP_X_ORDERED_FMT "%s", i, 1216 mp->mp_loads[i].bv_val ); 1217 if ( bv.bv_len >= sizeof( c->log ) ) { 1218 ber_bvarray_free_x( c->rvalue_vals, NULL ); 1219 c->rvalue_vals = NULL; 1220 break; 1221 } 1222 value_add_one( &c->rvalue_vals, &bv ); 1223 } 1224 } 1225 1226 rc = c->rvalue_vals ? 0 : 1; 1227 } 1228 break; 1229 case CFG_MODPATH: { 1230 ModPaths *mp = c->ca_private; 1231 if ( !BER_BVISNULL( &mp->mp_path )) 1232 value_add_one( &c->rvalue_vals, &mp->mp_path ); 1233 1234 rc = c->rvalue_vals ? 0 : 1; 1235 } 1236 break; 1237#endif 1238#ifdef LDAP_SLAPI 1239 case CFG_PLUGIN: 1240 slapi_int_plugin_unparse( c->be, &c->rvalue_vals ); 1241 if ( !c->rvalue_vals ) rc = 1; 1242 break; 1243#endif 1244#ifdef SLAP_AUTH_REWRITE 1245 case CFG_REWRITE: 1246 if ( authz_rewrites ) { 1247 struct berval bv, idx; 1248 char ibuf[32]; 1249 int i; 1250 1251 idx.bv_val = ibuf; 1252 for ( i=0; !BER_BVISNULL( &authz_rewrites[i] ); i++ ) { 1253 idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), SLAP_X_ORDERED_FMT, i ); 1254 if ( idx.bv_len >= sizeof( ibuf ) ) { 1255 ber_bvarray_free_x( c->rvalue_vals, NULL ); 1256 c->rvalue_vals = NULL; 1257 break; 1258 } 1259 bv.bv_len = idx.bv_len + authz_rewrites[i].bv_len; 1260 bv.bv_val = ch_malloc( bv.bv_len + 1 ); 1261 AC_MEMCPY( bv.bv_val, idx.bv_val, idx.bv_len ); 1262 AC_MEMCPY( &bv.bv_val[ idx.bv_len ], 1263 authz_rewrites[i].bv_val, 1264 authz_rewrites[i].bv_len + 1 ); 1265 ber_bvarray_add( &c->rvalue_vals, &bv ); 1266 } 1267 } 1268 if ( !c->rvalue_vals ) rc = 1; 1269 break; 1270#endif 1271 case CFG_PWS_REPLICA_NAME: 1272 if ( pws_replica_name ) 1273 c->value_string = ch_strdup( pws_replica_name ); 1274 else 1275 rc = 1; 1276 break; 1277 default: 1278 rc = 1; 1279 } 1280 return rc; 1281 } else if ( c->op == LDAP_MOD_DELETE ) { 1282 int rc = 0; 1283 switch(c->type) { 1284 /* single-valued attrs, no-ops */ 1285 case CFG_CONCUR: 1286 case CFG_THREADS: 1287 case CFG_TTHREADS: 1288 case CFG_LTHREADS: 1289 case CFG_RO: 1290 case CFG_AZPOLICY: 1291 case CFG_DEPTH: 1292 case CFG_LASTMOD: 1293 case CFG_MONITORING: 1294 case CFG_SASLSECP: 1295 case CFG_SSTR_IF_MAX: 1296 case CFG_SSTR_IF_MIN: 1297 case CFG_ACL_ADD: 1298 case CFG_SYNC_SUBENTRY: 1299 break; 1300 1301 /* no-ops, requires slapd restart */ 1302 case CFG_PLUGIN: 1303 case CFG_MODLOAD: 1304 case CFG_AZREGEXP: 1305 case CFG_REWRITE: 1306 snprintf(c->log, sizeof( c->log ), "change requires slapd restart"); 1307 break; 1308 1309 case CFG_MIRRORMODE: 1310 SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MULTI_SHADOW; 1311 if(SLAP_SHADOW(c->be)) 1312 SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW; 1313 break; 1314 1315 case CFG_SALT: 1316 ch_free( passwd_salt ); 1317 passwd_salt = NULL; 1318 break; 1319 1320 case CFG_LOGFILE: 1321 ch_free( logfileName ); 1322 logfileName = NULL; 1323 if ( logfile ) { 1324 fclose( logfile ); 1325 logfile = NULL; 1326 } 1327 break; 1328 1329 case CFG_SERVERID: { 1330 ServerID *si, **sip; 1331 1332 for ( i=0, si = sid_list, sip = &sid_list; 1333 si; si = *sip, i++ ) { 1334 if ( c->valx == -1 || i == c->valx ) { 1335 *sip = si->si_next; 1336 ch_free( si ); 1337 if ( c->valx >= 0 ) 1338 break; 1339 } else { 1340 sip = &si->si_next; 1341 } 1342 } 1343 } 1344 break; 1345 case CFG_HIDDEN: 1346 c->be->be_flags &= ~SLAP_DBFLAG_HIDDEN; 1347 break; 1348 1349 case CFG_IX_INTLEN: 1350 index_intlen = SLAP_INDEX_INTLEN_DEFAULT; 1351 index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN( 1352 SLAP_INDEX_INTLEN_DEFAULT ); 1353 break; 1354 1355 case CFG_ACL: 1356 if ( c->valx < 0 ) { 1357 acl_destroy( c->be->be_acl ); 1358 c->be->be_acl = NULL; 1359 1360 } else { 1361 AccessControl **prev, *a; 1362 int i; 1363 for (i=0, prev = &c->be->be_acl; i < c->valx; 1364 i++ ) { 1365 a = *prev; 1366 prev = &a->acl_next; 1367 } 1368 a = *prev; 1369 *prev = a->acl_next; 1370 acl_free( a ); 1371 } 1372 if ( SLAP_CONFIG( c->be ) && !c->be->be_acl ) { 1373 Debug( LDAP_DEBUG_CONFIG, "config_generic (CFG_ACL): " 1374 "Last explicit ACL for back-config removed. " 1375 "Using hardcoded default\n", 0, 0, 0 ); 1376 c->be->be_acl = defacl_parsed; 1377 } 1378 break; 1379 1380 case CFG_OC: { 1381 CfEntryInfo *ce; 1382 /* Can be NULL when undoing a failed add */ 1383 if ( c->ca_entry ) { 1384 ce = c->ca_entry->e_private; 1385 /* can't modify the hardcoded schema */ 1386 if ( ce->ce_parent->ce_type == Cft_Global ) 1387 return 1; 1388 } 1389 } 1390 cfn = c->ca_private; 1391 if ( c->valx < 0 ) { 1392 ObjectClass *oc; 1393 1394 for( oc = cfn->c_oc_head; oc; oc_next( &oc )) { 1395 oc_delete( oc ); 1396 if ( oc == cfn->c_oc_tail ) 1397 break; 1398 } 1399 cfn->c_oc_head = cfn->c_oc_tail = NULL; 1400 } else { 1401 ObjectClass *oc, *prev = NULL; 1402 1403 for ( i=0, oc=cfn->c_oc_head; i<c->valx; i++) { 1404 prev = oc; 1405 oc_next( &oc ); 1406 } 1407 oc_delete( oc ); 1408 if ( cfn->c_oc_tail == oc ) { 1409 cfn->c_oc_tail = prev; 1410 } 1411 if ( cfn->c_oc_head == oc ) { 1412 oc_next( &oc ); 1413 cfn->c_oc_head = oc; 1414 } 1415 } 1416 break; 1417 1418 case CFG_ATTR: { 1419 CfEntryInfo *ce; 1420 /* Can be NULL when undoing a failed add */ 1421 if ( c->ca_entry ) { 1422 ce = c->ca_entry->e_private; 1423 /* can't modify the hardcoded schema */ 1424 if ( ce->ce_parent->ce_type == Cft_Global ) 1425 return 1; 1426 } 1427 } 1428 cfn = c->ca_private; 1429 if ( c->valx < 0 ) { 1430 AttributeType *at; 1431 1432 for( at = cfn->c_at_head; at; at_next( &at )) { 1433 at_delete( at ); 1434 if ( at == cfn->c_at_tail ) 1435 break; 1436 } 1437 cfn->c_at_head = cfn->c_at_tail = NULL; 1438 } else { 1439 AttributeType *at, *prev = NULL; 1440 1441 for ( i=0, at=cfn->c_at_head; i<c->valx; i++) { 1442 prev = at; 1443 at_next( &at ); 1444 } 1445 at_delete( at ); 1446 if ( cfn->c_at_tail == at ) { 1447 cfn->c_at_tail = prev; 1448 } 1449 if ( cfn->c_at_head == at ) { 1450 at_next( &at ); 1451 cfn->c_at_head = at; 1452 } 1453 } 1454 break; 1455 1456 case CFG_SYNTAX: { 1457 CfEntryInfo *ce; 1458 /* Can be NULL when undoing a failed add */ 1459 if ( c->ca_entry ) { 1460 ce = c->ca_entry->e_private; 1461 /* can't modify the hardcoded schema */ 1462 if ( ce->ce_parent->ce_type == Cft_Global ) 1463 return 1; 1464 } 1465 } 1466 cfn = c->ca_private; 1467 if ( c->valx < 0 ) { 1468 Syntax *syn; 1469 1470 for( syn = cfn->c_syn_head; syn; syn_next( &syn )) { 1471 syn_delete( syn ); 1472 if ( syn == cfn->c_syn_tail ) 1473 break; 1474 } 1475 cfn->c_syn_head = cfn->c_syn_tail = NULL; 1476 } else { 1477 Syntax *syn, *prev = NULL; 1478 1479 for ( i = 0, syn = cfn->c_syn_head; i < c->valx; i++) { 1480 prev = syn; 1481 syn_next( &syn ); 1482 } 1483 syn_delete( syn ); 1484 if ( cfn->c_syn_tail == syn ) { 1485 cfn->c_syn_tail = prev; 1486 } 1487 if ( cfn->c_syn_head == syn ) { 1488 syn_next( &syn ); 1489 cfn->c_syn_head = syn; 1490 } 1491 } 1492 break; 1493 case CFG_SORTVALS: 1494 if ( c->valx < 0 ) { 1495 ADlist *sv; 1496 for ( sv = sortVals; sv; sv = sortVals ) { 1497 sortVals = sv->al_next; 1498 sv->al_desc->ad_type->sat_flags &= ~SLAP_AT_SORTED_VAL; 1499 ch_free( sv ); 1500 } 1501 } else { 1502 ADlist *sv, **prev; 1503 int i = 0; 1504 1505 for ( prev = &sortVals, sv = sortVals; i < c->valx; i++ ) { 1506 prev = &sv->al_next; 1507 sv = sv->al_next; 1508 } 1509 sv->al_desc->ad_type->sat_flags &= ~SLAP_AT_SORTED_VAL; 1510 *prev = sv->al_next; 1511 ch_free( sv ); 1512 } 1513 break; 1514 case CFG_PWS_REPLICA_NAME: 1515 ch_free( pws_replica_name ); 1516 pws_replica_name = NULL; 1517 break; 1518 case CFG_LIMITS: 1519 /* FIXME: there is no limits_free function */ 1520 if ( c->valx < 0 ) { 1521 limits_destroy( c->be->be_limits ); 1522 c->be->be_limits = NULL; 1523 1524 } else { 1525 int cnt, num = -1; 1526 1527 if ( c->be->be_limits ) { 1528 for ( num = 0; c->be->be_limits[ num ]; num++ ) 1529 /* just count */ ; 1530 } 1531 1532 if ( c->valx >= num ) { 1533 return 1; 1534 } 1535 1536 if ( num == 1 ) { 1537 limits_destroy( c->be->be_limits ); 1538 c->be->be_limits = NULL; 1539 1540 } else { 1541 limits_free_one( c->be->be_limits[ c->valx ] ); 1542 1543 for ( cnt = c->valx; cnt < num; cnt++ ) { 1544 c->be->be_limits[ cnt ] = c->be->be_limits[ cnt + 1 ]; 1545 } 1546 } 1547 } 1548 break; 1549 1550 case CFG_ATOPT: 1551 /* FIXME: there is no ad_option_free function */ 1552 case CFG_ROOTDSE: 1553 /* FIXME: there is no way to remove attributes added by 1554 a DSE file */ 1555 case CFG_OID: 1556 case CFG_DIT: 1557 case CFG_MODPATH: 1558 default: 1559 rc = 1; 1560 break; 1561 } 1562 return rc; 1563 } 1564 1565 switch(c->type) { 1566 case CFG_BACKEND: 1567 if(!(c->bi = backend_info(c->argv[1]))) { 1568 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> failed init", c->argv[0] ); 1569 Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n", 1570 c->log, c->cr_msg, c->argv[1] ); 1571 return(1); 1572 } 1573 break; 1574 1575 case CFG_DATABASE: 1576 c->bi = NULL; 1577 /* NOTE: config is always the first backend! 1578 */ 1579 if ( !strcasecmp( c->argv[1], "config" )) { 1580 c->be = LDAP_STAILQ_FIRST(&backendDB); 1581 } else if ( !strcasecmp( c->argv[1], "frontend" )) { 1582 c->be = frontendDB; 1583 } else { 1584 c->be = backend_db_init(c->argv[1], NULL, c->valx, &c->reply); 1585 if ( !c->be ) { 1586 if ( c->cr_msg[0] == 0 ) 1587 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> failed init", c->argv[0] ); 1588 Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", c->log, c->cr_msg, c->argv[1] ); 1589 return(1); 1590 } 1591 } 1592 break; 1593 1594 case CFG_CONCUR: 1595 ldap_pvt_thread_set_concurrency(c->value_int); 1596 break; 1597 1598 case CFG_THREADS: 1599 if ( c->value_int < 2 ) { 1600 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1601 "threads=%d smaller than minimum value 2", 1602 c->value_int ); 1603 Debug(LDAP_DEBUG_ANY, "%s: %s.\n", 1604 c->log, c->cr_msg, 0 ); 1605 return 1; 1606 1607 } else if ( c->value_int > 2 * SLAP_MAX_WORKER_THREADS ) { 1608 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1609 "warning, threads=%d larger than twice the default (2*%d=%d); YMMV", 1610 c->value_int, SLAP_MAX_WORKER_THREADS, 2 * SLAP_MAX_WORKER_THREADS ); 1611 Debug(LDAP_DEBUG_ANY, "%s: %s.\n", 1612 c->log, c->cr_msg, 0 ); 1613 } 1614 if ( slapMode & SLAP_SERVER_MODE ) 1615 ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int); 1616 connection_pool_max = c->value_int; /* save for reference */ 1617 break; 1618 1619 case CFG_TTHREADS: 1620 if ( slapMode & SLAP_TOOL_MODE ) 1621 ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int); 1622 slap_tool_thread_max = c->value_int; /* save for reference */ 1623 break; 1624 1625 case CFG_LTHREADS: 1626 { int mask = 0; 1627 /* use a power of two */ 1628 while (c->value_uint > 1) { 1629 c->value_uint >>= 1; 1630 mask <<= 1; 1631 mask |= 1; 1632 } 1633 slapd_daemon_mask = mask; 1634 slapd_daemon_threads = mask+1; 1635 } 1636 break; 1637 1638 case CFG_SALT: 1639 if ( passwd_salt ) ch_free( passwd_salt ); 1640 passwd_salt = c->value_string; 1641 lutil_salt_format(passwd_salt); 1642 break; 1643 1644 case CFG_LIMITS: 1645 if(limits_parse(c->be, c->fname, c->lineno, c->argc, c->argv)) 1646 return(1); 1647 break; 1648 1649 case CFG_RO: 1650 if(c->value_int) 1651 c->be->be_restrictops |= SLAP_RESTRICT_READONLY; 1652 else 1653 c->be->be_restrictops &= ~SLAP_RESTRICT_READONLY; 1654 break; 1655 1656 case CFG_AZPOLICY: 1657 ch_free(c->value_string); 1658 if (slap_sasl_setpolicy( c->argv[1] )) { 1659 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] ); 1660 Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", 1661 c->log, c->cr_msg, c->argv[1] ); 1662 return(1); 1663 } 1664 break; 1665 1666 case CFG_AZREGEXP: 1667 if (slap_sasl_regexp_config( c->argv[1], c->argv[2] )) 1668 return(1); 1669 break; 1670 1671#ifdef HAVE_CYRUS_SASL 1672 case CFG_SASLSECP: 1673 { 1674 char *txt = slap_sasl_secprops( c->argv[1] ); 1675 if ( txt ) { 1676 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> %s", 1677 c->argv[0], txt ); 1678 Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg, 0 ); 1679 return(1); 1680 } 1681 break; 1682 } 1683#endif 1684 1685 case CFG_DEPTH: 1686 c->be->be_max_deref_depth = c->value_int; 1687 break; 1688 1689 case CFG_OID: { 1690 OidMacro *om; 1691 1692 if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private ) 1693 cfn = c->ca_private; 1694 if(parse_oidm(c, 1, &om)) 1695 return(1); 1696 if (!cfn->c_om_head) cfn->c_om_head = om; 1697 cfn->c_om_tail = om; 1698 } 1699 break; 1700 1701 case CFG_OC: { 1702 ObjectClass *oc, *prev; 1703 1704 if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private ) 1705 cfn = c->ca_private; 1706 if ( c->valx < 0 ) { 1707 prev = cfn->c_oc_tail; 1708 } else { 1709 prev = NULL; 1710 /* If adding anything after the first, prev is easy */ 1711 if ( c->valx ) { 1712 int i; 1713 for (i=0, oc = cfn->c_oc_head; i<c->valx; i++) { 1714 prev = oc; 1715 if ( !oc_next( &oc )) 1716 break; 1717 } 1718 } else 1719 /* If adding the first, and head exists, find its prev */ 1720 if (cfn->c_oc_head) { 1721 for ( oc_start( &oc ); oc != cfn->c_oc_head; ) { 1722 prev = oc; 1723 oc_next( &oc ); 1724 } 1725 } 1726 /* else prev is NULL, append to end of global list */ 1727 } 1728 if(parse_oc(c, &oc, prev)) return(1); 1729 if (!cfn->c_oc_head) cfn->c_oc_head = oc; 1730 if (cfn->c_oc_tail == prev) cfn->c_oc_tail = oc; 1731 } 1732 break; 1733 1734 case CFG_ATTR: { 1735 AttributeType *at, *prev; 1736 1737 if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private ) 1738 cfn = c->ca_private; 1739 if ( c->valx < 0 ) { 1740 prev = cfn->c_at_tail; 1741 } else { 1742 prev = NULL; 1743 /* If adding anything after the first, prev is easy */ 1744 if ( c->valx ) { 1745 int i; 1746 for (i=0, at = cfn->c_at_head; i<c->valx; i++) { 1747 prev = at; 1748 if ( !at_next( &at )) 1749 break; 1750 } 1751 } else 1752 /* If adding the first, and head exists, find its prev */ 1753 if (cfn->c_at_head) { 1754 for ( at_start( &at ); at != cfn->c_at_head; ) { 1755 prev = at; 1756 at_next( &at ); 1757 } 1758 } 1759 /* else prev is NULL, append to end of global list */ 1760 } 1761 if(parse_at(c, &at, prev)) return(1); 1762 if (!cfn->c_at_head) cfn->c_at_head = at; 1763 if (cfn->c_at_tail == prev) cfn->c_at_tail = at; 1764 } 1765 break; 1766 1767 case CFG_SYNTAX: { 1768 Syntax *syn, *prev; 1769 1770 if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private ) 1771 cfn = c->ca_private; 1772 if ( c->valx < 0 ) { 1773 prev = cfn->c_syn_tail; 1774 } else { 1775 prev = NULL; 1776 /* If adding anything after the first, prev is easy */ 1777 if ( c->valx ) { 1778 int i; 1779 for ( i = 0, syn = cfn->c_syn_head; i < c->valx; i++ ) { 1780 prev = syn; 1781 if ( !syn_next( &syn )) 1782 break; 1783 } 1784 } else 1785 /* If adding the first, and head exists, find its prev */ 1786 if (cfn->c_syn_head) { 1787 for ( syn_start( &syn ); syn != cfn->c_syn_head; ) { 1788 prev = syn; 1789 syn_next( &syn ); 1790 } 1791 } 1792 /* else prev is NULL, append to end of global list */ 1793 } 1794 if ( parse_syn( c, &syn, prev ) ) return(1); 1795 if ( !cfn->c_syn_head ) cfn->c_syn_head = syn; 1796 if ( cfn->c_syn_tail == prev ) cfn->c_syn_tail = syn; 1797 } 1798 break; 1799 1800 case CFG_DIT: { 1801 ContentRule *cr; 1802 1803 if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private ) 1804 cfn = c->ca_private; 1805 if(parse_cr(c, &cr)) return(1); 1806 if (!cfn->c_cr_head) cfn->c_cr_head = cr; 1807 cfn->c_cr_tail = cr; 1808 } 1809 break; 1810 1811 case CFG_ATOPT: 1812 ad_define_option(NULL, NULL, 0); 1813 for(i = 1; i < c->argc; i++) 1814 if(ad_define_option(c->argv[i], c->fname, c->lineno)) 1815 return(1); 1816 break; 1817 1818 case CFG_IX_INTLEN: 1819 if ( c->value_int < SLAP_INDEX_INTLEN_DEFAULT ) 1820 c->value_int = SLAP_INDEX_INTLEN_DEFAULT; 1821 else if ( c->value_int > 255 ) 1822 c->value_int = 255; 1823 index_intlen = c->value_int; 1824 index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN( 1825 index_intlen ); 1826 break; 1827 1828 case CFG_SORTVALS: { 1829 ADlist *svnew = NULL, *svtail, *sv; 1830 1831 for ( i = 1; i < c->argc; i++ ) { 1832 AttributeDescription *ad = NULL; 1833 const char *text; 1834 int rc; 1835 1836 rc = slap_str2ad( c->argv[i], &ad, &text ); 1837 if ( rc ) { 1838 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown attribute type #%d", 1839 c->argv[0], i ); 1840sortval_reject: 1841 Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", 1842 c->log, c->cr_msg, c->argv[i] ); 1843 for ( sv = svnew; sv; sv = svnew ) { 1844 svnew = sv->al_next; 1845 ch_free( sv ); 1846 } 1847 return 1; 1848 } 1849 if (( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) || 1850 ad->ad_type->sat_single_value ) { 1851 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> inappropriate attribute type #%d", 1852 c->argv[0], i ); 1853 goto sortval_reject; 1854 } 1855 sv = ch_malloc( sizeof( ADlist )); 1856 sv->al_desc = ad; 1857 if ( !svnew ) { 1858 svnew = sv; 1859 } else { 1860 svtail->al_next = sv; 1861 } 1862 svtail = sv; 1863 } 1864 sv->al_next = NULL; 1865 for ( sv = svnew; sv; sv = sv->al_next ) 1866 sv->al_desc->ad_type->sat_flags |= SLAP_AT_SORTED_VAL; 1867 for ( sv = sortVals; sv && sv->al_next; sv = sv->al_next ); 1868 if ( sv ) 1869 sv->al_next = svnew; 1870 else 1871 sortVals = svnew; 1872 } 1873 break; 1874 1875 case CFG_ACL: 1876 if ( SLAP_CONFIG( c->be ) && c->be->be_acl == defacl_parsed) { 1877 c->be->be_acl = NULL; 1878 } 1879 /* Don't append to the global ACL if we're on a specific DB */ 1880 i = c->valx; 1881 if ( c->valx == -1 ) { 1882 AccessControl *a; 1883 i = 0; 1884 for ( a=c->be->be_acl; a; a = a->acl_next ) 1885 i++; 1886 } 1887 if ( parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, i ) ) { 1888 if ( SLAP_CONFIG( c->be ) && !c->be->be_acl) { 1889 c->be->be_acl = defacl_parsed; 1890 } 1891 return 1; 1892 } 1893 break; 1894 1895 case CFG_ACL_ADD: 1896 if(c->value_int) 1897 SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_ACL_ADD; 1898 else 1899 SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_ACL_ADD; 1900 break; 1901 1902 case CFG_ROOTDSE: 1903 if(root_dse_read_file(c->argv[1])) { 1904 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> could not read file", c->argv[0] ); 1905 Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", 1906 c->log, c->cr_msg, c->argv[1] ); 1907 return(1); 1908 } 1909 { 1910 struct berval bv; 1911 ber_str2bv( c->argv[1], 0, 1, &bv ); 1912 if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private ) 1913 cfn = c->ca_private; 1914 ber_bvarray_add( &cfn->c_dseFiles, &bv ); 1915 } 1916 break; 1917 1918 case CFG_SERVERID: 1919 { 1920 ServerID *si, **sip; 1921 LDAPURLDesc *lud; 1922 int num; 1923 if (( lutil_atoi( &num, c->argv[1] ) && 1924 lutil_atoix( &num, c->argv[1], 16 )) || 1925 num < 0 || num > SLAP_SYNC_SID_MAX ) 1926 { 1927 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1928 "<%s> illegal server ID", c->argv[0] ); 1929 Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", 1930 c->log, c->cr_msg, c->argv[1] ); 1931 return 1; 1932 } 1933 /* only one value allowed if no URL is given */ 1934 if ( c->argc > 2 ) { 1935 int len; 1936 1937 if ( sid_list && BER_BVISEMPTY( &sid_list->si_url )) { 1938 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1939 "<%s> only one server ID allowed now", c->argv[0] ); 1940 Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", 1941 c->log, c->cr_msg, c->argv[1] ); 1942 return 1; 1943 } 1944 1945 if ( ldap_url_parse( c->argv[2], &lud )) { 1946 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1947 "<%s> invalid URL", c->argv[0] ); 1948 Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", 1949 c->log, c->cr_msg, c->argv[2] ); 1950 return 1; 1951 } 1952 len = strlen( c->argv[2] ); 1953 si = ch_malloc( sizeof(ServerID) + len + 1 ); 1954 si->si_url.bv_val = (char *)(si+1); 1955 si->si_url.bv_len = len; 1956 strcpy( si->si_url.bv_val, c->argv[2] ); 1957 } else { 1958 if ( sid_list ) { 1959 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1960 "<%s> unqualified server ID not allowed now", c->argv[0] ); 1961 Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", 1962 c->log, c->cr_msg, c->argv[1] ); 1963 return 1; 1964 } 1965 si = ch_malloc( sizeof(ServerID) ); 1966 BER_BVZERO( &si->si_url ); 1967 slap_serverID = num; 1968 Debug( LDAP_DEBUG_CONFIG, 1969 "%s: SID=0x%03x\n", 1970 c->log, slap_serverID, 0 ); 1971 } 1972 si->si_next = NULL; 1973 si->si_num = num; 1974 for ( sip = &sid_list; *sip; sip = &(*sip)->si_next ); 1975 *sip = si; 1976 1977 if (( slapMode & SLAP_SERVER_MODE ) && c->argc > 2 ) { 1978 Listener *l = config_check_my_url( c->argv[2], lud ); 1979 if ( l ) { 1980 slap_serverID = si->si_num; 1981 Debug( LDAP_DEBUG_CONFIG, 1982 "%s: SID=0x%03x (listener=%s)\n", 1983 c->log, slap_serverID, 1984 l->sl_url.bv_val ); 1985 } 1986 } 1987 if ( c->argc > 2 ) 1988 ldap_free_urldesc( lud ); 1989 } 1990 break; 1991 case CFG_LOGFILE: { 1992 if ( logfileName ) ch_free( logfileName ); 1993 logfileName = c->value_string; 1994 logfile = fopen(logfileName, "w"); 1995 if(logfile) lutil_debug_file(logfile); 1996 } break; 1997 1998 case CFG_LASTMOD: 1999 if(SLAP_NOLASTMODCMD(c->be)) { 2000 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> not available for %s database", 2001 c->argv[0], c->be->bd_info->bi_type ); 2002 Debug(LDAP_DEBUG_ANY, "%s: %s\n", 2003 c->log, c->cr_msg, 0 ); 2004 return(1); 2005 } 2006 if(c->value_int) 2007 SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_NOLASTMOD; 2008 else 2009 SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_NOLASTMOD; 2010 break; 2011 2012 case CFG_MIRRORMODE: 2013 if(c->value_int && !SLAP_SHADOW(c->be)) { 2014 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> database is not a shadow", 2015 c->argv[0] ); 2016 Debug(LDAP_DEBUG_ANY, "%s: %s\n", 2017 c->log, c->cr_msg, 0 ); 2018 return(1); 2019 } 2020 if(c->value_int) { 2021 SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_SINGLE_SHADOW; 2022 SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_MULTI_SHADOW; 2023 } else { 2024 SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW; 2025 SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MULTI_SHADOW; 2026 } 2027 break; 2028 2029 case CFG_MONITORING: 2030 if(c->value_int) 2031 SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_MONITORING; 2032 else 2033 SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MONITORING; 2034 break; 2035 2036 case CFG_HIDDEN: 2037 if (c->value_int) 2038 SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_HIDDEN; 2039 else 2040 SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_HIDDEN; 2041 break; 2042 2043 case CFG_SYNC_SUBENTRY: 2044 if (c->value_int) 2045 SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SYNC_SUBENTRY; 2046 else 2047 SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_SYNC_SUBENTRY; 2048 break; 2049 2050 case CFG_SSTR_IF_MAX: 2051 if (c->value_uint < index_substr_if_minlen) { 2052 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value", c->argv[0] ); 2053 Debug(LDAP_DEBUG_ANY, "%s: %s (%d)\n", 2054 c->log, c->cr_msg, c->value_int ); 2055 return(1); 2056 } 2057 index_substr_if_maxlen = c->value_uint; 2058 break; 2059 2060 case CFG_SSTR_IF_MIN: 2061 if (c->value_uint > index_substr_if_maxlen) { 2062 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value", c->argv[0] ); 2063 Debug(LDAP_DEBUG_ANY, "%s: %s (%d)\n", 2064 c->log, c->cr_msg, c->value_int ); 2065 return(1); 2066 } 2067 index_substr_if_minlen = c->value_uint; 2068 break; 2069 2070#ifdef SLAPD_MODULES 2071 case CFG_MODLOAD: 2072 /* If we're just adding a module on an existing modpath, 2073 * make sure we've selected the current path. 2074 */ 2075 if ( c->op == LDAP_MOD_ADD && c->ca_private && modcur != c->ca_private ) { 2076 modcur = c->ca_private; 2077 /* This should never fail */ 2078 if ( module_path( modcur->mp_path.bv_val )) { 2079 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> module path no longer valid", 2080 c->argv[0] ); 2081 Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", 2082 c->log, c->cr_msg, modcur->mp_path.bv_val ); 2083 return(1); 2084 } 2085 } 2086 if(module_load(c->argv[1], c->argc - 2, (c->argc > 2) ? c->argv + 2 : NULL)) 2087 return(1); 2088 /* Record this load on the current path */ 2089 { 2090 struct berval bv; 2091 char *ptr; 2092 if ( c->op == SLAP_CONFIG_ADD ) { 2093 ptr = c->line + STRLENOF("moduleload"); 2094 while (!isspace((unsigned char) *ptr)) ptr++; 2095 while (isspace((unsigned char) *ptr)) ptr++; 2096 } else { 2097 ptr = c->line; 2098 } 2099 ber_str2bv(ptr, 0, 1, &bv); 2100 ber_bvarray_add( &modcur->mp_loads, &bv ); 2101 } 2102 /* Check for any new hardcoded schema */ 2103 if ( c->op == LDAP_MOD_ADD && CONFIG_ONLINE_ADD( c )) { 2104 config_check_schema( NULL, &cfBackInfo ); 2105 } 2106 break; 2107 2108 case CFG_MODPATH: 2109 if(module_path(c->argv[1])) return(1); 2110 /* Record which path was used with each module */ 2111 { 2112 ModPaths *mp; 2113 2114 if (!modpaths.mp_loads) { 2115 mp = &modpaths; 2116 } else { 2117 mp = ch_malloc( sizeof( ModPaths )); 2118 modlast->mp_next = mp; 2119 } 2120 ber_str2bv(c->argv[1], 0, 1, &mp->mp_path); 2121 mp->mp_next = NULL; 2122 mp->mp_loads = NULL; 2123 modlast = mp; 2124 c->ca_private = mp; 2125 modcur = mp; 2126 } 2127 2128 break; 2129#endif 2130 2131#ifdef LDAP_SLAPI 2132 case CFG_PLUGIN: 2133 if(slapi_int_read_config(c->be, c->fname, c->lineno, c->argc, c->argv) != LDAP_SUCCESS) 2134 return(1); 2135 slapi_plugins_used++; 2136 break; 2137#endif 2138 2139#ifdef SLAP_AUTH_REWRITE 2140 case CFG_REWRITE: { 2141 struct berval bv; 2142 char *line; 2143 int rc = 0; 2144 2145 if ( c->op == LDAP_MOD_ADD ) { 2146 c->argv++; 2147 c->argc--; 2148 } 2149 if(slap_sasl_rewrite_config(c->fname, c->lineno, c->argc, c->argv)) 2150 rc = 1; 2151 if ( rc == 0 ) { 2152 2153 if ( c->argc > 1 ) { 2154 char *s; 2155 2156 /* quote all args but the first */ 2157 line = ldap_charray2str( c->argv, "\" \"" ); 2158 ber_str2bv( line, 0, 0, &bv ); 2159 s = ber_bvchr( &bv, '"' ); 2160 assert( s != NULL ); 2161 /* move the trailing quote of argv[0] to the end */ 2162 AC_MEMCPY( s, s + 1, bv.bv_len - ( s - bv.bv_val ) ); 2163 bv.bv_val[ bv.bv_len - 1 ] = '"'; 2164 2165 } else { 2166 ber_str2bv( c->argv[ 0 ], 0, 1, &bv ); 2167 } 2168 2169 ber_bvarray_add( &authz_rewrites, &bv ); 2170 } 2171 if ( c->op == LDAP_MOD_ADD ) { 2172 c->argv--; 2173 c->argc++; 2174 } 2175 return rc; 2176 } 2177#endif 2178 2179 case CFG_PWS_REPLICA_NAME: { 2180 if ( pws_replica_name ) ch_free( pws_replica_name ); 2181 pws_replica_name = c->value_string; 2182 } break; 2183 2184 default: 2185 Debug( LDAP_DEBUG_ANY, 2186 "%s: unknown CFG_TYPE %d.\n", 2187 c->log, c->type, 0 ); 2188 return 1; 2189 2190 } 2191 return(0); 2192} 2193 2194 2195static int 2196config_fname(ConfigArgs *c) { 2197 if(c->op == SLAP_CONFIG_EMIT) { 2198 if (c->ca_private) { 2199 ConfigFile *cf = c->ca_private; 2200 value_add_one( &c->rvalue_vals, &cf->c_file ); 2201 return 0; 2202 } 2203 return 1; 2204 } 2205 return(0); 2206} 2207 2208static int 2209config_cfdir(ConfigArgs *c) { 2210 if(c->op == SLAP_CONFIG_EMIT) { 2211 if ( !BER_BVISEMPTY( &cfdir )) { 2212 value_add_one( &c->rvalue_vals, &cfdir ); 2213 return 0; 2214 } 2215 return 1; 2216 } 2217 return(0); 2218} 2219 2220static int 2221config_search_base(ConfigArgs *c) { 2222 if(c->op == SLAP_CONFIG_EMIT) { 2223 int rc = 1; 2224 if (!BER_BVISEMPTY(&default_search_base)) { 2225 value_add_one(&c->rvalue_vals, &default_search_base); 2226 value_add_one(&c->rvalue_nvals, &default_search_nbase); 2227 rc = 0; 2228 } 2229 return rc; 2230 } else if( c->op == LDAP_MOD_DELETE ) { 2231 ch_free( default_search_base.bv_val ); 2232 ch_free( default_search_nbase.bv_val ); 2233 BER_BVZERO( &default_search_base ); 2234 BER_BVZERO( &default_search_nbase ); 2235 return 0; 2236 } 2237 2238 if(c->bi || c->be != frontendDB) { 2239 Debug(LDAP_DEBUG_ANY, "%s: defaultSearchBase line must appear " 2240 "prior to any backend or database definition\n", 2241 c->log, 0, 0); 2242 return(1); 2243 } 2244 2245 if(default_search_nbase.bv_len) { 2246 free(default_search_base.bv_val); 2247 free(default_search_nbase.bv_val); 2248 } 2249 2250 default_search_base = c->value_dn; 2251 default_search_nbase = c->value_ndn; 2252 return(0); 2253} 2254 2255/* For RE23 compatibility we allow this in the global entry 2256 * but we now defer it to the frontend entry to allow modules 2257 * to load new hash types. 2258 */ 2259static int 2260config_passwd_hash(ConfigArgs *c) { 2261 int i; 2262 if (c->op == SLAP_CONFIG_EMIT) { 2263 struct berval bv; 2264 /* Don't generate it in the global entry */ 2265 if ( c->table == Cft_Global ) 2266 return 1; 2267 for (i=0; default_passwd_hash && default_passwd_hash[i]; i++) { 2268 ber_str2bv(default_passwd_hash[i], 0, 0, &bv); 2269 value_add_one(&c->rvalue_vals, &bv); 2270 } 2271 return i ? 0 : 1; 2272 } else if ( c->op == LDAP_MOD_DELETE ) { 2273 /* Deleting from global is a no-op, only the frontendDB entry matters */ 2274 if ( c->table == Cft_Global ) 2275 return 0; 2276 if ( c->valx < 0 ) { 2277 ldap_charray_free( default_passwd_hash ); 2278 default_passwd_hash = NULL; 2279 } else { 2280 i = c->valx; 2281 ch_free( default_passwd_hash[i] ); 2282 for (; default_passwd_hash[i]; i++ ) 2283 default_passwd_hash[i] = default_passwd_hash[i+1]; 2284 } 2285 return 0; 2286 } 2287 for(i = 1; i < c->argc; i++) { 2288 if(!lutil_passwd_scheme(c->argv[i])) { 2289 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> scheme not available", c->argv[0] ); 2290 Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", 2291 c->log, c->cr_msg, c->argv[i]); 2292 } else { 2293 ldap_charray_add(&default_passwd_hash, c->argv[i]); 2294 } 2295 } 2296 if(!default_passwd_hash) { 2297 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> no valid hashes found", c->argv[0] ); 2298 Debug(LDAP_DEBUG_ANY, "%s: %s\n", 2299 c->log, c->cr_msg, 0 ); 2300 return(1); 2301 } 2302 return(0); 2303} 2304 2305static int 2306config_schema_dn(ConfigArgs *c) { 2307 if ( c->op == SLAP_CONFIG_EMIT ) { 2308 int rc = 1; 2309 if ( !BER_BVISEMPTY( &c->be->be_schemadn )) { 2310 value_add_one(&c->rvalue_vals, &c->be->be_schemadn); 2311 value_add_one(&c->rvalue_nvals, &c->be->be_schemandn); 2312 rc = 0; 2313 } 2314 return rc; 2315 } else if ( c->op == LDAP_MOD_DELETE ) { 2316 ch_free( c->be->be_schemadn.bv_val ); 2317 ch_free( c->be->be_schemandn.bv_val ); 2318 BER_BVZERO( &c->be->be_schemadn ); 2319 BER_BVZERO( &c->be->be_schemandn ); 2320 return 0; 2321 } 2322 ch_free( c->be->be_schemadn.bv_val ); 2323 ch_free( c->be->be_schemandn.bv_val ); 2324 c->be->be_schemadn = c->value_dn; 2325 c->be->be_schemandn = c->value_ndn; 2326 return(0); 2327} 2328 2329static int 2330config_accountpolicy(ConfigArgs *c) { 2331 if ( c->op == SLAP_CONFIG_EMIT ) { 2332 int rc = 1; 2333 2334 if ( cf_accountpolicy_override ) { 2335 ber_bvarray_dup_x(&c->rvalue_vals, cf_accountpolicy_override, NULL); 2336 } 2337 2338 return rc; 2339 } else if ( c->op == LDAP_MOD_DELETE ) { 2340 ber_bvarray_free( cf_accountpolicy_override ); 2341 cf_accountpolicy_override = NULL; 2342 2343 return 0; 2344 } 2345 2346 struct berval bv; 2347 2348 ber_str2bv( c->value_string, 0, 0, &bv ); 2349 2350 ber_bvarray_add( &cf_accountpolicy_override, &bv); 2351 2352 return(0); 2353} 2354 2355static int 2356config_sizelimit(ConfigArgs *c) { 2357 int i, rc = 0; 2358 struct slap_limits_set *lim = &c->be->be_def_limit; 2359 if (c->op == SLAP_CONFIG_EMIT) { 2360 char buf[8192]; 2361 struct berval bv; 2362 bv.bv_val = buf; 2363 bv.bv_len = 0; 2364 limits_unparse_one( lim, SLAP_LIMIT_SIZE, &bv, sizeof( buf ) ); 2365 if ( !BER_BVISEMPTY( &bv )) 2366 value_add_one( &c->rvalue_vals, &bv ); 2367 else 2368 rc = 1; 2369 return rc; 2370 } else if ( c->op == LDAP_MOD_DELETE ) { 2371 /* Reset to defaults or values from frontend */ 2372 if ( c->be == frontendDB ) { 2373 lim->lms_s_soft = SLAPD_DEFAULT_SIZELIMIT; 2374 lim->lms_s_hard = 0; 2375 lim->lms_s_unchecked = -1; 2376 lim->lms_s_pr = 0; 2377 lim->lms_s_pr_hide = 0; 2378 lim->lms_s_pr_total = 0; 2379 } else { 2380 lim->lms_s_soft = frontendDB->be_def_limit.lms_s_soft; 2381 lim->lms_s_hard = frontendDB->be_def_limit.lms_s_hard; 2382 lim->lms_s_unchecked = frontendDB->be_def_limit.lms_s_unchecked; 2383 lim->lms_s_pr = frontendDB->be_def_limit.lms_s_pr; 2384 lim->lms_s_pr_hide = frontendDB->be_def_limit.lms_s_pr_hide; 2385 lim->lms_s_pr_total = frontendDB->be_def_limit.lms_s_pr_total; 2386 } 2387 goto ok; 2388 } 2389 for(i = 1; i < c->argc; i++) { 2390 if(!strncasecmp(c->argv[i], "size", 4)) { 2391 rc = limits_parse_one(c->argv[i], lim); 2392 if ( rc ) { 2393 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] ); 2394 Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", 2395 c->log, c->cr_msg, c->argv[i]); 2396 return(1); 2397 } 2398 } else { 2399 if(!strcasecmp(c->argv[i], "unlimited")) { 2400 lim->lms_s_soft = -1; 2401 } else { 2402 if ( lutil_atoix( &lim->lms_s_soft, c->argv[i], 0 ) != 0 ) { 2403 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse limit", c->argv[0]); 2404 Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", 2405 c->log, c->cr_msg, c->argv[i]); 2406 return(1); 2407 } 2408 } 2409 lim->lms_s_hard = 0; 2410 } 2411 } 2412 2413ok: 2414 if ( ( c->be == frontendDB ) && ( c->ca_entry ) ) { 2415 /* This is a modification to the global limits apply it to 2416 * the other databases as needed */ 2417 AttributeDescription *ad=NULL; 2418 const char *text = NULL; 2419 CfEntryInfo *ce = c->ca_entry->e_private; 2420 2421 slap_str2ad(c->argv[0], &ad, &text); 2422 /* if we got here... */ 2423 assert( ad != NULL ); 2424 2425 if ( ce->ce_type == Cft_Global ){ 2426 ce = ce->ce_kids; 2427 } 2428 for (; ce; ce=ce->ce_sibs) { 2429 Entry *dbe = ce->ce_entry; 2430 if ( (ce->ce_type == Cft_Database) && (ce->ce_be != frontendDB) 2431 && (!attr_find(dbe->e_attrs, ad)) ) { 2432 ce->ce_be->be_def_limit.lms_s_soft = lim->lms_s_soft; 2433 ce->ce_be->be_def_limit.lms_s_hard = lim->lms_s_hard; 2434 ce->ce_be->be_def_limit.lms_s_unchecked =lim->lms_s_unchecked; 2435 ce->ce_be->be_def_limit.lms_s_pr =lim->lms_s_pr; 2436 ce->ce_be->be_def_limit.lms_s_pr_hide =lim->lms_s_pr_hide; 2437 ce->ce_be->be_def_limit.lms_s_pr_total =lim->lms_s_pr_total; 2438 } 2439 } 2440 } 2441 return(0); 2442} 2443 2444static int 2445config_timelimit(ConfigArgs *c) { 2446 int i, rc = 0; 2447 struct slap_limits_set *lim = &c->be->be_def_limit; 2448 if (c->op == SLAP_CONFIG_EMIT) { 2449 char buf[8192]; 2450 struct berval bv; 2451 bv.bv_val = buf; 2452 bv.bv_len = 0; 2453 limits_unparse_one( lim, SLAP_LIMIT_TIME, &bv, sizeof( buf ) ); 2454 if ( !BER_BVISEMPTY( &bv )) 2455 value_add_one( &c->rvalue_vals, &bv ); 2456 else 2457 rc = 1; 2458 return rc; 2459 } else if ( c->op == LDAP_MOD_DELETE ) { 2460 /* Reset to defaults or values from frontend */ 2461 if ( c->be == frontendDB ) { 2462 lim->lms_t_soft = SLAPD_DEFAULT_TIMELIMIT; 2463 lim->lms_t_hard = 0; 2464 } else { 2465 lim->lms_t_soft = frontendDB->be_def_limit.lms_t_soft; 2466 lim->lms_t_hard = frontendDB->be_def_limit.lms_t_hard; 2467 } 2468 goto ok; 2469 } 2470 for(i = 1; i < c->argc; i++) { 2471 if(!strncasecmp(c->argv[i], "time", 4)) { 2472 rc = limits_parse_one(c->argv[i], lim); 2473 if ( rc ) { 2474 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] ); 2475 Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", 2476 c->log, c->cr_msg, c->argv[i]); 2477 return(1); 2478 } 2479 } else { 2480 if(!strcasecmp(c->argv[i], "unlimited")) { 2481 lim->lms_t_soft = -1; 2482 } else { 2483 if ( lutil_atoix( &lim->lms_t_soft, c->argv[i], 0 ) != 0 ) { 2484 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse limit", c->argv[0]); 2485 Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", 2486 c->log, c->cr_msg, c->argv[i]); 2487 return(1); 2488 } 2489 } 2490 lim->lms_t_hard = 0; 2491 } 2492 } 2493 2494ok: 2495 if ( ( c->be == frontendDB ) && ( c->ca_entry ) ) { 2496 /* This is a modification to the global limits apply it to 2497 * the other databases as needed */ 2498 AttributeDescription *ad=NULL; 2499 const char *text = NULL; 2500 CfEntryInfo *ce = c->ca_entry->e_private; 2501 2502 slap_str2ad(c->argv[0], &ad, &text); 2503 /* if we got here... */ 2504 assert( ad != NULL ); 2505 2506 if ( ce->ce_type == Cft_Global ){ 2507 ce = ce->ce_kids; 2508 } 2509 for (; ce; ce=ce->ce_sibs) { 2510 Entry *dbe = ce->ce_entry; 2511 if ( (ce->ce_type == Cft_Database) && (ce->ce_be != frontendDB) 2512 && (!attr_find(dbe->e_attrs, ad)) ) { 2513 ce->ce_be->be_def_limit.lms_t_soft = lim->lms_t_soft; 2514 ce->ce_be->be_def_limit.lms_t_hard = lim->lms_t_hard; 2515 } 2516 } 2517 } 2518 return(0); 2519} 2520 2521static int 2522config_overlay(ConfigArgs *c) { 2523 if (c->op == SLAP_CONFIG_EMIT) { 2524 return 1; 2525 } else if ( c->op == LDAP_MOD_DELETE ) { 2526 assert(0); 2527 } 2528 if(c->argv[1][0] == '-' && overlay_config(c->be, &c->argv[1][1], 2529 c->valx, &c->bi, &c->reply)) { 2530 /* log error */ 2531 Debug( LDAP_DEBUG_ANY, 2532 "%s: (optional) %s overlay \"%s\" configuration failed.\n", 2533 c->log, c->be == frontendDB ? "global " : "", &c->argv[1][1]); 2534 return 1; 2535 } else if(overlay_config(c->be, c->argv[1], c->valx, &c->bi, &c->reply)) { 2536 return(1); 2537 } 2538 return(0); 2539} 2540 2541static int 2542config_subordinate(ConfigArgs *c) 2543{ 2544 int rc = 1; 2545 int advertise = 0; 2546 2547 switch( c->op ) { 2548 case SLAP_CONFIG_EMIT: 2549 if ( SLAP_GLUE_SUBORDINATE( c->be )) { 2550 struct berval bv; 2551 2552 bv.bv_val = SLAP_GLUE_ADVERTISE( c->be ) ? "advertise" : "TRUE"; 2553 bv.bv_len = SLAP_GLUE_ADVERTISE( c->be ) ? STRLENOF("advertise") : 2554 STRLENOF("TRUE"); 2555 2556 value_add_one( &c->rvalue_vals, &bv ); 2557 rc = 0; 2558 } 2559 break; 2560 case LDAP_MOD_DELETE: 2561 if ( !c->line || strcasecmp( c->line, "advertise" )) { 2562 glue_sub_del( c->be ); 2563 } else { 2564 SLAP_DBFLAGS( c->be ) &= ~SLAP_DBFLAG_GLUE_ADVERTISE; 2565 } 2566 rc = 0; 2567 break; 2568 case LDAP_MOD_ADD: 2569 case SLAP_CONFIG_ADD: 2570 if ( c->be->be_nsuffix == NULL ) { 2571 /* log error */ 2572 snprintf( c->cr_msg, sizeof( c->cr_msg), 2573 "subordinate configuration needs a suffix" ); 2574 Debug( LDAP_DEBUG_ANY, 2575 "%s: %s.\n", 2576 c->log, c->cr_msg, 0 ); 2577 rc = 1; 2578 break; 2579 } 2580 2581 if ( c->argc == 2 ) { 2582 if ( strcasecmp( c->argv[1], "advertise" ) == 0 ) { 2583 advertise = 1; 2584 2585 } else if ( strcasecmp( c->argv[1], "TRUE" ) != 0 ) { 2586 /* log error */ 2587 snprintf( c->cr_msg, sizeof( c->cr_msg), 2588 "subordinate must be \"TRUE\" or \"advertise\"" ); 2589 Debug( LDAP_DEBUG_ANY, 2590 "%s: suffix \"%s\": %s.\n", 2591 c->log, c->be->be_suffix[0].bv_val, c->cr_msg ); 2592 rc = 1; 2593 break; 2594 } 2595 } 2596 2597 rc = glue_sub_add( c->be, advertise, CONFIG_ONLINE_ADD( c )); 2598 break; 2599 } 2600 2601 return rc; 2602} 2603 2604/* 2605 * [listener=<listener>] [{read|write}=]<size> 2606 */ 2607 2608#ifdef LDAP_TCP_BUFFER 2609static BerVarray tcp_buffer; 2610int tcp_buffer_num; 2611 2612#define SLAP_TCP_RMEM (0x1U) 2613#define SLAP_TCP_WMEM (0x2U) 2614 2615static int 2616tcp_buffer_parse( struct berval *val, int argc, char **argv, 2617 int *size, int *rw, Listener **l ) 2618{ 2619 int i, rc = LDAP_SUCCESS; 2620 LDAPURLDesc *lud = NULL; 2621 char *ptr; 2622 2623 if ( val != NULL && argv == NULL ) { 2624 char *s = val->bv_val; 2625 2626 argv = ldap_str2charray( s, " \t" ); 2627 if ( argv == NULL ) { 2628 return LDAP_OTHER; 2629 } 2630 } 2631 2632 i = 0; 2633 if ( strncasecmp( argv[ i ], "listener=", STRLENOF( "listener=" ) ) 2634 == 0 ) 2635 { 2636 char *url = argv[ i ] + STRLENOF( "listener=" ); 2637 2638 if ( ldap_url_parse( url, &lud ) ) { 2639 rc = LDAP_INVALID_SYNTAX; 2640 goto done; 2641 } 2642 2643 *l = config_check_my_url( url, lud ); 2644 if ( *l == NULL ) { 2645 rc = LDAP_NO_SUCH_ATTRIBUTE; 2646 goto done; 2647 } 2648 2649 i++; 2650 } 2651 2652 ptr = argv[ i ]; 2653 if ( strncasecmp( ptr, "read=", STRLENOF( "read=" ) ) == 0 ) { 2654 *rw |= SLAP_TCP_RMEM; 2655 ptr += STRLENOF( "read=" ); 2656 2657 } else if ( strncasecmp( ptr, "write=", STRLENOF( "write=" ) ) == 0 ) { 2658 *rw |= SLAP_TCP_WMEM; 2659 ptr += STRLENOF( "write=" ); 2660 2661 } else { 2662 *rw |= ( SLAP_TCP_RMEM | SLAP_TCP_WMEM ); 2663 } 2664 2665 /* accept any base */ 2666 if ( lutil_atoix( size, ptr, 0 ) ) { 2667 rc = LDAP_INVALID_SYNTAX; 2668 goto done; 2669 } 2670 2671done:; 2672 if ( val != NULL && argv != NULL ) { 2673 ldap_charray_free( argv ); 2674 } 2675 2676 if ( lud != NULL ) { 2677 ldap_free_urldesc( lud ); 2678 } 2679 2680 return rc; 2681} 2682 2683static int 2684tcp_buffer_delete_one( struct berval *val ) 2685{ 2686 int rc = 0; 2687 int size = -1, rw = 0; 2688 Listener *l = NULL; 2689 2690 rc = tcp_buffer_parse( val, 0, NULL, &size, &rw, &l ); 2691 if ( rc != 0 ) { 2692 return rc; 2693 } 2694 2695 if ( l != NULL ) { 2696 int i; 2697 Listener **ll = slapd_get_listeners(); 2698 2699 for ( i = 0; ll[ i ] != NULL; i++ ) { 2700 if ( ll[ i ] == l ) break; 2701 } 2702 2703 if ( ll[ i ] == NULL ) { 2704 return LDAP_NO_SUCH_ATTRIBUTE; 2705 } 2706 2707 if ( rw & SLAP_TCP_RMEM ) l->sl_tcp_rmem = -1; 2708 if ( rw & SLAP_TCP_WMEM ) l->sl_tcp_wmem = -1; 2709 2710 for ( i++ ; ll[ i ] != NULL && bvmatch( &l->sl_url, &ll[ i ]->sl_url ); i++ ) { 2711 if ( rw & SLAP_TCP_RMEM ) ll[ i ]->sl_tcp_rmem = -1; 2712 if ( rw & SLAP_TCP_WMEM ) ll[ i ]->sl_tcp_wmem = -1; 2713 } 2714 2715 } else { 2716 /* NOTE: this affects listeners without a specific setting, 2717 * does not reset all listeners. If a listener without 2718 * specific settings was assigned a buffer because of 2719 * a global setting, it will not be reset. In any case, 2720 * buffer changes will only take place at restart. */ 2721 if ( rw & SLAP_TCP_RMEM ) slapd_tcp_rmem = -1; 2722 if ( rw & SLAP_TCP_WMEM ) slapd_tcp_wmem = -1; 2723 } 2724 2725 return rc; 2726} 2727 2728static int 2729tcp_buffer_delete( BerVarray vals ) 2730{ 2731 int i; 2732 2733 for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) { 2734 tcp_buffer_delete_one( &vals[ i ] ); 2735 } 2736 2737 return 0; 2738} 2739 2740static int 2741tcp_buffer_unparse( int size, int rw, Listener *l, struct berval *val ) 2742{ 2743 char buf[sizeof("2147483648")], *ptr; 2744 2745 /* unparse for later use */ 2746 val->bv_len = snprintf( buf, sizeof( buf ), "%d", size ); 2747 if ( l != NULL ) { 2748 val->bv_len += STRLENOF( "listener=" " " ) + l->sl_url.bv_len; 2749 } 2750 2751 if ( rw != ( SLAP_TCP_RMEM | SLAP_TCP_WMEM ) ) { 2752 if ( rw & SLAP_TCP_RMEM ) { 2753 val->bv_len += STRLENOF( "read=" ); 2754 } else if ( rw & SLAP_TCP_WMEM ) { 2755 val->bv_len += STRLENOF( "write=" ); 2756 } 2757 } 2758 2759 val->bv_val = SLAP_MALLOC( val->bv_len + 1 ); 2760 2761 ptr = val->bv_val; 2762 2763 if ( l != NULL ) { 2764 ptr = lutil_strcopy( ptr, "listener=" ); 2765 ptr = lutil_strncopy( ptr, l->sl_url.bv_val, l->sl_url.bv_len ); 2766 *ptr++ = ' '; 2767 } 2768 2769 if ( rw != ( SLAP_TCP_RMEM | SLAP_TCP_WMEM ) ) { 2770 if ( rw & SLAP_TCP_RMEM ) { 2771 ptr = lutil_strcopy( ptr, "read=" ); 2772 } else if ( rw & SLAP_TCP_WMEM ) { 2773 ptr = lutil_strcopy( ptr, "write=" ); 2774 } 2775 } 2776 2777 ptr = lutil_strcopy( ptr, buf ); 2778 *ptr = '\0'; 2779 2780 assert( val->bv_val + val->bv_len == ptr ); 2781 2782 return LDAP_SUCCESS; 2783} 2784 2785static int 2786tcp_buffer_add_one( int argc, char **argv ) 2787{ 2788 int rc = 0; 2789 int size = -1, rw = 0; 2790 Listener *l = NULL; 2791 2792 struct berval val; 2793 2794 /* parse */ 2795 rc = tcp_buffer_parse( NULL, argc, argv, &size, &rw, &l ); 2796 if ( rc != 0 ) { 2797 return rc; 2798 } 2799 2800 /* unparse for later use */ 2801 rc = tcp_buffer_unparse( size, rw, l, &val ); 2802 if ( rc != LDAP_SUCCESS ) { 2803 return rc; 2804 } 2805 2806 /* use parsed values */ 2807 if ( l != NULL ) { 2808 int i; 2809 Listener **ll = slapd_get_listeners(); 2810 2811 for ( i = 0; ll[ i ] != NULL; i++ ) { 2812 if ( ll[ i ] == l ) break; 2813 } 2814 2815 if ( ll[ i ] == NULL ) { 2816 return LDAP_NO_SUCH_ATTRIBUTE; 2817 } 2818 2819 /* buffer only applies to TCP listeners; 2820 * we do not do any check here, and delegate them 2821 * to setsockopt(2) */ 2822 if ( rw & SLAP_TCP_RMEM ) l->sl_tcp_rmem = size; 2823 if ( rw & SLAP_TCP_WMEM ) l->sl_tcp_wmem = size; 2824 2825 for ( i++ ; ll[ i ] != NULL && bvmatch( &l->sl_url, &ll[ i ]->sl_url ); i++ ) { 2826 if ( rw & SLAP_TCP_RMEM ) ll[ i ]->sl_tcp_rmem = size; 2827 if ( rw & SLAP_TCP_WMEM ) ll[ i ]->sl_tcp_wmem = size; 2828 } 2829 2830 } else { 2831 /* NOTE: this affects listeners without a specific setting, 2832 * does not set all listeners */ 2833 if ( rw & SLAP_TCP_RMEM ) slapd_tcp_rmem = size; 2834 if ( rw & SLAP_TCP_WMEM ) slapd_tcp_wmem = size; 2835 } 2836 2837 tcp_buffer = SLAP_REALLOC( tcp_buffer, sizeof( struct berval ) * ( tcp_buffer_num + 2 ) ); 2838 /* append */ 2839 tcp_buffer[ tcp_buffer_num ] = val; 2840 2841 tcp_buffer_num++; 2842 BER_BVZERO( &tcp_buffer[ tcp_buffer_num ] ); 2843 2844 return rc; 2845} 2846 2847static int 2848config_tcp_buffer( ConfigArgs *c ) 2849{ 2850 if ( c->op == SLAP_CONFIG_EMIT ) { 2851 if ( tcp_buffer == NULL || BER_BVISNULL( &tcp_buffer[ 0 ] ) ) { 2852 return 1; 2853 } 2854 value_add( &c->rvalue_vals, tcp_buffer ); 2855 value_add( &c->rvalue_nvals, tcp_buffer ); 2856 2857 } else if ( c->op == LDAP_MOD_DELETE ) { 2858 if ( !c->line ) { 2859 tcp_buffer_delete( tcp_buffer ); 2860 ber_bvarray_free( tcp_buffer ); 2861 tcp_buffer = NULL; 2862 tcp_buffer_num = 0; 2863 2864 } else { 2865 int rc = 0; 2866 int size = -1, rw = 0; 2867 Listener *l = NULL; 2868 2869 struct berval val = BER_BVNULL; 2870 2871 int i; 2872 2873 if ( tcp_buffer_num == 0 ) { 2874 return 1; 2875 } 2876 2877 /* parse */ 2878 rc = tcp_buffer_parse( NULL, c->argc - 1, &c->argv[ 1 ], &size, &rw, &l ); 2879 if ( rc != 0 ) { 2880 return 1; 2881 } 2882 2883 /* unparse for later use */ 2884 rc = tcp_buffer_unparse( size, rw, l, &val ); 2885 if ( rc != LDAP_SUCCESS ) { 2886 return 1; 2887 } 2888 2889 for ( i = 0; !BER_BVISNULL( &tcp_buffer[ i ] ); i++ ) { 2890 if ( bvmatch( &tcp_buffer[ i ], &val ) ) { 2891 break; 2892 } 2893 } 2894 2895 if ( BER_BVISNULL( &tcp_buffer[ i ] ) ) { 2896 /* not found */ 2897 rc = 1; 2898 goto done; 2899 } 2900 2901 tcp_buffer_delete_one( &tcp_buffer[ i ] ); 2902 ber_memfree( tcp_buffer[ i ].bv_val ); 2903 for ( ; i < tcp_buffer_num; i++ ) { 2904 tcp_buffer[ i ] = tcp_buffer[ i + 1 ]; 2905 } 2906 tcp_buffer_num--; 2907 2908done:; 2909 if ( !BER_BVISNULL( &val ) ) { 2910 SLAP_FREE( val.bv_val ); 2911 } 2912 2913 } 2914 2915 } else { 2916 int rc; 2917 2918 rc = tcp_buffer_add_one( c->argc - 1, &c->argv[ 1 ] ); 2919 if ( rc ) { 2920 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2921 "<%s> unable to add value #%d", 2922 c->argv[0], tcp_buffer_num ); 2923 Debug( LDAP_DEBUG_ANY, "%s: %s\n", 2924 c->log, c->cr_msg, 0 ); 2925 return 1; 2926 } 2927 } 2928 2929 return 0; 2930} 2931#endif /* LDAP_TCP_BUFFER */ 2932 2933static int 2934config_suffix(ConfigArgs *c) 2935{ 2936 Backend *tbe; 2937 struct berval pdn, ndn; 2938 char *notallowed = NULL; 2939 2940 if ( c->be == frontendDB ) { 2941 notallowed = "frontend"; 2942 2943 } else if ( SLAP_MONITOR(c->be) ) { 2944 notallowed = "monitor"; 2945 2946 } else if ( SLAP_CONFIG(c->be) ) { 2947 notallowed = "config"; 2948 } 2949 2950 if ( notallowed != NULL ) { 2951 char buf[ SLAP_TEXT_BUFLEN ] = { '\0' }; 2952 2953 switch ( c->op ) { 2954 case LDAP_MOD_ADD: 2955 case LDAP_MOD_DELETE: 2956 case LDAP_MOD_REPLACE: 2957 case LDAP_MOD_INCREMENT: 2958 case SLAP_CONFIG_ADD: 2959 if ( !BER_BVISNULL( &c->value_dn ) ) { 2960 snprintf( buf, sizeof( buf ), "<%s> ", 2961 c->value_dn.bv_val ); 2962 } 2963 2964 Debug(LDAP_DEBUG_ANY, 2965 "%s: suffix %snot allowed in %s database.\n", 2966 c->log, buf, notallowed ); 2967 break; 2968 2969 case SLAP_CONFIG_EMIT: 2970 /* don't complain when emitting... */ 2971 break; 2972 2973 default: 2974 /* FIXME: don't know what values may be valid; 2975 * please remove assertion, or add legal values 2976 * to either block */ 2977 assert( 0 ); 2978 break; 2979 } 2980 2981 return 1; 2982 } 2983 2984 if (c->op == SLAP_CONFIG_EMIT) { 2985 if ( c->be->be_suffix == NULL 2986 || BER_BVISNULL( &c->be->be_suffix[0] ) ) 2987 { 2988 return 1; 2989 } else { 2990 value_add( &c->rvalue_vals, c->be->be_suffix ); 2991 value_add( &c->rvalue_nvals, c->be->be_nsuffix ); 2992 return 0; 2993 } 2994 } else if ( c->op == LDAP_MOD_DELETE ) { 2995 if ( c->valx < 0 ) { 2996 ber_bvarray_free( c->be->be_suffix ); 2997 ber_bvarray_free( c->be->be_nsuffix ); 2998 c->be->be_suffix = NULL; 2999 c->be->be_nsuffix = NULL; 3000 } else { 3001 int i = c->valx; 3002 ch_free( c->be->be_suffix[i].bv_val ); 3003 ch_free( c->be->be_nsuffix[i].bv_val ); 3004 do { 3005 c->be->be_suffix[i] = c->be->be_suffix[i+1]; 3006 c->be->be_nsuffix[i] = c->be->be_nsuffix[i+1]; 3007 i++; 3008 } while ( !BER_BVISNULL( &c->be->be_suffix[i] ) ); 3009 } 3010 return 0; 3011 } 3012 3013#ifdef SLAPD_MONITOR_DN 3014 if(!strcasecmp(c->argv[1], SLAPD_MONITOR_DN)) { 3015 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> DN is reserved for monitoring slapd", 3016 c->argv[0] ); 3017 Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", 3018 c->log, c->cr_msg, SLAPD_MONITOR_DN); 3019 return(1); 3020 } 3021#endif 3022 3023 if (SLAP_DB_ONE_SUFFIX( c->be ) && c->be->be_suffix ) { 3024 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> Only one suffix is allowed on this %s backend", 3025 c->argv[0], c->be->bd_info->bi_type ); 3026 Debug(LDAP_DEBUG_ANY, "%s: %s\n", 3027 c->log, c->cr_msg, 0); 3028 return(1); 3029 } 3030 3031 pdn = c->value_dn; 3032 ndn = c->value_ndn; 3033 3034 if (SLAP_DBHIDDEN( c->be )) 3035 tbe = NULL; 3036 else 3037 tbe = select_backend(&ndn, 0); 3038 if(tbe == c->be) { 3039 Debug( LDAP_DEBUG_ANY, "%s: suffix already served by this backend!.\n", 3040 c->log, 0, 0); 3041 return 1; 3042 free(pdn.bv_val); 3043 free(ndn.bv_val); 3044 } else if(tbe) { 3045 BackendDB *b2 = tbe; 3046 3047 /* Does tbe precede be? */ 3048 while (( b2 = LDAP_STAILQ_NEXT(b2, be_next )) && b2 && b2 != c->be ); 3049 3050 if ( b2 ) { 3051 char *type = tbe->bd_info->bi_type; 3052 3053 if ( overlay_is_over( tbe ) ) { 3054 slap_overinfo *oi = (slap_overinfo *)tbe->bd_info->bi_private; 3055 type = oi->oi_orig->bi_type; 3056 } 3057 3058 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> namingContext \"%s\" " 3059 "already served by a preceding %s database", 3060 c->argv[0], pdn.bv_val, type ); 3061 Debug(LDAP_DEBUG_ANY, "%s: %s serving namingContext \"%s\"\n", 3062 c->log, c->cr_msg, tbe->be_suffix[0].bv_val); 3063 free(pdn.bv_val); 3064 free(ndn.bv_val); 3065 return(1); 3066 } 3067 } 3068 if(pdn.bv_len == 0 && default_search_nbase.bv_len) { 3069 Debug(LDAP_DEBUG_ANY, "%s: suffix DN empty and default search " 3070 "base provided \"%s\" (assuming okay)\n", 3071 c->log, default_search_base.bv_val, 0); 3072 } 3073 ber_bvarray_add(&c->be->be_suffix, &pdn); 3074 ber_bvarray_add(&c->be->be_nsuffix, &ndn); 3075 return(0); 3076} 3077 3078static int 3079config_rootdn(ConfigArgs *c) { 3080 if (c->op == SLAP_CONFIG_EMIT) { 3081 if ( !BER_BVISNULL( &c->be->be_rootdn )) { 3082 value_add_one(&c->rvalue_vals, &c->be->be_rootdn); 3083 value_add_one(&c->rvalue_nvals, &c->be->be_rootndn); 3084 return 0; 3085 } else { 3086 return 1; 3087 } 3088 } else if ( c->op == LDAP_MOD_DELETE ) { 3089 ch_free( c->be->be_rootdn.bv_val ); 3090 ch_free( c->be->be_rootndn.bv_val ); 3091 BER_BVZERO( &c->be->be_rootdn ); 3092 BER_BVZERO( &c->be->be_rootndn ); 3093 return 0; 3094 } 3095 if ( !BER_BVISNULL( &c->be->be_rootdn )) { 3096 ch_free( c->be->be_rootdn.bv_val ); 3097 ch_free( c->be->be_rootndn.bv_val ); 3098 } 3099 c->be->be_rootdn = c->value_dn; 3100 c->be->be_rootndn = c->value_ndn; 3101 return(0); 3102} 3103 3104static int 3105config_rootpw(ConfigArgs *c) { 3106 Backend *tbe; 3107 3108 if (c->op == SLAP_CONFIG_EMIT) { 3109 if (!BER_BVISEMPTY(&c->be->be_rootpw)) { 3110 /* don't copy, because "rootpw" is marked 3111 * as CFG_BERVAL */ 3112 c->value_bv = c->be->be_rootpw; 3113 return 0; 3114 } 3115 return 1; 3116 } else if ( c->op == LDAP_MOD_DELETE ) { 3117 ch_free( c->be->be_rootpw.bv_val ); 3118 BER_BVZERO( &c->be->be_rootpw ); 3119 return 0; 3120 } 3121 3122 tbe = select_backend(&c->be->be_rootndn, 0); 3123 if(tbe != c->be) { 3124 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> can only be set when rootdn is under suffix", 3125 c->argv[0] ); 3126 Debug(LDAP_DEBUG_ANY, "%s: %s\n", 3127 c->log, c->cr_msg, 0); 3128 return(1); 3129 } 3130 if ( !BER_BVISNULL( &c->be->be_rootpw )) 3131 ch_free( c->be->be_rootpw.bv_val ); 3132 c->be->be_rootpw = c->value_bv; 3133 return(0); 3134} 3135 3136static int 3137config_restrict(ConfigArgs *c) { 3138 slap_mask_t restrictops = 0; 3139 int i; 3140 slap_verbmasks restrictable_ops[] = { 3141 { BER_BVC("bind"), SLAP_RESTRICT_OP_BIND }, 3142 { BER_BVC("add"), SLAP_RESTRICT_OP_ADD }, 3143 { BER_BVC("modify"), SLAP_RESTRICT_OP_MODIFY }, 3144 { BER_BVC("rename"), SLAP_RESTRICT_OP_RENAME }, 3145 { BER_BVC("modrdn"), 0 }, 3146 { BER_BVC("delete"), SLAP_RESTRICT_OP_DELETE }, 3147 { BER_BVC("search"), SLAP_RESTRICT_OP_SEARCH }, 3148 { BER_BVC("compare"), SLAP_RESTRICT_OP_COMPARE }, 3149 { BER_BVC("read"), SLAP_RESTRICT_OP_READS }, 3150 { BER_BVC("write"), SLAP_RESTRICT_OP_WRITES }, 3151 { BER_BVC("extended"), SLAP_RESTRICT_OP_EXTENDED }, 3152 { BER_BVC("extended=" LDAP_EXOP_START_TLS ), SLAP_RESTRICT_EXOP_START_TLS }, 3153 { BER_BVC("extended=" LDAP_EXOP_MODIFY_PASSWD ), SLAP_RESTRICT_EXOP_MODIFY_PASSWD }, 3154 { BER_BVC("extended=" LDAP_EXOP_X_WHO_AM_I ), SLAP_RESTRICT_EXOP_WHOAMI }, 3155 { BER_BVC("extended=" LDAP_EXOP_X_CANCEL ), SLAP_RESTRICT_EXOP_CANCEL }, 3156 { BER_BVC("all"), SLAP_RESTRICT_OP_ALL }, 3157 { BER_BVNULL, 0 } 3158 }; 3159 3160 if (c->op == SLAP_CONFIG_EMIT) { 3161 return mask_to_verbs( restrictable_ops, c->be->be_restrictops, 3162 &c->rvalue_vals ); 3163 } else if ( c->op == LDAP_MOD_DELETE ) { 3164 if ( !c->line ) { 3165 c->be->be_restrictops = 0; 3166 } else { 3167 i = verb_to_mask( c->line, restrictable_ops ); 3168 c->be->be_restrictops &= ~restrictable_ops[i].mask; 3169 } 3170 return 0; 3171 } 3172 i = verbs_to_mask( c->argc, c->argv, restrictable_ops, &restrictops ); 3173 if ( i ) { 3174 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown operation", c->argv[0] ); 3175 Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", 3176 c->log, c->cr_msg, c->argv[i]); 3177 return(1); 3178 } 3179 if ( restrictops & SLAP_RESTRICT_OP_EXTENDED ) 3180 restrictops &= ~SLAP_RESTRICT_EXOP_MASK; 3181 c->be->be_restrictops |= restrictops; 3182 return(0); 3183} 3184 3185static int 3186config_allows(ConfigArgs *c) { 3187 slap_mask_t allows = 0; 3188 int i; 3189 slap_verbmasks allowable_ops[] = { 3190 { BER_BVC("bind_v2"), SLAP_ALLOW_BIND_V2 }, 3191 { BER_BVC("bind_anon_cred"), SLAP_ALLOW_BIND_ANON_CRED }, 3192 { BER_BVC("bind_anon_dn"), SLAP_ALLOW_BIND_ANON_DN }, 3193 { BER_BVC("update_anon"), SLAP_ALLOW_UPDATE_ANON }, 3194 { BER_BVC("proxy_authz_anon"), SLAP_ALLOW_PROXY_AUTHZ_ANON }, 3195 { BER_BVNULL, 0 } 3196 }; 3197 if (c->op == SLAP_CONFIG_EMIT) { 3198 return mask_to_verbs( allowable_ops, global_allows, &c->rvalue_vals ); 3199 } else if ( c->op == LDAP_MOD_DELETE ) { 3200 if ( !c->line ) { 3201 global_allows = 0; 3202 } else { 3203 i = verb_to_mask( c->line, allowable_ops ); 3204 global_allows &= ~allowable_ops[i].mask; 3205 } 3206 return 0; 3207 } 3208 i = verbs_to_mask(c->argc, c->argv, allowable_ops, &allows); 3209 if ( i ) { 3210 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature", c->argv[0] ); 3211 Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", 3212 c->log, c->cr_msg, c->argv[i]); 3213 return(1); 3214 } 3215 global_allows |= allows; 3216 return(0); 3217} 3218 3219static int 3220config_disallows(ConfigArgs *c) { 3221 slap_mask_t disallows = 0; 3222 int i; 3223 slap_verbmasks disallowable_ops[] = { 3224 { BER_BVC("bind_anon"), SLAP_DISALLOW_BIND_ANON }, 3225 { BER_BVC("bind_simple"), SLAP_DISALLOW_BIND_SIMPLE }, 3226 { BER_BVC("tls_2_anon"), SLAP_DISALLOW_TLS_2_ANON }, 3227 { BER_BVC("tls_authc"), SLAP_DISALLOW_TLS_AUTHC }, 3228 { BER_BVC("proxy_authz_non_critical"), SLAP_DISALLOW_PROXY_AUTHZ_N_CRIT }, 3229 { BER_BVC("dontusecopy_non_critical"), SLAP_DISALLOW_DONTUSECOPY_N_CRIT }, 3230 { BER_BVNULL, 0 } 3231 }; 3232 if (c->op == SLAP_CONFIG_EMIT) { 3233 return mask_to_verbs( disallowable_ops, global_disallows, &c->rvalue_vals ); 3234 } else if ( c->op == LDAP_MOD_DELETE ) { 3235 if ( !c->line ) { 3236 global_disallows = 0; 3237 } else { 3238 i = verb_to_mask( c->line, disallowable_ops ); 3239 global_disallows &= ~disallowable_ops[i].mask; 3240 } 3241 return 0; 3242 } 3243 i = verbs_to_mask(c->argc, c->argv, disallowable_ops, &disallows); 3244 if ( i ) { 3245 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature", c->argv[0] ); 3246 Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", 3247 c->log, c->cr_msg, c->argv[i]); 3248 return(1); 3249 } 3250 global_disallows |= disallows; 3251 return(0); 3252} 3253 3254static int 3255config_requires(ConfigArgs *c) { 3256 slap_mask_t requires = frontendDB->be_requires; 3257 int i, argc = c->argc; 3258 char **argv = c->argv; 3259 3260 slap_verbmasks requires_ops[] = { 3261 { BER_BVC("bind"), SLAP_REQUIRE_BIND }, 3262 { BER_BVC("LDAPv3"), SLAP_REQUIRE_LDAP_V3 }, 3263 { BER_BVC("authc"), SLAP_REQUIRE_AUTHC }, 3264 { BER_BVC("sasl"), SLAP_REQUIRE_SASL }, 3265 { BER_BVC("strong"), SLAP_REQUIRE_STRONG }, 3266 { BER_BVNULL, 0 } 3267 }; 3268 if (c->op == SLAP_CONFIG_EMIT) { 3269 return mask_to_verbs( requires_ops, c->be->be_requires, &c->rvalue_vals ); 3270 } else if ( c->op == LDAP_MOD_DELETE ) { 3271 if ( !c->line ) { 3272 c->be->be_requires = 0; 3273 } else { 3274 i = verb_to_mask( c->line, requires_ops ); 3275 c->be->be_requires &= ~requires_ops[i].mask; 3276 } 3277 return 0; 3278 } 3279 /* "none" can only be first, to wipe out default/global values */ 3280 if ( strcasecmp( c->argv[ 1 ], "none" ) == 0 ) { 3281 argv++; 3282 argc--; 3283 requires = 0; 3284 } 3285 i = verbs_to_mask(argc, argv, requires_ops, &requires); 3286 if ( i ) { 3287 if (strcasecmp( c->argv[ i ], "none" ) == 0 ) { 3288 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> \"none\" (#%d) must be listed first", c->argv[0], i - 1 ); 3289 Debug(LDAP_DEBUG_ANY, "%s: %s\n", 3290 c->log, c->cr_msg, 0); 3291 } else { 3292 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature #%d", c->argv[0], i - 1 ); 3293 Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", 3294 c->log, c->cr_msg, c->argv[i]); 3295 } 3296 return(1); 3297 } 3298 c->be->be_requires = requires; 3299 return(0); 3300} 3301 3302static int 3303config_extra_attrs(ConfigArgs *c) 3304{ 3305 assert( c->be != NULL ); 3306 3307 if ( c->op == SLAP_CONFIG_EMIT ) { 3308 int i; 3309 3310 if ( c->be->be_extra_anlist == NULL ) { 3311 return 1; 3312 } 3313 3314 for ( i = 0; !BER_BVISNULL( &c->be->be_extra_anlist[i].an_name ); i++ ) { 3315 value_add_one( &c->rvalue_vals, &c->be->be_extra_anlist[i].an_name ); 3316 } 3317 3318 } else if ( c->op == LDAP_MOD_DELETE ) { 3319 if ( c->be->be_extra_anlist == NULL ) { 3320 return 1; 3321 } 3322 3323 if ( c->valx < 0 ) { 3324 anlist_free( c->be->be_extra_anlist, 1, NULL ); 3325 c->be->be_extra_anlist = NULL; 3326 3327 } else { 3328 int i; 3329 3330 for ( i = 0; i < c->valx && !BER_BVISNULL( &c->be->be_extra_anlist[i + 1].an_name ); i++ ) 3331 ; 3332 3333 if ( BER_BVISNULL( &c->be->be_extra_anlist[i].an_name ) ) { 3334 return 1; 3335 } 3336 3337 ch_free( c->be->be_extra_anlist[i].an_name.bv_val ); 3338 3339 for ( ; !BER_BVISNULL( &c->be->be_extra_anlist[i].an_name ); i++ ) { 3340 c->be->be_extra_anlist[i] = c->be->be_extra_anlist[i + 1]; 3341 } 3342 } 3343 3344 } else { 3345 c->be->be_extra_anlist = str2anlist( c->be->be_extra_anlist, c->argv[1], " ,\t" ); 3346 if ( c->be->be_extra_anlist == NULL ) { 3347 return 1; 3348 } 3349 } 3350 3351 return 0; 3352} 3353 3354static slap_verbmasks *loglevel_ops; 3355 3356static int 3357loglevel_init( void ) 3358{ 3359 slap_verbmasks lo[] = { 3360 { BER_BVC("Any"), (slap_mask_t) LDAP_DEBUG_ANY }, 3361 { BER_BVC("Trace"), LDAP_DEBUG_TRACE }, 3362 { BER_BVC("Packets"), LDAP_DEBUG_PACKETS }, 3363 { BER_BVC("Args"), LDAP_DEBUG_ARGS }, 3364 { BER_BVC("Conns"), LDAP_DEBUG_CONNS }, 3365 { BER_BVC("BER"), LDAP_DEBUG_BER }, 3366 { BER_BVC("Filter"), LDAP_DEBUG_FILTER }, 3367 { BER_BVC("Config"), LDAP_DEBUG_CONFIG }, 3368 { BER_BVC("ACL"), LDAP_DEBUG_ACL }, 3369 { BER_BVC("Stats"), LDAP_DEBUG_STATS }, 3370 { BER_BVC("Stats2"), LDAP_DEBUG_STATS2 }, 3371 { BER_BVC("Shell"), LDAP_DEBUG_SHELL }, 3372 { BER_BVC("Parse"), LDAP_DEBUG_PARSE }, 3373#if 0 /* no longer used (nor supported) */ 3374 { BER_BVC("Cache"), LDAP_DEBUG_CACHE }, 3375 { BER_BVC("Index"), LDAP_DEBUG_INDEX }, 3376#endif 3377 { BER_BVC("Sync"), LDAP_DEBUG_SYNC }, 3378 { BER_BVC("None"), LDAP_DEBUG_NONE }, 3379 { BER_BVNULL, 0 } 3380 }; 3381 3382 return slap_verbmasks_init( &loglevel_ops, lo ); 3383} 3384 3385static void 3386loglevel_destroy( void ) 3387{ 3388 if ( loglevel_ops ) { 3389 (void)slap_verbmasks_destroy( loglevel_ops ); 3390 } 3391 loglevel_ops = NULL; 3392} 3393 3394static slap_mask_t loglevel_ignore[] = { -1, 0 }; 3395 3396int 3397slap_loglevel_register( slap_mask_t m, struct berval *s ) 3398{ 3399 int rc; 3400 3401 if ( loglevel_ops == NULL ) { 3402 loglevel_init(); 3403 } 3404 3405 rc = slap_verbmasks_append( &loglevel_ops, m, s, loglevel_ignore ); 3406 3407 if ( rc != 0 ) { 3408 Debug( LDAP_DEBUG_ANY, "slap_loglevel_register(%lu, \"%s\") failed\n", 3409 m, s->bv_val, 0 ); 3410 } 3411 3412 return rc; 3413} 3414 3415int 3416slap_loglevel_get( struct berval *s, int *l ) 3417{ 3418 int rc; 3419 slap_mask_t m, i; 3420 3421 if ( loglevel_ops == NULL ) { 3422 loglevel_init(); 3423 } 3424 3425 for ( m = 0, i = 1; !BER_BVISNULL( &loglevel_ops[ i ].word ); i++ ) { 3426 m |= loglevel_ops[ i ].mask; 3427 } 3428 3429 for ( i = 1; m & i; i <<= 1 ) 3430 ; 3431 3432 if ( i == 0 ) { 3433 return -1; 3434 } 3435 3436 rc = slap_verbmasks_append( &loglevel_ops, i, s, loglevel_ignore ); 3437 3438 if ( rc != 0 ) { 3439 Debug( LDAP_DEBUG_ANY, "slap_loglevel_get(%lu, \"%s\") failed\n", 3440 i, s->bv_val, 0 ); 3441 3442 } else { 3443 *l = i; 3444 } 3445 3446 return rc; 3447} 3448 3449int 3450str2loglevel( const char *s, int *l ) 3451{ 3452 int i; 3453 3454 if ( loglevel_ops == NULL ) { 3455 loglevel_init(); 3456 } 3457 3458 i = verb_to_mask( s, loglevel_ops ); 3459 3460 if ( BER_BVISNULL( &loglevel_ops[ i ].word ) ) { 3461 return -1; 3462 } 3463 3464 *l = loglevel_ops[ i ].mask; 3465 3466 return 0; 3467} 3468 3469const char * 3470loglevel2str( int l ) 3471{ 3472 struct berval bv = BER_BVNULL; 3473 3474 loglevel2bv( l, &bv ); 3475 3476 return bv.bv_val; 3477} 3478 3479int 3480loglevel2bv( int l, struct berval *bv ) 3481{ 3482 if ( loglevel_ops == NULL ) { 3483 loglevel_init(); 3484 } 3485 3486 BER_BVZERO( bv ); 3487 3488 return enum_to_verb( loglevel_ops, l, bv ) == -1; 3489} 3490 3491int 3492loglevel2bvarray( int l, BerVarray *bva ) 3493{ 3494 if ( loglevel_ops == NULL ) { 3495 loglevel_init(); 3496 } 3497 3498 return mask_to_verbs( loglevel_ops, l, bva ); 3499} 3500 3501int 3502loglevel_print( FILE *out ) 3503{ 3504 int i; 3505 3506 if ( loglevel_ops == NULL ) { 3507 loglevel_init(); 3508 } 3509 3510 fprintf( out, "Installed log subsystems:\n\n" ); 3511 for ( i = 0; !BER_BVISNULL( &loglevel_ops[ i ].word ); i++ ) { 3512 unsigned mask = loglevel_ops[ i ].mask & 0xffffffffUL; 3513 fprintf( out, 3514 (mask == ((slap_mask_t) -1 & 0xffffffffUL) 3515 ? "\t%-30s (-1, 0xffffffff)\n" : "\t%-30s (%u, 0x%x)\n"), 3516 loglevel_ops[ i ].word.bv_val, mask, mask ); 3517 } 3518 3519 fprintf( out, "\nNOTE: custom log subsystems may be later installed " 3520 "by specific code\n\n" ); 3521 3522 return 0; 3523} 3524 3525static int config_syslog; 3526 3527static int 3528config_loglevel(ConfigArgs *c) { 3529 int i; 3530 3531 if ( loglevel_ops == NULL ) { 3532 loglevel_init(); 3533 } 3534 3535 if (c->op == SLAP_CONFIG_EMIT) { 3536 /* Get default or commandline slapd setting */ 3537 if ( ldap_syslog && !config_syslog ) 3538 config_syslog = ldap_syslog; 3539 return loglevel2bvarray( config_syslog, &c->rvalue_vals ); 3540 3541 } else if ( c->op == LDAP_MOD_DELETE ) { 3542 if ( !c->line ) { 3543 config_syslog = 0; 3544 } else { 3545 i = verb_to_mask( c->line, loglevel_ops ); 3546 config_syslog &= ~loglevel_ops[i].mask; 3547 } 3548 if ( slapMode & SLAP_SERVER_MODE ) { 3549 ldap_syslog = config_syslog; 3550 } 3551 return 0; 3552 } 3553 3554 for( i=1; i < c->argc; i++ ) { 3555 int level; 3556 3557 if ( isdigit((unsigned char)c->argv[i][0]) || c->argv[i][0] == '-' ) { 3558 if( lutil_atoix( &level, c->argv[i], 0 ) != 0 ) { 3559 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse level", c->argv[0] ); 3560 Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", 3561 c->log, c->cr_msg, c->argv[i]); 3562 return( 1 ); 3563 } 3564 } else { 3565 if ( str2loglevel( c->argv[i], &level ) ) { 3566 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown level", c->argv[0] ); 3567 Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", 3568 c->log, c->cr_msg, c->argv[i]); 3569 return( 1 ); 3570 } 3571 } 3572 /* Explicitly setting a zero clears all the levels */ 3573 if ( level ) 3574 config_syslog |= level; 3575 else 3576 config_syslog = 0; 3577 } 3578 if ( slapMode & SLAP_SERVER_MODE ) { 3579 ldap_syslog = config_syslog; 3580 } 3581 return(0); 3582} 3583 3584static int 3585config_referral(ConfigArgs *c) { 3586 struct berval val; 3587 if (c->op == SLAP_CONFIG_EMIT) { 3588 if ( default_referral ) { 3589 value_add( &c->rvalue_vals, default_referral ); 3590 return 0; 3591 } else { 3592 return 1; 3593 } 3594 } else if ( c->op == LDAP_MOD_DELETE ) { 3595 if ( c->valx < 0 ) { 3596 ber_bvarray_free( default_referral ); 3597 default_referral = NULL; 3598 } else { 3599 int i = c->valx; 3600 ch_free( default_referral[i].bv_val ); 3601 for (; default_referral[i].bv_val; i++ ) 3602 default_referral[i] = default_referral[i+1]; 3603 } 3604 return 0; 3605 } 3606 if(validate_global_referral(c->argv[1])) { 3607 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid URL", c->argv[0] ); 3608 Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", 3609 c->log, c->cr_msg, c->argv[1]); 3610 return(1); 3611 } 3612 3613 ber_str2bv(c->argv[1], 0, 0, &val); 3614 if(value_add_one(&default_referral, &val)) return(LDAP_OTHER); 3615 return(0); 3616} 3617 3618static struct { 3619 struct berval key; 3620 int off; 3621} sec_keys[] = { 3622 { BER_BVC("ssf="), offsetof(slap_ssf_set_t, sss_ssf) }, 3623 { BER_BVC("transport="), offsetof(slap_ssf_set_t, sss_transport) }, 3624 { BER_BVC("tls="), offsetof(slap_ssf_set_t, sss_tls) }, 3625 { BER_BVC("sasl="), offsetof(slap_ssf_set_t, sss_sasl) }, 3626 { BER_BVC("update_ssf="), offsetof(slap_ssf_set_t, sss_update_ssf) }, 3627 { BER_BVC("update_transport="), offsetof(slap_ssf_set_t, sss_update_transport) }, 3628 { BER_BVC("update_tls="), offsetof(slap_ssf_set_t, sss_update_tls) }, 3629 { BER_BVC("update_sasl="), offsetof(slap_ssf_set_t, sss_update_sasl) }, 3630 { BER_BVC("simple_bind="), offsetof(slap_ssf_set_t, sss_simple_bind) }, 3631 { BER_BVNULL, 0 } 3632}; 3633 3634static int 3635config_security(ConfigArgs *c) { 3636 slap_ssf_set_t *set = &c->be->be_ssf_set; 3637 char *next; 3638 int i, j; 3639 if (c->op == SLAP_CONFIG_EMIT) { 3640 char numbuf[32]; 3641 struct berval bv; 3642 slap_ssf_t *tgt; 3643 int rc = 1; 3644 3645 for (i=0; !BER_BVISNULL( &sec_keys[i].key ); i++) { 3646 tgt = (slap_ssf_t *)((char *)set + sec_keys[i].off); 3647 if ( *tgt ) { 3648 rc = 0; 3649 bv.bv_len = snprintf( numbuf, sizeof( numbuf ), "%u", *tgt ); 3650 if ( bv.bv_len >= sizeof( numbuf ) ) { 3651 ber_bvarray_free_x( c->rvalue_vals, NULL ); 3652 c->rvalue_vals = NULL; 3653 rc = 1; 3654 break; 3655 } 3656 bv.bv_len += sec_keys[i].key.bv_len; 3657 bv.bv_val = ch_malloc( bv.bv_len + 1); 3658 next = lutil_strcopy( bv.bv_val, sec_keys[i].key.bv_val ); 3659 strcpy( next, numbuf ); 3660 ber_bvarray_add( &c->rvalue_vals, &bv ); 3661 } 3662 } 3663 return rc; 3664 } 3665 for(i = 1; i < c->argc; i++) { 3666 slap_ssf_t *tgt = NULL; 3667 char *src = NULL; 3668 for ( j=0; !BER_BVISNULL( &sec_keys[j].key ); j++ ) { 3669 if(!strncasecmp(c->argv[i], sec_keys[j].key.bv_val, 3670 sec_keys[j].key.bv_len)) { 3671 src = c->argv[i] + sec_keys[j].key.bv_len; 3672 tgt = (slap_ssf_t *)((char *)set + sec_keys[j].off); 3673 break; 3674 } 3675 } 3676 if ( !tgt ) { 3677 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown factor", c->argv[0] ); 3678 Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", 3679 c->log, c->cr_msg, c->argv[i]); 3680 return(1); 3681 } 3682 3683 if ( lutil_atou( tgt, src ) != 0 ) { 3684 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse factor", c->argv[0] ); 3685 Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", 3686 c->log, c->cr_msg, c->argv[i]); 3687 return(1); 3688 } 3689 } 3690 return(0); 3691} 3692 3693char * 3694anlist_unparse( AttributeName *an, char *ptr, ber_len_t buflen ) { 3695 int comma = 0; 3696 char *start = ptr; 3697 3698 for (; !BER_BVISNULL( &an->an_name ); an++) { 3699 /* if buflen == 0, assume the buffer size has been 3700 * already checked otherwise */ 3701 if ( buflen > 0 && buflen - ( ptr - start ) < comma + an->an_name.bv_len ) return NULL; 3702 if ( comma ) *ptr++ = ','; 3703 ptr = lutil_strcopy( ptr, an->an_name.bv_val ); 3704 comma = 1; 3705 } 3706 return ptr; 3707} 3708 3709static int 3710config_updatedn(ConfigArgs *c) { 3711 if (c->op == SLAP_CONFIG_EMIT) { 3712 if (!BER_BVISEMPTY(&c->be->be_update_ndn)) { 3713 value_add_one(&c->rvalue_vals, &c->be->be_update_ndn); 3714 value_add_one(&c->rvalue_nvals, &c->be->be_update_ndn); 3715 return 0; 3716 } 3717 return 1; 3718 } else if ( c->op == LDAP_MOD_DELETE ) { 3719 ch_free( c->be->be_update_ndn.bv_val ); 3720 BER_BVZERO( &c->be->be_update_ndn ); 3721 SLAP_DBFLAGS(c->be) ^= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SLURP_SHADOW); 3722 return 0; 3723 } 3724 if(SLAP_SHADOW(c->be)) { 3725 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> database already shadowed", c->argv[0] ); 3726 Debug(LDAP_DEBUG_ANY, "%s: %s\n", 3727 c->log, c->cr_msg, 0); 3728 return(1); 3729 } 3730 3731 ber_memfree_x( c->value_dn.bv_val, NULL ); 3732 if ( !BER_BVISNULL( &c->be->be_update_ndn ) ) { 3733 ber_memfree_x( c->be->be_update_ndn.bv_val, NULL ); 3734 } 3735 c->be->be_update_ndn = c->value_ndn; 3736 BER_BVZERO( &c->value_dn ); 3737 BER_BVZERO( &c->value_ndn ); 3738 3739 return config_slurp_shadow( c ); 3740} 3741 3742int 3743config_shadow( ConfigArgs *c, slap_mask_t flag ) 3744{ 3745 char *notallowed = NULL; 3746 3747 if ( c->be == frontendDB ) { 3748 notallowed = "frontend"; 3749 3750 } else if ( SLAP_MONITOR(c->be) ) { 3751 notallowed = "monitor"; 3752 } 3753 3754 if ( notallowed != NULL ) { 3755 Debug( LDAP_DEBUG_ANY, "%s: %s database cannot be shadow.\n", c->log, notallowed, 0 ); 3756 return 1; 3757 } 3758 3759 if ( SLAP_SHADOW(c->be) ) { 3760 /* if already shadow, only check consistency */ 3761 if ( ( SLAP_DBFLAGS(c->be) & flag ) != flag ) { 3762 Debug( LDAP_DEBUG_ANY, "%s: inconsistent shadow flag 0x%lx.\n", 3763 c->log, flag, 0 ); 3764 return 1; 3765 } 3766 3767 } else { 3768 SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | flag); 3769 if ( !SLAP_MULTIMASTER( c->be )) 3770 SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW; 3771 } 3772 3773 return 0; 3774} 3775 3776static int 3777config_updateref(ConfigArgs *c) { 3778 struct berval val; 3779 if (c->op == SLAP_CONFIG_EMIT) { 3780 if ( c->be->be_update_refs ) { 3781 value_add( &c->rvalue_vals, c->be->be_update_refs ); 3782 return 0; 3783 } else { 3784 return 1; 3785 } 3786 } else if ( c->op == LDAP_MOD_DELETE ) { 3787 if ( c->valx < 0 ) { 3788 ber_bvarray_free( c->be->be_update_refs ); 3789 c->be->be_update_refs = NULL; 3790 } else { 3791 int i = c->valx; 3792 ch_free( c->be->be_update_refs[i].bv_val ); 3793 for (; c->be->be_update_refs[i].bv_val; i++) 3794 c->be->be_update_refs[i] = c->be->be_update_refs[i+1]; 3795 } 3796 return 0; 3797 } 3798 if(!SLAP_SHADOW(c->be) && !c->be->be_syncinfo) { 3799 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must appear after syncrepl or updatedn", 3800 c->argv[0] ); 3801 Debug(LDAP_DEBUG_ANY, "%s: %s\n", 3802 c->log, c->cr_msg, 0); 3803 return(1); 3804 } 3805 3806 if(validate_global_referral(c->argv[1])) { 3807 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid URL", c->argv[0] ); 3808 Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", 3809 c->log, c->cr_msg, c->argv[1]); 3810 return(1); 3811 } 3812 ber_str2bv(c->argv[1], 0, 0, &val); 3813 if(value_add_one(&c->be->be_update_refs, &val)) return(LDAP_OTHER); 3814 return(0); 3815} 3816 3817static int 3818config_obsolete(ConfigArgs *c) { 3819 if (c->op == SLAP_CONFIG_EMIT) 3820 return 1; 3821 3822 snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> keyword is obsolete (ignored)", 3823 c->argv[0] ); 3824 Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg, 0); 3825 return(0); 3826} 3827 3828static int 3829config_include(ConfigArgs *c) { 3830 int savelineno = c->lineno; 3831 int rc; 3832 ConfigFile *cf; 3833 ConfigFile *cfsave = cfn; 3834 ConfigFile *cf2 = NULL; 3835 3836 /* Leftover from RE23. No dynamic config for include files */ 3837 if ( c->op == SLAP_CONFIG_EMIT || c->op == LDAP_MOD_DELETE ) 3838 return 1; 3839 3840 cf = ch_calloc( 1, sizeof(ConfigFile)); 3841 if ( cfn->c_kids ) { 3842 for (cf2=cfn->c_kids; cf2 && cf2->c_sibs; cf2=cf2->c_sibs) ; 3843 cf2->c_sibs = cf; 3844 } else { 3845 cfn->c_kids = cf; 3846 } 3847 cfn = cf; 3848 ber_str2bv( c->argv[1], 0, 1, &cf->c_file ); 3849 rc = read_config_file(c->argv[1], c->depth + 1, c, config_back_cf_table); 3850 c->lineno = savelineno - 1; 3851 cfn = cfsave; 3852 if ( rc ) { 3853 if ( cf2 ) cf2->c_sibs = NULL; 3854 else cfn->c_kids = NULL; 3855 ch_free( cf->c_file.bv_val ); 3856 ch_free( cf ); 3857 } else { 3858 c->ca_private = cf; 3859 } 3860 return(rc); 3861} 3862 3863#ifdef HAVE_TLS 3864static int 3865config_tls_cleanup(ConfigArgs *c) { 3866 int rc = 0; 3867 3868 if ( slap_tls_ld ) { 3869 int opt = 1; 3870 3871// ldap_pvt_tls_ctx_free( slap_tls_ctx ); 3872 /* Force new ctx to be created */ 3873 slap_tls_ctx = NULL; 3874 rc = ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt ); 3875 if( rc == 0 ) { 3876 /* The ctx's refcount is bumped up here */ 3877 ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx ); 3878 /* This is a no-op if it's already loaded */ 3879 load_extop( &slap_EXOP_START_TLS, 0, starttls_extop ); 3880 } 3881 } 3882 return rc; 3883} 3884 3885static int 3886config_tls_option(ConfigArgs *c) { 3887 int flag; 3888 LDAP *ld = slap_tls_ld; 3889 switch(c->type) { 3890#ifndef HAVE_SECURE_TRANSPORT 3891 case CFG_TLS_RAND: flag = LDAP_OPT_X_TLS_RANDOM_FILE; ld = NULL; break; 3892#endif 3893 case CFG_TLS_CIPHER: flag = LDAP_OPT_X_TLS_CIPHER_SUITE; break; 3894#ifdef HAVE_SECURE_TRANSPORT 3895 case CFG_TLS_IDENTITY: flag = LDAP_OPT_X_TLS_IDENTITY; break; 3896 case CFG_TLS_TRUSTED_CERTS: flag = LDAP_OPT_X_TLS_TRUSTED_CERTS; break; 3897#else 3898 case CFG_TLS_CERT_FILE: flag = LDAP_OPT_X_TLS_CERTFILE; break; 3899 case CFG_TLS_CERT_KEY: flag = LDAP_OPT_X_TLS_KEYFILE; break; 3900 case CFG_TLS_CA_PATH: flag = LDAP_OPT_X_TLS_CACERTDIR; break; 3901 case CFG_TLS_CA_FILE: flag = LDAP_OPT_X_TLS_CACERTFILE; break; 3902#endif 3903 case CFG_TLS_DH_FILE: flag = LDAP_OPT_X_TLS_DHFILE; break; 3904#ifndef HAVE_SECURE_TRANSPORT 3905 case CFG_TLS_CERT_PASSPHRASE: flag = LDAP_OPT_X_TLS_PASSPHRASE; break; /*Apple Specific code*/ 3906 case CFG_TLS_IDENT_REF: flag = LDAP_OPT_X_TLS_CERT_IDENTITY; break; 3907#endif 3908 3909#ifdef HAVE_GNUTLS 3910 case CFG_TLS_CRL_FILE: flag = LDAP_OPT_X_TLS_CRLFILE; break; 3911#endif 3912 default: Debug(LDAP_DEBUG_ANY, "%s: " 3913 "unknown tls_option <0x%x>\n", 3914 c->log, c->type, 0); 3915 return 1; 3916 } 3917 if (c->op == SLAP_CONFIG_EMIT) { 3918 return ldap_pvt_tls_get_option( ld, flag, &c->value_string ); 3919 } else if ( c->op == LDAP_MOD_DELETE ) { 3920 c->cleanup = config_tls_cleanup; 3921#ifndef HAVE_SECURE_TRANSPORT 3922 if (flag == LDAP_OPT_X_TLS_PASSPHRASE) /*Apple Specific code*/ 3923 return ldap_pvt_tls_set_option( NULL, flag, NULL ); 3924#endif 3925 return ldap_pvt_tls_set_option( ld, flag, NULL ); 3926 } 3927 ch_free(c->value_string); 3928 c->cleanup = config_tls_cleanup; 3929#ifndef HAVE_SECURE_TRANSPORT 3930 if (flag == LDAP_OPT_X_TLS_PASSPHRASE) /*Apple Specific code*/ 3931 return ldap_pvt_tls_set_option( NULL, flag, c->argv[1] ); 3932#endif 3933 return(ldap_pvt_tls_set_option(ld, flag, c->argv[1])); 3934} 3935 3936/* FIXME: this ought to be provided by libldap */ 3937static int 3938config_tls_config(ConfigArgs *c) { 3939 int i, flag; 3940 switch(c->type) { 3941 case CFG_TLS_CRLCHECK: flag = LDAP_OPT_X_TLS_CRLCHECK; break; 3942 case CFG_TLS_VERIFY: flag = LDAP_OPT_X_TLS_REQUIRE_CERT; break; 3943 case CFG_TLS_PROTOCOL_MIN: flag = LDAP_OPT_X_TLS_PROTOCOL_MIN; break; 3944 default: 3945 Debug(LDAP_DEBUG_ANY, "%s: " 3946 "unknown tls_option <0x%x>\n", 3947 c->log, c->type, 0); 3948 return 1; 3949 } 3950 if (c->op == SLAP_CONFIG_EMIT) { 3951 return slap_tls_get_config( slap_tls_ld, flag, &c->value_string ); 3952 } else if ( c->op == LDAP_MOD_DELETE ) { 3953 int i = 0; 3954 c->cleanup = config_tls_cleanup; 3955 return ldap_pvt_tls_set_option( slap_tls_ld, flag, &i ); 3956 } 3957 ch_free( c->value_string ); 3958 c->cleanup = config_tls_cleanup; 3959 if ( isdigit( (unsigned char)c->argv[1][0] ) ) { 3960 if ( lutil_atoi( &i, c->argv[1] ) != 0 ) { 3961 Debug(LDAP_DEBUG_ANY, "%s: " 3962 "unable to parse %s \"%s\"\n", 3963 c->log, c->argv[0], c->argv[1] ); 3964 return 1; 3965 } 3966 return(ldap_pvt_tls_set_option(slap_tls_ld, flag, &i)); 3967 } else { 3968 return(ldap_int_tls_config(slap_tls_ld, flag, c->argv[1])); 3969 } 3970} 3971#endif 3972 3973static CfEntryInfo * 3974config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last ) 3975{ 3976 struct berval cdn; 3977 char *c; 3978 3979 if ( !root ) { 3980 *last = NULL; 3981 return NULL; 3982 } 3983 3984 if ( dn_match( &root->ce_entry->e_nname, dn )) 3985 return root; 3986 3987 c = dn->bv_val+dn->bv_len; 3988 for (;*c != ',';c--); 3989 3990 while(root) { 3991 *last = root; 3992 for (--c;c>dn->bv_val && *c != ',';c--); 3993 cdn.bv_val = c; 3994 if ( *c == ',' ) 3995 cdn.bv_val++; 3996 cdn.bv_len = dn->bv_len - (cdn.bv_val - dn->bv_val); 3997 3998 root = root->ce_kids; 3999 4000 for (;root;root=root->ce_sibs) { 4001 if ( dn_match( &root->ce_entry->e_nname, &cdn )) { 4002 if ( cdn.bv_val == dn->bv_val ) { 4003 return root; 4004 } 4005 break; 4006 } 4007 } 4008 } 4009 return root; 4010} 4011 4012typedef struct setup_cookie { 4013 CfBackInfo *cfb; 4014 ConfigArgs *ca; 4015 Entry *frontend; 4016 Entry *config; 4017 int got_frontend; 4018 int got_config; 4019} setup_cookie; 4020 4021static int 4022config_ldif_resp( Operation *op, SlapReply *rs ) 4023{ 4024 if ( rs->sr_type == REP_SEARCH ) { 4025 setup_cookie *sc = op->o_callback->sc_private; 4026 struct berval pdn; 4027 4028 sc->cfb->cb_got_ldif = 1; 4029 /* Does the frontend exist? */ 4030 if ( !sc->got_frontend ) { 4031 if ( !strncmp( rs->sr_entry->e_nname.bv_val, 4032 "olcDatabase", STRLENOF( "olcDatabase" ))) 4033 { 4034 if ( strncmp( rs->sr_entry->e_nname.bv_val + 4035 STRLENOF( "olcDatabase" ), "={-1}frontend", 4036 STRLENOF( "={-1}frontend" ))) 4037 { 4038 struct berval rdn; 4039 int i = op->o_noop; 4040 sc->ca->be = frontendDB; 4041 sc->ca->bi = frontendDB->bd_info; 4042 frontendDB->be_cf_ocs = &CFOC_FRONTEND; 4043 rdn.bv_val = sc->ca->log; 4044 rdn.bv_len = snprintf(rdn.bv_val, sizeof( sc->ca->log ), 4045 "%s=" SLAP_X_ORDERED_FMT "%s", 4046 cfAd_database->ad_cname.bv_val, -1, 4047 sc->ca->bi->bi_type); 4048 op->o_noop = 1; 4049 sc->frontend = config_build_entry( op, rs, 4050 sc->cfb->cb_root, sc->ca, &rdn, &CFOC_DATABASE, 4051 sc->ca->be->be_cf_ocs ); 4052 op->o_noop = i; 4053 sc->got_frontend++; 4054 } else { 4055 sc->got_frontend++; 4056 goto ok; 4057 } 4058 } 4059 } 4060 4061 dnParent( &rs->sr_entry->e_nname, &pdn ); 4062 4063 /* Does the configDB exist? */ 4064 if ( sc->got_frontend && !sc->got_config && 4065 !strncmp( rs->sr_entry->e_nname.bv_val, 4066 "olcDatabase", STRLENOF( "olcDatabase" )) && 4067 dn_match( &config_rdn, &pdn ) ) 4068 { 4069 if ( strncmp( rs->sr_entry->e_nname.bv_val + 4070 STRLENOF( "olcDatabase" ), "={0}config", 4071 STRLENOF( "={0}config" ))) 4072 { 4073 struct berval rdn; 4074 int i = op->o_noop; 4075 sc->ca->be = LDAP_STAILQ_FIRST( &backendDB ); 4076 sc->ca->bi = sc->ca->be->bd_info; 4077 rdn.bv_val = sc->ca->log; 4078 rdn.bv_len = snprintf(rdn.bv_val, sizeof( sc->ca->log ), 4079 "%s=" SLAP_X_ORDERED_FMT "%s", 4080 cfAd_database->ad_cname.bv_val, 0, 4081 sc->ca->bi->bi_type); 4082 op->o_noop = 1; 4083 sc->config = config_build_entry( op, rs, sc->cfb->cb_root, 4084 sc->ca, &rdn, &CFOC_DATABASE, sc->ca->be->be_cf_ocs ); 4085 op->o_noop = i; 4086 } 4087 sc->got_config++; 4088 } 4089 4090ok: 4091 rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL, NULL ); 4092 if ( rs->sr_err != LDAP_SUCCESS ) { 4093 Debug( LDAP_DEBUG_ANY, "config error processing %s: %s\n", 4094 rs->sr_entry->e_name.bv_val, sc->ca->cr_msg, 0 ); 4095 } 4096 } 4097 return rs->sr_err; 4098} 4099 4100/* Configure and read the underlying back-ldif store */ 4101static int 4102config_setup_ldif( BackendDB *be, const char *dir, int readit ) { 4103 CfBackInfo *cfb = be->be_private; 4104 ConfigArgs c = {0}; 4105 ConfigTable *ct; 4106 char *argv[3]; 4107 int rc = 0; 4108 setup_cookie sc; 4109 slap_callback cb = { NULL, config_ldif_resp, NULL, NULL }; 4110 Connection conn = {0}; 4111 OperationBuffer opbuf; 4112 Operation *op; 4113 SlapReply rs = {REP_RESULT}; 4114 Filter filter = { LDAP_FILTER_PRESENT }; 4115 struct berval filterstr = BER_BVC("(objectclass=*)"); 4116 struct stat st; 4117 4118 /* Is the config directory available? */ 4119 if ( stat( dir, &st ) < 0 ) { 4120 /* No, so don't bother using the backing store. 4121 * All changes will be in-memory only. 4122 */ 4123 return 0; 4124 } 4125 4126 cfb->cb_db.bd_info = backend_info( "ldif" ); 4127 if ( !cfb->cb_db.bd_info ) 4128 return 0; /* FIXME: eventually this will be a fatal error */ 4129 4130 if ( backend_db_init( "ldif", &cfb->cb_db, -1, NULL ) == NULL ) 4131 return 1; 4132 4133 cfb->cb_db.be_suffix = be->be_suffix; 4134 cfb->cb_db.be_nsuffix = be->be_nsuffix; 4135 4136 /* The suffix is always "cn=config". The underlying DB's rootdn 4137 * is always the same as the suffix. 4138 */ 4139 cfb->cb_db.be_rootdn = be->be_suffix[0]; 4140 cfb->cb_db.be_rootndn = be->be_nsuffix[0]; 4141 4142 ber_str2bv( dir, 0, 1, &cfdir ); 4143 4144 c.be = &cfb->cb_db; 4145 c.fname = "slapd"; 4146 c.argc = 2; 4147 argv[0] = "directory"; 4148 argv[1] = (char *)dir; 4149 argv[2] = NULL; 4150 c.argv = argv; 4151 c.reply.err = 0; 4152 c.reply.msg[0] = 0; 4153 c.table = Cft_Database; 4154 4155 ct = config_find_keyword( c.be->be_cf_ocs->co_table, &c ); 4156 if ( !ct ) 4157 return 1; 4158 4159 if ( config_add_vals( ct, &c )) 4160 return 1; 4161 4162 if ( backend_startup_one( &cfb->cb_db, &c.reply )) 4163 return 1; 4164 4165 if ( readit ) { 4166 void *thrctx = ldap_pvt_thread_pool_context(); 4167 int prev_DN_strict; 4168 4169 connection_fake_init( &conn, &opbuf, thrctx ); 4170 op = &opbuf.ob_op; 4171 4172 filter.f_desc = slap_schema.si_ad_objectClass; 4173 4174 op->o_tag = LDAP_REQ_SEARCH; 4175 4176 op->ors_filter = &filter; 4177 op->ors_filterstr = filterstr; 4178 op->ors_scope = LDAP_SCOPE_SUBTREE; 4179 4180 op->o_dn = c.be->be_rootdn; 4181 op->o_ndn = c.be->be_rootndn; 4182 4183 op->o_req_dn = be->be_suffix[0]; 4184 op->o_req_ndn = be->be_nsuffix[0]; 4185 4186 op->ors_tlimit = SLAP_NO_LIMIT; 4187 op->ors_slimit = SLAP_NO_LIMIT; 4188 4189 op->ors_attrs = slap_anlist_all_attributes; 4190 op->ors_attrsonly = 0; 4191 4192 op->o_callback = &cb; 4193 sc.cfb = cfb; 4194 sc.ca = &c; 4195 cb.sc_private = ≻ 4196 sc.got_frontend = 0; 4197 sc.got_config = 0; 4198 sc.frontend = NULL; 4199 sc.config = NULL; 4200 4201 op->o_bd = &cfb->cb_db; 4202 4203 /* Allow unknown attrs in DNs */ 4204 prev_DN_strict = slap_DN_strict; 4205 slap_DN_strict = 0; 4206 4207 rc = op->o_bd->be_search( op, &rs ); 4208 4209 /* Restore normal DN validation */ 4210 slap_DN_strict = prev_DN_strict; 4211 4212 op->o_tag = LDAP_REQ_ADD; 4213 if ( rc == LDAP_SUCCESS && sc.frontend ) { 4214 rs_reinit( &rs, REP_RESULT ); 4215 op->ora_e = sc.frontend; 4216 rc = op->o_bd->be_add( op, &rs ); 4217 } 4218 if ( rc == LDAP_SUCCESS && sc.config ) { 4219 rs_reinit( &rs, REP_RESULT ); 4220 op->ora_e = sc.config; 4221 rc = op->o_bd->be_add( op, &rs ); 4222 } 4223 ldap_pvt_thread_pool_context_reset( thrctx ); 4224 } 4225 4226 /* ITS#4194 - only use if it's present, or we're converting. */ 4227 if ( !readit || rc == LDAP_SUCCESS ) 4228 cfb->cb_use_ldif = 1; 4229 4230 return rc; 4231} 4232 4233static int 4234CfOc_cmp( const void *c1, const void *c2 ) { 4235 const ConfigOCs *co1 = c1; 4236 const ConfigOCs *co2 = c2; 4237 4238 return ber_bvcmp( co1->co_name, co2->co_name ); 4239} 4240 4241int 4242config_register_schema(ConfigTable *ct, ConfigOCs *ocs) { 4243 int i; 4244 4245 i = init_config_attrs( ct ); 4246 if ( i ) return i; 4247 4248 /* set up the objectclasses */ 4249 i = init_config_ocs( ocs ); 4250 if ( i ) return i; 4251 4252 for (i=0; ocs[i].co_def; i++) { 4253 if ( ocs[i].co_oc ) { 4254 ocs[i].co_name = &ocs[i].co_oc->soc_cname; 4255 if ( !ocs[i].co_table ) 4256 ocs[i].co_table = ct; 4257 avl_insert( &CfOcTree, &ocs[i], CfOc_cmp, avl_dup_error ); 4258 } 4259 } 4260 return 0; 4261} 4262 4263int 4264read_config(const char *fname, const char *dir) { 4265 BackendDB *be; 4266 CfBackInfo *cfb; 4267 const char *cfdir, *cfname; 4268 int rc; 4269 4270 /* Setup the config backend */ 4271 be = backend_db_init( "config", NULL, 0, NULL ); 4272 if ( !be ) 4273 return 1; 4274 4275 cfb = be->be_private; 4276 be->be_dfltaccess = ACL_NONE; 4277 4278 /* If no .conf, or a dir was specified, setup the dir */ 4279 if ( !fname || dir ) { 4280 if ( dir ) { 4281 /* If explicitly given, check for existence */ 4282 struct stat st; 4283 4284 if ( stat( dir, &st ) < 0 ) { 4285 Debug( LDAP_DEBUG_ANY, 4286 "invalid config directory %s, error %d\n", 4287 dir, errno, 0 ); 4288 return 1; 4289 } 4290 cfdir = dir; 4291 } else { 4292 cfdir = SLAPD_DEFAULT_CONFIGDIR; 4293 } 4294 /* if fname is defaulted, try reading .d */ 4295 rc = config_setup_ldif( be, cfdir, !fname ); 4296 4297 if ( rc ) { 4298 /* It may be OK if the base object doesn't exist yet. */ 4299 if ( rc != LDAP_NO_SUCH_OBJECT ) 4300 return 1; 4301 /* ITS#4194: But if dir was specified and no fname, 4302 * then we were supposed to read the dir. Unless we're 4303 * trying to slapadd the dir... 4304 */ 4305 if ( dir && !fname ) { 4306 if ( slapMode & (SLAP_SERVER_MODE|SLAP_TOOL_READMAIN|SLAP_TOOL_READONLY)) 4307 return 1; 4308 /* Assume it's slapadd with a config dir, let it continue */ 4309 rc = 0; 4310 cfb->cb_got_ldif = 1; 4311 cfb->cb_use_ldif = 1; 4312 goto done; 4313 } 4314 } 4315 4316 /* If we read the config from back-ldif, nothing to do here */ 4317 if ( cfb->cb_got_ldif ) { 4318 rc = 0; 4319 goto done; 4320 } 4321 } 4322 4323 if ( fname ) 4324 cfname = fname; 4325 else 4326 cfname = SLAPD_DEFAULT_CONFIGFILE; 4327 4328 rc = read_config_file(cfname, 0, NULL, config_back_cf_table); 4329 4330 if ( rc == 0 ) 4331 ber_str2bv( cfname, 0, 1, &cfb->cb_config->c_file ); 4332 4333done: 4334 if ( rc == 0 && BER_BVISNULL( &frontendDB->be_schemadn ) ) { 4335 ber_str2bv( SLAPD_SCHEMA_DN, STRLENOF( SLAPD_SCHEMA_DN ), 1, 4336 &frontendDB->be_schemadn ); 4337 rc = dnNormalize( 0, NULL, NULL, &frontendDB->be_schemadn, &frontendDB->be_schemandn, NULL ); 4338 if ( rc != LDAP_SUCCESS ) { 4339 Debug(LDAP_DEBUG_ANY, "read_config: " 4340 "unable to normalize default schema DN \"%s\"\n", 4341 frontendDB->be_schemadn.bv_val, 0, 0 ); 4342 /* must not happen */ 4343 assert( 0 ); 4344 } 4345 } 4346 return rc; 4347} 4348 4349static int 4350config_back_bind( Operation *op, SlapReply *rs ) 4351{ 4352 if ( be_isroot_pw( op ) ) { 4353 ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd )); 4354 /* frontend sends result */ 4355 return LDAP_SUCCESS; 4356 } 4357 4358 rs->sr_err = LDAP_INVALID_CREDENTIALS; 4359 send_ldap_result( op, rs ); 4360 4361 return rs->sr_err; 4362} 4363 4364static int 4365config_send( Operation *op, SlapReply *rs, CfEntryInfo *ce, int depth ) 4366{ 4367 int rc = 0; 4368 4369 if ( test_filter( op, ce->ce_entry, op->ors_filter ) == LDAP_COMPARE_TRUE ) 4370 { 4371 rs->sr_attrs = op->ors_attrs; 4372 rs->sr_entry = ce->ce_entry; 4373 rs->sr_flags = 0; 4374 rc = send_search_entry( op, rs ); 4375 if ( rc != LDAP_SUCCESS ) { 4376 return rc; 4377 } 4378 } 4379 if ( op->ors_scope == LDAP_SCOPE_SUBTREE ) { 4380 if ( ce->ce_kids ) { 4381 rc = config_send( op, rs, ce->ce_kids, 1 ); 4382 if ( rc ) return rc; 4383 } 4384 if ( depth ) { 4385 for (ce=ce->ce_sibs; ce; ce=ce->ce_sibs) { 4386 rc = config_send( op, rs, ce, 0 ); 4387 if ( rc ) break; 4388 } 4389 } 4390 } 4391 return rc; 4392} 4393 4394static ConfigTable * 4395config_find_table( ConfigOCs **colst, int nocs, AttributeDescription *ad, 4396 ConfigArgs *ca ) 4397{ 4398 int i, j; 4399 4400 for (j=0; j<nocs; j++) { 4401 for (i=0; colst[j]->co_table[i].name; i++) 4402 if ( colst[j]->co_table[i].ad == ad ) { 4403 ca->table = colst[j]->co_type; 4404 return &colst[j]->co_table[i]; 4405 } 4406 } 4407 return NULL; 4408} 4409 4410/* Sort the attributes of the entry according to the order defined 4411 * in the objectclass, with required attributes occurring before 4412 * allowed attributes. For any attributes with sequencing dependencies 4413 * (e.g., rootDN must be defined after suffix) the objectclass must 4414 * list the attributes in the desired sequence. 4415 */ 4416static void 4417sort_attrs( Entry *e, ConfigOCs **colst, int nocs ) 4418{ 4419 Attribute *a, *head = NULL, *tail = NULL, **prev; 4420 int i, j; 4421 4422 for (i=0; i<nocs; i++) { 4423 if ( colst[i]->co_oc->soc_required ) { 4424 AttributeType **at = colst[i]->co_oc->soc_required; 4425 for (j=0; at[j]; j++) { 4426 for (a=e->e_attrs, prev=&e->e_attrs; a; 4427 prev = &(*prev)->a_next, a=a->a_next) { 4428 if ( a->a_desc == at[j]->sat_ad ) { 4429 *prev = a->a_next; 4430 if (!head) { 4431 head = a; 4432 tail = a; 4433 } else { 4434 tail->a_next = a; 4435 tail = a; 4436 } 4437 break; 4438 } 4439 } 4440 } 4441 } 4442 if ( colst[i]->co_oc->soc_allowed ) { 4443 AttributeType **at = colst[i]->co_oc->soc_allowed; 4444 for (j=0; at[j]; j++) { 4445 for (a=e->e_attrs, prev=&e->e_attrs; a; 4446 prev = &(*prev)->a_next, a=a->a_next) { 4447 if ( a->a_desc == at[j]->sat_ad ) { 4448 *prev = a->a_next; 4449 if (!head) { 4450 head = a; 4451 tail = a; 4452 } else { 4453 tail->a_next = a; 4454 tail = a; 4455 } 4456 break; 4457 } 4458 } 4459 } 4460 } 4461 } 4462 if ( tail ) { 4463 tail->a_next = e->e_attrs; 4464 e->e_attrs = head; 4465 } 4466} 4467 4468static int 4469check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr ) 4470{ 4471 Attribute *a = NULL; 4472 AttributeDescription *ad; 4473 BerVarray vals; 4474 4475 int i, rc = 0; 4476 4477 if ( isAttr ) { 4478 a = ptr; 4479 ad = a->a_desc; 4480 vals = a->a_vals; 4481 } else { 4482 Modifications *ml = ptr; 4483 ad = ml->sml_desc; 4484 vals = ml->sml_values; 4485 } 4486 4487 if ( a && ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL )) { 4488 rc = ordered_value_sort( a, 1 ); 4489 if ( rc ) { 4490 snprintf(ca->cr_msg, sizeof( ca->cr_msg ), "ordered_value_sort failed on attr %s\n", 4491 ad->ad_cname.bv_val ); 4492 return rc; 4493 } 4494 } 4495 for ( i=0; vals[i].bv_val; i++ ) { 4496 ca->line = vals[i].bv_val; 4497 if (( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) && 4498 ca->line[0] == '{' ) { 4499 char *idx = strchr( ca->line, '}' ); 4500 if ( idx ) ca->line = idx+1; 4501 } 4502 rc = config_parse_vals( ct, ca, i ); 4503 if ( rc ) { 4504 break; 4505 } 4506 } 4507 return rc; 4508} 4509 4510static int 4511config_rename_attr( SlapReply *rs, Entry *e, struct berval *rdn, 4512 Attribute **at ) 4513{ 4514 struct berval rtype, rval; 4515 Attribute *a; 4516 AttributeDescription *ad = NULL; 4517 4518 dnRdn( &e->e_name, rdn ); 4519 rval.bv_val = strchr(rdn->bv_val, '=' ) + 1; 4520 rval.bv_len = rdn->bv_len - (rval.bv_val - rdn->bv_val); 4521 rtype.bv_val = rdn->bv_val; 4522 rtype.bv_len = rval.bv_val - rtype.bv_val - 1; 4523 4524 /* Find attr */ 4525 slap_bv2ad( &rtype, &ad, &rs->sr_text ); 4526 a = attr_find( e->e_attrs, ad ); 4527 if (!a ) return LDAP_NAMING_VIOLATION; 4528 *at = a; 4529 4530 return 0; 4531} 4532 4533static void 4534config_rename_kids( CfEntryInfo *ce ) 4535{ 4536 CfEntryInfo *ce2; 4537 struct berval rdn, nrdn; 4538 4539 for (ce2 = ce->ce_kids; ce2; ce2 = ce2->ce_sibs) { 4540 struct berval newdn, newndn; 4541 dnRdn ( &ce2->ce_entry->e_name, &rdn ); 4542 dnRdn ( &ce2->ce_entry->e_nname, &nrdn ); 4543 build_new_dn( &newdn, &ce->ce_entry->e_name, &rdn, NULL ); 4544 build_new_dn( &newndn, &ce->ce_entry->e_nname, &nrdn, NULL ); 4545 free( ce2->ce_entry->e_name.bv_val ); 4546 free( ce2->ce_entry->e_nname.bv_val ); 4547 ce2->ce_entry->e_name = newdn; 4548 ce2->ce_entry->e_nname = newndn; 4549 config_rename_kids( ce2 ); 4550 } 4551} 4552 4553static int 4554config_rename_one( Operation *op, SlapReply *rs, Entry *e, 4555 CfEntryInfo *parent, Attribute *a, struct berval *newrdn, 4556 struct berval *nnewrdn, int use_ldif ) 4557{ 4558 char *ptr1; 4559 int rc = 0; 4560 struct berval odn, ondn; 4561 4562 odn = e->e_name; 4563 ondn = e->e_nname; 4564 build_new_dn( &e->e_name, &parent->ce_entry->e_name, newrdn, NULL ); 4565 build_new_dn( &e->e_nname, &parent->ce_entry->e_nname, nnewrdn, NULL ); 4566 4567 /* Replace attr */ 4568 free( a->a_vals[0].bv_val ); 4569 ptr1 = strchr( newrdn->bv_val, '=' ) + 1; 4570 a->a_vals[0].bv_len = newrdn->bv_len - (ptr1 - newrdn->bv_val); 4571 a->a_vals[0].bv_val = ch_malloc( a->a_vals[0].bv_len + 1 ); 4572 strcpy( a->a_vals[0].bv_val, ptr1 ); 4573 4574 if ( a->a_nvals != a->a_vals ) { 4575 free( a->a_nvals[0].bv_val ); 4576 ptr1 = strchr( nnewrdn->bv_val, '=' ) + 1; 4577 a->a_nvals[0].bv_len = nnewrdn->bv_len - (ptr1 - nnewrdn->bv_val); 4578 a->a_nvals[0].bv_val = ch_malloc( a->a_nvals[0].bv_len + 1 ); 4579 strcpy( a->a_nvals[0].bv_val, ptr1 ); 4580 } 4581 if ( use_ldif ) { 4582 CfBackInfo *cfb = (CfBackInfo *)op->o_bd->be_private; 4583 BackendDB *be = op->o_bd; 4584 slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp; 4585 struct berval dn, ndn, xdn, xndn; 4586 4587 op->o_bd = &cfb->cb_db; 4588 4589 /* Save current rootdn; use the underlying DB's rootdn */ 4590 dn = op->o_dn; 4591 ndn = op->o_ndn; 4592 xdn = op->o_req_dn; 4593 xndn = op->o_req_ndn; 4594 op->o_dn = op->o_bd->be_rootdn; 4595 op->o_ndn = op->o_bd->be_rootndn; 4596 op->o_req_dn = odn; 4597 op->o_req_ndn = ondn; 4598 4599 scp = op->o_callback; 4600 op->o_callback = ≻ 4601 op->orr_newrdn = *newrdn; 4602 op->orr_nnewrdn = *nnewrdn; 4603 op->orr_newSup = NULL; 4604 op->orr_nnewSup = NULL; 4605 op->orr_deleteoldrdn = 1; 4606 op->orr_modlist = NULL; 4607 slap_modrdn2mods( op, rs ); 4608 slap_mods_opattrs( op, &op->orr_modlist, 1 ); 4609 rc = op->o_bd->be_modrdn( op, rs ); 4610 slap_mods_free( op->orr_modlist, 1 ); 4611 4612 op->o_bd = be; 4613 op->o_callback = scp; 4614 op->o_dn = dn; 4615 op->o_ndn = ndn; 4616 op->o_req_dn = xdn; 4617 op->o_req_ndn = xndn; 4618 } 4619 free( odn.bv_val ); 4620 free( ondn.bv_val ); 4621 if ( e->e_private ) 4622 config_rename_kids( e->e_private ); 4623 return rc; 4624} 4625 4626static int 4627config_renumber_one( Operation *op, SlapReply *rs, CfEntryInfo *parent, 4628 Entry *e, int idx, int tailindex, int use_ldif ) 4629{ 4630 struct berval ival, newrdn, nnewrdn; 4631 struct berval rdn; 4632 Attribute *a; 4633 char ibuf[32], *ptr1, *ptr2 = NULL; 4634 int rc = 0; 4635 4636 rc = config_rename_attr( rs, e, &rdn, &a ); 4637 if ( rc ) return rc; 4638 4639 ival.bv_val = ibuf; 4640 ival.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, idx ); 4641 if ( ival.bv_len >= sizeof( ibuf ) ) { 4642 return LDAP_NAMING_VIOLATION; 4643 } 4644 4645 newrdn.bv_len = rdn.bv_len + ival.bv_len; 4646 newrdn.bv_val = ch_malloc( newrdn.bv_len+1 ); 4647 4648 if ( tailindex ) { 4649 ptr1 = lutil_strncopy( newrdn.bv_val, rdn.bv_val, rdn.bv_len ); 4650 ptr1 = lutil_strcopy( ptr1, ival.bv_val ); 4651 } else { 4652 int xlen; 4653 ptr2 = ber_bvchr( &rdn, '}' ); 4654 if ( ptr2 ) { 4655 ptr2++; 4656 } else { 4657 ptr2 = rdn.bv_val + a->a_desc->ad_cname.bv_len + 1; 4658 } 4659 xlen = rdn.bv_len - (ptr2 - rdn.bv_val); 4660 ptr1 = lutil_strncopy( newrdn.bv_val, a->a_desc->ad_cname.bv_val, 4661 a->a_desc->ad_cname.bv_len ); 4662 *ptr1++ = '='; 4663 ptr1 = lutil_strcopy( ptr1, ival.bv_val ); 4664 ptr1 = lutil_strncopy( ptr1, ptr2, xlen ); 4665 *ptr1 = '\0'; 4666 } 4667 4668 /* Do the equivalent of ModRDN */ 4669 /* Replace DN / NDN */ 4670 newrdn.bv_len = ptr1 - newrdn.bv_val; 4671 rdnNormalize( 0, NULL, NULL, &newrdn, &nnewrdn, NULL ); 4672 rc = config_rename_one( op, rs, e, parent, a, &newrdn, &nnewrdn, use_ldif ); 4673 4674 free( nnewrdn.bv_val ); 4675 free( newrdn.bv_val ); 4676 return rc; 4677} 4678 4679static int 4680check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e, 4681 SlapReply *rs, int *renum, int *ibase ) 4682{ 4683 CfEntryInfo *ce; 4684 int index = -1, gotindex = 0, nsibs, rc = 0; 4685 int renumber = 0, tailindex = 0, isfrontend = 0, isconfig = 0; 4686 char *ptr1, *ptr2 = NULL; 4687 struct berval rdn; 4688 4689 if ( renum ) *renum = 0; 4690 4691 /* These entries don't get indexed/renumbered */ 4692 if ( ce_type == Cft_Global ) return 0; 4693 if ( ce_type == Cft_Schema && parent->ce_type == Cft_Global ) return 0; 4694 4695 if ( ce_type == Cft_Module ) 4696 tailindex = 1; 4697 4698 /* See if the rdn has an index already */ 4699 dnRdn( &e->e_name, &rdn ); 4700 if ( ce_type == Cft_Database ) { 4701 if ( !strncmp( rdn.bv_val + rdn.bv_len - STRLENOF("frontend"), 4702 "frontend", STRLENOF("frontend") )) 4703 isfrontend = 1; 4704 else if ( !strncmp( rdn.bv_val + rdn.bv_len - STRLENOF("config"), 4705 "config", STRLENOF("config") )) 4706 isconfig = 1; 4707 } 4708 ptr1 = ber_bvchr( &e->e_name, '{' ); 4709 if ( ptr1 && ptr1 < &e->e_name.bv_val[ rdn.bv_len ] ) { 4710 char *next; 4711 ptr2 = strchr( ptr1, '}' ); 4712 if ( !ptr2 || ptr2 > &e->e_name.bv_val[ rdn.bv_len ] ) 4713 return LDAP_NAMING_VIOLATION; 4714 if ( ptr2-ptr1 == 1) 4715 return LDAP_NAMING_VIOLATION; 4716 gotindex = 1; 4717 index = strtol( ptr1 + 1, &next, 10 ); 4718 if ( next == ptr1 + 1 || next[ 0 ] != '}' ) { 4719 return LDAP_NAMING_VIOLATION; 4720 } 4721 if ( index < 0 ) { 4722 /* Special case, we allow -1 for the frontendDB */ 4723 if ( index != -1 || !isfrontend ) 4724 return LDAP_NAMING_VIOLATION; 4725 } 4726 if ( isconfig && index != 0 ){ 4727 return LDAP_NAMING_VIOLATION; 4728 } 4729 } 4730 4731 /* count related kids */ 4732 for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) { 4733 if ( ce->ce_type == ce_type ) nsibs++; 4734 } 4735 4736 /* account for -1 frontend */ 4737 if ( ce_type == Cft_Database ) 4738 nsibs--; 4739 4740 if ( index != nsibs ) { 4741 if ( gotindex ) { 4742 if ( index < nsibs ) { 4743 if ( tailindex ) return LDAP_NAMING_VIOLATION; 4744 /* Siblings need to be renumbered */ 4745 if ( index != -1 || !isfrontend ) 4746 renumber = 1; 4747 } 4748 } 4749 /* config DB is always "0" */ 4750 if ( isconfig && index == -1 ) { 4751 index = 0; 4752 } 4753 if (( !isfrontend && index == -1 ) || ( index > nsibs ) ){ 4754 index = nsibs; 4755 } 4756 4757 /* just make index = nsibs */ 4758 if ( !renumber ) { 4759 rc = config_renumber_one( NULL, rs, parent, e, index, tailindex, 0 ); 4760 } 4761 } 4762 if ( ibase ) *ibase = index; 4763 if ( renum ) *renum = renumber; 4764 return rc; 4765} 4766 4767/* Insert all superior classes of the given class */ 4768static int 4769count_oc( ObjectClass *oc, ConfigOCs ***copp, int *nocs ) 4770{ 4771 ConfigOCs co, *cop; 4772 ObjectClass **sups; 4773 4774 for ( sups = oc->soc_sups; sups && *sups; sups++ ) { 4775 if ( count_oc( *sups, copp, nocs ) ) { 4776 return -1; 4777 } 4778 } 4779 4780 co.co_name = &oc->soc_cname; 4781 cop = avl_find( CfOcTree, &co, CfOc_cmp ); 4782 if ( cop ) { 4783 int i; 4784 4785 /* check for duplicates */ 4786 for ( i = 0; i < *nocs; i++ ) { 4787 if ( *copp && (*copp)[i] == cop ) { 4788 break; 4789 } 4790 } 4791 4792 if ( i == *nocs ) { 4793 ConfigOCs **tmp = ch_realloc( *copp, (*nocs + 1)*sizeof( ConfigOCs * ) ); 4794 if ( tmp == NULL ) { 4795 return -1; 4796 } 4797 *copp = tmp; 4798 (*copp)[*nocs] = cop; 4799 (*nocs)++; 4800 } 4801 } 4802 4803 return 0; 4804} 4805 4806/* Find all superior classes of the given objectclasses, 4807 * return list in order of most-subordinate first. 4808 * 4809 * Special / auxiliary / Cft_Misc classes always take precedence. 4810 */ 4811static ConfigOCs ** 4812count_ocs( Attribute *oc_at, int *nocs ) 4813{ 4814 int i, j, misc = -1; 4815 ConfigOCs **colst = NULL; 4816 4817 *nocs = 0; 4818 4819 for ( i = oc_at->a_numvals; i--; ) { 4820 ObjectClass *oc = oc_bvfind( &oc_at->a_nvals[i] ); 4821 4822 assert( oc != NULL ); 4823 if ( count_oc( oc, &colst, nocs ) ) { 4824 ch_free( colst ); 4825 return NULL; 4826 } 4827 } 4828 4829 /* invert order */ 4830 i = 0; 4831 j = *nocs - 1; 4832 while ( i < j ) { 4833 ConfigOCs *tmp = colst[i]; 4834 colst[i] = colst[j]; 4835 colst[j] = tmp; 4836 if (tmp->co_type == Cft_Misc) 4837 misc = j; 4838 i++; j--; 4839 } 4840 /* Move misc class to front of list */ 4841 if (misc > 0) { 4842 ConfigOCs *tmp = colst[misc]; 4843 for (i=misc; i>0; i--) 4844 colst[i] = colst[i-1]; 4845 colst[0] = tmp; 4846 } 4847 4848 return colst; 4849} 4850 4851static int 4852cfAddInclude( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) 4853{ 4854 /* Leftover from RE23. Never parse this entry */ 4855 return LDAP_COMPARE_TRUE; 4856} 4857 4858static int 4859cfAddSchema( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) 4860{ 4861 ConfigFile *cfo; 4862 4863 /* This entry is hardcoded, don't re-parse it */ 4864 if ( p->ce_type == Cft_Global ) { 4865 cfn = p->ce_private; 4866 ca->ca_private = cfn; 4867 return LDAP_COMPARE_TRUE; 4868 } 4869 if ( p->ce_type != Cft_Schema ) 4870 return LDAP_CONSTRAINT_VIOLATION; 4871 4872 cfn = ch_calloc( 1, sizeof(ConfigFile) ); 4873 ca->ca_private = cfn; 4874 cfo = p->ce_private; 4875 cfn->c_sibs = cfo->c_kids; 4876 cfo->c_kids = cfn; 4877 return LDAP_SUCCESS; 4878} 4879 4880static int 4881cfAddDatabase( CfEntryInfo *p, Entry *e, struct config_args_s *ca ) 4882{ 4883 if ( p->ce_type != Cft_Global ) { 4884 return LDAP_CONSTRAINT_VIOLATION; 4885 } 4886 /* config must be {0}, nothing else allowed */ 4887 if ( !strncmp( e->e_nname.bv_val, "olcDatabase={0}", STRLENOF("olcDatabase={0}")) && 4888 strncmp( e->e_nname.bv_val + STRLENOF("olcDatabase={0}"), "config,", STRLENOF("config,") )) { 4889 return LDAP_CONSTRAINT_VIOLATION; 4890 } 4891 ca->be = frontendDB; /* just to get past check_vals */ 4892 return LDAP_SUCCESS; 4893} 4894 4895static int 4896cfAddBackend( CfEntryInfo *p, Entry *e, struct config_args_s *ca ) 4897{ 4898 if ( p->ce_type != Cft_Global ) { 4899 return LDAP_CONSTRAINT_VIOLATION; 4900 } 4901 return LDAP_SUCCESS; 4902} 4903 4904static int 4905cfAddModule( CfEntryInfo *p, Entry *e, struct config_args_s *ca ) 4906{ 4907 if ( p->ce_type != Cft_Global ) { 4908 return LDAP_CONSTRAINT_VIOLATION; 4909 } 4910 return LDAP_SUCCESS; 4911} 4912 4913static int 4914cfAddOverlay( CfEntryInfo *p, Entry *e, struct config_args_s *ca ) 4915{ 4916 if ( p->ce_type != Cft_Database ) { 4917 return LDAP_CONSTRAINT_VIOLATION; 4918 } 4919 ca->be = p->ce_be; 4920 return LDAP_SUCCESS; 4921} 4922 4923static void 4924schema_destroy_one( ConfigArgs *ca, ConfigOCs **colst, int nocs, 4925 CfEntryInfo *p ) 4926{ 4927 ConfigTable *ct; 4928 ConfigFile *cfo; 4929 AttributeDescription *ad; 4930 const char *text; 4931 4932 ca->valx = -1; 4933 ca->line = NULL; 4934 ca->argc = 1; 4935 if ( cfn->c_cr_head ) { 4936 struct berval bv = BER_BVC("olcDitContentRules"); 4937 ad = NULL; 4938 slap_bv2ad( &bv, &ad, &text ); 4939 ct = config_find_table( colst, nocs, ad, ca ); 4940 config_del_vals( ct, ca ); 4941 } 4942 if ( cfn->c_oc_head ) { 4943 struct berval bv = BER_BVC("olcObjectClasses"); 4944 ad = NULL; 4945 slap_bv2ad( &bv, &ad, &text ); 4946 ct = config_find_table( colst, nocs, ad, ca ); 4947 config_del_vals( ct, ca ); 4948 } 4949 if ( cfn->c_at_head ) { 4950 struct berval bv = BER_BVC("olcAttributeTypes"); 4951 ad = NULL; 4952 slap_bv2ad( &bv, &ad, &text ); 4953 ct = config_find_table( colst, nocs, ad, ca ); 4954 config_del_vals( ct, ca ); 4955 } 4956 if ( cfn->c_syn_head ) { 4957 struct berval bv = BER_BVC("olcLdapSyntaxes"); 4958 ad = NULL; 4959 slap_bv2ad( &bv, &ad, &text ); 4960 ct = config_find_table( colst, nocs, ad, ca ); 4961 config_del_vals( ct, ca ); 4962 } 4963 if ( cfn->c_om_head ) { 4964 struct berval bv = BER_BVC("olcObjectIdentifier"); 4965 ad = NULL; 4966 slap_bv2ad( &bv, &ad, &text ); 4967 ct = config_find_table( colst, nocs, ad, ca ); 4968 config_del_vals( ct, ca ); 4969 } 4970 cfo = p->ce_private; 4971 cfo->c_kids = cfn->c_sibs; 4972 ch_free( cfn ); 4973} 4974 4975static int 4976config_add_oc( ConfigOCs **cop, CfEntryInfo *last, Entry *e, ConfigArgs *ca ) 4977{ 4978 int rc = LDAP_CONSTRAINT_VIOLATION; 4979 ObjectClass **ocp; 4980 4981 if ( (*cop)->co_ldadd ) { 4982 rc = (*cop)->co_ldadd( last, e, ca ); 4983 if ( rc != LDAP_CONSTRAINT_VIOLATION ) { 4984 return rc; 4985 } 4986 } 4987 4988 for ( ocp = (*cop)->co_oc->soc_sups; ocp && *ocp; ocp++ ) { 4989 ConfigOCs co = { 0 }; 4990 4991 co.co_name = &(*ocp)->soc_cname; 4992 *cop = avl_find( CfOcTree, &co, CfOc_cmp ); 4993 if ( *cop == NULL ) { 4994 return rc; 4995 } 4996 4997 rc = config_add_oc( cop, last, e, ca ); 4998 if ( rc != LDAP_CONSTRAINT_VIOLATION ) { 4999 return rc; 5000 } 5001 } 5002 5003 return rc; 5004} 5005 5006/* Parse an LDAP entry into config directives */ 5007static int 5008config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs, 5009 int *renum, Operation *op ) 5010{ 5011 CfEntryInfo *ce, *last = NULL; 5012 ConfigOCs co, *coptr, **colst; 5013 Attribute *a, *oc_at, *soc_at; 5014 int i, ibase = -1, nocs, rc = 0; 5015 struct berval pdn; 5016 ConfigTable *ct; 5017 char *ptr, *log_prefix = op ? op->o_log_prefix : ""; 5018 5019 memset( ca, 0, sizeof(ConfigArgs)); 5020 5021 /* Make sure parent exists and entry does not. But allow 5022 * Databases and Overlays to be inserted. Don't do any 5023 * auto-renumbering if manageDSAit control is present. 5024 */ 5025 ce = config_find_base( cfb->cb_root, &e->e_nname, &last ); 5026 if ( ce ) { 5027 if ( ( op && op->o_managedsait ) || 5028 ( ce->ce_type != Cft_Database && ce->ce_type != Cft_Overlay && 5029 ce->ce_type != Cft_Module ) ) 5030 { 5031 Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: " 5032 "DN=\"%s\" already exists\n", 5033 log_prefix, e->e_name.bv_val, 0 ); 5034 /* global schema ignores all writes */ 5035 if ( ce->ce_type == Cft_Schema && ce->ce_parent->ce_type == Cft_Global ) 5036 return LDAP_COMPARE_TRUE; 5037 return LDAP_ALREADY_EXISTS; 5038 } 5039 } 5040 5041 dnParent( &e->e_nname, &pdn ); 5042 5043 /* If last is NULL, the new entry is the root/suffix entry, 5044 * otherwise last should be the parent. 5045 */ 5046 if ( last && !dn_match( &last->ce_entry->e_nname, &pdn ) ) { 5047 if ( rs ) { 5048 rs->sr_matched = last->ce_entry->e_name.bv_val; 5049 } 5050 Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: " 5051 "DN=\"%s\" not child of DN=\"%s\"\n", 5052 log_prefix, e->e_name.bv_val, 5053 last->ce_entry->e_name.bv_val ); 5054 return LDAP_NO_SUCH_OBJECT; 5055 } 5056 5057 if ( op ) { 5058 /* No parent, must be root. This will never happen... */ 5059 if ( !last && !be_isroot( op ) && !be_shadow_update( op ) ) { 5060 return LDAP_NO_SUCH_OBJECT; 5061 } 5062 5063 if ( last && !access_allowed( op, last->ce_entry, 5064 slap_schema.si_ad_children, NULL, ACL_WADD, NULL ) ) 5065 { 5066 Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: " 5067 "DN=\"%s\" no write access to \"children\" of parent\n", 5068 log_prefix, e->e_name.bv_val, 0 ); 5069 return LDAP_INSUFFICIENT_ACCESS; 5070 } 5071 } 5072 5073 oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass ); 5074 if ( !oc_at ) { 5075 Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: " 5076 "DN=\"%s\" no objectClass\n", 5077 log_prefix, e->e_name.bv_val, 0 ); 5078 return LDAP_OBJECT_CLASS_VIOLATION; 5079 } 5080 5081 soc_at = attr_find( e->e_attrs, slap_schema.si_ad_structuralObjectClass ); 5082 if ( !soc_at ) { 5083 ObjectClass *soc = NULL; 5084 char textbuf[ SLAP_TEXT_BUFLEN ]; 5085 const char *text = textbuf; 5086 5087 /* FIXME: check result */ 5088 rc = structural_class( oc_at->a_nvals, &soc, NULL, 5089 &text, textbuf, sizeof(textbuf), NULL ); 5090 if ( rc != LDAP_SUCCESS ) { 5091 Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: " 5092 "DN=\"%s\" no structural objectClass (%s)\n", 5093 log_prefix, e->e_name.bv_val, text ); 5094 return rc; 5095 } 5096 attr_merge_one( e, slap_schema.si_ad_structuralObjectClass, &soc->soc_cname, NULL ); 5097 soc_at = attr_find( e->e_attrs, slap_schema.si_ad_structuralObjectClass ); 5098 if ( soc_at == NULL ) { 5099 Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: " 5100 "DN=\"%s\" no structural objectClass; " 5101 "unable to merge computed class %s\n", 5102 log_prefix, e->e_name.bv_val, 5103 soc->soc_cname.bv_val ); 5104 return LDAP_OBJECT_CLASS_VIOLATION; 5105 } 5106 5107 Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: " 5108 "DN=\"%s\" no structural objectClass; " 5109 "computed objectClass %s merged\n", 5110 log_prefix, e->e_name.bv_val, 5111 soc->soc_cname.bv_val ); 5112 } 5113 5114 /* Fake the coordinates based on whether we're part of an 5115 * LDAP Add or if reading the config dir 5116 */ 5117 if ( rs ) { 5118 ca->fname = "slapd"; 5119 ca->lineno = 0; 5120 } else { 5121 ca->fname = cfdir.bv_val; 5122 ca->lineno = 1; 5123 } 5124 ca->ca_op = op; 5125 5126 co.co_name = &soc_at->a_nvals[0]; 5127 coptr = avl_find( CfOcTree, &co, CfOc_cmp ); 5128 if ( coptr == NULL ) { 5129 Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: " 5130 "DN=\"%s\" no structural objectClass in configuration table\n", 5131 log_prefix, e->e_name.bv_val, 0 ); 5132 return LDAP_OBJECT_CLASS_VIOLATION; 5133 } 5134 5135 /* Only the root can be Cft_Global, everything else must 5136 * have a parent. Only limited nesting arrangements are allowed. 5137 */ 5138 rc = LDAP_CONSTRAINT_VIOLATION; 5139 if ( coptr->co_type == Cft_Global && !last ) { 5140 cfn = cfb->cb_config; 5141 ca->ca_private = cfn; 5142 ca->be = frontendDB; /* just to get past check_vals */ 5143 rc = LDAP_SUCCESS; 5144 } 5145 5146 colst = count_ocs( oc_at, &nocs ); 5147 5148 /* Check whether the Add is allowed by its parent, and do 5149 * any necessary arg setup 5150 */ 5151 if ( last ) { 5152 rc = config_add_oc( &coptr, last, e, ca ); 5153 if ( rc == LDAP_CONSTRAINT_VIOLATION ) { 5154 for ( i = 0; i<nocs; i++ ) { 5155 /* Already checked these */ 5156 if ( colst[i]->co_oc->soc_kind == LDAP_SCHEMA_STRUCTURAL ) 5157 continue; 5158 if ( colst[i]->co_ldadd && 5159 ( rc = colst[i]->co_ldadd( last, e, ca )) 5160 != LDAP_CONSTRAINT_VIOLATION ) { 5161 coptr = colst[i]; 5162 break; 5163 } 5164 } 5165 } 5166 if ( rc == LDAP_CONSTRAINT_VIOLATION ) { 5167 Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: " 5168 "DN=\"%s\" no structural objectClass add function\n", 5169 log_prefix, e->e_name.bv_val, 0 ); 5170 return LDAP_OBJECT_CLASS_VIOLATION; 5171 } 5172 } 5173 5174 /* Add the entry but don't parse it, we already have its contents */ 5175 if ( rc == LDAP_COMPARE_TRUE ) { 5176 rc = LDAP_SUCCESS; 5177 goto ok; 5178 } 5179 5180 if ( rc != LDAP_SUCCESS ) 5181 goto done_noop; 5182 5183 /* Parse all the values and check for simple syntax errors before 5184 * performing any set actions. 5185 * 5186 * If doing an LDAPadd, check for indexed names and any necessary 5187 * renaming/renumbering. Entries that don't need indexed names are 5188 * ignored. Entries that need an indexed name and arrive without one 5189 * are assigned to the end. Entries that arrive with an index may 5190 * cause the following entries to be renumbered/bumped down. 5191 * 5192 * Note that "pseudo-indexed" entries (cn=Include{xx}, cn=Module{xx}) 5193 * don't allow Adding an entry with an index that's already in use. 5194 * This is flagged as an error (LDAP_ALREADY_EXISTS) up above. 5195 * 5196 * These entries can have auto-assigned indexes (appended to the end) 5197 * but only the other types support auto-renumbering of siblings. 5198 */ 5199 { 5200 rc = check_name_index( last, coptr->co_type, e, rs, renum, 5201 &ibase ); 5202 if ( rc ) { 5203 goto done_noop; 5204 } 5205 if ( renum && *renum && coptr->co_type != Cft_Database && 5206 coptr->co_type != Cft_Overlay ) 5207 { 5208 snprintf( ca->cr_msg, sizeof( ca->cr_msg ), 5209 "operation requires sibling renumbering" ); 5210 rc = LDAP_UNWILLING_TO_PERFORM; 5211 goto done_noop; 5212 } 5213 } 5214 5215 init_config_argv( ca ); 5216 5217 /* Make sure we process attrs in the required order */ 5218 sort_attrs( e, colst, nocs ); 5219 5220 for ( a = e->e_attrs; a; a = a->a_next ) { 5221 if ( a == oc_at ) continue; 5222 ct = config_find_table( colst, nocs, a->a_desc, ca ); 5223 if ( !ct ) continue; /* user data? */ 5224 rc = check_vals( ct, ca, a, 1 ); 5225 if ( rc ) goto done_noop; 5226 } 5227 5228 /* Basic syntax checks are OK. Do the actual settings. */ 5229 for ( a=e->e_attrs; a; a=a->a_next ) { 5230 if ( a == oc_at ) continue; 5231 ct = config_find_table( colst, nocs, a->a_desc, ca ); 5232 if ( !ct ) continue; /* user data? */ 5233 for (i=0; a->a_vals[i].bv_val; i++) { 5234 char *iptr = NULL; 5235 ca->valx = -1; 5236 ca->line = a->a_vals[i].bv_val; 5237 if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED ) { 5238 ptr = strchr( ca->line, '}' ); 5239 if ( ptr ) { 5240 iptr = strchr( ca->line, '{' ); 5241 ca->line = ptr+1; 5242 } 5243 } 5244 if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED_SIB ) { 5245 if ( iptr ) { 5246 ca->valx = strtol( iptr+1, NULL, 0 ); 5247 } 5248 } else { 5249 ca->valx = i; 5250 } 5251 rc = config_parse_add( ct, ca, i ); 5252 if ( rc ) { 5253 rc = LDAP_OTHER; 5254 goto done; 5255 } 5256 } 5257 } 5258ok: 5259 /* Newly added databases and overlays need to be started up */ 5260 if ( CONFIG_ONLINE_ADD( ca )) { 5261 if ( coptr->co_type == Cft_Database ) { 5262 rc = backend_startup_one( ca->be, &ca->reply ); 5263 5264 } else if ( coptr->co_type == Cft_Overlay ) { 5265 if ( ca->bi->bi_db_open ) { 5266 BackendInfo *bi_orig = ca->be->bd_info; 5267 ca->be->bd_info = ca->bi; 5268 rc = ca->bi->bi_db_open( ca->be, &ca->reply ); 5269 ca->be->bd_info = bi_orig; 5270 } 5271 } else if ( ca->cleanup ) { 5272 rc = ca->cleanup( ca ); 5273 } 5274 if ( rc ) { 5275 if (ca->cr_msg[0] == '\0') 5276 snprintf( ca->cr_msg, sizeof( ca->cr_msg ), "<%s> failed startup", ca->argv[0] ); 5277 5278 Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n", 5279 ca->log, ca->cr_msg, ca->argv[1] ); 5280 rc = LDAP_OTHER; 5281 goto done; 5282 } 5283 } 5284 5285 ca->valx = ibase; 5286 ce = ch_calloc( 1, sizeof(CfEntryInfo) ); 5287 ce->ce_parent = last; 5288 ce->ce_entry = entry_dup( e ); 5289 ce->ce_entry->e_private = ce; 5290 ce->ce_type = coptr->co_type; 5291 ce->ce_be = ca->be; 5292 ce->ce_bi = ca->bi; 5293 ce->ce_private = ca->ca_private; 5294 ca->ca_entry = ce->ce_entry; 5295 if ( !last ) { 5296 cfb->cb_root = ce; 5297 } else if ( last->ce_kids ) { 5298 CfEntryInfo *c2, **cprev; 5299 5300 /* Advance to first of this type */ 5301 cprev = &last->ce_kids; 5302 for ( c2 = *cprev; c2 && c2->ce_type < ce->ce_type; ) { 5303 cprev = &c2->ce_sibs; 5304 c2 = c2->ce_sibs; 5305 } 5306 /* Account for the (-1) frontendDB entry */ 5307 if ( ce->ce_type == Cft_Database ) { 5308 if ( ca->be == frontendDB ) 5309 ibase = 0; 5310 else if ( ibase != -1 ) 5311 ibase++; 5312 } 5313 /* Append */ 5314 if ( ibase < 0 ) { 5315 for (c2 = *cprev; c2 && c2->ce_type == ce->ce_type;) { 5316 cprev = &c2->ce_sibs; 5317 c2 = c2->ce_sibs; 5318 } 5319 } else { 5320 /* Insert */ 5321 int i; 5322 for ( i=0; i<ibase; i++ ) { 5323 c2 = *cprev; 5324 cprev = &c2->ce_sibs; 5325 } 5326 } 5327 ce->ce_sibs = *cprev; 5328 *cprev = ce; 5329 } else { 5330 last->ce_kids = ce; 5331 } 5332 5333done: 5334 if ( rc ) { 5335 if ( (coptr->co_type == Cft_Database) && ca->be ) { 5336 if ( ca->be != frontendDB ) 5337 backend_destroy_one( ca->be, 1 ); 5338 } else if ( (coptr->co_type == Cft_Overlay) && ca->bi ) { 5339 overlay_destroy_one( ca->be, (slap_overinst *)ca->bi ); 5340 } else if ( coptr->co_type == Cft_Schema ) { 5341 schema_destroy_one( ca, colst, nocs, last ); 5342 } 5343 } 5344done_noop: 5345 5346 ch_free( ca->argv ); 5347 if ( colst ) ch_free( colst ); 5348 return rc; 5349} 5350 5351#define BIGTMP 10000 5352static int 5353config_rename_add( Operation *op, SlapReply *rs, CfEntryInfo *ce, 5354 int base, int rebase, int max, int use_ldif ) 5355{ 5356 CfEntryInfo *ce2, *ce3, *cetmp = NULL, *cerem = NULL; 5357 ConfigType etype = ce->ce_type; 5358 int count = 0, rc = 0; 5359 5360 /* Reverse ce list */ 5361 for (ce2 = ce->ce_sibs;ce2;ce2 = ce3) { 5362 if (ce2->ce_type != etype) { 5363 cerem = ce2; 5364 break; 5365 } 5366 ce3 = ce2->ce_sibs; 5367 ce2->ce_sibs = cetmp; 5368 cetmp = ce2; 5369 count++; 5370 if ( max && count >= max ) { 5371 cerem = ce3; 5372 break; 5373 } 5374 } 5375 5376 /* Move original to a temp name until increments are done */ 5377 if ( rebase ) { 5378 ce->ce_entry->e_private = NULL; 5379 rc = config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry, 5380 base+BIGTMP, 0, use_ldif ); 5381 ce->ce_entry->e_private = ce; 5382 } 5383 /* start incrementing */ 5384 for (ce2=cetmp; ce2; ce2=ce3) { 5385 ce3 = ce2->ce_sibs; 5386 ce2->ce_sibs = cerem; 5387 cerem = ce2; 5388 if ( rc == 0 ) 5389 rc = config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry, 5390 count+base, 0, use_ldif ); 5391 count--; 5392 } 5393 if ( rebase ) 5394 rc = config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry, 5395 base, 0, use_ldif ); 5396 return rc; 5397} 5398 5399static int 5400config_rename_del( Operation *op, SlapReply *rs, CfEntryInfo *ce, 5401 CfEntryInfo *ce2, int old, int use_ldif ) 5402{ 5403 int count = 0; 5404 5405 /* Renumber original to a temp value */ 5406 ce->ce_entry->e_private = NULL; 5407 config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry, 5408 old+BIGTMP, 0, use_ldif ); 5409 ce->ce_entry->e_private = ce; 5410 5411 /* start decrementing */ 5412 for (; ce2 != ce; ce2=ce2->ce_sibs) { 5413 config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry, 5414 count+old, 0, use_ldif ); 5415 count++; 5416 } 5417 return config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry, 5418 count+old, 0, use_ldif ); 5419} 5420 5421/* Parse an LDAP entry into config directives, then store in underlying 5422 * database. 5423 */ 5424static int 5425config_back_add( Operation *op, SlapReply *rs ) 5426{ 5427 CfBackInfo *cfb; 5428 int renumber; 5429 ConfigArgs ca; 5430 slap_mask_t mask; 5431 5432#ifdef BACKCONFIG_ACCESS_ROOTDNONLY 5433 if ( !be_isroot( op ) ) { 5434 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 5435 goto out; 5436 } 5437#endif 5438 5439 if ( !access_allowed( op, op->ora_e, slap_schema.si_ad_entry, 5440 NULL, ACL_WADD, NULL )) { 5441 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 5442 goto out; 5443 } 5444 5445 /* 5446 * Check for attribute ACL 5447 */ 5448 if ( !acl_check_modlist( op, op->ora_e, op->orm_modlist )) { 5449 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 5450 rs->sr_text = "no write access to attribute"; 5451 goto out; 5452 } 5453 cfb = (CfBackInfo *)op->o_bd->be_private; 5454 5455 /* add opattrs for syncprov */ 5456 { 5457 char textbuf[SLAP_TEXT_BUFLEN]; 5458 size_t textlen = sizeof textbuf; 5459 rs->sr_err = entry_schema_check(op, op->ora_e, NULL, 0, 1, NULL, 5460 &rs->sr_text, textbuf, sizeof( textbuf ) ); 5461 if ( rs->sr_err != LDAP_SUCCESS ) 5462 goto out; 5463 rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 ); 5464 if ( rs->sr_err != LDAP_SUCCESS ) { 5465 Debug( LDAP_DEBUG_TRACE, 5466 LDAP_XSTRING(config_back_add) ": entry failed op attrs add: " 5467 "%s (%d)\n", rs->sr_text, rs->sr_err, 0 ); 5468 goto out; 5469 } 5470 } 5471 5472 if ( op->o_abandon ) { 5473 rs->sr_err = SLAPD_ABANDON; 5474 goto out; 5475 } 5476 ldap_pvt_thread_pool_pause( &connection_pool ); 5477 5478 /* Strategy: 5479 * 1) check for existence of entry 5480 * 2) check for sibling renumbering 5481 * 3) perform internal add 5482 * 4) perform any necessary renumbering 5483 * 5) store entry in underlying database 5484 */ 5485 rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber, op ); 5486 if ( rs->sr_err != LDAP_SUCCESS ) { 5487 rs->sr_text = ca.cr_msg; 5488 goto out2; 5489 } 5490 5491 if ( renumber ) { 5492 CfEntryInfo *ce = ca.ca_entry->e_private; 5493 req_add_s addr = op->oq_add; 5494 op->o_tag = LDAP_REQ_MODRDN; 5495 rs->sr_err = config_rename_add( op, rs, ce, ca.valx, 0, 0, cfb->cb_use_ldif ); 5496 op->o_tag = LDAP_REQ_ADD; 5497 op->oq_add = addr; 5498 if ( rs->sr_err != LDAP_SUCCESS ) { 5499 goto out2; 5500 } 5501 } 5502 5503 if ( cfb->cb_use_ldif ) { 5504 BackendDB *be = op->o_bd; 5505 slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp; 5506 struct berval dn, ndn; 5507 5508 op->o_bd = &cfb->cb_db; 5509 5510 /* Save current rootdn; use the underlying DB's rootdn */ 5511 dn = op->o_dn; 5512 ndn = op->o_ndn; 5513 op->o_dn = op->o_bd->be_rootdn; 5514 op->o_ndn = op->o_bd->be_rootndn; 5515 5516 scp = op->o_callback; 5517 op->o_callback = ≻ 5518 op->o_bd->be_add( op, rs ); 5519 op->o_bd = be; 5520 op->o_callback = scp; 5521 op->o_dn = dn; 5522 op->o_ndn = ndn; 5523 } 5524 5525out2:; 5526 ldap_pvt_thread_pool_resume( &connection_pool ); 5527 5528out:; 5529 { int repl = op->o_dont_replicate; 5530 if ( rs->sr_err == LDAP_COMPARE_TRUE ) { 5531 rs->sr_text = NULL; /* Set after config_add_internal */ 5532 rs->sr_err = LDAP_SUCCESS; 5533 op->o_dont_replicate = 1; 5534 } 5535 send_ldap_result( op, rs ); 5536 op->o_dont_replicate = repl; 5537 } 5538 slap_graduate_commit_csn( op ); 5539 return rs->sr_err; 5540} 5541 5542typedef struct delrec { 5543 struct delrec *next; 5544 int nidx; 5545 int idx[1]; 5546} delrec; 5547 5548static int 5549config_modify_add( ConfigTable *ct, ConfigArgs *ca, AttributeDescription *ad, 5550 int i ) 5551{ 5552 int rc; 5553 5554 ca->valx = -1; 5555 if (ad->ad_type->sat_flags & SLAP_AT_ORDERED && 5556 ca->line[0] == '{' ) 5557 { 5558 char *ptr = strchr( ca->line + 1, '}' ); 5559 if ( ptr ) { 5560 char *next; 5561 5562 ca->valx = strtol( ca->line + 1, &next, 0 ); 5563 if ( next == ca->line + 1 || next[ 0 ] != '}' ) { 5564 return LDAP_OTHER; 5565 } 5566 ca->line = ptr+1; 5567 } 5568 } 5569 rc = config_parse_add( ct, ca, i ); 5570 if ( rc ) { 5571 rc = LDAP_OTHER; 5572 } 5573 return rc; 5574} 5575 5576static int 5577config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs, 5578 ConfigArgs *ca ) 5579{ 5580 int rc = LDAP_UNWILLING_TO_PERFORM; 5581 Modifications *ml; 5582 Entry *e = ce->ce_entry; 5583 Attribute *save_attrs = e->e_attrs, *oc_at, *s, *a; 5584 ConfigTable *ct; 5585 ConfigOCs **colst; 5586 int i, nocs; 5587 char *ptr; 5588 delrec *dels = NULL, *deltail = NULL; 5589 5590 oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass ); 5591 if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION; 5592 5593 for (ml = op->orm_modlist; ml; ml=ml->sml_next) { 5594 if (ml->sml_desc == slap_schema.si_ad_objectClass) 5595 return rc; 5596 } 5597 5598 colst = count_ocs( oc_at, &nocs ); 5599 5600 /* make sure add/del flags are clear; should always be true */ 5601 for ( s = save_attrs; s; s = s->a_next ) { 5602 s->a_flags &= ~(SLAP_ATTR_IXADD|SLAP_ATTR_IXDEL); 5603 } 5604 5605 e->e_attrs = attrs_dup( e->e_attrs ); 5606 5607 init_config_argv( ca ); 5608 ca->be = ce->ce_be; 5609 ca->bi = ce->ce_bi; 5610 ca->ca_private = ce->ce_private; 5611 ca->ca_entry = e; 5612 ca->fname = "slapd"; 5613 ca->ca_op = op; 5614 strcpy( ca->log, "back-config" ); 5615 5616 for (ml = op->orm_modlist; ml; ml=ml->sml_next) { 5617 ct = config_find_table( colst, nocs, ml->sml_desc, ca ); 5618 switch (ml->sml_op) { 5619 case LDAP_MOD_DELETE: 5620 case LDAP_MOD_REPLACE: 5621 case SLAP_MOD_SOFTDEL: 5622 { 5623 BerVarray vals = NULL, nvals = NULL; 5624 int *idx = NULL; 5625 if ( ct && ( ct->arg_type & ARG_NO_DELETE )) { 5626 rc = LDAP_OTHER; 5627 snprintf(ca->cr_msg, sizeof(ca->cr_msg), "cannot delete %s", 5628 ml->sml_desc->ad_cname.bv_val ); 5629 goto out_noop; 5630 } 5631 if ( ml->sml_op == LDAP_MOD_REPLACE ) { 5632 vals = ml->sml_values; 5633 nvals = ml->sml_nvalues; 5634 ml->sml_values = NULL; 5635 ml->sml_nvalues = NULL; 5636 } 5637 /* If we're deleting by values, remember the indexes of the 5638 * values we deleted. 5639 */ 5640 if ( ct && ml->sml_values ) { 5641 delrec *d; 5642 i = ml->sml_numvals; 5643 d = ch_malloc( sizeof(delrec) + (i - 1)* sizeof(int)); 5644 d->nidx = i; 5645 d->next = NULL; 5646 if ( dels ) { 5647 deltail->next = d; 5648 } else { 5649 dels = d; 5650 } 5651 deltail = d; 5652 idx = d->idx; 5653 } 5654 rc = modify_delete_vindex(e, &ml->sml_mod, 5655 get_permissiveModify(op), 5656 &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg), idx ); 5657 if ( ml->sml_op == LDAP_MOD_REPLACE ) { 5658 ml->sml_values = vals; 5659 ml->sml_nvalues = nvals; 5660 } 5661 if ( rc == LDAP_NO_SUCH_ATTRIBUTE && ml->sml_op == SLAP_MOD_SOFTDEL ) 5662 { 5663 rc = LDAP_SUCCESS; 5664 } 5665 /* FIXME: check rc before fallthru? */ 5666 if ( !vals ) 5667 break; 5668 } 5669 /* FALLTHRU: LDAP_MOD_REPLACE && vals */ 5670 5671 case SLAP_MOD_ADD_IF_NOT_PRESENT: 5672 if ( ml->sml_op == SLAP_MOD_ADD_IF_NOT_PRESENT 5673 && attr_find( e->e_attrs, ml->sml_desc ) ) 5674 { 5675 rc = LDAP_SUCCESS; 5676 break; 5677 } 5678 5679 case LDAP_MOD_ADD: 5680 case SLAP_MOD_SOFTADD: { 5681 int mop = ml->sml_op; 5682 int navals = -1; 5683 ml->sml_op = LDAP_MOD_ADD; 5684 if ( ct ) { 5685 if ( ct->arg_type & ARG_NO_INSERT ) { 5686 Attribute *a = attr_find( e->e_attrs, ml->sml_desc ); 5687 if ( a ) { 5688 navals = a->a_numvals; 5689 } 5690 } 5691 for ( i=0; !BER_BVISNULL( &ml->sml_values[i] ); i++ ) { 5692 if ( ml->sml_values[i].bv_val[0] == '{' && 5693 navals >= 0 ) 5694 { 5695 char *next, *val = ml->sml_values[i].bv_val + 1; 5696 int j; 5697 5698 j = strtol( val, &next, 0 ); 5699 if ( next == val || next[ 0 ] != '}' || j < navals ) { 5700 rc = LDAP_OTHER; 5701 snprintf(ca->cr_msg, sizeof(ca->cr_msg), "cannot insert %s", 5702 ml->sml_desc->ad_cname.bv_val ); 5703 goto out_noop; 5704 } 5705 } 5706 rc = check_vals( ct, ca, ml, 0 ); 5707 if ( rc ) goto out_noop; 5708 } 5709 } 5710 rc = modify_add_values(e, &ml->sml_mod, 5711 get_permissiveModify(op), 5712 &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg) ); 5713 5714 /* If value already exists, show success here 5715 * and ignore this operation down below. 5716 */ 5717 if ( mop == SLAP_MOD_SOFTADD ) { 5718 if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) 5719 rc = LDAP_SUCCESS; 5720 else 5721 mop = LDAP_MOD_ADD; 5722 } 5723 ml->sml_op = mop; 5724 break; 5725 } 5726 5727 break; 5728 case LDAP_MOD_INCREMENT: /* FIXME */ 5729 break; 5730 default: 5731 break; 5732 } 5733 if(rc != LDAP_SUCCESS) break; 5734 } 5735 5736 if ( rc == LDAP_SUCCESS) { 5737 /* check that the entry still obeys the schema */ 5738 rc = entry_schema_check(op, e, NULL, 0, 0, NULL, 5739 &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg) ); 5740 } 5741 if ( rc ) goto out_noop; 5742 5743 /* Basic syntax checks are OK. Do the actual settings. */ 5744 for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) { 5745 ct = config_find_table( colst, nocs, ml->sml_desc, ca ); 5746 if ( !ct ) continue; 5747 5748 s = attr_find( save_attrs, ml->sml_desc ); 5749 a = attr_find( e->e_attrs, ml->sml_desc ); 5750 5751 switch (ml->sml_op) { 5752 case LDAP_MOD_DELETE: 5753 case LDAP_MOD_REPLACE: { 5754 BerVarray vals = NULL, nvals = NULL; 5755 delrec *d = NULL; 5756 5757 if ( ml->sml_op == LDAP_MOD_REPLACE ) { 5758 vals = ml->sml_values; 5759 nvals = ml->sml_nvalues; 5760 ml->sml_values = NULL; 5761 ml->sml_nvalues = NULL; 5762 } 5763 5764 if ( ml->sml_values ) 5765 d = dels; 5766 5767 /* If we didn't delete the whole attribute */ 5768 if ( ml->sml_values && a ) { 5769 struct berval *mvals; 5770 int j; 5771 5772 if ( ml->sml_nvalues ) 5773 mvals = ml->sml_nvalues; 5774 else 5775 mvals = ml->sml_values; 5776 5777 /* use the indexes we saved up above */ 5778 for (i=0; i < d->nidx; i++) { 5779 struct berval bv = *mvals++; 5780 if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED && 5781 bv.bv_val[0] == '{' ) { 5782 ptr = strchr( bv.bv_val, '}' ) + 1; 5783 bv.bv_len -= ptr - bv.bv_val; 5784 bv.bv_val = ptr; 5785 } 5786 ca->line = bv.bv_val; 5787 ca->valx = d->idx[i]; 5788 config_parse_vals(ct, ca, d->idx[i] ); 5789 rc = config_del_vals( ct, ca ); 5790 if ( rc != LDAP_SUCCESS ) break; 5791 if ( s ) 5792 s->a_flags |= SLAP_ATTR_IXDEL; 5793 for (j=i+1; j < d->nidx; j++) 5794 if ( d->idx[j] >d->idx[i] ) 5795 d->idx[j]--; 5796 } 5797 } else { 5798 ca->valx = -1; 5799 ca->line = NULL; 5800 ca->argc = 1; 5801 rc = config_del_vals( ct, ca ); 5802 if ( rc ) rc = LDAP_OTHER; 5803 if ( s ) 5804 s->a_flags |= SLAP_ATTR_IXDEL; 5805 } 5806 if ( ml->sml_values ) { 5807 d = d->next; 5808 ch_free( dels ); 5809 dels = d; 5810 } 5811 if ( ml->sml_op == LDAP_MOD_REPLACE ) { 5812 ml->sml_values = vals; 5813 ml->sml_nvalues = nvals; 5814 } 5815 if ( !vals || rc != LDAP_SUCCESS ) 5816 break; 5817 } 5818 /* FALLTHRU: LDAP_MOD_REPLACE && vals */ 5819 5820 case LDAP_MOD_ADD: 5821 if ( !a ) 5822 break; 5823 for (i=0; ml->sml_values[i].bv_val; i++) { 5824 ca->line = ml->sml_values[i].bv_val; 5825 ca->valx = -1; 5826 rc = config_modify_add( ct, ca, ml->sml_desc, i ); 5827 if ( rc ) 5828 goto out; 5829 a->a_flags |= SLAP_ATTR_IXADD; 5830 } 5831 break; 5832 } 5833 } 5834 5835out: 5836 /* Undo for a failed operation */ 5837 if ( rc != LDAP_SUCCESS ) { 5838 ConfigReply msg = ca->reply; 5839 for ( s = save_attrs; s; s = s->a_next ) { 5840 if ( s->a_flags & SLAP_ATTR_IXDEL ) { 5841 s->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD); 5842 ct = config_find_table( colst, nocs, s->a_desc, ca ); 5843 a = attr_find( e->e_attrs, s->a_desc ); 5844 if ( a ) { 5845 /* clear the flag so the add check below will skip it */ 5846 a->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD); 5847 ca->valx = -1; 5848 ca->line = NULL; 5849 ca->argc = 1; 5850 config_del_vals( ct, ca ); 5851 } 5852 for ( i=0; !BER_BVISNULL( &s->a_vals[i] ); i++ ) { 5853 ca->line = s->a_vals[i].bv_val; 5854 ca->valx = -1; 5855 config_modify_add( ct, ca, s->a_desc, i ); 5856 } 5857 } 5858 } 5859 for ( a = e->e_attrs; a; a = a->a_next ) { 5860 if ( a->a_flags & SLAP_ATTR_IXADD ) { 5861 ct = config_find_table( colst, nocs, a->a_desc, ca ); 5862 ca->valx = -1; 5863 ca->line = NULL; 5864 ca->argc = 1; 5865 config_del_vals( ct, ca ); 5866 s = attr_find( save_attrs, a->a_desc ); 5867 if ( s ) { 5868 s->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD); 5869 for ( i=0; !BER_BVISNULL( &s->a_vals[i] ); i++ ) { 5870 ca->line = s->a_vals[i].bv_val; 5871 ca->valx = -1; 5872 config_modify_add( ct, ca, s->a_desc, i ); 5873 } 5874 } 5875 } 5876 } 5877 ca->reply = msg; 5878 } 5879 5880 if ( ca->cleanup ) 5881 ca->cleanup( ca ); 5882out_noop: 5883 if ( rc == LDAP_SUCCESS ) { 5884 attrs_free( save_attrs ); 5885 rs->sr_text = NULL; 5886 } else { 5887 attrs_free( e->e_attrs ); 5888 e->e_attrs = save_attrs; 5889 } 5890 ch_free( ca->argv ); 5891 if ( colst ) ch_free( colst ); 5892 while( dels ) { 5893 deltail = dels->next; 5894 ch_free( dels ); 5895 dels = deltail; 5896 } 5897 5898 return rc; 5899} 5900 5901static int 5902config_back_modify( Operation *op, SlapReply *rs ) 5903{ 5904 CfBackInfo *cfb; 5905 CfEntryInfo *ce, *last; 5906 Modifications *ml; 5907 ConfigArgs ca = {0}; 5908 struct berval rdn; 5909 char *ptr; 5910 AttributeDescription *rad = NULL; 5911 int do_pause = 1; 5912 slap_mask_t mask; 5913 5914#ifdef BACKCONFIG_ACCESS_ROOTDNONLY 5915 if ( !be_isroot( op ) ) { 5916 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 5917 goto out; 5918 } 5919#endif 5920 5921 cfb = (CfBackInfo *)op->o_bd->be_private; 5922 5923 ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last ); 5924 if ( !ce ) { 5925 if ( last ) 5926 rs->sr_matched = last->ce_entry->e_name.bv_val; 5927 rs->sr_err = LDAP_NO_SUCH_OBJECT; 5928 goto out; 5929 } 5930 5931 if ( !access_allowed_mask( op, ce->ce_entry, slap_schema.si_ad_entry, 5932 NULL, ACL_WRITE, NULL, &mask ) ) 5933 { 5934 Debug(LDAP_DEBUG_ACL, "config_back_modify LDAP_INSUFFICIENT_ACCESS\n", 0, 0, 0 ); 5935 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 5936 goto out; 5937 } 5938 5939 if ( !acl_check_modlist( op, ce->ce_entry, op->orm_modlist )) { 5940 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 5941 goto out; 5942 } 5943 5944 /* Get type of RDN */ 5945 rdn = ce->ce_entry->e_nname; 5946 ptr = strchr( rdn.bv_val, '=' ); 5947 rdn.bv_len = ptr - rdn.bv_val; 5948 rs->sr_err = slap_bv2ad( &rdn, &rad, &rs->sr_text ); 5949 if ( rs->sr_err != LDAP_SUCCESS ) { 5950 goto out; 5951 } 5952 5953 /* Some basic validation... */ 5954 for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) { 5955 /* Don't allow Modify of RDN; must use ModRdn for that. */ 5956 if ( ml->sml_desc == rad ) { 5957 rs->sr_err = LDAP_NOT_ALLOWED_ON_RDN; 5958 rs->sr_text = "Use modrdn to change the entry name"; 5959 goto out; 5960 } 5961 /* Internal update of contextCSN? */ 5962 if ( ml->sml_desc == slap_schema.si_ad_contextCSN && op->o_conn->c_conn_idx == -1 ) { 5963 do_pause = 0; 5964 break; 5965 } 5966 } 5967 5968 slap_mods_opattrs( op, &op->orm_modlist, 1 ); 5969 5970#ifndef __APPLE__ 5971 if ( do_pause ) { 5972 if ( op->o_abandon ) { 5973 rs->sr_err = SLAPD_ABANDON; 5974 goto out; 5975 } 5976 ldap_pvt_thread_pool_pause( &connection_pool ); 5977 } 5978#endif 5979 5980 /* Strategy: 5981 * 1) perform the Modify on the cached Entry. 5982 * 2) verify that the Entry still satisfies the schema. 5983 * 3) perform the individual config operations. 5984 * 4) store Modified entry in underlying LDIF backend. 5985 */ 5986 rs->sr_err = config_modify_internal( ce, op, rs, &ca ); 5987 if ( rs->sr_err ) { 5988 rs->sr_text = ca.cr_msg; 5989 } else if ( cfb->cb_use_ldif ) { 5990 BackendDB *be = op->o_bd; 5991 slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp; 5992 struct berval dn, ndn; 5993 5994 op->o_bd = &cfb->cb_db; 5995 5996 dn = op->o_dn; 5997 ndn = op->o_ndn; 5998 op->o_dn = op->o_bd->be_rootdn; 5999 op->o_ndn = op->o_bd->be_rootndn; 6000 6001 scp = op->o_callback; 6002 op->o_callback = ≻ 6003 op->o_bd->be_modify( op, rs ); 6004 op->o_bd = be; 6005 op->o_callback = scp; 6006 op->o_dn = dn; 6007 op->o_ndn = ndn; 6008 } 6009 6010#ifndef __APPLE__ 6011 if ( do_pause ) 6012 ldap_pvt_thread_pool_resume( &connection_pool ); 6013#endif 6014out: 6015 send_ldap_result( op, rs ); 6016 slap_graduate_commit_csn( op ); 6017 return rs->sr_err; 6018} 6019 6020static int 6021config_back_modrdn( Operation *op, SlapReply *rs ) 6022{ 6023 CfBackInfo *cfb; 6024 CfEntryInfo *ce, *last; 6025 struct berval rdn; 6026 int ixold, ixnew; 6027 slap_mask_t mask; 6028 6029#ifdef BACKCONFIG_ACCESS_ROOTDNONLY 6030 if ( !be_isroot( op ) ) { 6031 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 6032 goto out; 6033 } 6034#endif 6035 6036 cfb = (CfBackInfo *)op->o_bd->be_private; 6037 6038 ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last ); 6039 if ( !ce ) { 6040 if ( last ) 6041 rs->sr_matched = last->ce_entry->e_name.bv_val; 6042 rs->sr_err = LDAP_NO_SUCH_OBJECT; 6043 goto out; 6044 } 6045 if ( !access_allowed( op, ce->ce_entry, slap_schema.si_ad_entry, 6046 NULL, ACL_WRITE, NULL )) { 6047 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 6048 goto out; 6049 } 6050 { Entry *parent; 6051 if ( ce->ce_parent ) 6052 parent = ce->ce_parent->ce_entry; 6053 else 6054 parent = (Entry *)&slap_entry_root; 6055 if ( !access_allowed( op, parent, slap_schema.si_ad_children, 6056 NULL, ACL_WRITE, NULL )) { 6057 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 6058 goto out; 6059 } 6060 } 6061 6062 /* We don't allow moving objects to new parents. 6063 * Generally we only allow reordering a set of ordered entries. 6064 */ 6065 if ( op->orr_newSup ) { 6066 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 6067 goto out; 6068 } 6069 6070 /* If newRDN == oldRDN, quietly succeed */ 6071 dnRdn( &op->o_req_ndn, &rdn ); 6072 if ( dn_match( &rdn, &op->orr_nnewrdn )) { 6073 rs->sr_err = LDAP_SUCCESS; 6074 goto out; 6075 } 6076 6077 /* Current behavior, subject to change as needed: 6078 * 6079 * For backends and overlays, we only allow renumbering. 6080 * For schema, we allow renaming with the same number. 6081 * Otherwise, the op is not allowed. 6082 */ 6083 6084 if ( ce->ce_type == Cft_Schema ) { 6085 char *ptr1, *ptr2; 6086 int len; 6087 6088 /* Can't alter the main cn=schema entry */ 6089 if ( ce->ce_parent->ce_type == Cft_Global ) { 6090 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 6091 rs->sr_text = "renaming not allowed for this entry"; 6092 goto out; 6093 } 6094 6095 /* We could support this later if desired */ 6096 ptr1 = ber_bvchr( &rdn, '}' ); 6097 ptr2 = ber_bvchr( &op->orr_newrdn, '}' ); 6098 len = ptr1 - rdn.bv_val; 6099 if ( len != ptr2 - op->orr_newrdn.bv_val || 6100 strncmp( rdn.bv_val, op->orr_newrdn.bv_val, len )) { 6101 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 6102 rs->sr_text = "schema reordering not supported"; 6103 goto out; 6104 } 6105 } else if ( ce->ce_type == Cft_Database || 6106 ce->ce_type == Cft_Overlay ) { 6107 char *ptr1, *ptr2, *iptr1, *iptr2; 6108 int len1, len2; 6109 6110 iptr2 = ber_bvchr( &op->orr_newrdn, '=' ) + 1; 6111 if ( *iptr2 != '{' ) { 6112 rs->sr_err = LDAP_NAMING_VIOLATION; 6113 rs->sr_text = "new ordering index is required"; 6114 goto out; 6115 } 6116 iptr2++; 6117 iptr1 = ber_bvchr( &rdn, '{' ) + 1; 6118 ptr1 = ber_bvchr( &rdn, '}' ); 6119 ptr2 = ber_bvchr( &op->orr_newrdn, '}' ); 6120 if ( !ptr2 ) { 6121 rs->sr_err = LDAP_NAMING_VIOLATION; 6122 rs->sr_text = "new ordering index is required"; 6123 goto out; 6124 } 6125 6126 len1 = ptr1 - rdn.bv_val; 6127 len2 = ptr2 - op->orr_newrdn.bv_val; 6128 6129 if ( rdn.bv_len - len1 != op->orr_newrdn.bv_len - len2 || 6130 strncmp( ptr1, ptr2, rdn.bv_len - len1 )) { 6131 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 6132 rs->sr_text = "changing database/overlay type not allowed"; 6133 goto out; 6134 } 6135 ixold = strtol( iptr1, NULL, 0 ); 6136 ixnew = strtol( iptr2, &ptr1, 0 ); 6137 if ( ptr1 != ptr2 || ixold < 0 || ixnew < 0 ) { 6138 rs->sr_err = LDAP_NAMING_VIOLATION; 6139 goto out; 6140 } 6141 /* config DB is always 0, cannot be changed */ 6142 if ( ce->ce_type == Cft_Database && ( ixold == 0 || ixnew == 0 )) { 6143 rs->sr_err = LDAP_CONSTRAINT_VIOLATION; 6144 goto out; 6145 } 6146 } else { 6147 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 6148 rs->sr_text = "renaming not supported for this entry"; 6149 goto out; 6150 } 6151 6152 if ( op->o_abandon ) { 6153 rs->sr_err = SLAPD_ABANDON; 6154 goto out; 6155 } 6156 ldap_pvt_thread_pool_pause( &connection_pool ); 6157 6158 if ( ce->ce_type == Cft_Schema ) { 6159 req_modrdn_s modr = op->oq_modrdn; 6160 struct berval rdn; 6161 Attribute *a; 6162 rs->sr_err = config_rename_attr( rs, ce->ce_entry, &rdn, &a ); 6163 if ( rs->sr_err == LDAP_SUCCESS ) { 6164 rs->sr_err = config_rename_one( op, rs, ce->ce_entry, 6165 ce->ce_parent, a, &op->orr_newrdn, &op->orr_nnewrdn, 6166 cfb->cb_use_ldif ); 6167 } 6168 op->oq_modrdn = modr; 6169 } else { 6170 CfEntryInfo *ce2, *cebase, **cprev, **cbprev, *ceold; 6171 req_modrdn_s modr = op->oq_modrdn; 6172 int i; 6173 6174 /* Advance to first of this type */ 6175 cprev = &ce->ce_parent->ce_kids; 6176 for ( ce2 = *cprev; ce2 && ce2->ce_type != ce->ce_type; ) { 6177 cprev = &ce2->ce_sibs; 6178 ce2 = ce2->ce_sibs; 6179 } 6180 /* Skip the -1 entry */ 6181 if ( ce->ce_type == Cft_Database ) { 6182 cprev = &ce2->ce_sibs; 6183 ce2 = ce2->ce_sibs; 6184 } 6185 cebase = ce2; 6186 cbprev = cprev; 6187 6188 /* Remove from old slot */ 6189 for ( ce2 = *cprev; ce2 && ce2 != ce; ce2 = ce2->ce_sibs ) 6190 cprev = &ce2->ce_sibs; 6191 *cprev = ce->ce_sibs; 6192 ceold = ce->ce_sibs; 6193 6194 /* Insert into new slot */ 6195 cprev = cbprev; 6196 for ( i=0; i<ixnew; i++ ) { 6197 ce2 = *cprev; 6198 if ( !ce2 ) 6199 break; 6200 cprev = &ce2->ce_sibs; 6201 } 6202 ce->ce_sibs = *cprev; 6203 *cprev = ce; 6204 6205 ixnew = i; 6206 6207 /* NOTE: These should be encoded in the OC tables, not inline here */ 6208 if ( ce->ce_type == Cft_Database ) 6209 backend_db_move( ce->ce_be, ixnew ); 6210 else if ( ce->ce_type == Cft_Overlay ) 6211 overlay_move( ce->ce_be, (slap_overinst *)ce->ce_bi, ixnew ); 6212 6213 if ( ixold < ixnew ) { 6214 rs->sr_err = config_rename_del( op, rs, ce, ceold, ixold, 6215 cfb->cb_use_ldif ); 6216 } else { 6217 rs->sr_err = config_rename_add( op, rs, ce, ixnew, 1, 6218 ixold - ixnew, cfb->cb_use_ldif ); 6219 } 6220 op->oq_modrdn = modr; 6221 } 6222 6223 ldap_pvt_thread_pool_resume( &connection_pool ); 6224out: 6225 send_ldap_result( op, rs ); 6226 return rs->sr_err; 6227} 6228 6229static int 6230config_back_delete( Operation *op, SlapReply *rs ) 6231{ 6232#ifdef SLAP_CONFIG_DELETE 6233 CfBackInfo *cfb; 6234 CfEntryInfo *ce, *last, *ce2; 6235 6236 slap_mask_t mask; 6237 6238 cfb = (CfBackInfo *)op->o_bd->be_private; 6239 6240 ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last ); 6241 if ( !ce ) { 6242 if ( last ) 6243 rs->sr_matched = last->ce_entry->e_name.bv_val; 6244 rs->sr_err = LDAP_NO_SUCH_OBJECT; 6245 } else if ( ce->ce_kids ) { 6246 rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF; 6247 } else if ( op->o_abandon ) { 6248 rs->sr_err = SLAPD_ABANDON; 6249 } else if ( ce->ce_type == Cft_Overlay || 6250 ce->ce_type == Cft_Database || 6251 ce->ce_type == Cft_Misc ){ 6252 char *iptr; 6253 int count, ixold; 6254 6255 ldap_pvt_thread_pool_pause( &connection_pool ); 6256 6257 if ( ce->ce_type == Cft_Overlay ){ 6258 overlay_remove( ce->ce_be, (slap_overinst *)ce->ce_bi, op ); 6259 } else if ( ce->ce_type == Cft_Misc ) { 6260 /* 6261 * only Cft_Misc objects that have a co_lddel handler set in 6262 * the ConfigOCs struct can be deleted. This code also 6263 * assumes that the entry can be only have one objectclass 6264 * with co_type == Cft_Misc 6265 */ 6266 ConfigOCs co, *coptr; 6267 Attribute *oc_at; 6268 int i; 6269 6270 oc_at = attr_find( ce->ce_entry->e_attrs, 6271 slap_schema.si_ad_objectClass ); 6272 if ( !oc_at ) { 6273 rs->sr_err = LDAP_OTHER; 6274 rs->sr_text = "objectclass not found"; 6275 ldap_pvt_thread_pool_resume( &connection_pool ); 6276 goto out; 6277 } 6278 for ( i=0; !BER_BVISNULL(&oc_at->a_nvals[i]); i++ ) { 6279 co.co_name = &oc_at->a_nvals[i]; 6280 coptr = avl_find( CfOcTree, &co, CfOc_cmp ); 6281 if ( coptr == NULL || coptr->co_type != Cft_Misc ) { 6282 continue; 6283 } 6284 if ( ! coptr->co_lddel || coptr->co_lddel( ce, op ) ){ 6285 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 6286 if ( ! coptr->co_lddel ) { 6287 rs->sr_text = "No delete handler found"; 6288 } else { 6289 rs->sr_err = LDAP_OTHER; 6290 /* FIXME: We should return a helpful error message 6291 * here */ 6292 } 6293 ldap_pvt_thread_pool_resume( &connection_pool ); 6294 goto out; 6295 } 6296 break; 6297 } 6298 } else if (ce->ce_type == Cft_Database ) { 6299 if ( ce->ce_be == frontendDB || ce->ce_be == op->o_bd ){ 6300 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 6301 rs->sr_text = "Cannot delete config or frontend database"; 6302 ldap_pvt_thread_pool_resume( &connection_pool ); 6303 goto out; 6304 } 6305 if ( ce->ce_be->bd_info->bi_db_close ) { 6306 ce->ce_be->bd_info->bi_db_close( ce->ce_be, NULL ); 6307 } 6308 backend_destroy_one( ce->ce_be, 1); 6309 } 6310 6311 /* remove CfEntryInfo from the siblings list */ 6312 if ( ce->ce_parent->ce_kids == ce ) { 6313 ce->ce_parent->ce_kids = ce->ce_sibs; 6314 } else { 6315 for ( ce2 = ce->ce_parent->ce_kids ; ce2; ce2 = ce2->ce_sibs ) { 6316 if ( ce2->ce_sibs == ce ) { 6317 ce2->ce_sibs = ce->ce_sibs; 6318 break; 6319 } 6320 } 6321 } 6322 6323 /* remove from underlying database */ 6324 if ( cfb->cb_use_ldif ) { 6325 BackendDB *be = op->o_bd; 6326 slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp; 6327 struct berval dn, ndn, req_dn, req_ndn; 6328 6329 op->o_bd = &cfb->cb_db; 6330 6331 dn = op->o_dn; 6332 ndn = op->o_ndn; 6333 req_dn = op->o_req_dn; 6334 req_ndn = op->o_req_ndn; 6335 6336 op->o_dn = op->o_bd->be_rootdn; 6337 op->o_ndn = op->o_bd->be_rootndn; 6338 op->o_req_dn = ce->ce_entry->e_name; 6339 op->o_req_ndn = ce->ce_entry->e_nname; 6340 6341 scp = op->o_callback; 6342 op->o_callback = ≻ 6343 op->o_bd->be_delete( op, rs ); 6344 op->o_bd = be; 6345 op->o_callback = scp; 6346 op->o_dn = dn; 6347 op->o_ndn = ndn; 6348 op->o_req_dn = req_dn; 6349 op->o_req_ndn = req_ndn; 6350 } 6351 6352 /* renumber siblings */ 6353 iptr = ber_bvchr( &op->o_req_ndn, '{' ) + 1; 6354 ixold = strtol( iptr, NULL, 0 ); 6355 for (ce2 = ce->ce_sibs, count=0; ce2; ce2=ce2->ce_sibs) { 6356 config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry, 6357 count+ixold, 0, cfb->cb_use_ldif ); 6358 count++; 6359 } 6360 6361 ce->ce_entry->e_private=NULL; 6362 entry_free(ce->ce_entry); 6363 ch_free(ce); 6364 ldap_pvt_thread_pool_resume( &connection_pool ); 6365 } else { 6366 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 6367 } 6368out: 6369#else 6370 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 6371#endif /* SLAP_CONFIG_DELETE */ 6372 send_ldap_result( op, rs ); 6373 return rs->sr_err; 6374} 6375 6376static int 6377config_back_search( Operation *op, SlapReply *rs ) 6378{ 6379 CfBackInfo *cfb; 6380 CfEntryInfo *ce, *last; 6381 slap_mask_t mask; 6382#ifdef BACKCONFIG_ACCESS_ROOTDNONLY 6383 if ( !be_isroot( op ) ) { 6384 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 6385 goto out; 6386 } 6387#endif 6388 cfb = (CfBackInfo *)op->o_bd->be_private; 6389 6390 ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last ); 6391 if ( !ce ) { 6392 if ( last ) 6393 rs->sr_matched = last->ce_entry->e_name.bv_val; 6394 rs->sr_err = LDAP_NO_SUCH_OBJECT; 6395 goto out; 6396 } 6397 if ( !access_allowed_mask( op, ce->ce_entry, slap_schema.si_ad_entry, NULL, 6398 ACL_SEARCH, NULL, &mask )) 6399 { 6400 if ( !ACL_GRANT( mask, ACL_DISCLOSE )) { 6401 rs->sr_err = LDAP_NO_SUCH_OBJECT; 6402 } else { 6403 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 6404 } 6405 goto out; 6406 } 6407 switch ( op->ors_scope ) { 6408 case LDAP_SCOPE_BASE: 6409 case LDAP_SCOPE_SUBTREE: 6410 rs->sr_err = config_send( op, rs, ce, 0 ); 6411 break; 6412 6413 case LDAP_SCOPE_ONELEVEL: 6414 for (ce = ce->ce_kids; ce; ce=ce->ce_sibs) { 6415 rs->sr_err = config_send( op, rs, ce, 1 ); 6416 if ( rs->sr_err ) { 6417 break; 6418 } 6419 } 6420 break; 6421 } 6422 6423out: 6424 send_ldap_result( op, rs ); 6425 return rs->sr_err; 6426} 6427 6428/* no-op, we never free entries */ 6429int config_entry_release( 6430 Operation *op, 6431 Entry *e, 6432 int rw ) 6433{ 6434 if ( !e->e_private ) { 6435 entry_free( e ); 6436 } 6437 return LDAP_SUCCESS; 6438} 6439 6440/* return LDAP_SUCCESS IFF we can retrieve the specified entry. 6441 */ 6442int config_back_entry_get( 6443 Operation *op, 6444 struct berval *ndn, 6445 ObjectClass *oc, 6446 AttributeDescription *at, 6447 int rw, 6448 Entry **ent ) 6449{ 6450 CfBackInfo *cfb; 6451 CfEntryInfo *ce, *last; 6452 int rc = LDAP_NO_SUCH_OBJECT; 6453 6454 cfb = (CfBackInfo *)op->o_bd->be_private; 6455 6456 ce = config_find_base( cfb->cb_root, ndn, &last ); 6457 if ( ce ) { 6458 *ent = ce->ce_entry; 6459 if ( *ent ) { 6460 rc = LDAP_SUCCESS; 6461 if ( oc && !is_entry_objectclass_or_sub( *ent, oc ) ) { 6462 rc = LDAP_NO_SUCH_ATTRIBUTE; 6463 *ent = NULL; 6464 } 6465 } 6466 } 6467 6468 return rc; 6469} 6470 6471static int 6472config_build_attrs( Entry *e, AttributeType **at, AttributeDescription *ad, 6473 ConfigTable *ct, ConfigArgs *c ) 6474{ 6475 int i, rc; 6476 6477 for (; at && *at; at++) { 6478 /* Skip the naming attr */ 6479 if ((*at)->sat_ad == ad || (*at)->sat_ad == slap_schema.si_ad_cn ) 6480 continue; 6481 for (i=0;ct[i].name;i++) { 6482 if (ct[i].ad == (*at)->sat_ad) { 6483 rc = config_get_vals(&ct[i], c); 6484 /* NOTE: tolerate that config_get_vals() 6485 * returns success with no values */ 6486 if (rc == LDAP_SUCCESS && c->rvalue_vals != NULL ) { 6487 if ( c->rvalue_nvals ) 6488 rc = attr_merge(e, ct[i].ad, c->rvalue_vals, 6489 c->rvalue_nvals); 6490 else { 6491 slap_syntax_validate_func *validate = 6492 ct[i].ad->ad_type->sat_syntax->ssyn_validate; 6493 if ( validate ) { 6494 int j; 6495 for ( j=0; c->rvalue_vals[j].bv_val; j++ ) { 6496 rc = ordered_value_validate( ct[i].ad, 6497 &c->rvalue_vals[j], LDAP_MOD_ADD ); 6498 if ( rc ) { 6499 Debug( LDAP_DEBUG_ANY, 6500 "config_build_attrs: error %d on %s value #%d\n", 6501 rc, ct[i].ad->ad_cname.bv_val, j ); 6502 return rc; 6503 } 6504 } 6505 } 6506 6507 rc = attr_merge_normalize(e, ct[i].ad, 6508 c->rvalue_vals, NULL); 6509 } 6510 ber_bvarray_free( c->rvalue_nvals ); 6511 ber_bvarray_free( c->rvalue_vals ); 6512 if ( rc ) { 6513 Debug( LDAP_DEBUG_ANY, 6514 "config_build_attrs: error %d on %s\n", 6515 rc, ct[i].ad->ad_cname.bv_val, 0 ); 6516 return rc; 6517 } 6518 } 6519 break; 6520 } 6521 } 6522 } 6523 return 0; 6524} 6525 6526/* currently (2010) does not access rs except possibly writing rs->sr_err */ 6527 6528Entry * 6529config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent, 6530 ConfigArgs *c, struct berval *rdn, ConfigOCs *main, ConfigOCs *extra ) 6531{ 6532 Entry *e = entry_alloc(); 6533 CfEntryInfo *ce = ch_calloc( 1, sizeof(CfEntryInfo) ); 6534 struct berval val; 6535 struct berval ad_name; 6536 AttributeDescription *ad = NULL; 6537 int rc; 6538 char *ptr; 6539 const char *text = ""; 6540 Attribute *oc_at; 6541 struct berval pdn; 6542 ObjectClass *oc; 6543 CfEntryInfo *ceprev = NULL; 6544 6545 Debug( LDAP_DEBUG_TRACE, "config_build_entry: \"%s\"\n", rdn->bv_val, 0, 0); 6546 e->e_private = ce; 6547 ce->ce_entry = e; 6548 ce->ce_type = main->co_type; 6549 ce->ce_parent = parent; 6550 if ( parent ) { 6551 pdn = parent->ce_entry->e_nname; 6552 if ( parent->ce_kids && parent->ce_kids->ce_type <= ce->ce_type ) 6553 for ( ceprev = parent->ce_kids; ceprev->ce_sibs && 6554 ceprev->ce_type <= ce->ce_type; 6555 ceprev = ceprev->ce_sibs ); 6556 } else { 6557 BER_BVZERO( &pdn ); 6558 } 6559 6560 ce->ce_private = c->ca_private; 6561 ce->ce_be = c->be; 6562 ce->ce_bi = c->bi; 6563 6564 build_new_dn( &e->e_name, &pdn, rdn, NULL ); 6565 ber_dupbv( &e->e_nname, &e->e_name ); 6566 6567 attr_merge_normalize_one(e, slap_schema.si_ad_objectClass, 6568 main->co_name, NULL ); 6569 if ( extra ) 6570 attr_merge_normalize_one(e, slap_schema.si_ad_objectClass, 6571 extra->co_name, NULL ); 6572 ptr = strchr(rdn->bv_val, '='); 6573 ad_name.bv_val = rdn->bv_val; 6574 ad_name.bv_len = ptr - rdn->bv_val; 6575 rc = slap_bv2ad( &ad_name, &ad, &text ); 6576 if ( rc ) { 6577 goto fail; 6578 } 6579 val.bv_val = ptr+1; 6580 val.bv_len = rdn->bv_len - (val.bv_val - rdn->bv_val); 6581 attr_merge_normalize_one(e, ad, &val, NULL ); 6582 6583 oc = main->co_oc; 6584 c->table = main->co_type; 6585 if ( oc->soc_required ) { 6586 rc = config_build_attrs( e, oc->soc_required, ad, main->co_table, c ); 6587 if ( rc ) goto fail; 6588 } 6589 6590 if ( oc->soc_allowed ) { 6591 rc = config_build_attrs( e, oc->soc_allowed, ad, main->co_table, c ); 6592 if ( rc ) goto fail; 6593 } 6594 6595 if ( extra ) { 6596 oc = extra->co_oc; 6597 c->table = extra->co_type; 6598 if ( oc->soc_required ) { 6599 rc = config_build_attrs( e, oc->soc_required, ad, extra->co_table, c ); 6600 if ( rc ) goto fail; 6601 } 6602 6603 if ( oc->soc_allowed ) { 6604 rc = config_build_attrs( e, oc->soc_allowed, ad, extra->co_table, c ); 6605 if ( rc ) goto fail; 6606 } 6607 } 6608 6609 oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass ); 6610 rc = structural_class(oc_at->a_vals, &oc, NULL, &text, c->cr_msg, 6611 sizeof(c->cr_msg), op ? op->o_tmpmemctx : NULL ); 6612 if ( rc != LDAP_SUCCESS ) { 6613fail: 6614 Debug( LDAP_DEBUG_ANY, 6615 "config_build_entry: build \"%s\" failed: \"%s\"\n", 6616 rdn->bv_val, text, 0); 6617 return NULL; 6618 } 6619 attr_merge_normalize_one(e, slap_schema.si_ad_structuralObjectClass, &oc->soc_cname, NULL ); 6620 if ( op ) { 6621 op->ora_e = e; 6622 op->ora_modlist = NULL; 6623 slap_add_opattrs( op, NULL, NULL, 0, 0 ); 6624 if ( !op->o_noop ) { 6625 SlapReply rs2 = {REP_RESULT}; 6626 op->o_bd->be_add( op, &rs2 ); 6627 rs->sr_err = rs2.sr_err; 6628 rs_assert_done( &rs2 ); 6629 if ( ( rs2.sr_err != LDAP_SUCCESS ) 6630 && (rs2.sr_err != LDAP_ALREADY_EXISTS) ) { 6631 goto fail; 6632 } 6633 } 6634 } 6635 if ( ceprev ) { 6636 ce->ce_sibs = ceprev->ce_sibs; 6637 ceprev->ce_sibs = ce; 6638 } else if ( parent ) { 6639 ce->ce_sibs = parent->ce_kids; 6640 parent->ce_kids = ce; 6641 } 6642 6643 return e; 6644} 6645 6646static int 6647config_build_schema_inc( ConfigArgs *c, CfEntryInfo *ceparent, 6648 Operation *op, SlapReply *rs ) 6649{ 6650 Entry *e; 6651 ConfigFile *cf = c->ca_private; 6652 char *ptr; 6653 struct berval bv, rdn; 6654 6655 for (; cf; cf=cf->c_sibs, c->depth++) { 6656 if ( !cf->c_at_head && !cf->c_cr_head && !cf->c_oc_head && 6657 !cf->c_om_head && !cf->c_syn_head ) continue; 6658 c->value_dn.bv_val = c->log; 6659 LUTIL_SLASHPATH( cf->c_file.bv_val ); 6660 bv.bv_val = strrchr(cf->c_file.bv_val, LDAP_DIRSEP[0]); 6661 if ( !bv.bv_val ) { 6662 bv = cf->c_file; 6663 } else { 6664 bv.bv_val++; 6665 bv.bv_len = cf->c_file.bv_len - (bv.bv_val - cf->c_file.bv_val); 6666 } 6667 ptr = strchr( bv.bv_val, '.' ); 6668 if ( ptr ) 6669 bv.bv_len = ptr - bv.bv_val; 6670 c->value_dn.bv_len = snprintf(c->value_dn.bv_val, sizeof( c->log ), "cn=" SLAP_X_ORDERED_FMT, c->depth); 6671 if ( c->value_dn.bv_len >= sizeof( c->log ) ) { 6672 /* FIXME: how can indicate error? */ 6673 return -1; 6674 } 6675 strncpy( c->value_dn.bv_val + c->value_dn.bv_len, bv.bv_val, 6676 bv.bv_len ); 6677 c->value_dn.bv_len += bv.bv_len; 6678 c->value_dn.bv_val[c->value_dn.bv_len] ='\0'; 6679 rdnNormalize( 0, NULL, NULL, &c->value_dn, &rdn, NULL ); 6680 6681 c->ca_private = cf; 6682 e = config_build_entry( op, rs, ceparent, c, &rdn, 6683 &CFOC_SCHEMA, NULL ); 6684 ch_free( rdn.bv_val ); 6685 if ( !e ) { 6686 return -1; 6687 } else if ( e && cf->c_kids ) { 6688 c->ca_private = cf->c_kids; 6689 config_build_schema_inc( c, e->e_private, op, rs ); 6690 } 6691 } 6692 return 0; 6693} 6694 6695#ifdef SLAPD_MODULES 6696 6697static int 6698config_build_modules( ConfigArgs *c, CfEntryInfo *ceparent, 6699 Operation *op, SlapReply *rs ) 6700{ 6701 int i; 6702 ModPaths *mp; 6703 6704 for (i=0, mp=&modpaths; mp; mp=mp->mp_next, i++) { 6705 if ( BER_BVISNULL( &mp->mp_path ) && !mp->mp_loads ) 6706 continue; 6707 c->value_dn.bv_val = c->log; 6708 c->value_dn.bv_len = snprintf(c->value_dn.bv_val, sizeof( c->log ), "cn=module" SLAP_X_ORDERED_FMT, i); 6709 if ( c->value_dn.bv_len >= sizeof( c->log ) ) { 6710 /* FIXME: how can indicate error? */ 6711 return -1; 6712 } 6713 c->ca_private = mp; 6714 if ( ! config_build_entry( op, rs, ceparent, c, &c->value_dn, &CFOC_MODULE, NULL )) { 6715 return -1; 6716 } 6717 } 6718 return 0; 6719} 6720#endif 6721 6722static int 6723config_check_schema(Operation *op, CfBackInfo *cfb) 6724{ 6725 struct berval schema_dn = BER_BVC(SCHEMA_RDN "," CONFIG_RDN); 6726 ConfigArgs c = {0}; 6727 CfEntryInfo *ce, *last; 6728 Entry *e; 6729 6730 /* If there's no root entry, we must be in the midst of converting */ 6731 if ( !cfb->cb_root ) 6732 return 0; 6733 6734 /* Make sure the main schema entry exists */ 6735 ce = config_find_base( cfb->cb_root, &schema_dn, &last ); 6736 if ( ce ) { 6737 Attribute *a; 6738 struct berval *bv; 6739 6740 e = ce->ce_entry; 6741 6742 /* Make sure it's up to date */ 6743 if ( cf_om_tail != om_sys_tail ) { 6744 a = attr_find( e->e_attrs, cfAd_om ); 6745 if ( a ) { 6746 if ( a->a_nvals != a->a_vals ) 6747 ber_bvarray_free( a->a_nvals ); 6748 ber_bvarray_free( a->a_vals ); 6749 a->a_vals = NULL; 6750 a->a_nvals = NULL; 6751 a->a_numvals = 0; 6752 } 6753 oidm_unparse( &bv, NULL, NULL, 1 ); 6754 attr_merge_normalize( e, cfAd_om, bv, NULL ); 6755 ber_bvarray_free( bv ); 6756 cf_om_tail = om_sys_tail; 6757 } 6758 if ( cf_at_tail != at_sys_tail ) { 6759 a = attr_find( e->e_attrs, cfAd_attr ); 6760 if ( a ) { 6761 if ( a->a_nvals != a->a_vals ) 6762 ber_bvarray_free( a->a_nvals ); 6763 ber_bvarray_free( a->a_vals ); 6764 a->a_vals = NULL; 6765 a->a_nvals = NULL; 6766 a->a_numvals = 0; 6767 } 6768 at_unparse( &bv, NULL, NULL, 1 ); 6769 attr_merge_normalize( e, cfAd_attr, bv, NULL ); 6770 ber_bvarray_free( bv ); 6771 cf_at_tail = at_sys_tail; 6772 } 6773 if ( cf_oc_tail != oc_sys_tail ) { 6774 a = attr_find( e->e_attrs, cfAd_oc ); 6775 if ( a ) { 6776 if ( a->a_nvals != a->a_vals ) 6777 ber_bvarray_free( a->a_nvals ); 6778 ber_bvarray_free( a->a_vals ); 6779 a->a_vals = NULL; 6780 a->a_nvals = NULL; 6781 a->a_numvals = 0; 6782 } 6783 oc_unparse( &bv, NULL, NULL, 1 ); 6784 attr_merge_normalize( e, cfAd_oc, bv, NULL ); 6785 ber_bvarray_free( bv ); 6786 cf_oc_tail = oc_sys_tail; 6787 } 6788 if ( cf_syn_tail != syn_sys_tail ) { 6789 a = attr_find( e->e_attrs, cfAd_syntax ); 6790 if ( a ) { 6791 if ( a->a_nvals != a->a_vals ) 6792 ber_bvarray_free( a->a_nvals ); 6793 ber_bvarray_free( a->a_vals ); 6794 a->a_vals = NULL; 6795 a->a_nvals = NULL; 6796 a->a_numvals = 0; 6797 } 6798 syn_unparse( &bv, NULL, NULL, 1 ); 6799 attr_merge_normalize( e, cfAd_syntax, bv, NULL ); 6800 ber_bvarray_free( bv ); 6801 cf_syn_tail = syn_sys_tail; 6802 } 6803 } else { 6804 SlapReply rs = {REP_RESULT}; 6805 c.ca_private = NULL; 6806 e = config_build_entry( op, &rs, cfb->cb_root, &c, &schema_rdn, 6807 &CFOC_SCHEMA, NULL ); 6808 if ( !e ) { 6809 return -1; 6810 } 6811 ce = e->e_private; 6812 ce->ce_private = cfb->cb_config; 6813 cf_at_tail = at_sys_tail; 6814 cf_oc_tail = oc_sys_tail; 6815 cf_om_tail = om_sys_tail; 6816 cf_syn_tail = syn_sys_tail; 6817 } 6818 return 0; 6819} 6820 6821static const char *defacl[] = { 6822 NULL, "to", "*", "by", "*", "none", NULL 6823}; 6824 6825static int 6826config_back_db_open( BackendDB *be, ConfigReply *cr ) 6827{ 6828 CfBackInfo *cfb = be->be_private; 6829 struct berval rdn; 6830 Entry *e, *parent; 6831 CfEntryInfo *ce, *ceparent; 6832 int i, unsupp = 0; 6833 BackendInfo *bi; 6834 ConfigArgs c; 6835 Connection conn = {0}; 6836 OperationBuffer opbuf; 6837 Operation *op; 6838 slap_callback cb = { NULL, slap_null_cb, NULL, NULL }; 6839 SlapReply rs = {REP_RESULT}; 6840 void *thrctx = NULL; 6841 AccessControl *save_access; 6842 6843 Debug( LDAP_DEBUG_TRACE, "config_back_db_open\n", 0, 0, 0); 6844 6845 /* If we have no explicitly configured ACLs, don't just use 6846 * the global ACLs. Explicitly deny access to everything. 6847 */ 6848 save_access = be->bd_self->be_acl; 6849 be->bd_self->be_acl = NULL; 6850 parse_acl(be->bd_self, "config_back_db_open", 0, 6, (char **)defacl, 0 ); 6851 defacl_parsed = be->bd_self->be_acl; 6852 if ( save_access ) { 6853 be->bd_self->be_acl = save_access; 6854 } else { 6855 Debug( LDAP_DEBUG_CONFIG, "config_back_db_open: " 6856 "No explicit ACL for back-config configured. " 6857 "Using hardcoded default\n", 0, 0, 0 ); 6858 } 6859 6860 thrctx = ldap_pvt_thread_pool_context(); 6861 connection_fake_init( &conn, &opbuf, thrctx ); 6862 op = &opbuf.ob_op; 6863 6864 op->o_tag = LDAP_REQ_ADD; 6865 op->o_callback = &cb; 6866 op->o_bd = &cfb->cb_db; 6867 op->o_dn = op->o_bd->be_rootdn; 6868 op->o_ndn = op->o_bd->be_rootndn; 6869 6870 if ( !cfb->cb_use_ldif ) { 6871 op->o_noop = 1; 6872 } 6873 6874 /* If we read the config from back-ldif, do some quick sanity checks */ 6875 if ( cfb->cb_got_ldif ) { 6876 return config_check_schema( op, cfb ); 6877 } 6878 6879 /* create root of tree */ 6880 rdn = config_rdn; 6881 c.ca_private = cfb->cb_config; 6882 c.be = frontendDB; 6883 e = config_build_entry( op, &rs, NULL, &c, &rdn, &CFOC_GLOBAL, NULL ); 6884 if ( !e ) { 6885 return -1; 6886 } 6887 ce = e->e_private; 6888 cfb->cb_root = ce; 6889 6890 parent = e; 6891 ceparent = ce; 6892 6893#ifdef SLAPD_MODULES 6894 /* Create Module nodes... */ 6895 if ( modpaths.mp_loads ) { 6896 if ( config_build_modules( &c, ceparent, op, &rs ) ){ 6897 return -1; 6898 } 6899 } 6900#endif 6901 6902 /* Create schema nodes... cn=schema will contain the hardcoded core 6903 * schema, read-only. Child objects will contain runtime loaded schema 6904 * files. 6905 */ 6906 rdn = schema_rdn; 6907 c.ca_private = NULL; 6908 e = config_build_entry( op, &rs, ceparent, &c, &rdn, &CFOC_SCHEMA, NULL ); 6909 if ( !e ) { 6910 return -1; 6911 } 6912 ce = e->e_private; 6913 ce->ce_private = cfb->cb_config; 6914 cf_at_tail = at_sys_tail; 6915 cf_oc_tail = oc_sys_tail; 6916 cf_om_tail = om_sys_tail; 6917 cf_syn_tail = syn_sys_tail; 6918 6919 /* Create schema nodes for included schema... */ 6920 if ( cfb->cb_config->c_kids ) { 6921 int rc; 6922 c.depth = 0; 6923 c.ca_private = cfb->cb_config->c_kids; 6924 rc = config_build_schema_inc( &c, ce, op, &rs ); 6925 if ( rc ) { 6926 return -1; 6927 } 6928 } 6929 6930 /* Create backend nodes. Skip if they don't provide a cf_table. 6931 * There usually aren't any of these. 6932 */ 6933 6934 c.line = 0; 6935 LDAP_STAILQ_FOREACH( bi, &backendInfo, bi_next) { 6936 if (!bi->bi_cf_ocs) { 6937 /* If it only supports the old config mech, complain. */ 6938 if ( bi->bi_config ) { 6939 Debug( LDAP_DEBUG_ANY, 6940 "WARNING: No dynamic config support for backend %s.\n", 6941 bi->bi_type, 0, 0 ); 6942 unsupp++; 6943 } 6944 continue; 6945 } 6946 if (!bi->bi_private) continue; 6947 6948 rdn.bv_val = c.log; 6949 rdn.bv_len = snprintf(rdn.bv_val, sizeof( c.log ), 6950 "%s=%s", cfAd_backend->ad_cname.bv_val, bi->bi_type); 6951 if ( rdn.bv_len >= sizeof( c.log ) ) { 6952 /* FIXME: holler ... */ ; 6953 } 6954 c.bi = bi; 6955 e = config_build_entry( op, &rs, ceparent, &c, &rdn, &CFOC_BACKEND, 6956 bi->bi_cf_ocs ); 6957 if ( !e ) { 6958 return -1; 6959 } 6960 } 6961 6962 /* Create database nodes... */ 6963 frontendDB->be_cf_ocs = &CFOC_FRONTEND; 6964 LDAP_STAILQ_NEXT(frontendDB, be_next) = LDAP_STAILQ_FIRST(&backendDB); 6965 for ( i = -1, be = frontendDB ; be; 6966 i++, be = LDAP_STAILQ_NEXT( be, be_next )) { 6967 slap_overinfo *oi = NULL; 6968 6969 if ( overlay_is_over( be )) { 6970 oi = be->bd_info->bi_private; 6971 bi = oi->oi_orig; 6972 } else { 6973 bi = be->bd_info; 6974 } 6975 6976 /* If this backend supports the old config mechanism, but not 6977 * the new mech, complain. 6978 */ 6979 if ( !be->be_cf_ocs && bi->bi_db_config ) { 6980 Debug( LDAP_DEBUG_ANY, 6981 "WARNING: No dynamic config support for database %s.\n", 6982 bi->bi_type, 0, 0 ); 6983 unsupp++; 6984 } 6985 rdn.bv_val = c.log; 6986 rdn.bv_len = snprintf(rdn.bv_val, sizeof( c.log ), 6987 "%s=" SLAP_X_ORDERED_FMT "%s", cfAd_database->ad_cname.bv_val, 6988 i, bi->bi_type); 6989 if ( rdn.bv_len >= sizeof( c.log ) ) { 6990 /* FIXME: holler ... */ ; 6991 } 6992 c.be = be; 6993 c.bi = bi; 6994 e = config_build_entry( op, &rs, ceparent, &c, &rdn, &CFOC_DATABASE, 6995 be->be_cf_ocs ); 6996 if ( !e ) { 6997 return -1; 6998 } 6999 ce = e->e_private; 7000 if ( be->be_cf_ocs && be->be_cf_ocs->co_cfadd ) { 7001 rs_reinit( &rs, REP_RESULT ); 7002 be->be_cf_ocs->co_cfadd( op, &rs, e, &c ); 7003 } 7004 /* Iterate through overlays */ 7005 if ( oi ) { 7006 slap_overinst *on; 7007 Entry *oe; 7008 int j; 7009 voidList *vl, *v0 = NULL; 7010 7011 /* overlays are in LIFO order, must reverse stack */ 7012 for (on=oi->oi_list; on; on=on->on_next) { 7013 vl = ch_malloc( sizeof( voidList )); 7014 vl->vl_next = v0; 7015 v0 = vl; 7016 vl->vl_ptr = on; 7017 } 7018 for (j=0; vl; j++,vl=v0) { 7019 on = vl->vl_ptr; 7020 v0 = vl->vl_next; 7021 ch_free( vl ); 7022 if ( on->on_bi.bi_db_config && !on->on_bi.bi_cf_ocs ) { 7023 Debug( LDAP_DEBUG_ANY, 7024 "WARNING: No dynamic config support for overlay %s.\n", 7025 on->on_bi.bi_type, 0, 0 ); 7026 unsupp++; 7027 } 7028 rdn.bv_val = c.log; 7029 rdn.bv_len = snprintf(rdn.bv_val, sizeof( c.log ), 7030 "%s=" SLAP_X_ORDERED_FMT "%s", 7031 cfAd_overlay->ad_cname.bv_val, j, on->on_bi.bi_type ); 7032 if ( rdn.bv_len >= sizeof( c.log ) ) { 7033 /* FIXME: holler ... */ ; 7034 } 7035 c.be = be; 7036 c.bi = &on->on_bi; 7037 oe = config_build_entry( op, &rs, ce, &c, &rdn, 7038 &CFOC_OVERLAY, c.bi->bi_cf_ocs ); 7039 if ( !oe ) { 7040 return -1; 7041 } 7042 if ( c.bi->bi_cf_ocs && c.bi->bi_cf_ocs->co_cfadd ) { 7043 rs_reinit( &rs, REP_RESULT ); 7044 c.bi->bi_cf_ocs->co_cfadd( op, &rs, oe, &c ); 7045 } 7046 } 7047 } 7048 } 7049 if ( thrctx ) 7050 ldap_pvt_thread_pool_context_reset( thrctx ); 7051 7052 if ( unsupp && cfb->cb_use_ldif ) { 7053 Debug( LDAP_DEBUG_ANY, "\nWARNING: The converted cn=config " 7054 "directory is incomplete and may not work.\n\n", 0, 0, 0 ); 7055 } 7056 7057 return 0; 7058} 7059 7060static void 7061cfb_free_cffile( ConfigFile *cf ) 7062{ 7063 ConfigFile *next; 7064 7065 for (; cf; cf=next) { 7066 next = cf->c_sibs; 7067 if ( cf->c_kids ) 7068 cfb_free_cffile( cf->c_kids ); 7069 ch_free( cf->c_file.bv_val ); 7070 ber_bvarray_free( cf->c_dseFiles ); 7071 ch_free( cf ); 7072 } 7073} 7074 7075static void 7076cfb_free_entries( CfEntryInfo *ce ) 7077{ 7078 CfEntryInfo *next; 7079 7080 for (; ce; ce=next) { 7081 next = ce->ce_sibs; 7082 if ( ce->ce_kids ) 7083 cfb_free_entries( ce->ce_kids ); 7084 ce->ce_entry->e_private = NULL; 7085 entry_free( ce->ce_entry ); 7086 ch_free( ce ); 7087 } 7088} 7089 7090static int 7091config_back_db_close( BackendDB *be, ConfigReply *cr ) 7092{ 7093 CfBackInfo *cfb = be->be_private; 7094 7095 cfb_free_entries( cfb->cb_root ); 7096 cfb->cb_root = NULL; 7097 7098 if ( cfb->cb_db.bd_info ) { 7099 backend_shutdown( &cfb->cb_db ); 7100 } 7101 7102 if ( defacl_parsed && be->be_acl != defacl_parsed ) { 7103 acl_free( defacl_parsed ); 7104 defacl_parsed = NULL; 7105 } 7106 7107 return 0; 7108} 7109 7110static int 7111config_back_db_destroy( BackendDB *be, ConfigReply *cr ) 7112{ 7113 CfBackInfo *cfb = be->be_private; 7114 7115 cfb_free_cffile( cfb->cb_config ); 7116 7117 ch_free( cfdir.bv_val ); 7118 7119 avl_free( CfOcTree, NULL ); 7120 7121 if ( cfb->cb_db.bd_info ) { 7122 cfb->cb_db.be_suffix = NULL; 7123 cfb->cb_db.be_nsuffix = NULL; 7124 BER_BVZERO( &cfb->cb_db.be_rootdn ); 7125 BER_BVZERO( &cfb->cb_db.be_rootndn ); 7126 7127 backend_destroy_one( &cfb->cb_db, 0 ); 7128 } 7129 7130 loglevel_destroy(); 7131 7132 return 0; 7133} 7134 7135static int 7136config_back_db_init( BackendDB *be, ConfigReply* cr ) 7137{ 7138 struct berval dn; 7139 CfBackInfo *cfb; 7140 7141 cfb = &cfBackInfo; 7142 cfb->cb_config = ch_calloc( 1, sizeof(ConfigFile)); 7143 cfn = cfb->cb_config; 7144 be->be_private = cfb; 7145 7146 ber_dupbv( &be->be_rootdn, &config_rdn ); 7147 ber_dupbv( &be->be_rootndn, &be->be_rootdn ); 7148 ber_dupbv( &dn, &be->be_rootdn ); 7149 ber_bvarray_add( &be->be_suffix, &dn ); 7150 ber_dupbv( &dn, &be->be_rootdn ); 7151 ber_bvarray_add( &be->be_nsuffix, &dn ); 7152 7153 /* Hide from namingContexts */ 7154 SLAP_BFLAGS(be) |= SLAP_BFLAG_CONFIG; 7155 7156 /* Check ACLs on content of Adds by default */ 7157 SLAP_DBFLAGS(be) |= SLAP_DBFLAG_ACL_ADD; 7158 7159 return 0; 7160} 7161 7162static int 7163config_back_destroy( BackendInfo *bi ) 7164{ 7165 ldif_must_b64_encode_release(); 7166 return 0; 7167} 7168 7169static int 7170config_tool_entry_open( BackendDB *be, int mode ) 7171{ 7172 CfBackInfo *cfb = be->be_private; 7173 BackendInfo *bi = cfb->cb_db.bd_info; 7174 7175 if ( bi && bi->bi_tool_entry_open ) 7176 return bi->bi_tool_entry_open( &cfb->cb_db, mode ); 7177 else 7178 return -1; 7179 7180} 7181 7182static int 7183config_tool_entry_close( BackendDB *be ) 7184{ 7185 CfBackInfo *cfb = be->be_private; 7186 BackendInfo *bi = cfb->cb_db.bd_info; 7187 7188 if ( bi && bi->bi_tool_entry_close ) 7189 return bi->bi_tool_entry_close( &cfb->cb_db ); 7190 else 7191 return -1; 7192} 7193 7194static ID 7195config_tool_entry_first( BackendDB *be ) 7196{ 7197 CfBackInfo *cfb = be->be_private; 7198 BackendInfo *bi = cfb->cb_db.bd_info; 7199 7200 if ( bi && bi->bi_tool_entry_first ) { 7201 return bi->bi_tool_entry_first( &cfb->cb_db ); 7202 } 7203 if ( bi && bi->bi_tool_entry_first_x ) { 7204 return bi->bi_tool_entry_first_x( &cfb->cb_db, 7205 NULL, LDAP_SCOPE_DEFAULT, NULL ); 7206 } 7207 return NOID; 7208} 7209 7210static ID 7211config_tool_entry_first_x( 7212 BackendDB *be, 7213 struct berval *base, 7214 int scope, 7215 Filter *f ) 7216{ 7217 CfBackInfo *cfb = be->be_private; 7218 BackendInfo *bi = cfb->cb_db.bd_info; 7219 7220 if ( bi && bi->bi_tool_entry_first_x ) { 7221 return bi->bi_tool_entry_first_x( &cfb->cb_db, base, scope, f ); 7222 } 7223 return NOID; 7224} 7225 7226static ID 7227config_tool_entry_next( BackendDB *be ) 7228{ 7229 CfBackInfo *cfb = be->be_private; 7230 BackendInfo *bi = cfb->cb_db.bd_info; 7231 7232 if ( bi && bi->bi_tool_entry_next ) 7233 return bi->bi_tool_entry_next( &cfb->cb_db ); 7234 else 7235 return NOID; 7236} 7237 7238static Entry * 7239config_tool_entry_get( BackendDB *be, ID id ) 7240{ 7241 CfBackInfo *cfb = be->be_private; 7242 BackendInfo *bi = cfb->cb_db.bd_info; 7243 7244 if ( bi && bi->bi_tool_entry_get ) 7245 return bi->bi_tool_entry_get( &cfb->cb_db, id ); 7246 else 7247 return NULL; 7248} 7249 7250static int entry_put_got_frontend=0; 7251static int entry_put_got_config=0; 7252static ID 7253config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text ) 7254{ 7255 CfBackInfo *cfb = be->be_private; 7256 BackendInfo *bi = cfb->cb_db.bd_info; 7257 int rc; 7258 struct berval rdn, vals[ 2 ]; 7259 ConfigArgs ca; 7260 OperationBuffer opbuf; 7261 Entry *ce; 7262 Connection conn = {0}; 7263 Operation *op = NULL; 7264 void *thrctx; 7265 int isFrontend = 0; 7266 int isFrontendChild = 0; 7267 7268 /* Create entry for frontend database if it does not exist already */ 7269 if ( !entry_put_got_frontend ) { 7270 if ( !strncmp( e->e_nname.bv_val, "olcDatabase", 7271 STRLENOF( "olcDatabase" ))) { 7272 if ( strncmp( e->e_nname.bv_val + 7273 STRLENOF( "olcDatabase" ), "={-1}frontend", 7274 STRLENOF( "={-1}frontend" )) && 7275 strncmp( e->e_nname.bv_val + 7276 STRLENOF( "olcDatabase" ), "=frontend", 7277 STRLENOF( "=frontend" ))) { 7278 vals[1].bv_len = 0; 7279 vals[1].bv_val = NULL; 7280 memset( &ca, 0, sizeof(ConfigArgs)); 7281 ca.be = frontendDB; 7282 ca.bi = frontendDB->bd_info; 7283 ca.be->be_cf_ocs = &CFOC_FRONTEND; 7284 rdn.bv_val = ca.log; 7285 rdn.bv_len = snprintf(rdn.bv_val, sizeof( ca.log ), 7286 "%s=" SLAP_X_ORDERED_FMT "%s", 7287 cfAd_database->ad_cname.bv_val, -1, 7288 ca.bi->bi_type); 7289 ce = config_build_entry( NULL, NULL, cfb->cb_root, &ca, &rdn, 7290 &CFOC_DATABASE, ca.be->be_cf_ocs ); 7291 thrctx = ldap_pvt_thread_pool_context(); 7292 connection_fake_init2( &conn, &opbuf, thrctx,0 ); 7293 op = &opbuf.ob_op; 7294 op->o_bd = &cfb->cb_db; 7295 op->o_tag = LDAP_REQ_ADD; 7296 op->ora_e = ce; 7297 op->o_dn = be->be_rootdn; 7298 op->o_ndn = be->be_rootndn; 7299 rc = slap_add_opattrs(op, NULL, NULL, 0, 0); 7300 if ( rc != LDAP_SUCCESS ) { 7301 text->bv_val = "autocreation of \"olcDatabase={-1}frontend\" failed"; 7302 text->bv_len = STRLENOF("autocreation of \"olcDatabase={-1}frontend\" failed"); 7303 return NOID; 7304 } 7305 7306 if ( ce && bi && bi->bi_tool_entry_put && 7307 bi->bi_tool_entry_put( &cfb->cb_db, ce, text ) != NOID ) { 7308 entry_put_got_frontend++; 7309 } else { 7310 text->bv_val = "autocreation of \"olcDatabase={-1}frontend\" failed"; 7311 text->bv_len = STRLENOF("autocreation of \"olcDatabase={-1}frontend\" failed"); 7312 return NOID; 7313 } 7314 } else { 7315 if ( !strncmp( e->e_nname.bv_val + 7316 STRLENOF( "olcDatabase" ), "=frontend", 7317 STRLENOF( "=frontend" ) ) ) 7318 { 7319 struct berval rdn, pdn, ndn; 7320 dnParent( &e->e_nname, &pdn ); 7321 rdn.bv_val = ca.log; 7322 rdn.bv_len = snprintf(rdn.bv_val, sizeof( ca.log ), 7323 "%s=" SLAP_X_ORDERED_FMT "%s", 7324 cfAd_database->ad_cname.bv_val, -1, 7325 frontendDB->bd_info->bi_type ); 7326 build_new_dn( &ndn, &pdn, &rdn, NULL ); 7327 ber_memfree( e->e_name.bv_val ); 7328 e->e_name = ndn; 7329 ber_bvreplace( &e->e_nname, &e->e_name ); 7330 } 7331 entry_put_got_frontend++; 7332 isFrontend = 1; 7333 } 7334 } 7335 } 7336 7337 /* Child entries of the frontend database, e.g. slapo-chain's back-ldap 7338 * instances, may appear before the config database entry in the ldif, skip 7339 * auto-creation of olcDatabase={0}config in such a case */ 7340 if ( !entry_put_got_config && 7341 !strncmp( e->e_nname.bv_val, "olcDatabase", STRLENOF( "olcDatabase" ))) { 7342 struct berval pdn; 7343 dnParent( &e->e_nname, &pdn ); 7344 while ( pdn.bv_len ) { 7345 if ( !strncmp( pdn.bv_val, "olcDatabase", 7346 STRLENOF( "olcDatabase" ))) { 7347 if ( !strncmp( pdn.bv_val + 7348 STRLENOF( "olcDatabase" ), "={-1}frontend", 7349 STRLENOF( "={-1}frontend" )) || 7350 !strncmp( pdn.bv_val + 7351 STRLENOF( "olcDatabase" ), "=frontend", 7352 STRLENOF( "=frontend" ))) { 7353 7354 isFrontendChild = 1; 7355 break; 7356 } 7357 } 7358 dnParent( &pdn, &pdn ); 7359 } 7360 } 7361 7362 /* Create entry for config database if it does not exist already */ 7363 if ( !entry_put_got_config && !isFrontend && !isFrontendChild ) { 7364 if ( !strncmp( e->e_nname.bv_val, "olcDatabase", 7365 STRLENOF( "olcDatabase" ))) { 7366 if ( strncmp( e->e_nname.bv_val + 7367 STRLENOF( "olcDatabase" ), "={0}config", 7368 STRLENOF( "={0}config" )) && 7369 strncmp( e->e_nname.bv_val + 7370 STRLENOF( "olcDatabase" ), "=config", 7371 STRLENOF( "=config" )) ) { 7372 vals[1].bv_len = 0; 7373 vals[1].bv_val = NULL; 7374 memset( &ca, 0, sizeof(ConfigArgs)); 7375 ca.be = LDAP_STAILQ_FIRST( &backendDB ); 7376 ca.bi = ca.be->bd_info; 7377 rdn.bv_val = ca.log; 7378 rdn.bv_len = snprintf(rdn.bv_val, sizeof( ca.log ), 7379 "%s=" SLAP_X_ORDERED_FMT "%s", 7380 cfAd_database->ad_cname.bv_val, 0, 7381 ca.bi->bi_type); 7382 ce = config_build_entry( NULL, NULL, cfb->cb_root, &ca, &rdn, &CFOC_DATABASE, 7383 ca.be->be_cf_ocs ); 7384 if ( ! op ) { 7385 thrctx = ldap_pvt_thread_pool_context(); 7386 connection_fake_init2( &conn, &opbuf, thrctx,0 ); 7387 op = &opbuf.ob_op; 7388 op->o_bd = &cfb->cb_db; 7389 op->o_tag = LDAP_REQ_ADD; 7390 op->o_dn = be->be_rootdn; 7391 op->o_ndn = be->be_rootndn; 7392 } 7393 op->ora_e = ce; 7394 rc = slap_add_opattrs(op, NULL, NULL, 0, 0); 7395 if ( rc != LDAP_SUCCESS ) { 7396 text->bv_val = "autocreation of \"olcDatabase={0}config\" failed"; 7397 text->bv_len = STRLENOF("autocreation of \"olcDatabase={0}config\" failed"); 7398 return NOID; 7399 } 7400 if (ce && bi && bi->bi_tool_entry_put && 7401 bi->bi_tool_entry_put( &cfb->cb_db, ce, text ) != NOID ) { 7402 entry_put_got_config++; 7403 } else { 7404 text->bv_val = "autocreation of \"olcDatabase={0}config\" failed"; 7405 text->bv_len = STRLENOF("autocreation of \"olcDatabase={0}config\" failed"); 7406 return NOID; 7407 } 7408 } else { 7409 entry_put_got_config++; 7410 } 7411 } 7412 } 7413 if ( bi && bi->bi_tool_entry_put && 7414 config_add_internal( cfb, e, &ca, NULL, NULL, NULL ) == 0 ) 7415 return bi->bi_tool_entry_put( &cfb->cb_db, e, text ); 7416 else 7417 return NOID; 7418} 7419 7420static struct { 7421 char *name; 7422 AttributeDescription **desc; 7423} ads[] = { 7424 { "attribute", &cfAd_attr }, 7425 { "backend", &cfAd_backend }, 7426 { "database", &cfAd_database }, 7427 { "include", &cfAd_include }, 7428 { "ldapsyntax", &cfAd_syntax }, 7429 { "objectclass", &cfAd_oc }, 7430 { "objectidentifier", &cfAd_om }, 7431 { "overlay", &cfAd_overlay }, 7432 { NULL, NULL } 7433}; 7434 7435/* Notes: 7436 * add / delete: all types that may be added or deleted must use an 7437 * X-ORDERED attributeType for their RDN. Adding and deleting entries 7438 * should automatically renumber the index of any siblings as needed, 7439 * so that no gaps in the numbering sequence exist after the add/delete 7440 * is completed. 7441 * What can be added: 7442 * schema objects 7443 * backend objects for backend-specific config directives 7444 * database objects 7445 * overlay objects 7446 * 7447 * delete: probably no support this time around. 7448 * 7449 * modrdn: generally not done. Will be invoked automatically by add/ 7450 * delete to update numbering sequence. Perform as an explicit operation 7451 * so that the renumbering effect may be replicated. Subtree rename must 7452 * be supported, since renumbering a database will affect all its child 7453 * overlays. 7454 * 7455 * modify: must be fully supported. 7456 */ 7457 7458int 7459config_back_initialize( BackendInfo *bi ) 7460{ 7461 ConfigTable *ct = config_back_cf_table; 7462 ConfigArgs ca; 7463 char *argv[4]; 7464 int i; 7465 AttributeDescription *ad = NULL; 7466 const char *text; 7467 static char *controls[] = { 7468 LDAP_CONTROL_MANAGEDSAIT, 7469 NULL 7470 }; 7471 7472 /* Make sure we don't exceed the bits reserved for userland */ 7473 config_check_userland( CFG_LAST ); 7474 7475 bi->bi_controls = controls; 7476 7477 bi->bi_open = 0; 7478 bi->bi_close = 0; 7479 bi->bi_config = 0; 7480 bi->bi_destroy = config_back_destroy; 7481 7482 bi->bi_db_init = config_back_db_init; 7483 bi->bi_db_config = 0; 7484 bi->bi_db_open = config_back_db_open; 7485 bi->bi_db_close = config_back_db_close; 7486 bi->bi_db_destroy = config_back_db_destroy; 7487 7488 bi->bi_op_bind = config_back_bind; 7489 bi->bi_op_unbind = 0; 7490 bi->bi_op_search = config_back_search; 7491 bi->bi_op_compare = 0; 7492 bi->bi_op_modify = config_back_modify; 7493 bi->bi_op_modrdn = config_back_modrdn; 7494 bi->bi_op_add = config_back_add; 7495 bi->bi_op_delete = config_back_delete; 7496 bi->bi_op_abandon = 0; 7497 7498 bi->bi_extended = 0; 7499 7500 bi->bi_chk_referrals = 0; 7501 7502 bi->bi_access_allowed = slap_access_allowed; 7503 7504 bi->bi_connection_init = 0; 7505 bi->bi_connection_destroy = 0; 7506 7507 bi->bi_entry_release_rw = config_entry_release; 7508 bi->bi_entry_get_rw = config_back_entry_get; 7509 7510 bi->bi_tool_entry_open = config_tool_entry_open; 7511 bi->bi_tool_entry_close = config_tool_entry_close; 7512 bi->bi_tool_entry_first = config_tool_entry_first; 7513 bi->bi_tool_entry_first_x = config_tool_entry_first_x; 7514 bi->bi_tool_entry_next = config_tool_entry_next; 7515 bi->bi_tool_entry_get = config_tool_entry_get; 7516 bi->bi_tool_entry_put = config_tool_entry_put; 7517 7518 ca.argv = argv; 7519 argv[ 0 ] = "slapd"; 7520 ca.argv = argv; 7521 ca.argc = 3; 7522 ca.fname = argv[0]; 7523 7524 argv[3] = NULL; 7525 for (i=0; OidMacros[i].name; i++ ) { 7526 argv[1] = OidMacros[i].name; 7527 argv[2] = OidMacros[i].oid; 7528 parse_oidm( &ca, 0, NULL ); 7529 } 7530 7531 bi->bi_cf_ocs = cf_ocs; 7532 7533 i = config_register_schema( ct, cf_ocs ); 7534 if ( i ) return i; 7535 7536 i = slap_str2ad( "olcDatabase", &olcDatabaseDummy[0].ad, &text ); 7537 if ( i ) return i; 7538 7539 /* setup olcRootPW to be base64-encoded when written in LDIF form; 7540 * basically, we don't care if it fails */ 7541 i = slap_str2ad( "olcRootPW", &ad, &text ); 7542 if ( i ) { 7543 Debug( LDAP_DEBUG_ANY, "config_back_initialize: " 7544 "warning, unable to get \"olcRootPW\" " 7545 "attribute description: %d: %s\n", 7546 i, text, 0 ); 7547 } else { 7548 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val, 7549 ad->ad_type->sat_oid ); 7550 } 7551 7552 /* set up the notable AttributeDescriptions */ 7553 i = 0; 7554 for (;ct->name;ct++) { 7555 if (strcmp(ct->name, ads[i].name)) continue; 7556 *ads[i].desc = ct->ad; 7557 i++; 7558 if (!ads[i].name) break; 7559 } 7560 7561 return 0; 7562} 7563