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