1 /* bconfig.c - the config backend */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2005 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
17 * This work was originally developed by Howard Chu for inclusion
18 * in OpenLDAP Software.
24 #include <ac/string.h>
32 #include "slapi/slapi.h"
40 static struct berval config_rdn = BER_BVC("cn=config");
41 static struct berval schema_rdn = BER_BVC("cn=schema");
46 typedef struct modpath_s {
47 struct modpath_s *mp_next;
48 struct berval mp_path;
52 static ModPaths modpaths, *modlast = &modpaths, *modcur = &modpaths;
55 typedef struct ConfigFile {
56 struct ConfigFile *c_sibs;
57 struct ConfigFile *c_kids;
59 AttributeType *c_at_head, *c_at_tail;
60 ContentRule *c_cr_head, *c_cr_tail;
61 ObjectClass *c_oc_head, *c_oc_tail;
62 OidMacro *c_om_head, *c_om_tail;
66 typedef struct CfOcInfo {
67 struct berval *co_name;
68 ConfigTable *co_table;
73 typedef struct CfEntryInfo {
74 struct CfEntryInfo *ce_parent;
75 struct CfEntryInfo *ce_sibs;
76 struct CfEntryInfo *ce_kids;
84 ConfigFile *cb_config;
86 BackendDB cb_db; /* underlying database */
91 /* These do nothing in slapd, they're kept only to make them
94 static char *replica_pidFile, *replica_argsFile;
95 static int replicationInterval;
97 static char *passwd_salt;
98 static char *logfileName;
99 static BerVarray authz_rewrites;
101 static struct berval cfdir;
104 static AttributeDescription *cfAd_backend, *cfAd_database, *cfAd_overlay,
107 static ObjectClass *cfOc_schema, *cfOc_global, *cfOc_backend, *cfOc_database,
108 *cfOc_include, *cfOc_overlay, *cfOc_module;
110 static ConfigFile cf_prv, *cfn = &cf_prv;
112 static Avlnode *CfOcTree;
114 static int add_syncrepl LDAP_P(( Backend *, char **, int ));
115 static int parse_syncrepl_line LDAP_P(( char **, int, syncinfo_t *));
116 static void syncrepl_unparse LDAP_P (( syncinfo_t *, struct berval *));
117 static int config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs,
120 static ConfigDriver config_fname;
121 static ConfigDriver config_cfdir;
122 static ConfigDriver config_generic;
123 static ConfigDriver config_search_base;
124 static ConfigDriver config_passwd_hash;
125 static ConfigDriver config_schema_dn;
126 static ConfigDriver config_sizelimit;
127 static ConfigDriver config_timelimit;
128 static ConfigDriver config_limits;
129 static ConfigDriver config_overlay;
130 static ConfigDriver config_suffix;
131 static ConfigDriver config_deref_depth;
132 static ConfigDriver config_rootdn;
133 static ConfigDriver config_rootpw;
134 static ConfigDriver config_restrict;
135 static ConfigDriver config_allows;
136 static ConfigDriver config_disallows;
137 static ConfigDriver config_requires;
138 static ConfigDriver config_security;
139 static ConfigDriver config_referral;
140 static ConfigDriver config_loglevel;
141 static ConfigDriver config_syncrepl;
142 static ConfigDriver config_replica;
143 static ConfigDriver config_updatedn;
144 static ConfigDriver config_updateref;
145 static ConfigDriver config_include;
147 static ConfigDriver config_tls_option;
148 static ConfigDriver config_tls_config;
197 static OidRec OidMacros[] = {
198 /* OpenLDAProot:666.11.1 */
199 { "OLcfg", "1.3.6.1.4.1.4203.666.11.1" },
200 { "OLcfgAt", "OLcfg:3" },
201 { "OLcfgGlAt", "OLcfgAt:0" },
202 { "OLcfgBkAt", "OLcfgAt:1" },
203 { "OLcfgDbAt", "OLcfgAt:2" },
204 { "OLcfgOvAt", "OLcfgAt:3" },
205 { "OLcfgOc", "OLcfg:4" },
206 { "OLcfgGlOc", "OLcfgOc:0" },
207 { "OLcfgBkOc", "OLcfgOc:1" },
208 { "OLcfgDbOc", "OLcfgOc:2" },
209 { "OLcfgOvOc", "OLcfgOc:3" },
210 { "OMsyn", "1.3.6.1.4.1.1466.115.121.1" },
211 { "OMsInteger", "OMsyn:27" },
212 { "OMsBoolean", "OMsyn:7" },
213 { "OMsDN", "OMsyn:12" },
214 { "OMsDirectoryString", "OMsyn:15" },
215 { "OMsOctetString", "OMsyn:40" },
220 * OLcfg{Bk|Db}{Oc|At}:0 -> common
221 * OLcfg{Bk|Db}{Oc|At}:1 -> bdb
222 * OLcfg{Bk|Db}{Oc|At}:2 -> ldif
223 * OLcfg{Bk|Db}{Oc|At}:3 -> ldap?
226 /* alphabetical ordering */
228 ConfigTable config_back_cf_table[] = {
229 /* This attr is read-only */
230 { "", "", 0, 0, 0, ARG_MAGIC,
231 &config_fname, "( OLcfgGlAt:78 NAME 'olcConfigFile' "
232 "DESC 'File for slapd configuration directives' "
233 "EQUALITY caseIgnoreMatch "
234 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
235 { "", "", 0, 0, 0, ARG_MAGIC,
236 &config_cfdir, "( OLcfgGlAt:79 NAME 'olcConfigDir' "
237 "DESC 'Directory for slapd configuration backend' "
238 "EQUALITY caseIgnoreMatch "
239 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
240 { "access", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC|CFG_ACL,
241 &config_generic, "( OLcfgGlAt:1 NAME 'olcAccess' "
242 "DESC 'Access Control List' "
243 "EQUALITY caseIgnoreMatch "
244 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
245 { "allows", "features", 2, 0, 5, ARG_PRE_DB|ARG_MAGIC,
246 &config_allows, "( OLcfgGlAt:2 NAME 'olcAllows' "
247 "DESC 'Allowed set of deprecated features' "
248 "EQUALITY caseIgnoreMatch "
249 "SYNTAX OMsDirectoryString )", NULL, NULL },
250 { "argsfile", "file", 2, 2, 0, ARG_STRING,
251 &slapd_args_file, "( OLcfgGlAt:3 NAME 'olcArgsFile' "
252 "DESC 'File for slapd command line options' "
253 "EQUALITY caseIgnoreMatch "
254 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
255 { "attribute", "attribute", 2, 0, 9, ARG_PAREN|ARG_MAGIC|CFG_ATTR,
256 &config_generic, "( OLcfgGlAt:4 NAME 'olcAttributeTypes' "
257 "DESC 'OpenLDAP attributeTypes' "
258 "EQUALITY caseIgnoreMatch "
259 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
261 { "attributeoptions", NULL, 0, 0, 0, ARG_MAGIC|CFG_ATOPT,
262 &config_generic, "( OLcfgGlAt:5 NAME 'olcAttributeOptions' "
263 "EQUALITY caseIgnoreMatch "
264 "SYNTAX OMsDirectoryString )", NULL, NULL },
265 { "authid-rewrite", NULL, 2, 0, 0,
266 #ifdef SLAP_AUTH_REWRITE
267 ARG_MAGIC|CFG_REWRITE|ARG_NO_DELETE|ARG_NO_INSERT, &config_generic,
271 "( OLcfgGlAt:6 NAME 'olcAuthIDRewrite' "
272 "EQUALITY caseIgnoreMatch "
273 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
274 { "authz-policy", "policy", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_AZPOLICY,
275 &config_generic, "( OLcfgGlAt:7 NAME 'olcAuthzPolicy' "
276 "EQUALITY caseIgnoreMatch "
277 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
278 { "authz-regexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP|ARG_NO_DELETE|ARG_NO_INSERT,
279 &config_generic, "( OLcfgGlAt:8 NAME 'olcAuthzRegexp' "
280 "EQUALITY caseIgnoreMatch "
281 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
282 { "backend", "type", 2, 2, 0, ARG_PRE_DB|ARG_MAGIC|CFG_BACKEND,
283 &config_generic, "( OLcfgGlAt:9 NAME 'olcBackend' "
284 "DESC 'A type of backend' "
285 "EQUALITY caseIgnoreMatch "
286 "SYNTAX OMsDirectoryString SINGLE-VALUE X-ORDERED 'SIBLINGS' )",
288 { "concurrency", "level", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_CONCUR,
289 &config_generic, "( OLcfgGlAt:10 NAME 'olcConcurrency' "
290 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
291 { "conn_max_pending", "max", 2, 2, 0, ARG_INT,
292 &slap_conn_max_pending, "( OLcfgGlAt:11 NAME 'olcConnMaxPending' "
293 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
294 { "conn_max_pending_auth", "max", 2, 2, 0, ARG_INT,
295 &slap_conn_max_pending_auth, "( OLcfgGlAt:12 NAME 'olcConnMaxPendingAuth' "
296 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
297 { "database", "type", 2, 2, 0, ARG_MAGIC|CFG_DATABASE,
298 &config_generic, "( OLcfgGlAt:13 NAME 'olcDatabase' "
299 "DESC 'The backend type for a database instance' "
300 "SUP olcBackend SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL },
301 { "defaultSearchBase", "dn", 2, 2, 0, ARG_PRE_BI|ARG_PRE_DB|ARG_DN|ARG_MAGIC,
302 &config_search_base, "( OLcfgGlAt:14 NAME 'olcDefaultSearchBase' "
303 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
304 { "disallows", "features", 2, 0, 8, ARG_PRE_DB|ARG_MAGIC,
305 &config_disallows, "( OLcfgGlAt:15 NAME 'olcDisallows' "
306 "EQUALITY caseIgnoreMatch "
307 "SYNTAX OMsDirectoryString )", NULL, NULL },
308 { "ditcontentrule", NULL, 0, 0, 0, ARG_MAGIC|CFG_DIT,
309 &config_generic, "( OLcfgGlAt:16 NAME 'olcDitContentRules' "
310 "DESC 'OpenLDAP DIT content rules' "
311 "EQUALITY caseIgnoreMatch "
312 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
314 { "gentlehup", "on|off", 2, 2, 0,
316 ARG_ON_OFF, &global_gentlehup,
320 "( OLcfgGlAt:17 NAME 'olcGentleHUP' "
321 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
322 { "idletimeout", "timeout", 2, 2, 0, ARG_INT,
323 &global_idletimeout, "( OLcfgGlAt:18 NAME 'olcIdleTimeout' "
324 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
325 { "include", "file", 2, 2, 0, ARG_MAGIC,
326 &config_include, "( OLcfgGlAt:19 NAME 'olcInclude' "
327 "SUP labeledURI )", NULL, NULL },
328 { "index_substr_if_minlen", "min", 2, 2, 0, ARG_INT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MIN,
329 &config_generic, "( OLcfgGlAt:20 NAME 'olcIndexSubstrIfMinLen' "
330 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
331 { "index_substr_if_maxlen", "max", 2, 2, 0, ARG_INT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MAX,
332 &config_generic, "( OLcfgGlAt:21 NAME 'olcIndexSubstrIfMaxLen' "
333 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
334 { "index_substr_any_len", "len", 2, 2, 0, ARG_INT|ARG_NONZERO,
335 &index_substr_any_len, "( OLcfgGlAt:22 NAME 'olcIndexSubstrAnyLen' "
336 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
337 { "index_substr_step", "step", 2, 2, 0, ARG_INT|ARG_NONZERO,
338 &index_substr_any_step, "( OLcfgGlAt:23 NAME 'olcIndexSubstrAnyStep' "
339 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
340 { "lastmod", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_LASTMOD,
341 &config_generic, "( OLcfgDbAt:0.4 NAME 'olcLastMod' "
342 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
343 { "limits", "limits", 2, 0, 0, ARG_DB|ARG_MAGIC|CFG_LIMITS,
344 &config_generic, "( OLcfgDbAt:0.5 NAME 'olcLimits' "
345 "SYNTAX OMsDirectoryString )", NULL, NULL },
346 { "localSSF", "ssf", 2, 2, 0, ARG_INT,
347 &local_ssf, "( OLcfgGlAt:26 NAME 'olcLocalSSF' "
348 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
349 { "logfile", "file", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_LOGFILE,
350 &config_generic, "( OLcfgGlAt:27 NAME 'olcLogFile' "
351 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
352 { "loglevel", "level", 2, 0, 0, ARG_MAGIC,
353 &config_loglevel, "( OLcfgGlAt:28 NAME 'olcLogLevel' "
354 "SYNTAX OMsDirectoryString )", NULL, NULL },
355 { "maxDerefDepth", "depth", 2, 2, 0, ARG_DB|ARG_INT|ARG_MAGIC|CFG_DEPTH,
356 &config_generic, "( OLcfgDbAt:0.6 NAME 'olcMaxDerefDepth' "
357 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
358 { "moduleload", "file", 2, 0, 0,
360 ARG_MAGIC|CFG_MODLOAD, &config_generic,
364 "( OLcfgGlAt:30 NAME 'olcModuleLoad' "
365 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
366 { "modulepath", "path", 2, 2, 0,
368 ARG_MAGIC|CFG_MODPATH, &config_generic,
372 "( OLcfgGlAt:31 NAME 'olcModulePath' "
373 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
374 { "objectclass", "objectclass", 2, 0, 0, ARG_PAREN|ARG_MAGIC|CFG_OC,
375 &config_generic, "( OLcfgGlAt:32 NAME 'olcObjectClasses' "
376 "DESC 'OpenLDAP object classes' "
377 "EQUALITY caseIgnoreMatch "
378 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
380 { "objectidentifier", NULL, 0, 0, 0, ARG_MAGIC|CFG_OID,
381 &config_generic, "( OLcfgGlAt:33 NAME 'olcObjectIdentifier' "
382 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
383 { "overlay", "overlay", 2, 2, 0, ARG_MAGIC,
384 &config_overlay, "( OLcfgGlAt:34 NAME 'olcOverlay' "
385 "SUP olcDatabase SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL },
386 { "password-crypt-salt-format", "salt", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_SALT,
387 &config_generic, "( OLcfgGlAt:35 NAME 'olcPasswordCryptSaltFormat' "
388 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
389 { "password-hash", "hash", 2, 2, 0, ARG_MAGIC,
390 &config_passwd_hash, "( OLcfgGlAt:36 NAME 'olcPasswordHash' "
391 "SYNTAX OMsDirectoryString )", NULL, NULL },
392 { "pidfile", "file", 2, 2, 0, ARG_STRING,
393 &slapd_pid_file, "( OLcfgGlAt:37 NAME 'olcPidFile' "
394 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
395 { "plugin", NULL, 0, 0, 0,
397 ARG_MAGIC|CFG_PLUGIN, &config_generic,
401 "( OLcfgGlAt:38 NAME 'olcPlugin' "
402 "SYNTAX OMsDirectoryString )", NULL, NULL },
403 { "pluginlog", "filename", 2, 2, 0,
405 ARG_STRING, &slapi_log_file,
409 "( OLcfgGlAt:39 NAME 'olcPluginLogFile' "
410 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
411 { "readonly", "on|off", 2, 2, 0, ARG_MAY_DB|ARG_ON_OFF|ARG_MAGIC|CFG_RO,
412 &config_generic, "( OLcfgGlAt:40 NAME 'olcReadOnly' "
413 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
414 { "referral", "url", 2, 2, 0, ARG_MAGIC,
415 &config_referral, "( OLcfgGlAt:41 NAME 'olcReferral' "
416 "SUP labeledURI SINGLE-VALUE )", NULL, NULL },
417 { "replica", "host or uri", 2, 0, 0, ARG_DB|ARG_MAGIC,
418 &config_replica, "( OLcfgDbAt:0.7 NAME 'olcReplica' "
419 "SUP labeledURI )", NULL, NULL },
420 { "replica-argsfile", NULL, 0, 0, 0, ARG_STRING,
421 &replica_argsFile, "( OLcfgGlAt:43 NAME 'olcReplicaArgsFile' "
422 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
423 { "replica-pidfile", NULL, 0, 0, 0, ARG_STRING,
424 &replica_pidFile, "( OLcfgGlAt:44 NAME 'olcReplicaPidFile' "
425 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
426 { "replicationInterval", NULL, 0, 0, 0, ARG_INT,
427 &replicationInterval, "( OLcfgGlAt:45 NAME 'olcReplicationInterval' "
428 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
429 { "replogfile", "filename", 2, 2, 0, ARG_MAY_DB|ARG_MAGIC|ARG_STRING|CFG_REPLOG,
430 &config_generic, "( OLcfgGlAt:46 NAME 'olcReplogFile' "
431 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
432 { "require", "features", 2, 0, 7, ARG_MAY_DB|ARG_MAGIC,
433 &config_requires, "( OLcfgGlAt:47 NAME 'olcRequires' "
434 "SYNTAX OMsDirectoryString )", NULL, NULL },
435 { "restrict", "op_list", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
436 &config_restrict, "( OLcfgGlAt:48 NAME 'olcRestrict' "
437 "SYNTAX OMsDirectoryString )", NULL, NULL },
438 { "reverse-lookup", "on|off", 2, 2, 0,
439 #ifdef SLAPD_RLOOKUPS
440 ARG_ON_OFF, &use_reverse_lookup,
444 "( OLcfgGlAt:49 NAME 'olcReverseLookup' "
445 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
446 { "rootdn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_MAGIC,
447 &config_rootdn, "( OLcfgDbAt:0.8 NAME 'olcRootDN' "
448 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
449 { "rootDSE", "file", 2, 2, 0, ARG_MAGIC|CFG_ROOTDSE,
450 &config_generic, "( OLcfgGlAt:51 NAME 'olcRootDSE' "
451 "SYNTAX OMsDirectoryString )", NULL, NULL },
452 { "rootpw", "password", 2, 2, 0, ARG_BERVAL|ARG_DB|ARG_MAGIC,
453 &config_rootpw, "( OLcfgDbAt:0.9 NAME 'olcRootPW' "
454 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
455 { "sasl-authz-policy", NULL, 2, 2, 0, ARG_MAGIC|CFG_AZPOLICY,
456 &config_generic, NULL, NULL, NULL },
457 { "sasl-host", "host", 2, 2, 0,
458 #ifdef HAVE_CYRUS_SASL
459 ARG_STRING|ARG_UNIQUE, &global_host,
463 "( OLcfgGlAt:53 NAME 'olcSaslHost' "
464 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
465 { "sasl-realm", "realm", 2, 2, 0,
466 #ifdef HAVE_CYRUS_SASL
467 ARG_STRING|ARG_UNIQUE, &global_realm,
471 "( OLcfgGlAt:54 NAME 'olcSaslRealm' "
472 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
473 { "sasl-regexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP,
474 &config_generic, NULL, NULL, NULL },
475 { "sasl-secprops", "properties", 2, 2, 0,
476 #ifdef HAVE_CYRUS_SASL
477 ARG_MAGIC|CFG_SASLSECP, &config_generic,
481 "( OLcfgGlAt:56 NAME 'olcSaslSecProps' "
482 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
483 { "saslRegexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP,
484 &config_generic, NULL, NULL, NULL },
485 { "schemacheck", "on|off", 2, 2, 0, ARG_ON_OFF|ARG_MAGIC|CFG_CHECK,
486 &config_generic, "( OLcfgGlAt:57 NAME 'olcSchemaCheck' "
487 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
488 { "schemadn", "dn", 2, 2, 0, ARG_MAY_DB|ARG_DN|ARG_MAGIC,
489 &config_schema_dn, "( OLcfgGlAt:58 NAME 'olcSchemaDN' "
490 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
491 { "security", "factors", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
492 &config_security, "( OLcfgGlAt:59 NAME 'olcSecurity' "
493 "SYNTAX OMsDirectoryString )", NULL, NULL },
494 { "sizelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC|CFG_SIZE,
495 &config_sizelimit, "( OLcfgGlAt:60 NAME 'olcSizeLimit' "
496 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
497 { "sockbuf_max_incoming", "max", 2, 2, 0, ARG_BER_LEN_T,
498 &sockbuf_max_incoming, "( OLcfgGlAt:61 NAME 'olcSockbufMaxIncoming' "
499 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
500 { "sockbuf_max_incoming_auth", "max", 2, 2, 0, ARG_BER_LEN_T,
501 &sockbuf_max_incoming_auth, "( OLcfgGlAt:62 NAME 'olcSockbufMaxIncomingAuth' "
502 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
503 { "srvtab", "file", 2, 2, 0,
504 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
505 ARG_STRING, &ldap_srvtab,
509 "( OLcfgGlAt:63 NAME 'olcSrvtab' "
510 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
511 { "suffix", "suffix", 2, 2, 0, ARG_DB|ARG_DN|ARG_MAGIC,
512 &config_suffix, "( OLcfgDbAt:0.10 NAME 'olcSuffix' "
513 "SYNTAX OMsDN )", NULL, NULL },
514 { "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
515 &config_syncrepl, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
516 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
517 { "threads", "count", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_THREADS,
518 &config_generic, "( OLcfgGlAt:66 NAME 'olcThreads' "
519 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
520 { "timelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC|CFG_TIME,
521 &config_timelimit, "( OLcfgGlAt:67 NAME 'olcTimeLimit' "
522 "SYNTAX OMsInteger )", NULL, NULL },
523 { "TLSCACertificateFile", NULL, 0, 0, 0,
525 CFG_TLS_CA_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
529 "( OLcfgGlAt:68 NAME 'olcTLSCACertificateFile' "
530 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
531 { "TLSCACertificatePath", NULL, 0, 0, 0,
533 CFG_TLS_CA_PATH|ARG_STRING|ARG_MAGIC, &config_tls_option,
537 "( OLcfgGlAt:69 NAME 'olcTLSCACertificatePath' "
538 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
539 { "TLSCertificateFile", NULL, 0, 0, 0,
541 CFG_TLS_CERT_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
545 "( OLcfgGlAt:70 NAME 'olcTLSCertificateFile' "
546 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
547 { "TLSCertificateKeyFile", NULL, 0, 0, 0,
549 CFG_TLS_CERT_KEY|ARG_STRING|ARG_MAGIC, &config_tls_option,
553 "( OLcfgGlAt:71 NAME 'olcTLSCertificateKeyFile' "
554 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
555 { "TLSCipherSuite", NULL, 0, 0, 0,
557 CFG_TLS_CIPHER|ARG_STRING|ARG_MAGIC, &config_tls_option,
561 "( OLcfgGlAt:72 NAME 'olcTLSCipherSuite' "
562 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
563 { "TLSCRLCheck", NULL, 0, 0, 0,
564 #if defined(HAVE_TLS) && defined(HAVE_OPENSSL_CRL)
565 CFG_TLS_CRLCHECK|ARG_STRING|ARG_MAGIC, &config_tls_config,
569 "( OLcfgGlAt:73 NAME 'olcTLSCRLCheck' "
570 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
571 { "TLSRandFile", NULL, 0, 0, 0,
573 CFG_TLS_RAND|ARG_STRING|ARG_MAGIC, &config_tls_option,
577 "( OLcfgGlAt:74 NAME 'olcTLSRandFile' "
578 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
579 { "TLSVerifyClient", NULL, 0, 0, 0,
581 CFG_TLS_VERIFY|ARG_STRING|ARG_MAGIC, &config_tls_config,
585 "( OLcfgGlAt:75 NAME 'olcTLSVerifyClient' "
586 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
587 { "ucdata-path", "path", 2, 2, 0, ARG_IGNORED,
588 NULL, NULL, NULL, NULL },
589 { "updatedn", "dn", 2, 2, 0, ARG_DB|ARG_MAGIC,
590 &config_updatedn, "( OLcfgDbAt:0.12 NAME 'olcUpdateDN' "
591 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
592 { "updateref", "url", 2, 2, 0, ARG_DB|ARG_MAGIC,
593 &config_updateref, "( OLcfgDbAt:0.13 NAME 'olcUpdateRef' "
594 "SUP labeledURI )", NULL, NULL },
595 { NULL, NULL, 0, 0, 0, ARG_IGNORED,
596 NULL, NULL, NULL, NULL }
599 static ConfigOCs cf_ocs[] = {
602 "DESC 'OpenLDAP configuration object' "
603 "ABSTRACT SUP top )", Cft_Abstract, NULL },
606 "DESC 'OpenLDAP Global configuration options' "
607 "SUP olcConfig STRUCTURAL "
608 "MAY ( cn $ olcConfigFile $ olcConfigDir $ olcAllows $ olcArgsFile $ "
609 "olcAttributeOptions $ olcAuthIDRewrite $ "
610 "olcAuthzPolicy $ olcAuthzRegexp $ olcConcurrency $ "
611 "olcConnMaxPending $ olcConnMaxPendingAuth $ olcDefaultSearchBase $ "
612 "olcDisallows $ olcGentleHUP $ olcIdleTimeout $ "
613 "olcIndexSubstrIfMaxLen $ olcIndexSubstrIfMinLen $ "
614 "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcLocalSSF $ "
615 "olcLogLevel $ olcModulePath $ "
616 "olcPasswordCryptSaltFormat $ olcPasswordHash $ olcPidFile $ "
617 "olcPluginLogFile $ olcReadOnly $ olcReferral $ "
618 "olcReplicaPidFile $ olcReplicaArgsFile $ olcReplicationInterval $ "
619 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
620 "olcRootDSE $ olcRootPW $ "
621 "olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
622 "olcSchemaCheck $ olcSecurity $ olcSizeLimit $ "
623 "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ olcSrvtab $ "
624 "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
625 "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
626 "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
627 "olcTLSRandFile $ olcTLSVerifyClient $ "
628 "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ "
629 "olcDitContentRules ) )", Cft_Global, &cfOc_global },
631 "NAME 'olcSchemaConfig' "
632 "DESC 'OpenLDAP schema object' "
633 "SUP olcConfig STRUCTURAL "
634 "MAY ( cn $ olcObjectIdentifier $ olcAttributeTypes $ "
635 "olcObjectClasses $ olcDitContentRules ) )",
636 Cft_Schema, &cfOc_schema },
638 "NAME 'olcBackendConfig' "
639 "DESC 'OpenLDAP Backend-specific options' "
640 "SUP olcConfig STRUCTURAL "
641 "MUST olcBackend )", Cft_Backend, &cfOc_backend },
643 "NAME 'olcDatabaseConfig' "
644 "DESC 'OpenLDAP Database-specific options' "
645 "SUP olcConfig STRUCTURAL "
647 "MAY ( olcSuffix $ olcAccess $ olcLastMod $ olcLimits $ "
648 "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
649 "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
650 "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncrepl $ "
651 "olcTimeLimit $ olcUpdateDN $ olcUpdateRef ) )",
652 Cft_Database, &cfOc_database },
654 "NAME 'olcOverlayConfig' "
655 "DESC 'OpenLDAP Overlay-specific options' "
656 "SUP olcConfig STRUCTURAL "
657 "MUST olcOverlay )", Cft_Overlay, &cfOc_overlay },
659 "NAME 'olcIncludeFile' "
660 "DESC 'OpenLDAP configuration include file' "
661 "SUP olcConfig STRUCTURAL "
663 "MAY ( cn $ olcRootDSE ) )",
664 Cft_Include, &cfOc_include },
667 "NAME 'olcModuleList' "
668 "DESC 'OpenLDAP dynamic module info' "
669 "SUP olcConfig STRUCTURAL "
670 "MUST olcModuleLoad "
671 "MAY cn )", Cft_Module, &cfOc_module },
677 config_generic(ConfigArgs *c) {
681 if ( c->op == SLAP_CONFIG_EMIT ) {
685 c->value_int = ldap_pvt_thread_get_concurrency();
688 c->value_int = connection_pool_max;
692 c->value_string = ch_strdup( passwd_salt );
697 if ( c->be->be_limits ) {
702 for ( i=0; c->be->be_limits[i]; i++ ) {
703 bv.bv_len = sprintf( buf, IFMT, i );
704 bv.bv_val = buf+bv.bv_len;
705 limits_unparse( c->be->be_limits[i], &bv );
706 bv.bv_len += bv.bv_val - buf;
708 value_add_one( &c->rvalue_vals, &bv );
711 if ( !c->rvalue_vals ) rc = 1;
714 c->value_int = (c->be->be_restrictops & SLAP_RESTRICT_OP_WRITES) != 0;
717 c->value_string = ch_strdup( slap_sasl_getpolicy());
720 slap_sasl_regexp_unparse( &c->rvalue_vals );
721 if ( !c->rvalue_vals ) rc = 1;
723 #ifdef HAVE_CYRUS_SASL
725 struct berval bv = BER_BVNULL;
726 slap_sasl_secprops_unparse( &bv );
727 if ( !BER_BVISNULL( &bv )) {
728 ber_bvarray_add( &c->rvalue_vals, &bv );
736 c->value_int = c->be->be_max_deref_depth;
739 ConfigFile *cf = c->private;
741 oidm_unparse( &c->rvalue_vals, NULL, NULL, 1 );
742 else if ( cf->c_om_head )
743 oidm_unparse( &c->rvalue_vals, cf->c_om_head,
745 if ( !c->rvalue_vals )
750 ConfigFile *cf = c->private;
752 oc_unparse( &c->rvalue_vals, NULL, NULL, 1 );
753 else if ( cf->c_oc_head )
754 oc_unparse( &c->rvalue_vals, cf->c_oc_head,
756 if ( !c->rvalue_vals )
761 ConfigFile *cf = c->private;
763 at_unparse( &c->rvalue_vals, NULL, NULL, 1 );
764 else if ( cf->c_at_head )
765 at_unparse( &c->rvalue_vals, cf->c_at_head,
767 if ( !c->rvalue_vals )
772 ConfigFile *cf = c->private;
774 cr_unparse( &c->rvalue_vals, NULL, NULL, 1 );
775 else if ( cf->c_cr_head )
776 cr_unparse( &c->rvalue_vals, cf->c_cr_head,
778 if ( !c->rvalue_vals )
784 c->value_int = global_schemacheck;
788 char *src, *dst, ibuf[11];
789 struct berval bv, abv;
790 for (i=0, a=c->be->be_acl; a; i++,a=a->acl_next) {
791 abv.bv_len = sprintf( ibuf, IFMT, i );
792 acl_unparse( a, &bv );
793 abv.bv_val = ch_malloc( abv.bv_len + bv.bv_len + 1 );
794 AC_MEMCPY( abv.bv_val, ibuf, abv.bv_len );
795 /* Turn TAB / EOL into plain space */
796 for (src=bv.bv_val,dst=abv.bv_val+abv.bv_len; *src; src++) {
797 if (isspace(*src)) *dst++ = ' ';
801 if (dst[-1] == ' ') {
805 abv.bv_len = dst - abv.bv_val;
806 ber_bvarray_add( &c->rvalue_vals, &abv );
812 if ( c->be->be_replogfile )
813 c->value_string = ch_strdup( c->be->be_replogfile );
816 ConfigFile *cf = c->private;
817 if ( cf->c_dseFiles ) {
818 value_add( &c->rvalue_vals, cf->c_dseFiles );
826 c->value_string = ch_strdup( logfileName );
831 c->value_int = (SLAP_NOLASTMOD(c->be) == 0);
833 case CFG_SSTR_IF_MAX:
834 c->value_int = index_substr_if_maxlen;
836 case CFG_SSTR_IF_MIN:
837 c->value_int = index_substr_if_minlen;
841 ModPaths *mp = c->private;
844 for (i=0; !BER_BVISNULL(&mp->mp_loads[i]); i++) {
847 bv.bv_len = sprintf( bv.bv_val, IFMT "%s", i,
848 mp->mp_loads[i].bv_val );
849 value_add_one( &c->rvalue_vals, &bv );
853 rc = c->rvalue_vals ? 0 : 1;
858 for (i=0, mp=&modpaths; mp; mp=mp->mp_next, i++) {
860 if ( BER_BVISNULL( &mp->mp_path ) && !mp->mp_loads )
863 bv.bv_len = sprintf( bv.bv_val, IFMT "%s", i,
864 mp->mp_path.bv_val );
865 value_add_one( &c->rvalue_vals, &bv );
867 rc = c->rvalue_vals ? 0 : 1;
873 slapi_int_plugin_unparse( c->be, &c->rvalue_vals );
874 if ( !c->rvalue_vals ) rc = 1;
877 #ifdef SLAP_AUTH_REWRITE
879 if ( authz_rewrites ) {
880 struct berval bv, idx;
885 for ( i=0; !BER_BVISNULL( &authz_rewrites[i] ); i++ ) {
886 idx.bv_len = sprintf( idx.bv_val, IFMT, i );
887 bv.bv_len = idx.bv_len + authz_rewrites[i].bv_len;
888 bv.bv_val = ch_malloc( bv.bv_len + 1 );
889 strcpy( bv.bv_val, idx.bv_val );
890 strcpy( bv.bv_val+idx.bv_len, authz_rewrites[i].bv_val );
891 ber_bvarray_add( &c->rvalue_vals, &bv );
894 if ( !c->rvalue_vals ) rc = 1;
901 } else if ( c->op == LDAP_MOD_DELETE ) {
904 /* single-valued attrs, no-ops */
912 case CFG_SSTR_IF_MAX:
913 case CFG_SSTR_IF_MIN:
917 ch_free( passwd_salt );
922 ch_free( c->be->be_replogfile );
923 c->be->be_replogfile = NULL;
927 ch_free( logfileName );
934 if ( c->be == frontendDB )
937 end = frontendDB->be_acl;
938 acl_destroy( c->be->be_acl, end );
940 AccessControl **prev, *a;
942 for (i=0, prev = &c->be->be_acl; i < c->valx;
959 p = strchr(c->line,'(' /*')'*/);
963 if(!(c->bi = backend_info(c->argv[1]))) {
964 Debug(LDAP_DEBUG_ANY, "%s: "
965 "backend %s failed init!\n", c->log, c->argv[1], 0);
972 /* NOTE: config is always the first backend!
974 if ( !strcasecmp( c->argv[1], "config" )) {
975 c->be = LDAP_STAILQ_FIRST(&backendDB);
976 } else if ( !strcasecmp( c->argv[1], "frontend" )) {
978 } else if(!(c->be = backend_db_init(c->argv[1]))) {
979 Debug(LDAP_DEBUG_ANY, "%s: "
980 "database %s failed init!\n", c->log, c->argv[1], 0);
986 ldap_pvt_thread_set_concurrency(c->value_int);
990 ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int);
991 connection_pool_max = c->value_int; /* save for reference */
995 if ( passwd_salt ) ch_free( passwd_salt );
996 passwd_salt = c->value_string;
997 lutil_salt_format(passwd_salt);
1001 if(limits_parse(c->be, c->fname, c->lineno, c->argc, c->argv))
1007 c->be->be_restrictops |= SLAP_RESTRICT_OP_WRITES;
1009 c->be->be_restrictops &= ~SLAP_RESTRICT_OP_WRITES;
1013 ch_free(c->value_string);
1014 if (slap_sasl_setpolicy( c->argv[1] )) {
1015 Debug(LDAP_DEBUG_ANY, "%s: unable to parse value \"%s\" in"
1016 " \"authz-policy <policy>\"\n",
1017 c->log, c->argv[1], 0 );
1023 if (slap_sasl_regexp_config( c->argv[1], c->argv[2] ))
1027 #ifdef HAVE_CYRUS_SASL
1030 char *txt = slap_sasl_secprops( c->argv[1] );
1032 Debug(LDAP_DEBUG_ANY, "%s: sasl-secprops: %s\n",
1041 c->be->be_max_deref_depth = c->value_int;
1047 if(parse_oidm(c->fname, c->lineno, c->argc, c->argv, 1, &om))
1049 if (!cfn->c_om_head) cfn->c_om_head = om;
1050 cfn->c_om_tail = om;
1057 if(parse_oc(c->fname, c->lineno, p, c->argv, &oc)) return(1);
1058 if (!cfn->c_oc_head) cfn->c_oc_head = oc;
1059 cfn->c_oc_tail = oc;
1066 if(parse_cr(c->fname, c->lineno, p, c->argv, &cr)) return(1);
1067 if (!cfn->c_cr_head) cfn->c_cr_head = cr;
1068 cfn->c_cr_tail = cr;
1075 if(parse_at(c->fname, c->lineno, p, c->argv, &at)) return(1);
1076 if (!cfn->c_at_head) cfn->c_at_head = at;
1077 cfn->c_at_tail = at;
1082 ad_define_option(NULL, NULL, 0);
1083 for(i = 1; i < c->argc; i++)
1084 if(ad_define_option(c->argv[i], c->fname, c->lineno))
1089 global_schemacheck = c->value_int;
1090 if(!global_schemacheck) Debug(LDAP_DEBUG_ANY, "%s: "
1091 "schema checking disabled! your mileage may vary!\n",
1096 parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, c->valx);
1100 if(SLAP_MONITOR(c->be)) {
1101 Debug(LDAP_DEBUG_ANY, "%s: "
1102 "\"replogfile\" should not be used "
1103 "inside monitor database\n",
1105 return(0); /* FIXME: should this be an error? */
1108 c->be->be_replogfile = c->value_string;
1112 if(read_root_dse_file(c->argv[1])) {
1113 Debug(LDAP_DEBUG_ANY, "%s: "
1114 "could not read \"rootDSE <filename>\" line\n",
1120 ber_str2bv( c->argv[1], 0, 1, &bv );
1121 ber_bvarray_add( &cfn->c_dseFiles, &bv );
1127 if ( logfileName ) ch_free( logfileName );
1128 logfileName = c->value_string;
1129 logfile = fopen(logfileName, "w");
1130 if(logfile) lutil_debug_file(logfile);
1134 if(SLAP_NOLASTMODCMD(c->be)) {
1135 Debug(LDAP_DEBUG_ANY, "%s: "
1136 "lastmod not available for %s databases\n",
1137 c->log, c->be->bd_info->bi_type, 0);
1141 SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_NOLASTMOD;
1143 SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_NOLASTMOD;
1146 case CFG_SSTR_IF_MAX:
1147 if (c->value_int < index_substr_if_minlen) {
1148 Debug(LDAP_DEBUG_ANY, "%s: "
1149 "invalid max value (%d)\n",
1150 c->log, c->value_int, 0 );
1153 index_substr_if_maxlen = c->value_int;
1156 case CFG_SSTR_IF_MIN:
1157 if (c->value_int > index_substr_if_maxlen) {
1158 Debug(LDAP_DEBUG_ANY, "%s: "
1159 "invalid min value (%d)\n",
1160 c->log, c->value_int, 0 );
1163 index_substr_if_minlen = c->value_int;
1166 #ifdef SLAPD_MODULES
1168 if(module_load(c->argv[1], c->argc - 2, (c->argc > 2) ? c->argv + 2 : NULL))
1170 /* Record this load on the current path */
1173 char *ptr = c->line + STRLENOF("moduleload");
1174 while (!isspace(*ptr)) ptr++;
1175 while (isspace(*ptr)) ptr++;
1176 ber_str2bv(ptr, 0, 1, &bv);
1177 ber_bvarray_add( &modcur->mp_loads, &bv );
1182 if(module_path(c->argv[1])) return(1);
1183 /* Record which path was used with each module */
1187 if (!modpaths.mp_loads) {
1190 mp = ch_malloc( sizeof( ModPaths ));
1191 modlast->mp_next = mp;
1193 ber_str2bv(c->argv[1], 0, 1, &mp->mp_path);
1195 mp->mp_loads = NULL;
1197 if ( c->op == SLAP_CONFIG_ADD )
1206 if(slapi_int_read_config(c->be, c->fname, c->lineno, c->argc, c->argv) != LDAP_SUCCESS)
1208 slapi_plugins_used++;
1212 #ifdef SLAP_AUTH_REWRITE
1215 if(slap_sasl_rewrite_config(c->fname, c->lineno, c->argc, c->argv))
1217 ber_str2bv( c->line, 0, 1, &bv );
1218 ber_bvarray_add( &authz_rewrites, &bv );
1225 Debug(LDAP_DEBUG_ANY, "%s: unknown CFG_TYPE %d"
1226 "(ignored)\n", c->log, c->type, 0);
1234 config_fname(ConfigArgs *c) {
1235 if(c->op == SLAP_CONFIG_EMIT) {
1237 ConfigFile *cf = c->private;
1238 value_add_one( &c->rvalue_vals, &cf->c_file );
1247 config_cfdir(ConfigArgs *c) {
1248 if(c->op == SLAP_CONFIG_EMIT) {
1249 value_add_one( &c->rvalue_vals, &cfdir );
1256 config_search_base(ConfigArgs *c) {
1259 if(c->op == SLAP_CONFIG_EMIT) {
1261 if (!BER_BVISEMPTY(&default_search_base)) {
1262 value_add_one(&c->rvalue_vals, &default_search_base);
1263 value_add_one(&c->rvalue_nvals, &default_search_nbase);
1267 } else if( c->op == LDAP_MOD_DELETE ) {
1268 ch_free( default_search_base.bv_val );
1269 ch_free( default_search_nbase.bv_val );
1270 BER_BVZERO( &default_search_base );
1271 BER_BVZERO( &default_search_nbase );
1275 if(c->bi || c->be != frontendDB) {
1276 Debug(LDAP_DEBUG_ANY, "%s: defaultSearchBase line must appear "
1277 "prior to any backend or database definition\n",
1282 if(default_search_nbase.bv_len) {
1283 Debug(LDAP_DEBUG_ANY, "%s: "
1284 "default search base \"%s\" already defined "
1285 "(discarding old)\n",
1286 c->log, default_search_base.bv_val, 0);
1287 free(default_search_base.bv_val);
1288 free(default_search_nbase.bv_val);
1291 default_search_base = c->value_dn;
1292 default_search_nbase = c->value_ndn;
1297 config_passwd_hash(ConfigArgs *c) {
1299 if (c->op == SLAP_CONFIG_EMIT) {
1301 for (i=0; default_passwd_hash && default_passwd_hash[i]; i++) {
1302 ber_str2bv(default_passwd_hash[i], 0, 0, &bv);
1303 value_add_one(&c->rvalue_vals, &bv);
1306 } else if ( c->op == LDAP_MOD_DELETE ) {
1307 if ( c->valx < 0 ) {
1308 ldap_charray_free( default_passwd_hash );
1309 default_passwd_hash = NULL;
1312 ch_free( default_passwd_hash[i] );
1313 for (; default_passwd_hash[i]; i++ )
1314 default_passwd_hash[i] = default_passwd_hash[i+1];
1318 if(default_passwd_hash) {
1319 Debug(LDAP_DEBUG_ANY, "%s: "
1320 "already set default password_hash\n",
1324 for(i = 1; i < c->argc; i++) {
1325 if(!lutil_passwd_scheme(c->argv[i])) {
1326 Debug(LDAP_DEBUG_ANY, "%s: "
1327 "password scheme \"%s\" not available\n",
1328 c->log, c->argv[i], 0);
1330 ldap_charray_add(&default_passwd_hash, c->argv[i]);
1332 if(!default_passwd_hash) {
1333 Debug(LDAP_DEBUG_ANY, "%s: no valid hashes found\n",
1342 config_schema_dn(ConfigArgs *c) {
1343 if ( c->op == SLAP_CONFIG_EMIT ) {
1345 if ( !BER_BVISEMPTY( &c->be->be_schemadn )) {
1346 value_add_one(&c->rvalue_vals, &c->be->be_schemadn);
1347 value_add_one(&c->rvalue_nvals, &c->be->be_schemandn);
1351 } else if ( c->op == LDAP_MOD_DELETE ) {
1352 ch_free( c->be->be_schemadn.bv_val );
1353 ch_free( c->be->be_schemandn.bv_val );
1354 BER_BVZERO( &c->be->be_schemadn );
1355 BER_BVZERO( &c->be->be_schemandn );
1358 ch_free( c->be->be_schemadn.bv_val );
1359 ch_free( c->be->be_schemandn.bv_val );
1360 c->be->be_schemadn = c->value_dn;
1361 c->be->be_schemandn = c->value_ndn;
1366 config_sizelimit(ConfigArgs *c) {
1369 struct slap_limits_set *lim = &c->be->be_def_limit;
1370 if (c->op == SLAP_CONFIG_EMIT) {
1375 limits_unparse_one( lim, SLAP_LIMIT_SIZE, &bv );
1376 if ( !BER_BVISEMPTY( &bv ))
1377 value_add_one( &c->rvalue_vals, &bv );
1381 } else if ( c->op == LDAP_MOD_DELETE ) {
1382 /* Reset to defaults */
1383 lim->lms_s_soft = SLAPD_DEFAULT_SIZELIMIT;
1384 lim->lms_s_hard = 0;
1385 lim->lms_s_unchecked = -1;
1387 lim->lms_s_pr_hide = 0;
1388 lim->lms_s_pr_total = 0;
1391 for(i = 1; i < c->argc; i++) {
1392 if(!strncasecmp(c->argv[i], "size", 4)) {
1393 rc = limits_parse_one(c->argv[i], lim);
1395 Debug(LDAP_DEBUG_ANY, "%s: "
1396 "unable to parse value \"%s\" in \"sizelimit <limit>\" line\n",
1397 c->log, c->argv[i], 0);
1401 if(!strcasecmp(c->argv[i], "unlimited")) {
1402 lim->lms_s_soft = -1;
1404 lim->lms_s_soft = strtol(c->argv[i], &next, 0);
1405 if(next == c->argv[i]) {
1406 Debug(LDAP_DEBUG_ANY, "%s: "
1407 "unable to parse limit \"%s\" in \"sizelimit <limit>\" line\n",
1408 c->log, c->argv[i], 0);
1410 } else if(next[0] != '\0') {
1411 Debug(LDAP_DEBUG_ANY, "%s: "
1412 "trailing chars \"%s\" in \"sizelimit <limit>\" line (ignored)\n",
1416 lim->lms_s_hard = 0;
1423 config_timelimit(ConfigArgs *c) {
1426 struct slap_limits_set *lim = &c->be->be_def_limit;
1427 if (c->op == SLAP_CONFIG_EMIT) {
1432 limits_unparse_one( lim, SLAP_LIMIT_TIME, &bv );
1433 if ( !BER_BVISEMPTY( &bv ))
1434 value_add_one( &c->rvalue_vals, &bv );
1438 } else if ( c->op == LDAP_MOD_DELETE ) {
1439 /* Reset to defaults */
1440 lim->lms_t_soft = SLAPD_DEFAULT_TIMELIMIT;
1441 lim->lms_t_hard = 0;
1444 for(i = 1; i < c->argc; i++) {
1445 if(!strncasecmp(c->argv[i], "time", 4)) {
1446 rc = limits_parse_one(c->argv[i], lim);
1448 Debug(LDAP_DEBUG_ANY, "%s: "
1449 "unable to parse value \"%s\" in \"timelimit <limit>\" line\n",
1450 c->log, c->argv[i], 0);
1454 if(!strcasecmp(c->argv[i], "unlimited")) {
1455 lim->lms_t_soft = -1;
1457 lim->lms_t_soft = strtol(c->argv[i], &next, 0);
1458 if(next == c->argv[i]) {
1459 Debug(LDAP_DEBUG_ANY, "%s: "
1460 "unable to parse limit \"%s\" in \"timelimit <limit>\" line\n",
1461 c->log, c->argv[i], 0);
1463 } else if(next[0] != '\0') {
1464 Debug(LDAP_DEBUG_ANY, "%s: "
1465 "trailing chars \"%s\" in \"timelimit <limit>\" line (ignored)\n",
1469 lim->lms_t_hard = 0;
1476 config_overlay(ConfigArgs *c) {
1477 if (c->op == SLAP_CONFIG_EMIT) {
1479 } else if ( c->op == LDAP_MOD_DELETE ) {
1482 if(c->argv[1][0] == '-' && overlay_config(c->be, &c->argv[1][1])) {
1484 Debug(LDAP_DEBUG_ANY, "%s: (optional) %s overlay \"%s\" configuration failed (ignored)\n",
1485 c->log, c->be == frontendDB ? "global " : "", c->argv[1][1]);
1486 } else if(overlay_config(c->be, c->argv[1])) {
1493 config_suffix(ConfigArgs *c) {
1495 struct berval pdn, ndn;
1498 if (c->be == frontendDB || SLAP_MONITOR(c->be) ||
1499 SLAP_CONFIG(c->be)) return 1;
1501 if (c->op == SLAP_CONFIG_EMIT) {
1502 if ( c->be->be_suffix == NULL
1503 || BER_BVISNULL( &c->be->be_suffix[0] ) )
1507 value_add( &c->rvalue_vals, c->be->be_suffix );
1508 value_add( &c->rvalue_nvals, c->be->be_nsuffix );
1511 } else if ( c->op == LDAP_MOD_DELETE ) {
1512 if ( c->valx < 0 ) {
1513 ber_bvarray_free( c->be->be_suffix );
1514 ber_bvarray_free( c->be->be_nsuffix );
1515 c->be->be_suffix = NULL;
1516 c->be->be_nsuffix = NULL;
1519 ch_free( c->be->be_suffix[i].bv_val );
1520 ch_free( c->be->be_nsuffix[i].bv_val );
1521 for (; c->be->be_suffix[i].bv_val; i++) {
1522 c->be->be_suffix[i] = c->be->be_suffix[i+1];
1523 c->be->be_nsuffix[i] = c->be->be_nsuffix[i+1];
1528 #ifdef SLAPD_MONITOR_DN
1529 if(!strcasecmp(c->argv[1], SLAPD_MONITOR_DN)) {
1530 Debug(LDAP_DEBUG_ANY, "%s: "
1531 "\"%s\" is reserved for monitoring slapd\n",
1532 c->log, SLAPD_MONITOR_DN, 0);
1539 tbe = select_backend(&ndn, 0, 0);
1541 Debug(LDAP_DEBUG_ANY, "%s: suffix already served by this backend! (ignored)\n",
1546 Debug(LDAP_DEBUG_ANY, "%s: suffix already served by a preceding backend \"%s\"\n",
1547 c->log, tbe->be_suffix[0].bv_val, 0);
1551 } else if(pdn.bv_len == 0 && default_search_nbase.bv_len) {
1552 Debug(LDAP_DEBUG_ANY, "%s: suffix DN empty and default search "
1553 "base provided \"%s\" (assuming okay)\n",
1554 c->log, default_search_base.bv_val, 0);
1556 ber_bvarray_add(&c->be->be_suffix, &pdn);
1557 ber_bvarray_add(&c->be->be_nsuffix, &ndn);
1562 config_rootdn(ConfigArgs *c) {
1563 if (c->op == SLAP_CONFIG_EMIT) {
1564 if ( !BER_BVISNULL( &c->be->be_rootdn )) {
1565 value_add_one(&c->rvalue_vals, &c->be->be_rootdn);
1566 value_add_one(&c->rvalue_nvals, &c->be->be_rootndn);
1571 } else if ( c->op == LDAP_MOD_DELETE ) {
1572 ch_free( c->be->be_rootdn.bv_val );
1573 ch_free( c->be->be_rootndn.bv_val );
1574 BER_BVZERO( &c->be->be_rootdn );
1575 BER_BVZERO( &c->be->be_rootndn );
1578 if ( !BER_BVISNULL( &c->be->be_rootdn )) {
1579 ch_free( c->be->be_rootdn.bv_val );
1580 ch_free( c->be->be_rootndn.bv_val );
1582 c->be->be_rootdn = c->value_dn;
1583 c->be->be_rootndn = c->value_ndn;
1588 config_rootpw(ConfigArgs *c) {
1590 if (c->op == SLAP_CONFIG_EMIT) {
1591 if (!BER_BVISEMPTY(&c->be->be_rootpw)) {
1592 ber_dupbv( &c->value_bv, &c->be->be_rootpw);
1596 } else if ( c->op == LDAP_MOD_DELETE ) {
1597 ch_free( c->be->be_rootpw.bv_val );
1598 BER_BVZERO( &c->be->be_rootpw );
1602 tbe = select_backend(&c->be->be_rootndn, 0, 0);
1604 Debug(LDAP_DEBUG_ANY, "%s: "
1605 "rootpw can only be set when rootdn is under suffix\n",
1609 if ( !BER_BVISNULL( &c->be->be_rootpw ))
1610 ch_free( c->be->be_rootpw.bv_val );
1611 c->be->be_rootpw = c->value_bv;
1616 config_restrict(ConfigArgs *c) {
1617 slap_mask_t restrictops = 0;
1619 slap_verbmasks restrictable_ops[] = {
1620 { BER_BVC("bind"), SLAP_RESTRICT_OP_BIND },
1621 { BER_BVC("add"), SLAP_RESTRICT_OP_ADD },
1622 { BER_BVC("modify"), SLAP_RESTRICT_OP_MODIFY },
1623 { BER_BVC("rename"), SLAP_RESTRICT_OP_RENAME },
1624 { BER_BVC("modrdn"), 0 },
1625 { BER_BVC("delete"), SLAP_RESTRICT_OP_DELETE },
1626 { BER_BVC("search"), SLAP_RESTRICT_OP_SEARCH },
1627 { BER_BVC("compare"), SLAP_RESTRICT_OP_COMPARE },
1628 { BER_BVC("read"), SLAP_RESTRICT_OP_READS },
1629 { BER_BVC("write"), SLAP_RESTRICT_OP_WRITES },
1630 { BER_BVC("extended"), SLAP_RESTRICT_OP_EXTENDED },
1631 { BER_BVC("extended=" LDAP_EXOP_START_TLS ), SLAP_RESTRICT_EXOP_START_TLS },
1632 { BER_BVC("extended=" LDAP_EXOP_MODIFY_PASSWD ), SLAP_RESTRICT_EXOP_MODIFY_PASSWD },
1633 { BER_BVC("extended=" LDAP_EXOP_X_WHO_AM_I ), SLAP_RESTRICT_EXOP_WHOAMI },
1634 { BER_BVC("extended=" LDAP_EXOP_X_CANCEL ), SLAP_RESTRICT_EXOP_CANCEL },
1638 if (c->op == SLAP_CONFIG_EMIT) {
1639 return mask_to_verbs( restrictable_ops, c->be->be_restrictops,
1641 } else if ( c->op == LDAP_MOD_DELETE ) {
1643 c->be->be_restrictops = 0;
1645 restrictops = verb_to_mask( c->line, restrictable_ops );
1646 c->be->be_restrictops ^= restrictops;
1650 i = verbs_to_mask( c->argc, c->argv, restrictable_ops, &restrictops );
1652 Debug(LDAP_DEBUG_ANY, "%s: "
1653 "unknown operation %s in \"restrict <features>\" line\n",
1654 c->log, c->argv[i], 0);
1657 if ( restrictops & SLAP_RESTRICT_OP_EXTENDED )
1658 restrictops &= ~SLAP_RESTRICT_EXOP_MASK;
1659 c->be->be_restrictops |= restrictops;
1664 config_allows(ConfigArgs *c) {
1665 slap_mask_t allows = 0;
1667 slap_verbmasks allowable_ops[] = {
1668 { BER_BVC("bind_v2"), SLAP_ALLOW_BIND_V2 },
1669 { BER_BVC("bind_anon_cred"), SLAP_ALLOW_BIND_ANON_CRED },
1670 { BER_BVC("bind_anon_dn"), SLAP_ALLOW_BIND_ANON_DN },
1671 { BER_BVC("update_anon"), SLAP_ALLOW_UPDATE_ANON },
1674 if (c->op == SLAP_CONFIG_EMIT) {
1675 return mask_to_verbs( allowable_ops, global_allows, &c->rvalue_vals );
1676 } else if ( c->op == LDAP_MOD_DELETE ) {
1680 allows = verb_to_mask( c->line, allowable_ops );
1681 global_allows ^= allows;
1685 i = verbs_to_mask(c->argc, c->argv, allowable_ops, &allows);
1687 Debug(LDAP_DEBUG_ANY, "%s: "
1688 "unknown feature %s in \"allow <features>\" line\n",
1689 c->log, c->argv[i], 0);
1692 global_allows |= allows;
1697 config_disallows(ConfigArgs *c) {
1698 slap_mask_t disallows = 0;
1700 slap_verbmasks disallowable_ops[] = {
1701 { BER_BVC("bind_anon"), SLAP_DISALLOW_BIND_ANON },
1702 { BER_BVC("bind_simple"), SLAP_DISALLOW_BIND_SIMPLE },
1703 { BER_BVC("bind_krb4"), SLAP_DISALLOW_BIND_KRBV4 },
1704 { BER_BVC("tls_2_anon"), SLAP_DISALLOW_TLS_2_ANON },
1705 { BER_BVC("tls_authc"), SLAP_DISALLOW_TLS_AUTHC },
1708 if (c->op == SLAP_CONFIG_EMIT) {
1709 return mask_to_verbs( disallowable_ops, global_disallows, &c->rvalue_vals );
1710 } else if ( c->op == LDAP_MOD_DELETE ) {
1712 global_disallows = 0;
1714 disallows = verb_to_mask( c->line, disallowable_ops );
1715 global_disallows ^= disallows;
1719 i = verbs_to_mask(c->argc, c->argv, disallowable_ops, &disallows);
1721 Debug(LDAP_DEBUG_ANY, "%s: "
1722 "unknown feature %s in \"disallow <features>\" line\n",
1723 c->log, c->argv[i], 0);
1726 global_disallows |= disallows;
1731 config_requires(ConfigArgs *c) {
1732 slap_mask_t requires = 0;
1734 slap_verbmasks requires_ops[] = {
1735 { BER_BVC("bind"), SLAP_REQUIRE_BIND },
1736 { BER_BVC("LDAPv3"), SLAP_REQUIRE_LDAP_V3 },
1737 { BER_BVC("authc"), SLAP_REQUIRE_AUTHC },
1738 { BER_BVC("sasl"), SLAP_REQUIRE_SASL },
1739 { BER_BVC("strong"), SLAP_REQUIRE_STRONG },
1742 if (c->op == SLAP_CONFIG_EMIT) {
1743 return mask_to_verbs( requires_ops, c->be->be_requires, &c->rvalue_vals );
1744 } else if ( c->op == LDAP_MOD_DELETE ) {
1746 c->be->be_requires = 0;
1748 requires = verb_to_mask( c->line, requires_ops );
1749 c->be->be_requires ^= requires;
1753 i = verbs_to_mask(c->argc, c->argv, requires_ops, &requires);
1755 Debug(LDAP_DEBUG_ANY, "%s: "
1756 "unknown feature %s in \"require <features>\" line\n",
1757 c->log, c->argv[i], 0);
1760 c->be->be_requires = requires;
1765 config_loglevel(ConfigArgs *c) {
1768 slap_verbmasks loglevel_ops[] = {
1769 { BER_BVC("Trace"), LDAP_DEBUG_TRACE },
1770 { BER_BVC("Packets"), LDAP_DEBUG_PACKETS },
1771 { BER_BVC("Args"), LDAP_DEBUG_ARGS },
1772 { BER_BVC("Conns"), LDAP_DEBUG_CONNS },
1773 { BER_BVC("BER"), LDAP_DEBUG_BER },
1774 { BER_BVC("Filter"), LDAP_DEBUG_FILTER },
1775 { BER_BVC("Config"), LDAP_DEBUG_CONFIG },
1776 { BER_BVC("ACL"), LDAP_DEBUG_ACL },
1777 { BER_BVC("Stats"), LDAP_DEBUG_STATS },
1778 { BER_BVC("Stats2"), LDAP_DEBUG_STATS2 },
1779 { BER_BVC("Shell"), LDAP_DEBUG_SHELL },
1780 { BER_BVC("Parse"), LDAP_DEBUG_PARSE },
1781 { BER_BVC("Cache"), LDAP_DEBUG_CACHE },
1782 { BER_BVC("Index"), LDAP_DEBUG_INDEX },
1783 { BER_BVC("Any"), -1 },
1787 if (c->op == SLAP_CONFIG_EMIT) {
1788 return mask_to_verbs( loglevel_ops, ldap_syslog, &c->rvalue_vals );
1789 } else if ( c->op == LDAP_MOD_DELETE ) {
1793 int level = verb_to_mask( c->line, loglevel_ops );
1794 ldap_syslog ^= level;
1801 for( i=1; i < c->argc; i++ ) {
1804 if ( isdigit( c->argv[i][0] ) ) {
1805 level = strtol( c->argv[i], &next, 10 );
1806 if ( next == NULL || next[0] != '\0' ) {
1807 Debug( LDAP_DEBUG_ANY,
1808 "%s: unable to parse level \"%s\" "
1809 "in \"loglevel <level> [...]\" line.\n",
1810 c->log, c->argv[i], 0);
1814 int j = verb_to_mask(c->argv[i], loglevel_ops);
1815 if(BER_BVISNULL(&loglevel_ops[j].word)) {
1816 Debug( LDAP_DEBUG_ANY,
1817 "%s: unknown level \"%s\" "
1818 "in \"loglevel <level> [...]\" line.\n",
1819 c->log, c->argv[i], 0);
1822 level = loglevel_ops[j].mask;
1824 ldap_syslog |= level;
1830 config_syncrepl(ConfigArgs *c) {
1831 if (c->op == SLAP_CONFIG_EMIT) {
1832 if ( c->be->be_syncinfo ) {
1834 syncrepl_unparse( c->be->be_syncinfo, &bv );
1835 ber_bvarray_add( &c->rvalue_vals, &bv );
1839 } else if ( c->op == LDAP_MOD_DELETE ) {
1842 if ( c->be->be_syncinfo ) {
1843 re = ldap_pvt_runqueue_find( &slapd_rq, do_syncrepl, c->be->be_syncinfo );
1845 if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ))
1846 ldap_pvt_runqueue_stoptask( &slapd_rq, re );
1847 ldap_pvt_runqueue_remove( &slapd_rq, re );
1849 syncinfo_free( c->be->be_syncinfo );
1850 c->be->be_syncinfo = NULL;
1854 if(SLAP_SHADOW(c->be)) {
1855 Debug(LDAP_DEBUG_ANY, "%s: "
1856 "syncrepl: database already shadowed.\n",
1859 } else if(add_syncrepl(c->be, c->argv, c->argc)) {
1862 SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SYNC_SHADOW);
1867 config_referral(ConfigArgs *c) {
1868 struct berval vals[2];
1869 if (c->op == SLAP_CONFIG_EMIT) {
1870 if ( default_referral ) {
1871 value_add( &c->rvalue_vals, default_referral );
1876 } else if ( c->op == LDAP_MOD_DELETE ) {
1877 if ( c->valx < 0 ) {
1878 ber_bvarray_free( default_referral );
1879 default_referral = NULL;
1882 ch_free( default_referral[i].bv_val );
1883 for (; default_referral[i].bv_val; i++ )
1884 default_referral[i] = default_referral[i+1];
1888 if(validate_global_referral(c->argv[1])) {
1889 Debug(LDAP_DEBUG_ANY, "%s: "
1890 "invalid URL (%s) in \"referral\" line.\n",
1891 c->log, c->argv[1], 0);
1895 ber_str2bv(c->argv[1], 0, 0, &vals[0]);
1896 vals[1].bv_val = NULL; vals[1].bv_len = 0;
1897 if(value_add(&default_referral, vals)) return(LDAP_OTHER);
1905 { BER_BVC("ssf="), offsetof(slap_ssf_set_t, sss_ssf) },
1906 { BER_BVC("transport="), offsetof(slap_ssf_set_t, sss_transport) },
1907 { BER_BVC("tls="), offsetof(slap_ssf_set_t, sss_tls) },
1908 { BER_BVC("sasl="), offsetof(slap_ssf_set_t, sss_sasl) },
1909 { BER_BVC("update_ssf="), offsetof(slap_ssf_set_t, sss_update_ssf) },
1910 { BER_BVC("update_transport="), offsetof(slap_ssf_set_t, sss_update_transport) },
1911 { BER_BVC("update_tls="), offsetof(slap_ssf_set_t, sss_update_tls) },
1912 { BER_BVC("update_sasl="), offsetof(slap_ssf_set_t, sss_update_sasl) },
1913 { BER_BVC("simple_bind="), offsetof(slap_ssf_set_t, sss_simple_bind) },
1918 config_security(ConfigArgs *c) {
1919 slap_ssf_set_t *set = &c->be->be_ssf_set;
1922 if (c->op == SLAP_CONFIG_EMIT) {
1928 for (i=0; !BER_BVISNULL( &sec_keys[i].key ); i++) {
1929 tgt = (slap_ssf_t *)((char *)set + sec_keys[i].off);
1932 bv.bv_len = sprintf( numbuf, "%u", *tgt );
1933 bv.bv_len += sec_keys[i].key.bv_len;
1934 bv.bv_val = ch_malloc( bv.bv_len + 1);
1935 next = lutil_strcopy( bv.bv_val, sec_keys[i].key.bv_val );
1936 strcpy( next, numbuf );
1937 ber_bvarray_add( &c->rvalue_vals, &bv );
1942 for(i = 1; i < c->argc; i++) {
1943 slap_ssf_t *tgt = NULL;
1945 for ( j=0; !BER_BVISNULL( &sec_keys[j].key ); j++ ) {
1946 if(!strncasecmp(c->argv[i], sec_keys[j].key.bv_val,
1947 sec_keys[j].key.bv_len)) {
1948 src = c->argv[i] + sec_keys[j].key.bv_len;
1949 tgt = (slap_ssf_t *)((char *)set + sec_keys[j].off);
1954 Debug(LDAP_DEBUG_ANY, "%s: "
1955 "unknown factor %s in \"security <factors>\" line\n",
1956 c->log, c->argv[i], 0);
1960 *tgt = strtol(src, &next, 10);
1961 if(next == NULL || next[0] != '\0' ) {
1962 Debug(LDAP_DEBUG_ANY, "%s: "
1963 "unable to parse factor \"%s\" in \"security <factors>\" line\n",
1964 c->log, c->argv[i], 0);
1972 anlist_unparse( AttributeName *an, char *ptr ) {
1975 for (; !BER_BVISNULL( &an->an_name ); an++) {
1976 if ( comma ) *ptr++ = ',';
1977 ptr = lutil_strcopy( ptr, an->an_name.bv_val );
1984 replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv )
1988 struct berval bc = {0};
1991 len = sprintf(numbuf, IFMT, i );
1993 len += strlen( ri->ri_uri ) + STRLENOF("uri=");
1994 if ( ri->ri_nsuffix ) {
1995 for (i=0; !BER_BVISNULL( &ri->ri_nsuffix[i] ); i++) {
1996 len += ri->ri_nsuffix[i].bv_len + STRLENOF(" suffix=\"\"");
1999 if ( ri->ri_attrs ) {
2000 len += STRLENOF("attr");
2001 if ( ri->ri_exclude ) len++;
2002 for (i=0; !BER_BVISNULL( &ri->ri_attrs[i].an_name ); i++) {
2003 len += 1 + ri->ri_attrs[i].an_name.bv_len;
2006 bindconf_unparse( &ri->ri_bindconf, &bc );
2009 bv->bv_val = ch_malloc(len + 1);
2012 ptr = lutil_strcopy( bv->bv_val, numbuf );
2013 ptr = lutil_strcopy( ptr, "uri=" );
2014 ptr = lutil_strcopy( ptr, ri->ri_uri );
2016 if ( ri->ri_nsuffix ) {
2017 for (i=0; !BER_BVISNULL( &ri->ri_nsuffix[i] ); i++) {
2018 ptr = lutil_strcopy( ptr, " suffix=\"" );
2019 ptr = lutil_strcopy( ptr, ri->ri_nsuffix[i].bv_val );
2023 if ( ri->ri_attrs ) {
2024 ptr = lutil_strcopy( ptr, "attr" );
2025 if ( ri->ri_exclude ) *ptr++ = '!';
2027 ptr = anlist_unparse( ri->ri_attrs, ptr );
2030 strcpy( ptr, bc.bv_val );
2031 ch_free( bc.bv_val );
2036 config_replica(ConfigArgs *c) {
2037 int i, nr = -1, len;
2038 char *replicahost, *replicauri;
2041 if (c->op == SLAP_CONFIG_EMIT) {
2042 if (c->be->be_replica) {
2044 for (i=0;c->be->be_replica[i]; i++) {
2045 replica_unparse( c->be->be_replica[i], i, &bv );
2046 ber_bvarray_add( &c->rvalue_vals, &bv );
2051 } else if ( c->op == LDAP_MOD_DELETE ) {
2052 if ( c->valx < 0 ) {
2056 if(SLAP_MONITOR(c->be)) {
2057 Debug(LDAP_DEBUG_ANY, "%s: "
2058 "\"replica\" should not be used inside monitor database\n",
2060 return(0); /* FIXME: should this be an error? */
2063 for(i = 1; i < c->argc; i++) {
2064 if(!strncasecmp(c->argv[i], "host=", STRLENOF("host="))) {
2065 replicahost = c->argv[i] + STRLENOF("host=");
2066 len = strlen( replicahost );
2067 replicauri = ch_malloc( len + STRLENOF("ldap://") + 1 );
2068 sprintf( replicauri, "ldap://%s", replicahost );
2069 replicahost = replicauri + STRLENOF( "ldap://");
2070 nr = add_replica_info(c->be, replicauri, replicahost);
2072 } else if(!strncasecmp(c->argv[i], "uri=", STRLENOF("uri="))) {
2073 if(ldap_url_parse(c->argv[i] + STRLENOF("uri="), &ludp) != LDAP_SUCCESS) {
2074 Debug(LDAP_DEBUG_ANY, "%s: "
2075 "replica line contains invalid "
2076 "uri definition.\n", c->log, 0, 0);
2079 if(!ludp->lud_host) {
2080 Debug(LDAP_DEBUG_ANY, "%s: "
2081 "replica line contains invalid "
2082 "uri definition - missing hostname.\n",
2086 ldap_free_urldesc(ludp);
2087 replicauri = c->argv[i] + STRLENOF("uri=");
2088 replicauri = ch_strdup( replicauri );
2089 replicahost = strchr( replicauri, '/' );
2091 nr = add_replica_info(c->be, replicauri, replicahost);
2096 Debug(LDAP_DEBUG_ANY, "%s: "
2097 "missing host or uri in \"replica\" line\n",
2100 } else if(nr == -1) {
2101 Debug(LDAP_DEBUG_ANY, "%s: "
2102 "unable to add replica \"%s\"\n",
2103 c->log, replicauri, 0);
2106 for(i = 1; i < c->argc; i++) {
2107 if(!strncasecmp(c->argv[i], "suffix=", STRLENOF( "suffix="))) {
2108 switch(add_replica_suffix(c->be, nr, c->argv[i] + STRLENOF("suffix="))) {
2110 Debug(LDAP_DEBUG_ANY, "%s: "
2111 "suffix \"%s\" in \"replica\" line is not valid for backend (ignored)\n",
2112 c->log, c->argv[i] + STRLENOF("suffix="), 0);
2115 Debug(LDAP_DEBUG_ANY, "%s: "
2116 "unable to normalize suffix in \"replica\" line (ignored)\n",
2121 } else if(!strncasecmp(c->argv[i], "attr", STRLENOF("attr"))) {
2123 char *arg = c->argv[i] + STRLENOF("attr");
2131 if(add_replica_attrs(c->be, nr, arg + 1, exclude)) {
2132 Debug(LDAP_DEBUG_ANY, "%s: "
2133 "attribute \"%s\" in \"replica\" line is unknown\n",
2134 c->log, arg + 1, 0);
2137 } else if ( bindconf_parse( c->argv[i],
2138 &c->be->be_replica[nr]->ri_bindconf ) ) {
2147 config_updatedn(ConfigArgs *c) {
2150 if (c->op == SLAP_CONFIG_EMIT) {
2151 if (!BER_BVISEMPTY(&c->be->be_update_ndn)) {
2152 value_add_one(&c->rvalue_vals, &c->be->be_update_ndn);
2153 value_add_one(&c->rvalue_nvals, &c->be->be_update_ndn);
2157 } else if ( c->op == LDAP_MOD_DELETE ) {
2158 ch_free( c->be->be_update_ndn.bv_val );
2159 c->be->be_update_ndn.bv_val = NULL;
2160 SLAP_DBFLAGS(c->be) ^= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SLURP_SHADOW);
2163 if(SLAP_SHADOW(c->be)) {
2164 Debug(LDAP_DEBUG_ANY, "%s: "
2165 "updatedn: database already shadowed.\n",
2170 ber_str2bv(c->argv[1], 0, 0, &dn);
2172 rc = dnNormalize(0, NULL, NULL, &dn, &c->be->be_update_ndn, NULL);
2174 if(rc != LDAP_SUCCESS) {
2175 Debug(LDAP_DEBUG_ANY, "%s: "
2176 "updatedn DN is invalid: %d (%s)\n",
2177 c->log, rc, ldap_err2string( rc ));
2181 SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SLURP_SHADOW);
2186 config_updateref(ConfigArgs *c) {
2187 struct berval vals[2];
2188 if (c->op == SLAP_CONFIG_EMIT) {
2189 if ( c->be->be_update_refs ) {
2190 value_add( &c->rvalue_vals, c->be->be_update_refs );
2195 } else if ( c->op == LDAP_MOD_DELETE ) {
2196 if ( c->valx < 0 ) {
2197 ber_bvarray_free( c->be->be_update_refs );
2198 c->be->be_update_refs = NULL;
2201 ch_free( c->be->be_update_refs[i].bv_val );
2202 for (; c->be->be_update_refs[i].bv_val; i++)
2203 c->be->be_update_refs[i] = c->be->be_update_refs[i+1];
2207 if(!SLAP_SHADOW(c->be)) {
2208 Debug(LDAP_DEBUG_ANY, "%s: "
2209 "updateref line must come after syncrepl or updatedn.\n",
2214 if(validate_global_referral(c->argv[1])) {
2215 Debug(LDAP_DEBUG_ANY, "%s: "
2216 "invalid URL (%s) in \"updateref\" line.\n",
2217 c->log, c->argv[1], 0);
2220 ber_str2bv(c->argv[1], 0, 0, &vals[0]);
2221 vals[1].bv_val = NULL;
2222 if(value_add(&c->be->be_update_refs, vals)) return(LDAP_OTHER);
2227 config_include(ConfigArgs *c) {
2228 unsigned long savelineno = c->lineno;
2231 ConfigFile *cfsave = cfn;
2232 ConfigFile *cf2 = NULL;
2233 if (c->op == SLAP_CONFIG_EMIT) {
2235 ConfigFile *cf = c->private;
2236 value_add_one( &c->rvalue_vals, &cf->c_file );
2240 } else if ( c->op == LDAP_MOD_DELETE ) {
2242 cf = ch_calloc( 1, sizeof(ConfigFile));
2243 if ( cfn->c_kids ) {
2244 for (cf2=cfn->c_kids; cf2 && cf2->c_sibs; cf2=cf2->c_sibs) ;
2250 ber_str2bv( c->argv[1], 0, 1, &cf->c_file );
2251 rc = read_config_file(c->argv[1], c->depth + 1, c);
2252 c->lineno = savelineno - 1;
2255 if ( cf2 ) cf2->c_sibs = NULL;
2256 else cfn->c_kids = NULL;
2257 ch_free( cf->c_file.bv_val );
2265 config_tls_option(ConfigArgs *c) {
2268 case CFG_TLS_RAND: flag = LDAP_OPT_X_TLS_RANDOM_FILE; break;
2269 case CFG_TLS_CIPHER: flag = LDAP_OPT_X_TLS_CIPHER_SUITE; break;
2270 case CFG_TLS_CERT_FILE: flag = LDAP_OPT_X_TLS_CERTFILE; break;
2271 case CFG_TLS_CERT_KEY: flag = LDAP_OPT_X_TLS_KEYFILE; break;
2272 case CFG_TLS_CA_PATH: flag = LDAP_OPT_X_TLS_CACERTDIR; break;
2273 case CFG_TLS_CA_FILE: flag = LDAP_OPT_X_TLS_CACERTFILE; break;
2274 default: Debug(LDAP_DEBUG_ANY, "%s: "
2275 "unknown tls_option <0x%x>\n",
2276 c->log, c->type, 0);
2278 if (c->op == SLAP_CONFIG_EMIT) {
2279 return ldap_pvt_tls_get_option( NULL, flag, &c->value_string );
2280 } else if ( c->op == LDAP_MOD_DELETE ) {
2281 return ldap_pvt_tls_set_option( NULL, flag, NULL );
2283 ch_free(c->value_string);
2284 return(ldap_pvt_tls_set_option(NULL, flag, c->argv[1]));
2287 /* FIXME: this ought to be provided by libldap */
2289 config_tls_config(ConfigArgs *c) {
2291 slap_verbmasks crlkeys[] = {
2292 { BER_BVC("none"), LDAP_OPT_X_TLS_CRL_NONE },
2293 { BER_BVC("peer"), LDAP_OPT_X_TLS_CRL_PEER },
2294 { BER_BVC("all"), LDAP_OPT_X_TLS_CRL_ALL },
2297 slap_verbmasks vfykeys[] = {
2298 { BER_BVC("never"), LDAP_OPT_X_TLS_NEVER },
2299 { BER_BVC("demand"), LDAP_OPT_X_TLS_DEMAND },
2300 { BER_BVC("try"), LDAP_OPT_X_TLS_TRY },
2301 { BER_BVC("hard"), LDAP_OPT_X_TLS_HARD },
2305 case CFG_TLS_CRLCHECK: flag = LDAP_OPT_X_TLS_CRLCHECK; keys = crlkeys; break;
2306 case CFG_TLS_VERIFY: flag = LDAP_OPT_X_TLS_REQUIRE_CERT; keys = vfykeys; break;
2308 Debug(LDAP_DEBUG_ANY, "%s: "
2309 "unknown tls_option <0x%x>\n",
2310 c->log, c->type, 0);
2312 if (c->op == SLAP_CONFIG_EMIT) {
2313 ldap_pvt_tls_get_option( NULL, flag, &c->value_int );
2314 for (i=0; !BER_BVISNULL(&keys[i].word); i++) {
2315 if (keys[i].mask == c->value_int) {
2316 c->value_string = ch_strdup( keys[i].word.bv_val );
2321 } else if ( c->op == LDAP_MOD_DELETE ) {
2323 return ldap_pvt_tls_set_option( NULL, flag, &i );
2325 ch_free( c->value_string );
2326 if(isdigit((unsigned char)c->argv[1][0])) {
2327 i = atoi(c->argv[1]);
2328 return(ldap_pvt_tls_set_option(NULL, flag, &i));
2330 return(ldap_int_tls_config(NULL, flag, c->argv[1]));
2345 if ( !( be->be_search && be->be_add && be->be_modify && be->be_delete )) {
2346 Debug( LDAP_DEBUG_ANY, "database %s does not support operations "
2347 "required for syncrepl\n", be->be_type, 0, 0 );
2350 si = (syncinfo_t *) ch_calloc( 1, sizeof( syncinfo_t ) );
2353 Debug( LDAP_DEBUG_ANY, "out of memory in add_syncrepl\n", 0, 0, 0 );
2357 si->si_bindconf.sb_tls = SB_TLS_OFF;
2358 si->si_bindconf.sb_method = LDAP_AUTH_SIMPLE;
2359 si->si_schemachecking = 0;
2360 ber_str2bv( "(objectclass=*)", STRLENOF("(objectclass=*)"), 1,
2361 &si->si_filterstr );
2362 si->si_base.bv_val = NULL;
2363 si->si_scope = LDAP_SCOPE_SUBTREE;
2364 si->si_attrsonly = 0;
2365 si->si_anlist = (AttributeName *) ch_calloc( 1, sizeof( AttributeName ));
2366 si->si_exanlist = (AttributeName *) ch_calloc( 1, sizeof( AttributeName ));
2367 si->si_attrs = NULL;
2368 si->si_allattrs = 0;
2369 si->si_allopattrs = 0;
2370 si->si_exattrs = NULL;
2371 si->si_type = LDAP_SYNC_REFRESH_ONLY;
2372 si->si_interval = 86400;
2373 si->si_retryinterval = NULL;
2374 si->si_retrynum_init = NULL;
2375 si->si_retrynum = NULL;
2376 si->si_manageDSAit = 0;
2380 si->si_presentlist = NULL;
2381 LDAP_LIST_INIT( &si->si_nonpresentlist );
2382 ldap_pvt_thread_mutex_init( &si->si_mutex );
2384 rc = parse_syncrepl_line( cargv, cargc, si );
2387 Debug( LDAP_DEBUG_ANY, "failed to add syncinfo\n", 0, 0, 0 );
2388 syncinfo_free( si );
2391 Debug( LDAP_DEBUG_CONFIG,
2392 "Config: ** successfully added syncrepl \"%s\"\n",
2393 BER_BVISNULL( &si->si_provideruri ) ?
2394 "(null)" : si->si_provideruri.bv_val, 0, 0 );
2395 if ( !si->si_schemachecking ) {
2396 SLAP_DBFLAGS(be) |= SLAP_DBFLAG_NO_SCHEMA_CHECK;
2399 be->be_syncinfo = si;
2400 init_syncrepl( si );
2401 ldap_pvt_runqueue_insert( &slapd_rq,si->si_interval,do_syncrepl,si );
2406 /* NOTE: used & documented in slapd.conf(5) */
2408 #define PROVIDERSTR "provider"
2409 #define TYPESTR "type"
2410 #define INTERVALSTR "interval"
2411 #define SEARCHBASESTR "searchbase"
2412 #define FILTERSTR "filter"
2413 #define SCOPESTR "scope"
2414 #define ATTRSSTR "attrs"
2415 #define ATTRSONLYSTR "attrsonly"
2416 #define SLIMITSTR "sizelimit"
2417 #define TLIMITSTR "timelimit"
2418 #define SCHEMASTR "schemachecking"
2420 /* FIXME: undocumented */
2421 #define OLDAUTHCSTR "bindprincipal"
2422 #define EXATTRSSTR "exattrs"
2423 #define RETRYSTR "retry"
2426 #define LASTMODSTR "lastmod"
2427 #define LMGENSTR "gen"
2428 #define LMNOSTR "no"
2429 #define LMREQSTR "req"
2430 #define SRVTABSTR "srvtab"
2431 #define SUFFIXSTR "suffix"
2432 #define MANAGEDSAITSTR "manageDSAit"
2435 #define GOT_ID 0x0001
2436 #define GOT_PROVIDER 0x0002
2439 #define GOT_ALL (GOT_ID|GOT_PROVIDER)
2445 { BER_BVC("base"), LDAP_SCOPE_BASE },
2446 { BER_BVC("one"), LDAP_SCOPE_ONELEVEL },
2447 #ifdef LDAP_SCOPE_SUBORDINATE
2448 { BER_BVC("children"), LDAP_SCOPE_SUBORDINATE },
2449 { BER_BVC("subordinate"), 0 },
2451 { BER_BVC("sub"), LDAP_SCOPE_SUBTREE },
2456 parse_syncrepl_line(
2466 for ( i = 1; i < cargc; i++ ) {
2467 if ( !strncasecmp( cargv[ i ], IDSTR "=",
2468 STRLENOF( IDSTR "=" ) ) )
2471 /* '\0' string terminator accounts for '=' */
2472 val = cargv[ i ] + STRLENOF( IDSTR "=" );
2474 if ( tmp >= 1000 || tmp < 0 ) {
2475 fprintf( stderr, "Error: parse_syncrepl_line: "
2476 "syncrepl id %d is out of range [0..999]\n", tmp );
2481 } else if ( !strncasecmp( cargv[ i ], PROVIDERSTR "=",
2482 STRLENOF( PROVIDERSTR "=" ) ) )
2484 val = cargv[ i ] + STRLENOF( PROVIDERSTR "=" );
2485 ber_str2bv( val, 0, 1, &si->si_provideruri );
2486 gots |= GOT_PROVIDER;
2487 } else if ( !strncasecmp( cargv[ i ], SCHEMASTR "=",
2488 STRLENOF( SCHEMASTR "=" ) ) )
2490 val = cargv[ i ] + STRLENOF( SCHEMASTR "=" );
2491 if ( !strncasecmp( val, "on", STRLENOF( "on" ) )) {
2492 si->si_schemachecking = 1;
2493 } else if ( !strncasecmp( val, "off", STRLENOF( "off" ) ) ) {
2494 si->si_schemachecking = 0;
2496 si->si_schemachecking = 1;
2498 } else if ( !strncasecmp( cargv[ i ], FILTERSTR "=",
2499 STRLENOF( FILTERSTR "=" ) ) )
2501 val = cargv[ i ] + STRLENOF( FILTERSTR "=" );
2502 ber_str2bv( val, 0, 1, &si->si_filterstr );
2503 } else if ( !strncasecmp( cargv[ i ], SEARCHBASESTR "=",
2504 STRLENOF( SEARCHBASESTR "=" ) ) )
2509 val = cargv[ i ] + STRLENOF( SEARCHBASESTR "=" );
2510 if ( si->si_base.bv_val ) {
2511 ch_free( si->si_base.bv_val );
2513 ber_str2bv( val, 0, 0, &bv );
2514 rc = dnNormalize( 0, NULL, NULL, &bv, &si->si_base, NULL );
2515 if ( rc != LDAP_SUCCESS ) {
2516 fprintf( stderr, "Invalid base DN \"%s\": %d (%s)\n",
2517 val, rc, ldap_err2string( rc ) );
2520 } else if ( !strncasecmp( cargv[ i ], SCOPESTR "=",
2521 STRLENOF( SCOPESTR "=" ) ) )
2524 val = cargv[ i ] + STRLENOF( SCOPESTR "=" );
2525 for ( j=0; !BER_BVISNULL(&scopes[j].key); j++ ) {
2526 if (!strncasecmp( val, scopes[j].key.bv_val,
2527 scopes[j].key.bv_len )) {
2528 while (!scopes[j].val) j--;
2529 si->si_scope = scopes[j].val;
2533 if ( BER_BVISNULL(&scopes[j].key) ) {
2534 fprintf( stderr, "Error: parse_syncrepl_line: "
2535 "unknown scope \"%s\"\n", val);
2538 } else if ( !strncasecmp( cargv[ i ], ATTRSONLYSTR "=",
2539 STRLENOF( ATTRSONLYSTR "=" ) ) )
2541 si->si_attrsonly = 1;
2542 } else if ( !strncasecmp( cargv[ i ], ATTRSSTR "=",
2543 STRLENOF( ATTRSSTR "=" ) ) )
2545 val = cargv[ i ] + STRLENOF( ATTRSSTR "=" );
2546 if ( !strncasecmp( val, ":include:", STRLENOF(":include:") ) ) {
2548 attr_fname = ch_strdup( val + STRLENOF(":include:") );
2549 si->si_anlist = file2anlist( si->si_anlist, attr_fname, " ,\t" );
2550 if ( si->si_anlist == NULL ) {
2551 ch_free( attr_fname );
2554 si->si_anfile = attr_fname;
2556 char *str, *s, *next;
2557 char delimstr[] = " ,\t";
2558 str = ch_strdup( val );
2559 for ( s = ldap_pvt_strtok( str, delimstr, &next );
2561 s = ldap_pvt_strtok( NULL, delimstr, &next ) )
2563 if ( strlen(s) == 1 && *s == '*' ) {
2564 si->si_allattrs = 1;
2565 *(val + ( s - str )) = delimstr[0];
2567 if ( strlen(s) == 1 && *s == '+' ) {
2568 si->si_allopattrs = 1;
2569 *(val + ( s - str )) = delimstr[0];
2573 si->si_anlist = str2anlist( si->si_anlist, val, " ,\t" );
2574 if ( si->si_anlist == NULL ) {
2578 } else if ( !strncasecmp( cargv[ i ], EXATTRSSTR "=",
2579 STRLENOF( EXATTRSSTR "=" ) ) )
2581 val = cargv[ i ] + STRLENOF( EXATTRSSTR "=" );
2582 if ( !strncasecmp( val, ":include:", STRLENOF(":include:") )) {
2584 attr_fname = ch_strdup( val + STRLENOF(":include:") );
2585 si->si_exanlist = file2anlist(
2586 si->si_exanlist, attr_fname, " ,\t" );
2587 if ( si->si_exanlist == NULL ) {
2588 ch_free( attr_fname );
2591 ch_free( attr_fname );
2593 si->si_exanlist = str2anlist( si->si_exanlist, val, " ,\t" );
2594 if ( si->si_exanlist == NULL ) {
2598 } else if ( !strncasecmp( cargv[ i ], TYPESTR "=",
2599 STRLENOF( TYPESTR "=" ) ) )
2601 val = cargv[ i ] + STRLENOF( TYPESTR "=" );
2602 if ( !strncasecmp( val, "refreshOnly",
2603 STRLENOF("refreshOnly") ))
2605 si->si_type = LDAP_SYNC_REFRESH_ONLY;
2606 } else if ( !strncasecmp( val, "refreshAndPersist",
2607 STRLENOF("refreshAndPersist") ))
2609 si->si_type = LDAP_SYNC_REFRESH_AND_PERSIST;
2610 si->si_interval = 60;
2612 fprintf( stderr, "Error: parse_syncrepl_line: "
2613 "unknown sync type \"%s\"\n", val);
2616 } else if ( !strncasecmp( cargv[ i ], INTERVALSTR "=",
2617 STRLENOF( INTERVALSTR "=" ) ) )
2619 val = cargv[ i ] + STRLENOF( INTERVALSTR "=" );
2620 if ( si->si_type == LDAP_SYNC_REFRESH_AND_PERSIST ) {
2621 si->si_interval = 0;
2629 hstr = strchr( dstr, ':' );
2630 if ( hstr == NULL ) {
2631 fprintf( stderr, "Error: parse_syncrepl_line: "
2632 "invalid interval \"%s\"\n", val );
2636 mstr = strchr( hstr, ':' );
2637 if ( mstr == NULL ) {
2638 fprintf( stderr, "Error: parse_syncrepl_line: "
2639 "invalid interval \"%s\"\n", val );
2643 sstr = strchr( mstr, ':' );
2644 if ( sstr == NULL ) {
2645 fprintf( stderr, "Error: parse_syncrepl_line: "
2646 "invalid interval \"%s\"\n", val );
2655 if (( hh > 24 ) || ( hh < 0 ) ||
2656 ( mm > 60 ) || ( mm < 0 ) ||
2657 ( ss > 60 ) || ( ss < 0 ) || ( dd < 0 )) {
2658 fprintf( stderr, "Error: parse_syncrepl_line: "
2659 "invalid interval \"%s\"\n", val );
2662 si->si_interval = (( dd * 24 + hh ) * 60 + mm ) * 60 + ss;
2664 if ( si->si_interval < 0 ) {
2665 fprintf( stderr, "Error: parse_syncrepl_line: "
2666 "invalid interval \"%ld\"\n",
2667 (long) si->si_interval);
2670 } else if ( !strncasecmp( cargv[ i ], RETRYSTR "=",
2671 STRLENOF( RETRYSTR "=" ) ) )
2676 val = cargv[ i ] + STRLENOF( RETRYSTR "=" );
2677 retry_list = (char **) ch_calloc( 1, sizeof( char * ));
2678 retry_list[0] = NULL;
2680 slap_str2clist( &retry_list, val, " ,\t" );
2682 for ( k = 0; retry_list && retry_list[k]; k++ ) ;
2686 "Error: incomplete syncrepl retry list\n" );
2687 for ( k = 0; retry_list && retry_list[k]; k++ ) {
2688 ch_free( retry_list[k] );
2690 ch_free( retry_list );
2691 exit( EXIT_FAILURE );
2693 si->si_retryinterval = (time_t *) ch_calloc( n + 1, sizeof( time_t ));
2694 si->si_retrynum = (int *) ch_calloc( n + 1, sizeof( int ));
2695 si->si_retrynum_init = (int *) ch_calloc( n + 1, sizeof( int ));
2696 for ( j = 0; j < n; j++ ) {
2697 si->si_retryinterval[j] = atoi( retry_list[j*2] );
2698 if ( *retry_list[j*2+1] == '+' ) {
2699 si->si_retrynum_init[j] = -1;
2700 si->si_retrynum[j] = -1;
2704 si->si_retrynum_init[j] = atoi( retry_list[j*2+1] );
2705 si->si_retrynum[j] = atoi( retry_list[j*2+1] );
2708 si->si_retrynum_init[j] = -2;
2709 si->si_retrynum[j] = -2;
2710 si->si_retryinterval[j] = 0;
2712 for ( k = 0; retry_list && retry_list[k]; k++ ) {
2713 ch_free( retry_list[k] );
2715 ch_free( retry_list );
2716 } else if ( !strncasecmp( cargv[ i ], MANAGEDSAITSTR "=",
2717 STRLENOF( MANAGEDSAITSTR "=" ) ) )
2719 val = cargv[ i ] + STRLENOF( MANAGEDSAITSTR "=" );
2720 si->si_manageDSAit = atoi( val );
2721 } else if ( !strncasecmp( cargv[ i ], SLIMITSTR "=",
2722 STRLENOF( SLIMITSTR "=") ) )
2724 val = cargv[ i ] + STRLENOF( SLIMITSTR "=" );
2725 si->si_slimit = atoi( val );
2726 } else if ( !strncasecmp( cargv[ i ], TLIMITSTR "=",
2727 STRLENOF( TLIMITSTR "=" ) ) )
2729 val = cargv[ i ] + STRLENOF( TLIMITSTR "=" );
2730 si->si_tlimit = atoi( val );
2731 } else if ( bindconf_parse( cargv[i], &si->si_bindconf )) {
2732 fprintf( stderr, "Error: parse_syncrepl_line: "
2733 "unknown keyword \"%s\"\n", cargv[ i ] );
2738 if ( gots != GOT_ALL ) {
2740 "Error: Malformed \"syncrepl\" line in slapd config file" );
2748 syncrepl_unparse( syncinfo_t *si, struct berval *bv )
2751 char buf[BUFSIZ*2], *ptr;
2754 bindconf_unparse( &si->si_bindconf, &bc );
2756 ptr += sprintf( ptr, IDSTR "=%03d " PROVIDERSTR "=%s",
2757 si->si_rid, si->si_provideruri.bv_val );
2758 if ( !BER_BVISNULL( &bc )) {
2759 ptr = lutil_strcopy( ptr, bc.bv_val );
2762 if ( !BER_BVISEMPTY( &si->si_filterstr )) {
2763 ptr = lutil_strcopy( ptr, " " FILTERSTR "=\"" );
2764 ptr = lutil_strcopy( ptr, si->si_filterstr.bv_val );
2767 if ( !BER_BVISNULL( &si->si_base )) {
2768 ptr = lutil_strcopy( ptr, " " SEARCHBASESTR "=\"" );
2769 ptr = lutil_strcopy( ptr, si->si_base.bv_val );
2772 for (i=0; !BER_BVISNULL(&scopes[i].key);i++) {
2773 if ( si->si_scope == scopes[i].val ) {
2774 ptr = lutil_strcopy( ptr, " " SCOPESTR "=" );
2775 ptr = lutil_strcopy( ptr, scopes[i].key.bv_val );
2779 if ( si->si_attrsonly ) {
2780 ptr = lutil_strcopy( ptr, " " ATTRSONLYSTR "=yes" );
2782 if ( si->si_anfile ) {
2783 ptr = lutil_strcopy( ptr, " " ATTRSSTR "=:include:" );
2784 ptr = lutil_strcopy( ptr, si->si_anfile );
2785 } else if ( si->si_allattrs || si->si_allopattrs ||
2786 ( si->si_anlist && !BER_BVISNULL(&si->si_anlist[0].an_name) )) {
2788 ptr = lutil_strcopy( ptr, " " ATTRSSTR "=\"" );
2790 ptr = anlist_unparse( si->si_anlist, ptr );
2791 if ( si->si_allattrs ) {
2792 if ( old != ptr ) *ptr++ = ',';
2795 if ( si->si_allopattrs ) {
2796 if ( old != ptr ) *ptr++ = ',';
2801 if ( si->si_exanlist && !BER_BVISNULL(&si->si_exanlist[0].an_name) ) {
2802 ptr = lutil_strcopy( ptr, " " EXATTRSSTR "=" );
2803 ptr = anlist_unparse( si->si_exanlist, ptr );
2805 ptr = lutil_strcopy( ptr, " " SCHEMASTR "=" );
2806 ptr = lutil_strcopy( ptr, si->si_schemachecking ? "on" : "off" );
2808 ptr = lutil_strcopy( ptr, " " TYPESTR "=" );
2809 ptr = lutil_strcopy( ptr, si->si_type == LDAP_SYNC_REFRESH_AND_PERSIST ?
2810 "refreshAndPersist" : "refreshOnly" );
2812 if ( si->si_type == LDAP_SYNC_REFRESH_ONLY ) {
2815 dd = si->si_interval;
2822 ptr = lutil_strcopy( ptr, " " INTERVALSTR "=" );
2823 ptr += sprintf( ptr, "%02d:%02d:%02d:%02d", dd, hh, mm, ss );
2824 } else if ( si->si_retryinterval ) {
2826 ptr = lutil_strcopy( ptr, " " RETRYSTR "=\"" );
2827 for (i=0; si->si_retryinterval[i]; i++) {
2828 if ( space ) *ptr++ = ' ';
2830 ptr += sprintf( ptr, "%d", si->si_retryinterval[i] );
2831 if ( si->si_retrynum_init[i] == -1 )
2834 ptr += sprintf( ptr, "%d", si->si_retrynum_init );
2839 #if 0 /* FIXME: unused in syncrepl.c, should remove it */
2840 ptr = lutil_strcopy( ptr, " " MANAGEDSAITSTR "=" );
2841 ptr += sprintf( ptr, "%d", si->si_manageDSAit );
2844 if ( si->si_slimit ) {
2845 ptr = lutil_strcopy( ptr, " " SLIMITSTR "=" );
2846 ptr += sprintf( ptr, "%d", si->si_slimit );
2849 if ( si->si_tlimit ) {
2850 ptr = lutil_strcopy( ptr, " " TLIMITSTR "=" );
2851 ptr += sprintf( ptr, "%d", si->si_tlimit );
2853 bc.bv_len = ptr - buf;
2855 ber_dupbv( bv, &bc );
2858 static CfEntryInfo *
2859 config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last )
2869 if ( dn_match( &root->ce_entry->e_nname, dn ))
2872 c = dn->bv_val+dn->bv_len;
2873 for (;*c != ',';c--);
2877 for (--c;c>dn->bv_val && *c != ',';c--);
2881 cdn.bv_len = dn->bv_len - (cdn.bv_val - dn->bv_val);
2883 root = root->ce_kids;
2885 for (;root;root=root->ce_sibs) {
2886 if ( dn_match( &root->ce_entry->e_nname, &cdn )) {
2887 if ( cdn.bv_val == dn->bv_val ) {
2898 config_ldif_resp( Operation *op, SlapReply *rs )
2900 if ( rs->sr_type == REP_SEARCH ) {
2901 CfBackInfo *cfb = op->o_callback->sc_private;
2903 cfb->cb_got_ldif = 1;
2904 rs->sr_err = config_add_internal( cfb, rs->sr_entry, NULL, NULL );
2909 /* Configure and read the underlying back-ldif store */
2911 config_setup_ldif( BackendDB *be, const char *dir ) {
2912 CfBackInfo *cfb = be->be_private;
2917 slap_callback cb = { NULL, config_ldif_resp, NULL, NULL };
2918 Connection conn = {0};
2919 char opbuf[OPERATION_BUFFER_SIZE];
2921 SlapReply rs = {REP_RESULT};
2922 Filter filter = { LDAP_FILTER_PRESENT };
2923 struct berval filterstr = BER_BVC("(objectclass=*)");
2926 /* Is the config directory available? */
2927 if ( stat( dir, &st ) < 0 ) {
2928 /* No, so don't bother using the backing store.
2929 * All changes will be in-memory only.
2934 cfb->cb_db.bd_info = backend_info( "ldif" );
2935 if ( !cfb->cb_db.bd_info )
2936 return 0; /* FIXME: eventually this will be a fatal error */
2938 if ( cfb->cb_db.bd_info->bi_db_init( &cfb->cb_db )) return 1;
2940 /* Mark that back-ldif type is in use */
2941 cfb->cb_db.bd_info->bi_nDB++;
2943 cfb->cb_db.be_suffix = be->be_suffix;
2944 cfb->cb_db.be_nsuffix = be->be_nsuffix;
2945 cfb->cb_db.be_rootdn = be->be_rootdn;
2946 cfb->cb_db.be_rootndn = be->be_rootndn;
2948 ber_str2bv( dir, 0, 1, &cfdir );
2953 argv[0] = "directory";
2954 argv[1] = (char *)dir;
2958 ct = config_find_keyword( c.be->be_cf_table, &c );
2962 if ( config_add_vals( ct, &c ))
2965 if ( backend_startup_one( &cfb->cb_db ))
2968 op = (Operation *)opbuf;
2969 connection_fake_init( &conn, op, cfb );
2971 filter.f_desc = slap_schema.si_ad_objectClass;
2973 op->o_tag = LDAP_REQ_SEARCH;
2975 op->ors_filter = &filter;
2976 op->ors_filterstr = filterstr;
2977 op->ors_scope = LDAP_SCOPE_SUBTREE;
2979 op->o_dn = be->be_rootdn;
2980 op->o_ndn = be->be_rootndn;
2982 op->o_req_dn = be->be_suffix[0];
2983 op->o_req_ndn = be->be_nsuffix[0];
2985 op->ors_tlimit = SLAP_NO_LIMIT;
2986 op->ors_slimit = SLAP_NO_LIMIT;
2988 op->ors_attrs = slap_anlist_all_attributes;
2989 op->ors_attrsonly = 0;
2991 op->o_callback = &cb;
2992 cb.sc_private = cfb;
2994 op->o_bd = &cfb->cb_db;
2995 op->o_bd->be_search( op, &rs );
2997 cfb->cb_use_ldif = 1;
3003 CfOcInfo_cmp( const void *c1, const void *c2 ) {
3004 const CfOcInfo *co1 = c1;
3005 const CfOcInfo *co2 = c2;
3007 return ber_bvcmp( co1->co_name, co2->co_name );
3011 config_register_schema(ConfigTable *ct, ConfigOCs *ocs) {
3015 i = init_config_attrs( ct );
3018 /* set up the objectclasses */
3019 i = init_config_ocs( ocs );
3022 for (i=0; ocs[i].def; i++) {
3024 co = ch_malloc( sizeof(CfOcInfo) );
3025 co->co_oc = *ocs[i].oc;
3026 co->co_name = &co->co_oc->soc_cname;
3028 co->co_type = ocs[i].cft;
3029 avl_insert( &CfOcTree, co, CfOcInfo_cmp, avl_dup_error );
3036 read_config(const char *fname, const char *dir) {
3040 /* Setup the config backend */
3041 be = backend_db_init( "config" );
3045 cfb = be->be_private;
3047 /* Setup the underlying back-ldif backend */
3048 if ( config_setup_ldif( be, dir ))
3051 #ifdef SLAP_USE_CONFDIR
3052 /* If we read the config from back-ldif, nothing to do here */
3053 if ( cfb->cb_got_ldif )
3056 ber_str2bv( fname, 0, 1, &cf_prv.c_file );
3058 return read_config_file(fname, 0, NULL);
3062 config_back_bind( Operation *op, SlapReply *rs )
3064 if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
3065 ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ));
3066 /* frontend sends result */
3067 return LDAP_SUCCESS;
3070 rs->sr_err = LDAP_INVALID_CREDENTIALS;
3071 send_ldap_result( op, rs );
3077 config_send( Operation *op, SlapReply *rs, CfEntryInfo *ce, int depth )
3081 if ( test_filter( op, ce->ce_entry, op->ors_filter ) == LDAP_COMPARE_TRUE )
3083 rs->sr_attrs = op->ors_attrs;
3084 rs->sr_entry = ce->ce_entry;
3085 rc = send_search_entry( op, rs );
3087 if ( op->ors_scope == LDAP_SCOPE_SUBTREE ) {
3088 if ( ce->ce_kids ) {
3089 rc = config_send( op, rs, ce->ce_kids, 1 );
3090 if ( rc ) return rc;
3093 for (ce=ce->ce_sibs; ce; ce=ce->ce_sibs) {
3094 rc = config_send( op, rs, ce, 0 );
3102 static ConfigTable *
3103 config_find_table( CfOcInfo **colst, int nocs, AttributeDescription *ad )
3107 for (j=0; j<nocs; j++) {
3108 for (i=0; colst[j]->co_table[i].name; i++)
3109 if ( colst[j]->co_table[i].ad == ad )
3110 return &colst[j]->co_table[i];
3115 /* Sort the attributes of the entry according to the order defined
3116 * in the objectclass, with required attributes occurring before
3117 * allowed attributes. For any attributes with sequencing dependencies
3118 * (e.g., rootDN must be defined after suffix) the objectclass must
3119 * list the attributes in the desired sequence.
3122 sort_attrs( Entry *e, CfOcInfo **colst, int nocs )
3124 Attribute *a, *head = NULL, *tail = NULL, **prev;
3127 for (i=0; i<nocs; i++) {
3128 if ( colst[i]->co_oc->soc_required ) {
3129 AttributeType **at = colst[i]->co_oc->soc_required;
3130 for (j=0; at[j]; j++) {
3131 for (a=e->e_attrs, prev=&e->e_attrs; a;
3132 prev = &(*prev)->a_next, a=a->a_next) {
3133 if ( a->a_desc == at[j]->sat_ad ) {
3147 if ( colst[i]->co_oc->soc_allowed ) {
3148 AttributeType **at = colst[i]->co_oc->soc_allowed;
3149 for (j=0; at[j]; j++) {
3150 for (a=e->e_attrs, prev=&e->e_attrs; a;
3151 prev = &(*prev)->a_next, a=a->a_next) {
3152 if ( a->a_desc == at[j]->sat_ad ) {
3168 tail->a_next = e->e_attrs;
3174 check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr )
3176 Attribute *a = NULL;
3177 AttributeDescription *ad;
3180 int i, rc = 0, sort = 0;
3187 Modifications *ml = ptr;
3189 vals = ml->sml_values;
3192 if ( a && ( ad->ad_type->sat_flags & SLAP_AT_ORDERED )) {
3194 rc = ordered_value_sort( a, 1 );
3198 for ( i=0; vals[i].bv_val; i++ ) {
3199 ca->line = vals[i].bv_val;
3201 char *idx = strchr( ca->line, '}' );
3202 if ( idx ) ca->line = idx+1;
3204 rc = config_parse_vals( ct, ca, i );
3212 check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
3213 SlapReply *rs, int *renum )
3216 int index = -1, gotindex = 0, nsibs;
3217 int renumber = 0, tailindex = 0;
3221 if ( renum ) *renum = 0;
3223 /* These entries don't get indexed/renumbered */
3224 if ( ce_type == Cft_Global ) return 0;
3225 if ( ce_type == Cft_Schema && parent->ce_type == Cft_Global ) return 0;
3227 if ( ce_type == Cft_Include || ce_type == Cft_Module )
3230 /* See if the rdn has an index already */
3231 dnRdn( &e->e_name, &rdn );
3232 ptr1 = strchr( e->e_name.bv_val, '{' );
3233 if ( ptr1 && ptr1 - e->e_name.bv_val < rdn.bv_len ) {
3234 ptr2 = strchr( ptr1, '}' );
3235 if (!ptr2 || ptr2 - e->e_name.bv_val > rdn.bv_len)
3236 return LDAP_NAMING_VIOLATION;
3237 if ( ptr2-ptr1 == 1)
3238 return LDAP_NAMING_VIOLATION;
3240 index = atoi(ptr1+1);
3242 return LDAP_NAMING_VIOLATION;
3245 /* count related kids */
3246 for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) {
3247 if ( ce->ce_type == ce_type ) nsibs++;
3250 if ( index != nsibs ) {
3252 if ( index < nsibs ) {
3253 if ( tailindex ) return LDAP_NAMING_VIOLATION;
3254 /* Siblings need to be renumbered */
3259 struct berval ival, newrdn, nnewrdn;
3260 struct berval rtype, rval;
3262 AttributeDescription *ad = NULL;
3266 rval.bv_val = strchr(rdn.bv_val, '=' ) + 1;
3267 rval.bv_len = rdn.bv_len - (rval.bv_val - rdn.bv_val);
3268 rtype.bv_val = rdn.bv_val;
3269 rtype.bv_len = rval.bv_val - rtype.bv_val - 1;
3272 slap_bv2ad( &rtype, &ad, &text );
3273 a = attr_find( e->e_attrs, ad );
3274 if (!a ) return LDAP_NAMING_VIOLATION;
3277 ival.bv_len = sprintf( ibuf, IFMT, nsibs );
3279 newrdn.bv_len = rdn.bv_len + ival.bv_len;
3280 newrdn.bv_val = ch_malloc( newrdn.bv_len+1 );
3283 ptr1 = lutil_strncopy( newrdn.bv_val, rdn.bv_val, rdn.bv_len );
3284 ptr1 = lutil_strcopy( ptr1, ival.bv_val );
3291 xlen = rdn.bv_len - (ptr2 - rdn.bv_val);
3293 ptr1 = lutil_strncopy( newrdn.bv_val, rtype.bv_val,
3296 ptr1 = lutil_strcopy( ptr1, ival.bv_val );
3297 ptr1 = lutil_strncopy( ptr1, ptr2, xlen );
3301 /* Do the equivalent of ModRDN */
3302 /* Replace DN / NDN */
3303 newrdn.bv_len = ptr1 - newrdn.bv_val;
3304 rdnNormalize( 0, NULL, NULL, &newrdn, &nnewrdn, NULL );
3305 free( e->e_name.bv_val );
3306 build_new_dn( &e->e_name, &parent->ce_entry->e_name,
3308 free( e->e_nname.bv_val );
3309 build_new_dn( &e->e_nname, &parent->ce_entry->e_nname,
3313 free( a->a_vals[0].bv_val );
3314 ptr1 = strchr( newrdn.bv_val, '=' ) + 1;
3315 a->a_vals[0].bv_len = newrdn.bv_len - (ptr1 - newrdn.bv_val);
3316 a->a_vals[0].bv_val = ch_malloc( a->a_vals[0].bv_len + 1 );
3317 strcpy( a->a_vals[0].bv_val, ptr1 );
3319 if ( a->a_nvals != a->a_vals ) {
3320 free( a->a_nvals[0].bv_val );
3321 ptr1 = strchr( nnewrdn.bv_val, '=' ) + 1;
3322 a->a_nvals[0].bv_len = nnewrdn.bv_len - (ptr1 - nnewrdn.bv_val);
3323 a->a_nvals[0].bv_val = ch_malloc( a->a_nvals[0].bv_len + 1 );
3324 strcpy( a->a_nvals[0].bv_val, ptr1 );
3326 free( nnewrdn.bv_val );
3327 free( newrdn.bv_val );
3330 if ( renum ) *renum = renumber;
3335 count_ocs( Attribute *oc_at, int *nocs )
3338 CfOcInfo co, *coptr, **colst;
3340 /* count the objectclasses */
3341 for ( i=0; oc_at->a_nvals[i].bv_val; i++ );
3343 colst = (CfOcInfo **)ch_malloc( n * sizeof(CfOcInfo *));
3345 for ( i=0, j=0; i<n; i++) {
3346 co.co_name = &oc_at->a_nvals[i];
3347 coptr = avl_find( CfOcTree, &co, CfOcInfo_cmp );
3349 /* ignore non-config objectclasses. probably should be
3350 * an error, general data doesn't belong here.
3352 if ( !coptr ) continue;
3354 /* Ignore the root objectclass, it has no implementation.
3356 if ( coptr->co_type == Cft_Abstract ) continue;
3363 /* Only the root can be Cft_Global, everything else must
3364 /* Parse an LDAP entry into config directives */
3366 config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum )
3368 CfEntryInfo *ce, *last;
3370 Attribute *a, *oc_at, *type_attr;
3371 AttributeDescription *type_ad = NULL;
3373 ConfigArgs ca = {0};
3375 ConfigTable *ct, *type_ct = NULL;
3378 /* Make sure parent exists and entry does not */
3379 ce = config_find_base( cfb->cb_root, &e->e_nname, &last );
3381 return LDAP_ALREADY_EXISTS;
3383 dnParent( &e->e_nname, &pdn );
3385 /* If last is NULL, the new entry is the root/suffix entry,
3386 * otherwise last should be the parent.
3388 if ( last && !dn_match( &last->ce_entry->e_nname, &pdn )) {
3390 rs->sr_matched = last->ce_entry->e_name.bv_val;
3391 return LDAP_NO_SUCH_OBJECT;
3394 oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
3395 if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
3397 colst = count_ocs( oc_at, &nocs );
3399 /* Only the root can be Cft_Global, everything else must
3400 * have a parent. Only limited nesting arrangements are allowed.
3402 switch( colst[0]->co_type ) {
3405 rc = LDAP_CONSTRAINT_VIOLATION;
3413 if ( !last || ( last->ce_type != Cft_Global &&
3414 last->ce_type != colst[0]->co_type )) {
3415 rc = LDAP_CONSTRAINT_VIOLATION;
3420 if ( !last || ( last->ce_type != Cft_Global &&
3421 last->ce_type != Cft_Database &&
3422 last->ce_type != colst[0]->co_type )) {
3423 rc = LDAP_CONSTRAINT_VIOLATION;
3427 #ifdef SLAPD_MODULES
3429 if ( !last || last->ce_type != Cft_Global ) {
3430 rc = LDAP_CONSTRAINT_VIOLATION;
3437 sort_attrs( e, colst, nocs );
3439 /* Parse all the values and check for simple syntax errors before
3440 * performing any set actions.
3442 switch (colst[0]->co_type) {
3444 /* The cn=schema entry is all hardcoded, so never reparse it */
3445 if (last->ce_type == Cft_Global )
3449 ca.be = LDAP_STAILQ_FIRST(&backendDB);
3453 if ( last->ce_type == Cft_Backend )
3454 ca.bi = last->ce_bi;
3456 type_ad = cfAd_backend;
3459 if ( last->ce_type == Cft_Database ) {
3460 ca.be = last->ce_be;
3462 type_ad = cfAd_database;
3463 /* dummy, just to get past check_attr */
3469 ca.be = last->ce_be;
3470 type_ad = cfAd_overlay;
3475 nocs = 0; /* ignored */
3478 type_ad = cfAd_include;
3480 #ifdef SLAPD_MODULES
3484 ptr = strchr( e->e_name.bv_val, '{' );
3486 rc = LDAP_NAMING_VIOLATION;
3490 for (i=0, mp=&modpaths; mp && i<j; mp=mp->mp_next);
3491 /* There is no corresponding modpath for this load? */
3493 rc = LDAP_NAMING_VIOLATION;
3496 module_path( mp->mp_path.bv_val );
3503 /* If doing an LDAPadd, check for indexed names and any necessary
3504 * renaming/renumbering. Entries that don't need indexed names are
3505 * ignored. Entries that need an indexed name and arrive without one
3506 * are assigned to the end. Entries that arrive with an index may
3507 * cause the following entries to be renumbered/bumped down.
3509 * Note that "pseudo-indexed" entries (cn=Include{xx}, cn=Module{xx})
3510 * don't allow Adding an entry with an index that's already in use.
3511 * This is flagged as an error (LDAP_ALREADY_EXISTS) up above.
3513 * These entries can have auto-assigned indexes (appended to the end)
3514 * but only the other types support auto-renumbering of siblings.
3516 rc = check_name_index( last, colst[0]->co_type, e, rs, renum );
3520 init_config_argv( &ca );
3522 type_attr = attr_find( e->e_attrs, type_ad );
3524 rc = LDAP_OBJECT_CLASS_VIOLATION;
3527 type_ct = config_find_table( colst, nocs, type_ad );
3529 rc = LDAP_OBJECT_CLASS_VIOLATION;
3532 rc = check_vals( type_ct, &ca, type_attr, 1);
3533 if ( rc ) goto leave;
3535 for ( a=e->e_attrs; a; a=a->a_next ) {
3536 if ( a == type_attr || a == oc_at ) continue;
3537 ct = config_find_table( colst, nocs, a->a_desc );
3538 if ( !ct ) continue; /* user data? */
3539 rc = check_vals( ct, &ca, a, 1 );
3540 if ( rc ) goto leave;
3543 /* Basic syntax checks are OK. Do the actual settings. */
3545 ca.line = type_attr->a_vals[0].bv_val;
3546 if ( type_ad->ad_type->sat_flags & SLAP_AT_ORDERED ) {
3547 ptr = strchr( ca.line, '}' );
3548 if ( ptr ) ca.line = ptr+1;
3551 rc = config_parse_add( type_ct, &ca );
3557 for ( a=e->e_attrs; a; a=a->a_next ) {
3558 if ( a == type_attr || a == oc_at ) continue;
3559 ct = config_find_table( colst, nocs, a->a_desc );
3560 if ( !ct ) continue; /* user data? */
3561 for (i=0; a->a_vals[i].bv_val; i++) {
3562 ca.line = a->a_vals[i].bv_val;
3563 if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED ) {
3564 ptr = strchr( ca.line, '}' );
3565 if ( ptr ) ca.line = ptr+1;
3568 rc = config_parse_add( ct, &ca );
3576 ce = ch_calloc( 1, sizeof(CfEntryInfo) );
3577 ce->ce_parent = last;
3578 ce->ce_entry = entry_dup( e );
3579 ce->ce_entry->e_private = ce;
3580 ce->ce_type = colst[0]->co_type;
3585 } else if ( last->ce_kids ) {
3588 for (c2=last->ce_kids; c2 && c2->ce_sibs; c2 = c2->ce_sibs);
3597 if ( colst ) ch_free( colst );
3601 /* Parse an LDAP entry into config directives, then store in underlying
3605 config_back_add( Operation *op, SlapReply *rs )
3608 CfEntryInfo *ce, *last;
3611 if ( !be_isroot( op ) ) {
3612 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
3616 cfb = (CfBackInfo *)op->o_bd->be_private;
3618 ldap_pvt_thread_pool_pause( &connection_pool );
3621 * 1) check for existence of entry
3622 * 2) check for sibling renumbering
3623 * 3) perform internal add
3624 * 4) store entry in underlying database
3625 * 5) perform any necessary renumbering
3627 rs->sr_err = config_add_internal( cfb, op->ora_e, rs, &renumber );
3628 if ( rs->sr_err == LDAP_SUCCESS && cfb->cb_use_ldif ) {
3629 BackendDB *be = op->o_bd;
3630 slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
3631 op->o_bd = &cfb->cb_db;
3632 sc.sc_next = op->o_callback;
3633 op->o_callback = ≻
3634 op->o_bd->be_add( op, rs );
3636 op->o_callback = sc.sc_next;
3641 ldap_pvt_thread_pool_resume( &connection_pool );
3644 send_ldap_result( op, rs );
3648 typedef struct delrec {
3649 struct delrec *next;
3655 config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
3656 char *textbuf, int textsize )
3658 CfBackInfo *cfb = (CfBackInfo *)op->o_bd->be_private;
3659 int rc = LDAP_UNWILLING_TO_PERFORM;
3661 Entry *e = ce->ce_entry;
3662 Attribute *save_attrs = e->e_attrs, *oc_at;
3663 ConfigArgs ca = {0};
3668 delrec *dels = NULL, *deltail = NULL;
3670 oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
3671 if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
3673 colst = count_ocs( oc_at, &nocs );
3675 e->e_attrs = attrs_dup( e->e_attrs );
3677 init_config_argv( &ca );
3681 for (ml = op->orm_modlist; ml; ml=ml->sml_next) {
3682 ct = config_find_table( colst, nocs, ml->sml_desc );
3683 switch (ml->sml_op) {
3684 case LDAP_MOD_DELETE:
3685 case LDAP_MOD_REPLACE: {
3686 BerVarray vals = NULL, nvals;
3688 if ( ct && ( ct->arg_type & ARG_NO_DELETE )) {
3689 rc = LDAP_UNWILLING_TO_PERFORM;
3690 snprintf(textbuf, textsize, "cannot delete %s",
3692 rs->sr_text = textbuf;
3695 if ( ml->sml_op == LDAP_MOD_REPLACE ) {
3696 vals = ml->sml_values;
3697 nvals = ml->sml_nvalues;
3698 ml->sml_values = NULL;
3699 ml->sml_nvalues = NULL;
3701 /* If we're deleting by values, remember the indexes of the
3702 * values we deleted.
3704 if ( ct && ml->sml_values ) {
3706 for (i=0; ml->sml_values[i].bv_val; i++);
3707 d = ch_malloc( sizeof(delrec) + i * sizeof(int));
3718 rc = modify_delete_vindex(e, &ml->sml_mod,
3719 get_permissiveModify(op),
3720 &rs->sr_text, textbuf, textsize, idx );
3721 if ( ml->sml_op == LDAP_MOD_REPLACE ) {
3722 ml->sml_values = vals;
3723 ml->sml_nvalues = nvals;
3728 /* FALLTHRU: LDAP_MOD_REPLACE && vals */
3731 case SLAP_MOD_SOFTADD: {
3732 int mop = ml->sml_op;
3734 ml->sml_op = LDAP_MOD_ADD;
3736 if ( ct->arg_type & ARG_NO_INSERT ) {
3737 Attribute *a = attr_find( e->e_attrs, ml->sml_desc );
3739 for (i = 0; a->a_vals[i].bv_val; i++ );
3743 for ( i=0; !BER_BVISNULL( &ml->sml_values[i] ); i++ ) {
3744 if ( ml->sml_values[i].bv_val[0] == '{' &&
3746 int j = strtol( ml->sml_values[i].bv_val+1, NULL, 0 );
3748 rc = LDAP_UNWILLING_TO_PERFORM;
3749 snprintf(textbuf, textsize, "cannot insert %s",
3751 rs->sr_text = textbuf;
3755 rc = check_vals( ct, &ca, ml, 0 );
3759 rc = modify_add_values(e, &ml->sml_mod,
3760 get_permissiveModify(op),
3761 &rs->sr_text, textbuf, textsize );
3763 /* If value already exists, show success here
3764 * and ignore this operation down below.
3766 if ( mop == SLAP_MOD_SOFTADD ) {
3767 if ( rc == LDAP_TYPE_OR_VALUE_EXISTS )
3777 case LDAP_MOD_INCREMENT: /* FIXME */
3782 if(rc != LDAP_SUCCESS) break;
3785 if(rc == LDAP_SUCCESS) {
3786 /* check that the entry still obeys the schema */
3787 rc = entry_schema_check(op->o_bd, e, NULL,
3788 &rs->sr_text, textbuf, textsize );
3790 if ( rc == LDAP_SUCCESS ) {
3791 /* Basic syntax checks are OK. Do the actual settings. */
3792 for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
3793 ct = config_find_table( colst, nocs, ml->sml_desc );
3794 if ( !ct ) continue;
3796 switch (ml->sml_op) {
3797 case LDAP_MOD_DELETE:
3798 case LDAP_MOD_REPLACE: {
3799 BerVarray vals = NULL, nvals;
3803 a = attr_find( e->e_attrs, ml->sml_desc );
3805 if ( ml->sml_op == LDAP_MOD_REPLACE ) {
3806 vals = ml->sml_values;
3807 nvals = ml->sml_nvalues;
3808 ml->sml_values = NULL;
3809 ml->sml_nvalues = NULL;
3811 /* If we didn't delete the whole attribute */
3812 if ( ml->sml_values && a ) {
3813 struct berval *mvals;
3816 if ( ml->sml_nvalues )
3817 mvals = ml->sml_nvalues;
3819 mvals = ml->sml_values;
3821 /* use the indexes we saved up above */
3822 for (i=0; i < d->nidx; i++) {
3823 struct berval bv = *mvals++;
3824 if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED &&
3825 bv.bv_val[0] == '{' ) {
3826 ptr = strchr( bv.bv_val, '}' ) + 1;
3827 bv.bv_len -= ptr - bv.bv_val;
3830 ca.line = bv.bv_val;
3831 ca.valx = d->idx[i];
3832 rc = config_del_vals( ct, &ca );
3833 if ( rc != LDAP_SUCCESS ) break;
3834 for (j=i+1; j < d->nidx; j++)
3835 if ( d->idx[j] >d->idx[i] )
3841 rc = config_del_vals( ct, &ca );
3845 if ( ml->sml_op == LDAP_MOD_REPLACE ) {
3846 ml->sml_values = vals;
3847 ml->sml_nvalues = nvals;
3849 if ( !vals || rc != LDAP_SUCCESS )
3852 /* FALLTHRU: LDAP_MOD_REPLACE && vals */
3855 for (i=0; ml->sml_values[i].bv_val; i++) {
3856 ca.line = ml->sml_values[i].bv_val;
3858 if ( ml->sml_desc->ad_type->sat_flags & SLAP_AT_ORDERED &&
3859 ca.line[0] == '{' ) {
3860 ptr = strchr( ca.line, '}' );
3862 ca.valx = strtol( ca.line+1, NULL, 0 );
3866 rc = config_parse_add( ct, &ca );
3879 if ( rc == LDAP_SUCCESS ) {
3880 attrs_free( save_attrs );
3882 attrs_free( e->e_attrs );
3883 e->e_attrs = save_attrs;
3886 if ( colst ) ch_free( colst );
3892 config_back_modify( Operation *op, SlapReply *rs )
3895 CfEntryInfo *ce, *last;
3897 char textbuf[SLAP_TEXT_BUFLEN];
3900 AttributeDescription *rad = NULL;
3902 if ( !be_isroot( op ) ) {
3903 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
3907 cfb = (CfBackInfo *)op->o_bd->be_private;
3909 ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
3912 rs->sr_matched = last->ce_entry->e_name.bv_val;
3913 rs->sr_err = LDAP_NO_SUCH_OBJECT;
3917 /* Get type of RDN */
3918 rdn = ce->ce_entry->e_nname;
3919 ptr = strchr( rdn.bv_val, '=' );
3920 rdn.bv_len = ptr - rdn.bv_val;
3921 slap_bv2ad( &rdn, &rad, &rs->sr_text );
3923 /* Some basic validation... */
3924 for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
3925 /* Don't allow Modify of RDN; must use ModRdn for that. */
3926 if ( ml->sml_desc == rad ) {
3927 rs->sr_err = LDAP_NOT_ALLOWED_ON_RDN;
3928 rs->sr_text = "Use modrdn to change the entry name";
3933 ldap_pvt_thread_pool_pause( &connection_pool );
3936 * 1) perform the Modify on the cached Entry.
3937 * 2) verify that the Entry still satisfies the schema.
3938 * 3) perform the individual config operations.
3939 * 4) store Modified entry in underlying LDIF backend.
3941 rs->sr_err = config_modify_internal( ce, op, rs, textbuf, sizeof(textbuf) );
3942 if ( rs->sr_err == LDAP_SUCCESS && cfb->cb_use_ldif ) {
3943 BackendDB *be = op->o_bd;
3944 slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
3945 op->o_bd = &cfb->cb_db;
3946 sc.sc_next = op->o_callback;
3947 op->o_callback = ≻
3948 op->o_bd->be_modify( op, rs );
3950 op->o_callback = sc.sc_next;
3953 ldap_pvt_thread_pool_resume( &connection_pool );
3955 send_ldap_result( op, rs );
3960 config_back_modrdn( Operation *op, SlapReply *rs )
3963 CfEntryInfo *ce, *last;
3965 if ( !be_isroot( op ) ) {
3966 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
3970 cfb = (CfBackInfo *)op->o_bd->be_private;
3972 ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
3975 rs->sr_matched = last->ce_entry->e_name.bv_val;
3976 rs->sr_err = LDAP_NO_SUCH_OBJECT;
3980 /* We don't allow moving objects to new parents.
3981 * Generally we only allow reordering a set of ordered entries.
3983 if ( op->orr_newSup ) {
3984 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
3987 ldap_pvt_thread_pool_pause( &connection_pool );
3989 ldap_pvt_thread_pool_resume( &connection_pool );
3991 send_ldap_result( op, rs );
3996 config_back_search( Operation *op, SlapReply *rs )
3999 CfEntryInfo *ce, *last;
4002 if ( !be_isroot( op ) ) {
4003 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
4007 cfb = (CfBackInfo *)op->o_bd->be_private;
4009 ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
4012 rs->sr_matched = last->ce_entry->e_name.bv_val;
4013 rs->sr_err = LDAP_NO_SUCH_OBJECT;
4016 switch ( op->ors_scope ) {
4017 case LDAP_SCOPE_BASE:
4018 case LDAP_SCOPE_SUBTREE:
4019 config_send( op, rs, ce, 0 );
4022 case LDAP_SCOPE_ONELEVEL:
4023 for (ce = ce->ce_kids; ce; ce=ce->ce_sibs) {
4024 config_send( op, rs, ce, 1 );
4029 rs->sr_err = LDAP_SUCCESS;
4031 send_ldap_result( op, rs );
4036 config_alloc_entry( CfEntryInfo *parent, struct berval *rdn )
4038 Entry *e = ch_calloc( 1, sizeof(Entry) );
4039 CfEntryInfo *ce = ch_calloc( 1, sizeof(CfEntryInfo) );
4044 ce->ce_parent = parent;
4046 pdn = parent->ce_entry->e_nname;
4051 build_new_dn( &e->e_name, &pdn, rdn, NULL );
4052 ber_dupbv( &e->e_nname, &e->e_name );
4061 config_build_entry( ConfigArgs *c, Entry *e, ObjectClass *oc,
4062 struct berval *rdn, ConfigTable *ct, int table )
4064 struct berval vals[2];
4065 struct berval ad_name;
4066 AttributeDescription *ad = NULL;
4070 char textbuf[SLAP_TEXT_BUFLEN];
4071 size_t textlen = sizeof(textbuf);
4075 BER_BVZERO( &vals[1] );
4077 vals[0] = oc->soc_cname;
4078 attr_merge_normalize(e, slap_schema.si_ad_objectClass, vals, NULL );
4079 ptr = strchr(rdn->bv_val, '=');
4080 ad_name.bv_val = rdn->bv_val;
4081 ad_name.bv_len = ptr - rdn->bv_val;
4082 rc = slap_bv2ad( &ad_name, &ad, &text );
4086 vals[0].bv_val = ptr+1;
4087 vals[0].bv_len = rdn->bv_len - (vals[0].bv_val - rdn->bv_val);
4088 attr_merge_normalize(e, ad, vals, NULL );
4090 for (at=oc->soc_required; at && *at; at++) {
4091 /* Skip the naming attr */
4092 if ((*at)->sat_ad == ad || (*at)->sat_ad == slap_schema.si_ad_cn )
4094 for (i=0;ct[i].name;i++) {
4095 if (ct[i].ad == (*at)->sat_ad) {
4096 rc = config_get_vals(&ct[i], c);
4097 if (rc == LDAP_SUCCESS) {
4098 if ( c->rvalue_nvals )
4099 attr_merge(e, ct[i].ad, c->rvalue_vals,
4102 attr_merge_normalize(e, ct[i].ad,
4103 c->rvalue_vals, NULL);
4104 ber_bvarray_free( c->rvalue_nvals );
4105 ber_bvarray_free( c->rvalue_vals );
4112 for (at=oc->soc_allowed; at && *at; at++) {
4113 /* Skip the naming attr */
4114 if ((*at)->sat_ad == ad || (*at)->sat_ad == slap_schema.si_ad_cn )
4116 for (i=0;ct[i].name;i++) {
4117 if (ct[i].ad == (*at)->sat_ad) {
4118 rc = config_get_vals(&ct[i], c);
4119 if (rc == LDAP_SUCCESS) {
4120 if ( c->rvalue_nvals )
4121 attr_merge(e, ct[i].ad, c->rvalue_vals, c->rvalue_nvals);
4123 attr_merge_normalize(e, ct[i].ad, c->rvalue_vals, NULL);
4124 ber_bvarray_free( c->rvalue_nvals );
4125 ber_bvarray_free( c->rvalue_vals );
4133 if ( table == BI_TABLE )
4134 ct = c->bi->bi_cf_table;
4136 ct = c->be->be_cf_table;
4137 for (;ct && ct->name;ct++) {
4138 if (!ct->ad) continue;
4139 rc = config_get_vals(ct, c);
4140 if (rc == LDAP_SUCCESS) {
4141 if ( c->rvalue_nvals )
4142 attr_merge(e, ct->ad, c->rvalue_vals, c->rvalue_nvals);
4144 attr_merge_normalize(e, ct->ad, c->rvalue_vals, NULL);
4148 oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
4149 rc = structural_class(oc_at->a_vals, vals, NULL, &text, textbuf, textlen);
4150 BER_BVZERO( &vals[1] );
4151 attr_merge_normalize(e, slap_schema.si_ad_structuralObjectClass, vals, NULL );
4157 config_build_schema_inc( ConfigArgs *c, CfEntryInfo *ceparent,
4158 Operation *op, SlapReply *rs )
4161 ConfigFile *cf = c->private;
4162 CfEntryInfo *ce, *ceprev;
4166 if ( ceparent->ce_kids ) {
4167 for ( ceprev = ceparent->ce_kids; ceprev->ce_sibs;
4168 ceprev = ceprev->ce_sibs );
4171 for (; cf; cf=cf->c_sibs, c->depth++) {
4172 c->value_dn.bv_val = c->log;
4173 bv.bv_val = strrchr(cf->c_file.bv_val, LDAP_DIRSEP[0]);
4178 bv.bv_len = cf->c_file.bv_len - (bv.bv_val - cf->c_file.bv_val);
4180 ptr = strchr( bv.bv_val, '.' );
4182 bv.bv_len = ptr - bv.bv_val;
4183 c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=" IFMT, c->depth);
4184 strncpy( c->value_dn.bv_val + c->value_dn.bv_len, bv.bv_val,
4186 c->value_dn.bv_len += bv.bv_len;
4187 c->value_dn.bv_val[c->value_dn.bv_len] ='\0';
4189 e = config_alloc_entry( ceparent, &c->value_dn );
4191 config_build_entry( c, e, cfOc_schema, &c->value_dn,
4192 c->bi->bi_cf_table, NO_TABLE );
4194 ce->ce_type = Cft_Schema;
4197 op->o_bd->be_add( op, rs );
4200 if ( !ceparent->ce_kids ) {
4201 ceparent->ce_kids = ce;
4203 ceprev->ce_sibs = ce;
4207 c->private = cf->c_kids;
4208 config_build_schema_inc( c, ceparent, op, rs );
4213 static CfEntryInfo *
4214 config_build_includes( ConfigArgs *c, CfEntryInfo *ceparent,
4215 Operation *op, SlapReply *rs )
4219 ConfigFile *cf = c->private;
4220 CfEntryInfo *ce, *ceprev;
4222 if ( ceparent->ce_kids ) {
4223 for ( ceprev = ceparent->ce_kids; ceprev->ce_sibs;
4224 ceprev = ceprev->ce_sibs );
4227 for (i=0; cf; cf=cf->c_sibs, i++) {
4228 c->value_dn.bv_val = c->log;
4229 c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=include" IFMT, i);
4230 e = config_alloc_entry( ceparent, &c->value_dn );
4232 config_build_entry( c, e, cfOc_include, &c->value_dn,
4233 c->bi->bi_cf_table, NO_TABLE );
4236 op->o_bd->be_add( op, rs );
4239 ce->ce_type = Cft_Include;
4241 if ( !ceparent->ce_kids ) {
4242 ceparent->ce_kids = ce;
4244 ceprev->ce_sibs = ce;
4248 c->private = cf->c_kids;
4249 config_build_includes( c, ce, op, rs );
4255 #ifdef SLAPD_MODULES
4257 static CfEntryInfo *
4258 config_build_modules( ConfigArgs *c, CfEntryInfo *ceparent,
4259 Operation *op, SlapReply *rs )
4263 CfEntryInfo *ce, *ceprev;
4266 if ( ceparent->ce_kids ) {
4267 for ( ceprev = ceparent->ce_kids; ceprev->ce_sibs;
4268 ceprev = ceprev->ce_sibs );
4271 for (i=0, mp=&modpaths; mp; mp=mp->mp_next, i++) {
4272 if ( BER_BVISNULL( &mp->mp_path ) && !mp->mp_loads )
4274 c->value_dn.bv_val = c->log;
4275 c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=module" IFMT, i);
4276 e = config_alloc_entry( ceparent, &c->value_dn );
4278 ce->ce_type = Cft_Include;
4280 config_build_entry( c, e, cfOc_module, &c->value_dn,
4281 c->bi->bi_cf_table, NO_TABLE );
4284 op->o_bd->be_add( op, rs );
4287 if ( !ceparent->ce_kids ) {
4288 ceparent->ce_kids = ce;
4290 ceprev->ce_sibs = ce;
4299 config_back_db_open( BackendDB *be )
4301 CfBackInfo *cfb = be->be_private;
4304 CfEntryInfo *ce, *ceparent, *ceprev;
4310 Connection conn = {0};
4311 char opbuf[OPERATION_BUFFER_SIZE];
4313 slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
4314 SlapReply rs = {REP_RESULT};
4316 /* If we read the config from back-ldif, nothing to do here */
4317 if ( cfb->cb_got_ldif )
4320 if ( cfb->cb_use_ldif ) {
4321 op = (Operation *)opbuf;
4322 connection_fake_init( &conn, op, cfb );
4324 op->o_dn = be->be_rootdn;
4325 op->o_ndn = be->be_rootndn;
4327 op->o_tag = LDAP_REQ_ADD;
4328 op->o_callback = &cb;
4329 op->o_bd = &cfb->cb_db;
4334 /* create root of tree */
4336 e = config_alloc_entry( NULL, &rdn );
4338 ce->ce_type = Cft_Global;
4342 c.private = cfb->cb_config;
4343 ct = c.bi->bi_cf_table;
4344 config_build_entry( &c, e, cfOc_global, &rdn, ct, NO_TABLE );
4347 op->o_bd->be_add( op, &rs );
4354 /* Create schema nodes... cn=schema will contain the hardcoded core
4355 * schema, read-only. Child objects will contain runtime loaded schema
4359 e = config_alloc_entry( ceparent, &rdn );
4361 ce->ce_type = Cft_Schema;
4363 config_build_entry( &c, e, cfOc_schema, &rdn, ct, NO_TABLE );
4366 op->o_bd->be_add( op, &rs );
4368 if ( !ceparent->ce_kids ) {
4369 ceparent->ce_kids = ce;
4371 ceprev->ce_sibs = ce;
4375 /* Create includeFile nodes and schema nodes for included schema... */
4376 if ( cfb->cb_config->c_kids ) {
4378 c.private = cfb->cb_config->c_kids;
4379 config_build_schema_inc( &c, ce, op, &rs );
4380 c.private = cfb->cb_config->c_kids;
4381 ceprev = config_build_includes( &c, ceparent, op, &rs );
4384 #ifdef SLAPD_MODULES
4385 /* Create Module nodes... */
4386 if ( modpaths.mp_loads ) {
4387 ceprev = config_build_modules( &c, ceparent, op, &rs );
4391 /* Create backend nodes. Skip if they don't provide a cf_table.
4392 * There usually aren't any of these.
4396 LDAP_STAILQ_FOREACH( bi, &backendInfo, bi_next) {
4397 if (!bi->bi_cf_table) continue;
4398 if (!bi->bi_private) continue;
4401 rdn.bv_len = sprintf(rdn.bv_val, "%s=%s", cfAd_backend->ad_cname.bv_val, bi->bi_type);
4402 e = config_alloc_entry( ceparent, &rdn );
4404 ce->ce_type = Cft_Backend;
4407 config_build_entry( &c, e, cfOc_backend, &rdn, ct, BI_TABLE );
4410 op->o_bd->be_add( op, &rs );
4412 if ( !ceparent->ce_kids ) {
4413 ceparent->ce_kids = ce;
4415 ceprev->ce_sibs = ce;
4420 /* Create database nodes... */
4422 LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
4423 slap_overinfo *oi = NULL;
4430 if ( overlay_is_over( bptr )) {
4431 oi = bptr->bd_info->bi_private;
4437 rdn.bv_len = sprintf(rdn.bv_val, "%s=" IFMT "%s", cfAd_database->ad_cname.bv_val,
4439 e = config_alloc_entry( ceparent, &rdn );
4443 ce->ce_type = Cft_Database;
4446 config_build_entry( &c, e, cfOc_database, &rdn, ct, BE_TABLE );
4449 op->o_bd->be_add( op, &rs );
4451 if ( !ceparent->ce_kids ) {
4452 ceparent->ce_kids = ce;
4454 ceprev->ce_sibs = ce;
4457 /* Iterate through overlays */
4461 CfEntryInfo *opar = ce, *oprev = NULL;
4464 for (j=0,on=oi->oi_list; on; j++,on=on->on_next) {
4466 rdn.bv_len = sprintf(rdn.bv_val, "%s=" IFMT "%s",
4467 cfAd_overlay->ad_cname.bv_val, j, on->on_bi.bi_type );
4468 oe = config_alloc_entry( opar, &rdn );
4472 ce->ce_type = Cft_Overlay;
4475 config_build_entry( &c, oe, cfOc_overlay, &rdn, ct, BI_TABLE );
4478 op->o_bd->be_add( op, &rs );
4480 if ( !opar->ce_kids ) {
4483 oprev->ce_sibs = ce;
4494 config_back_db_destroy( Backend *be )
4496 free( be->be_private );
4501 config_back_db_init( Backend *be )
4506 cfb = ch_calloc( 1, sizeof(CfBackInfo));
4507 cfb->cb_config = &cf_prv;
4508 be->be_private = cfb;
4510 ber_dupbv( &be->be_rootdn, &config_rdn );
4511 ber_dupbv( &be->be_rootndn, &be->be_rootdn );
4512 ber_dupbv( &dn, &be->be_rootdn );
4513 ber_bvarray_add( &be->be_suffix, &dn );
4514 ber_dupbv( &dn, &be->be_rootdn );
4515 ber_bvarray_add( &be->be_nsuffix, &dn );
4517 /* Hide from namingContexts */
4518 SLAP_BFLAGS(be) |= SLAP_BFLAG_CONFIG;
4524 config_back_destroy( BackendInfo *bi )
4526 ldif_must_b64_encode_release();
4532 AttributeDescription **desc;
4534 { "backend", &cfAd_backend },
4535 { "database", &cfAd_database },
4536 { "include", &cfAd_include },
4537 { "overlay", &cfAd_overlay },
4542 * add / delete: all types that may be added or deleted must use an
4543 * X-ORDERED attributeType for their RDN. Adding and deleting entries
4544 * should automatically renumber the index of any siblings as needed,
4545 * so that no gaps in the numbering sequence exist after the add/delete
4547 * What can be added:
4549 * backend objects for backend-specific config directives
4553 * delete: probably no support this time around.
4555 * modrdn: generally not done. Will be invoked automatically by add/
4556 * delete to update numbering sequence. Perform as an explicit operation
4557 * so that the renumbering effect may be replicated. Subtree rename must
4558 * be supported, since renumbering a database will affect all its child
4561 * modify: must be fully supported.
4565 config_back_initialize( BackendInfo *bi )
4567 ConfigTable *ct = config_back_cf_table;
4570 AttributeDescription *ad = NULL;
4572 static char *controls[] = {
4573 LDAP_CONTROL_MANAGEDSAIT,
4577 bi->bi_controls = controls;
4582 bi->bi_destroy = config_back_destroy;
4584 bi->bi_db_init = config_back_db_init;
4585 bi->bi_db_config = 0;
4586 bi->bi_db_open = config_back_db_open;
4587 bi->bi_db_close = 0;
4588 bi->bi_db_destroy = config_back_db_destroy;
4590 bi->bi_op_bind = config_back_bind;
4591 bi->bi_op_unbind = 0;
4592 bi->bi_op_search = config_back_search;
4593 bi->bi_op_compare = 0;
4594 bi->bi_op_modify = config_back_modify;
4595 bi->bi_op_modrdn = config_back_modrdn;
4596 bi->bi_op_add = config_back_add;
4597 bi->bi_op_delete = 0;
4598 bi->bi_op_abandon = 0;
4600 bi->bi_extended = 0;
4602 bi->bi_chk_referrals = 0;
4604 #ifdef SLAP_OVERLAY_ACCESS
4605 bi->bi_access_allowed = slap_access_always_allowed;
4606 #endif /* SLAP_OVERLAY_ACCESS */
4608 bi->bi_connection_init = 0;
4609 bi->bi_connection_destroy = 0;
4612 for (i=0; OidMacros[i].name; i++ ) {
4613 argv[1] = OidMacros[i].name;
4614 argv[2] = OidMacros[i].oid;
4615 parse_oidm( "slapd", i, 3, argv, 0, NULL );
4618 bi->bi_cf_table = ct;
4620 i = config_register_schema( ct, cf_ocs );
4623 /* setup olcRootPW to be base64-encoded when written in LDIF form;
4624 * basically, we don't care if it fails */
4625 i = slap_str2ad( "olcRootPW", &ad, &text );
4627 Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
4628 "warning, unable to get \"olcRootPW\" "
4629 "attribute description: %d: %s\n",
4632 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
4633 ad->ad_type->sat_oid );
4636 /* set up the notable AttributeDescriptions */
4638 for (;ct->name;ct++) {
4639 if (strcmp(ct->name, ads[i].name)) continue;
4640 *ads[i].desc = ct->ad;
4642 if (!ads[i].name) break;