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>
31 #include "slapi/slapi.h"
38 static struct berval config_rdn = BER_BVC("cn=config");
39 static struct berval access_rdn = BER_BVC("cn=access");
42 typedef struct modpath_s {
43 struct modpath_s *mp_next;
44 struct berval mp_path;
49 typedef struct ConfigFile {
50 struct ConfigFile *c_sibs;
51 struct ConfigFile *c_kids;
60 typedef struct CfEntryInfo {
61 struct CfEntryInfo *ce_sibs;
62 struct CfEntryInfo *ce_kids;
69 ConfigFile *cb_config;
71 BackendDB cb_db; /* underlying database */
75 /* These do nothing in slapd, they're kept only to make them
78 static char *replica_pidFile, *replica_argsFile;
79 static int replicationInterval;
81 static char *passwd_salt;
82 static char *logfileName;
83 static BerVarray authz_rewrites;
85 static struct berval cfdir;
87 static AttributeDescription *cfAd_backend, *cfAd_database, *cfAd_overlay,
90 static ObjectClass *cfOc_global, *cfOc_backend, *cfOc_database,
91 *cfOc_include, *cfOc_overlay, *cfOc_access;
93 static ConfigFile cf_prv, *cfn = &cf_prv;
95 static int add_syncrepl LDAP_P(( Backend *, char **, int ));
96 static int parse_syncrepl_line LDAP_P(( char **, int, syncinfo_t *));
97 static void syncrepl_unparse LDAP_P (( syncinfo_t *, struct berval *));
99 static ConfigDriver config_fname;
100 static ConfigDriver config_cfdir;
101 static ConfigDriver config_generic;
102 static ConfigDriver config_search_base;
103 static ConfigDriver config_passwd_hash;
104 static ConfigDriver config_schema_dn;
105 static ConfigDriver config_sizelimit;
106 static ConfigDriver config_timelimit;
107 static ConfigDriver config_limits;
108 static ConfigDriver config_overlay;
109 static ConfigDriver config_suffix;
110 static ConfigDriver config_deref_depth;
111 static ConfigDriver config_rootdn;
112 static ConfigDriver config_rootpw;
113 static ConfigDriver config_restrict;
114 static ConfigDriver config_allows;
115 static ConfigDriver config_disallows;
116 static ConfigDriver config_requires;
117 static ConfigDriver config_security;
118 static ConfigDriver config_referral;
119 static ConfigDriver config_loglevel;
120 static ConfigDriver config_syncrepl;
121 static ConfigDriver config_replica;
122 static ConfigDriver config_updatedn;
123 static ConfigDriver config_updateref;
124 static ConfigDriver config_include;
126 static ConfigDriver config_tls_option;
127 static ConfigDriver config_tls_config;
176 static OidRec OidMacros[] = {
177 /* OpenLDAProot:666.11.1 */
178 { "OLcfg", "1.3.6.1.4.1.4203.666.11.1" },
179 { "OLcfgAt", "OLcfg:3" },
180 { "OLcfgOc", "OLcfg:4" },
181 { "OMsyn", "1.3.6.1.4.1.1466.115.121.1" },
182 { "OMsInteger", "OMsyn:2" },
183 { "OMsBoolean", "OMsyn:7" },
184 { "OMsDN", "OMsyn:12" },
185 { "OMsDirectoryString", "OMsyn:15" },
186 { "OMsOctetString", "OMsyn:40" },
190 /* alphabetical ordering */
192 ConfigTable config_back_cf_table[] = {
193 /* This attr is read-only */
194 { "", "", 0, 0, 0, ARG_MAGIC,
195 &config_fname, "( OLcfgAt:78 NAME 'olcConfigFile' "
196 "DESC 'File for slapd configuration directives' "
197 "EQUALITY caseIgnoreMatch "
198 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
199 { "", "", 0, 0, 0, ARG_MAGIC,
200 &config_cfdir, "( OLcfgAt:79 NAME 'olcConfigDir' "
201 "DESC 'Directory for slapd configuration backend' "
202 "EQUALITY caseIgnoreMatch "
203 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
204 { "access", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC|CFG_ACL,
205 &config_generic, "( OLcfgAt:1 NAME 'olcAccess' "
206 "DESC 'Access Control List' "
207 "EQUALITY caseIgnoreMatch "
208 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
209 { "allows", "features", 2, 0, 5, ARG_PRE_DB|ARG_MAGIC,
210 &config_allows, "( OLcfgAt:2 NAME 'olcAllows' "
211 "DESC 'Allowed set of deprecated features' "
212 "EQUALITY caseIgnoreMatch "
213 "SYNTAX OMsDirectoryString )", NULL, NULL },
214 { "argsfile", "file", 2, 2, 0, ARG_STRING,
215 &slapd_args_file, "( OLcfgAt:3 NAME 'olcArgsFile' "
216 "DESC 'File for slapd command line options' "
217 "EQUALITY caseIgnoreMatch "
218 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
219 /* Use standard 'attributeTypes' attr */
220 { "attribute", "attribute", 2, 0, 9, ARG_PAREN|ARG_MAGIC|CFG_ATTR,
221 &config_generic, NULL, NULL, NULL },
222 { "attributeoptions", NULL, 0, 0, 0, ARG_MAGIC|CFG_ATOPT,
223 &config_generic, "( OLcfgAt:5 NAME 'olcAttributeOptions' "
224 "EQUALITY caseIgnoreMatch "
225 "SYNTAX OMsDirectoryString )", NULL, NULL },
226 { "authid-rewrite", NULL, 2, 0, 0,
227 #ifdef SLAP_AUTH_REWRITE
228 ARG_MAGIC|CFG_REWRITE, &config_generic,
232 "( OLcfgAt:6 NAME 'olcAuthIDRewrite' "
233 "EQUALITY caseIgnoreMatch "
234 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
235 { "authz-policy", "policy", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_AZPOLICY,
236 &config_generic, "( OLcfgAt:7 NAME 'olcAuthzPolicy' "
237 "EQUALITY caseIgnoreMatch "
238 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
239 { "authz-regexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP,
240 &config_generic, "( OLcfgAt:8 NAME 'olcAuthzRegexp' "
241 "EQUALITY caseIgnoreMatch "
242 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
243 { "backend", "type", 2, 2, 0, ARG_PRE_DB|ARG_MAGIC|CFG_BACKEND,
244 &config_generic, "( OLcfgAt:9 NAME 'olcBackend' "
245 "DESC 'A type of backend' "
246 "EQUALITY caseIgnoreMatch "
247 "SYNTAX OMsDirectoryString )", NULL, NULL },
248 { "concurrency", "level", 2, 2, 0, ARG_INT|ARG_NONZERO|ARG_MAGIC|CFG_CONCUR,
249 &config_generic, "( OLcfgAt:10 NAME 'olcConcurrency' "
250 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
251 { "conn_max_pending", "max", 2, 2, 0, ARG_INT,
252 &slap_conn_max_pending, "( OLcfgAt:11 NAME 'olcConnMaxPending' "
253 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
254 { "conn_max_pending_auth", "max", 2, 2, 0, ARG_INT,
255 &slap_conn_max_pending_auth, "( OLcfgAt:12 NAME 'olcConnMaxPendingAuth' "
256 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
257 { "database", "type", 2, 2, 0, ARG_MAGIC|CFG_DATABASE,
258 &config_generic, "( OLcfgAt:13 NAME 'olcDatabase' "
259 "DESC 'The backend type for a database instance' "
260 "SUP olcBackend )", NULL, NULL },
261 { "defaultSearchBase", "dn", 2, 2, 0, ARG_PRE_BI|ARG_PRE_DB|ARG_DN|ARG_MAGIC,
262 &config_search_base, "( OLcfgAt:14 NAME 'olcDefaultSearchBase' "
263 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
264 { "disallows", "features", 2, 0, 8, ARG_PRE_DB|ARG_MAGIC,
265 &config_disallows, "( OLcfgAt:15 NAME 'olcDisallows' "
266 "EQUALITY caseIgnoreMatch "
267 "SYNTAX OMsDirectoryString )", NULL, NULL },
268 /* use standard schema */
269 { "ditcontentrule", NULL, 0, 0, 0, ARG_MAGIC|CFG_DIT,
270 &config_generic, NULL, NULL, NULL },
271 { "gentlehup", "on|off", 2, 2, 0,
273 ARG_ON_OFF, &global_gentlehup,
277 "( OLcfgAt:17 NAME 'olcGentleHUP' "
278 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
279 { "idletimeout", "timeout", 2, 2, 0, ARG_INT,
280 &global_idletimeout, "( OLcfgAt:18 NAME 'olcIdleTimeout' "
281 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
282 /* XXX -- special case? */
283 { "include", "file", 2, 2, 0, ARG_MAGIC,
284 &config_include, "( OLcfgAt:19 NAME 'olcInclude' "
285 "SUP labeledURI )", NULL, NULL },
286 { "index_substr_if_minlen", "min", 2, 2, 0, ARG_INT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MIN,
287 &config_generic, "( OLcfgAt:20 NAME 'olcIndexSubstrIfMinLen' "
288 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
289 { "index_substr_if_maxlen", "max", 2, 2, 0, ARG_INT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MAX,
290 &config_generic, "( OLcfgAt:21 NAME 'olcIndexSubstrIfMaxLen' "
291 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
292 { "index_substr_any_len", "len", 2, 2, 0, ARG_INT|ARG_NONZERO,
293 &index_substr_any_len, "( OLcfgAt:22 NAME 'olcIndexSubstrAnyLen' "
294 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
295 { "index_substr_step", "step", 2, 2, 0, ARG_INT|ARG_NONZERO,
296 &index_substr_any_step, "( OLcfgAt:23 NAME 'olcIndexSubstrAnyStep' "
297 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
298 { "lastmod", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_LASTMOD,
299 &config_generic, "( OLcfgAt:24 NAME 'olcLastMod' "
300 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
301 { "limits", "limits", 2, 0, 0, ARG_DB|ARG_MAGIC|CFG_LIMITS,
302 &config_generic, "( OLcfgAt:25 NAME 'olcLimits' "
303 "SYNTAX OMsDirectoryString )", NULL, NULL },
304 { "localSSF", "ssf", 2, 2, 0, ARG_INT,
305 &local_ssf, "( OLcfgAt:26 NAME 'olcLocalSSF' "
306 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
307 { "logfile", "file", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_LOGFILE,
308 &config_generic, "( OLcfgAt:27 NAME 'olcLogFile' "
309 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
310 { "loglevel", "level", 2, 0, 0, ARG_MAGIC,
311 &config_loglevel, "( OLcfgAt:28 NAME 'olcLogLevel' "
312 "SYNTAX OMsDirectoryString )", NULL, NULL },
313 { "maxDerefDepth", "depth", 2, 2, 0, ARG_DB|ARG_INT|ARG_MAGIC|CFG_DEPTH,
314 &config_generic, "( OLcfgAt:29 NAME 'olcMaxDerefDepth' "
315 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
316 { "moduleload", "file", 2, 0, 0,
318 ARG_MAGIC|CFG_MODLOAD, &config_generic,
322 "( OLcfgAt:30 NAME 'olcModuleLoad' "
323 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
324 { "modulepath", "path", 2, 2, 0,
326 ARG_MAGIC|CFG_MODPATH, &config_generic,
330 "( OLcfgAt:31 NAME 'olcModulePath' "
331 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
332 /* use standard schema */
333 { "objectclass", "objectclass", 2, 0, 0, ARG_PAREN|ARG_MAGIC|CFG_OC,
334 &config_generic, NULL, NULL, NULL },
335 { "objectidentifier", NULL, 0, 0, 0, ARG_MAGIC|CFG_OID,
336 &config_generic, "( OLcfgAt:33 NAME 'olcObjectIdentifier' "
337 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
338 { "overlay", "overlay", 2, 2, 0, ARG_MAGIC,
339 &config_overlay, "( OLcfgAt:34 NAME 'olcOverlay' "
340 "SUP olcDatabase )", NULL, NULL },
341 { "password-crypt-salt-format", "salt", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_SALT,
342 &config_generic, "( OLcfgAt:35 NAME 'olcPasswordCryptSaltFormat' "
343 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
344 { "password-hash", "hash", 2, 2, 0, ARG_MAGIC,
345 &config_passwd_hash, "( OLcfgAt:36 NAME 'olcPasswordHash' "
346 "SYNTAX OMsDirectoryString )", NULL, NULL },
347 { "pidfile", "file", 2, 2, 0, ARG_STRING,
348 &slapd_pid_file, "( OLcfgAt:37 NAME 'olcPidFile' "
349 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
350 { "plugin", NULL, 0, 0, 0,
352 ARG_MAGIC|CFG_PLUGIN, &config_generic,
356 "( OLcfgAt:38 NAME 'olcPlugin' "
357 "SYNTAX OMsDirectoryString )", NULL, NULL },
358 { "pluginlog", "filename", 2, 2, 0,
360 ARG_STRING, &slapi_log_file,
364 "( OLcfgAt:39 NAME 'olcPluginLogFile' "
365 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
366 { "readonly", "on|off", 2, 2, 0, ARG_MAY_DB|ARG_ON_OFF|ARG_MAGIC|CFG_RO,
367 &config_generic, "( OLcfgAt:40 NAME 'olcReadOnly' "
368 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
369 { "referral", "url", 2, 2, 0, ARG_MAGIC,
370 &config_referral, "( OLcfgAt:41 NAME 'olcReferral' "
371 "SUP labeledURI SINGLE-VALUE )", NULL, NULL },
372 { "replica", "host or uri", 2, 0, 0, ARG_DB|ARG_MAGIC,
373 &config_replica, "( OLcfgAt:42 NAME 'olcReplica' "
374 "SUP labeledURI )", NULL, NULL },
375 { "replica-argsfile", NULL, 0, 0, 0, ARG_STRING,
376 &replica_argsFile, "( OLcfgAt:43 NAME 'olcReplicaArgsFile' "
377 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
378 { "replica-pidfile", NULL, 0, 0, 0, ARG_STRING,
379 &replica_pidFile, "( OLcfgAt:44 NAME 'olcReplicaPidFile' "
380 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
381 { "replicationInterval", NULL, 0, 0, 0, ARG_INT,
382 &replicationInterval, "( OLcfgAt:45 NAME 'olcReplicationInterval' "
383 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
384 { "replogfile", "filename", 2, 2, 0, ARG_MAY_DB|ARG_MAGIC|ARG_STRING|CFG_REPLOG,
385 &config_generic, "( OLcfgAt:46 NAME 'olcReplogFile' "
386 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
387 { "require", "features", 2, 0, 7, ARG_MAY_DB|ARG_MAGIC,
388 &config_requires, "( OLcfgAt:47 NAME 'olcRequires' "
389 "SYNTAX OMsDirectoryString )", NULL, NULL },
390 { "restrict", "op_list", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
391 &config_restrict, "( OLcfgAt:48 NAME 'olcRestrict' "
392 "SYNTAX OMsDirectoryString )", NULL, NULL },
393 { "reverse-lookup", "on|off", 2, 2, 0,
394 #ifdef SLAPD_RLOOKUPS
395 ARG_ON_OFF, &use_reverse_lookup,
399 "( OLcfgAt:49 NAME 'olcReverseLookup' "
400 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
401 { "rootdn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_MAGIC,
402 &config_rootdn, "( OLcfgAt:50 NAME 'olcRootDN' "
403 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
404 { "rootDSE", "file", 2, 2, 0, ARG_MAGIC|CFG_ROOTDSE,
405 &config_generic, "( OLcfgAt:51 NAME 'olcRootDSE' "
406 "SYNTAX OMsDirectoryString )", NULL, NULL },
407 { "rootpw", "password", 2, 2, 0, ARG_STRING|ARG_DB|ARG_MAGIC,
408 &config_rootpw, "( OLcfgAt:52 NAME 'olcRootPW' "
409 "SYNTAX OMsOctetString SINGLE-VALUE )", NULL, NULL },
410 { "sasl-authz-policy", NULL, 2, 2, 0, ARG_MAGIC|CFG_AZPOLICY,
411 &config_generic, NULL, NULL, NULL },
412 { "sasl-host", "host", 2, 2, 0,
413 #ifdef HAVE_CYRUS_SASL
414 ARG_STRING|ARG_UNIQUE, &global_host,
418 "( OLcfgAt:53 NAME 'olcSaslHost' "
419 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
420 { "sasl-realm", "realm", 2, 2, 0,
421 #ifdef HAVE_CYRUS_SASL
422 ARG_STRING|ARG_UNIQUE, &global_realm,
426 "( OLcfgAt:54 NAME 'olcSaslRealm' "
427 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
428 { "sasl-regexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP,
429 &config_generic, NULL, NULL, NULL },
430 { "sasl-secprops", "properties", 2, 2, 0,
431 #ifdef HAVE_CYRUS_SASL
432 ARG_MAGIC|CFG_SASLSECP, &config_generic,
436 "( OLcfgAt:56 NAME 'olcSaslSecProps' "
437 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
438 { "saslRegexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP,
439 &config_generic, NULL, NULL, NULL },
440 { "schemacheck", "on|off", 2, 2, 0, ARG_ON_OFF|ARG_MAGIC|CFG_CHECK,
441 &config_generic, "( OLcfgAt:57 NAME 'olcSchemaCheck' "
442 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
443 { "schemadn", "dn", 2, 2, 0, ARG_MAY_DB|ARG_DN|ARG_MAGIC,
444 &config_schema_dn, "( OLcfgAt:58 NAME 'olcSchemaDN' "
445 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
446 { "security", "factors", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
447 &config_security, "( OLcfgAt:59 NAME 'olcSecurity' "
448 "SYNTAX OMsDirectoryString )", NULL, NULL },
449 { "sizelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC|CFG_SIZE,
450 &config_sizelimit, "( OLcfgAt:60 NAME 'olcSizeLimit' "
451 "SYNTAX OMsInteger )", NULL, NULL },
452 { "sockbuf_max_incoming", "max", 2, 2, 0, ARG_BER_LEN_T,
453 &sockbuf_max_incoming, "( OLcfgAt:61 NAME 'olcSockbufMaxIncoming' "
454 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
455 { "sockbuf_max_incoming_auth", "max", 2, 2, 0, ARG_BER_LEN_T,
456 &sockbuf_max_incoming_auth, "( OLcfgAt:62 NAME 'olcSockbufMaxIncomingAuth' "
457 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
458 { "srvtab", "file", 2, 2, 0,
459 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
460 ARG_STRING, &ldap_srvtab,
464 "( OLcfgAt:63 NAME 'olcSrvtab' "
465 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
466 { "suffix", "suffix", 2, 2, 0, ARG_DB|ARG_DN|ARG_MAGIC,
467 &config_suffix, "( OLcfgAt:64 NAME 'olcSuffix' "
468 "SYNTAX OMsDN )", NULL, NULL },
469 { "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
470 &config_syncrepl, "( OLcfgAt:65 NAME 'olcSyncrepl' "
471 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
472 { "threads", "count", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_THREADS,
473 &config_generic, "( OLcfgAt:66 NAME 'olcThreads' "
474 "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
475 { "timelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC|CFG_TIME,
476 &config_timelimit, "( OLcfgAt:67 NAME 'olcTimeLimit' "
477 "SYNTAX OMsInteger )", NULL, NULL },
478 { "TLSCACertificateFile", NULL, 0, 0, 0,
480 CFG_TLS_CA_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
484 "( OLcfgAt:68 NAME 'olcTLSCACertificateFile' "
485 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
486 { "TLSCACertificatePath", NULL, 0, 0, 0,
488 CFG_TLS_CA_PATH|ARG_STRING|ARG_MAGIC, &config_tls_option,
492 "( OLcfgAt:69 NAME 'olcTLSCACertificatePath' "
493 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
494 { "TLSCertificateFile", NULL, 0, 0, 0,
496 CFG_TLS_CERT_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
500 "( OLcfgAt:70 NAME 'olcTLSCertificateFile' "
501 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
502 { "TLSCertificateKeyFile", NULL, 0, 0, 0,
504 CFG_TLS_CERT_KEY|ARG_STRING|ARG_MAGIC, &config_tls_option,
508 "( OLcfgAt:71 NAME 'olcTLSCertificateKeyFile' "
509 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
510 { "TLSCipherSuite", NULL, 0, 0, 0,
512 CFG_TLS_CIPHER|ARG_STRING|ARG_MAGIC, &config_tls_option,
516 "( OLcfgAt:72 NAME 'olcTLSCipherSuite' "
517 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
518 { "TLSCRLCheck", NULL, 0, 0, 0,
520 CFG_TLS_CRLCHECK|ARG_STRING|ARG_MAGIC, &config_tls_config,
524 "( OLcfgAt:73 NAME 'olcTLSCRLCheck' "
525 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
526 { "TLSRandFile", NULL, 0, 0, 0,
528 CFG_TLS_RAND|ARG_STRING|ARG_MAGIC, &config_tls_option,
532 "( OLcfgAt:74 NAME 'olcTLSRandFile' "
533 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
534 { "TLSVerifyClient", NULL, 0, 0, 0,
536 CFG_TLS_VERIFY|ARG_STRING|ARG_MAGIC, &config_tls_config,
540 "( OLcfgAt:75 NAME 'olcTLSVerifyClient' "
541 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
542 { "ucdata-path", "path", 2, 2, 0, ARG_IGNORED,
543 NULL, NULL, NULL, NULL },
544 { "updatedn", "dn", 2, 2, 0, ARG_DB|ARG_MAGIC,
545 &config_updatedn, "( OLcfgAt:76 NAME 'olcUpdateDN' "
546 "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
547 { "updateref", "url", 2, 2, 0, ARG_DB|ARG_MAGIC,
548 &config_updateref, "( OLcfgAt:77 NAME 'olcUpdateRef' "
549 "SUP labeledURI )", NULL, NULL },
550 { NULL, NULL, 0, 0, 0, ARG_IGNORED,
551 NULL, NULL, NULL, NULL }
554 static ConfigOCs cf_ocs[] = {
557 "DESC 'OpenLDAP configuration object' "
559 "MAY ( cn $ olcConfigFile ) )", NULL },
562 "DESC 'OpenLDAP Global configuration options' "
563 "SUP olcConfig STRUCTURAL "
564 "MAY ( olcConfigDir $ olcAllows $ olcArgsFile $ olcAttributeOptions $ "
565 "olcAuthIDRewrite $ olcAuthzPolicy $ olcAuthzRegexp $ "
566 "olcConcurrency $ olcConnMaxPending $ olcConnMaxPendingAuth $ "
567 "olcDefaultSearchBase $ olcDisallows $ olcGentleHUP $ "
568 "olcIdleTimeout $ olcIndexSubstrIfMaxLen $ olcIndexSubstrIfMinLen $ "
569 "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcLocalSSF $ "
570 "olcLogLevel $ olcModuleLoad $ olcModulePath $ olcObjectIdentifier $ "
571 "olcPasswordCryptSaltFormat $ olcPasswordHash $ olcPidFile $ "
572 "olcPlugin $ olcPluginLogFile $ olcReadOnly $ olcReferral $ "
573 "olcReplicaPidFile $ olcReplicaArgsFile $ olcReplicationInterval $ "
574 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
575 "olcRootDSE $ olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
576 "olcSchemaCheck $ olcSchemaDN $ olcSecurity $ olcSizeLimit $ "
577 "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ olcSrvtab $ "
578 "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
579 "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
580 "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
581 "olcTLSRandFile $ olcTLSVerifyClient ) )", &cfOc_global },
583 "NAME 'olcBackendConfig' "
584 "DESC 'OpenLDAP Backend-specific options' "
585 "SUP olcConfig STRUCTURAL "
586 "MAY ( olcBackend ) )", &cfOc_backend },
588 "NAME 'olcDatabaseConfig' "
589 "DESC 'OpenLDAP Database-specific options' "
590 "SUP olcConfig STRUCTURAL "
591 "MAY ( olcDatabase $ olcAccess $ olcLastMod $ olcLimits $ "
592 "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
593 "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
594 "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSuffix $ olcSyncrepl $ "
595 "olcTimeLimit $ olcUpdateDN $ olcUpdateRef ) )", &cfOc_database },
597 "NAME 'olcIncludeFile' "
598 "DESC 'OpenLDAP configuration include file' "
599 "SUP olcConfig STRUCTURAL "
600 "MAY ( olcInclude $ olcModuleLoad $ olcModulePath $ olcRootDSE ) )",
603 "NAME 'olcOverlayConfig' "
604 "DESC 'OpenLDAP Overlay-specific options' "
605 "SUP olcConfig STRUCTURAL "
606 "MAY ( olcOverlay ) )", &cfOc_overlay },
609 "DESC 'OpenLDAP Access Control List' "
610 "SUP olcConfig STRUCTURAL "
611 "MUST ( olcAccess ) )", &cfOc_access },
616 config_generic(ConfigArgs *c) {
620 if ( c->op == SLAP_CONFIG_EMIT ) {
624 c->value_int = ldap_pvt_thread_get_concurrency();
627 c->value_int = connection_pool_max;
631 c->value_string = ch_strdup( passwd_salt );
636 if ( c->be->be_limits ) {
641 for ( i=0; c->be->be_limits[i]; i++ ) {
642 bv.bv_len = sprintf( buf, "{%d}", i );
643 bv.bv_val = buf+bv.bv_len;
644 limits_unparse( c->be->be_limits[i], &bv );
645 bv.bv_len += bv.bv_val - buf;
647 value_add_one( &c->rvalue_vals, &bv );
650 if ( !c->rvalue_vals ) rc = 1;
653 c->value_int = (c->be->be_restrictops & SLAP_RESTRICT_OP_WRITES) != 0;
656 c->value_string = ch_strdup( slap_sasl_getpolicy());
659 slap_sasl_regexp_unparse( &c->rvalue_vals );
660 if ( !c->rvalue_vals ) rc = 1;
662 #ifdef HAVE_CYRUS_SASL
664 struct berval bv = BER_BVNULL;
665 slap_sasl_secprops_unparse( &bv );
666 if ( !BER_BVISNULL( &bv )) {
667 ber_bvarray_add( &c->rvalue_vals, &bv );
675 c->value_int = c->be->be_max_deref_depth;
678 oidm_unparse( &c->rvalue_vals );
679 if ( !c->rvalue_vals )
683 c->value_int = global_schemacheck;
687 char *src, *dst, ibuf[11];
688 struct berval bv, abv;
689 for (i=0, a=c->be->be_acl; a; i++,a=a->acl_next) {
690 abv.bv_len = sprintf( ibuf, "{%x}", i );
691 acl_unparse( a, &bv );
692 abv.bv_val = ch_malloc( abv.bv_len + bv.bv_len + 1 );
693 AC_MEMCPY( abv.bv_val, ibuf, abv.bv_len );
694 /* Turn TAB / EOL into plain space */
695 for (src=bv.bv_val,dst=abv.bv_val+abv.bv_len; *src; src++) {
696 if (isspace(*src)) *dst++ = ' ';
700 if (dst[-1] == ' ') {
704 abv.bv_len = dst - abv.bv_val;
705 ber_bvarray_add( &c->rvalue_vals, &abv );
711 if ( c->be->be_replogfile )
712 c->value_string = ch_strdup( c->be->be_replogfile );
715 ConfigFile *cf = (ConfigFile *)c->line;
716 if ( cf->c_dseFiles ) {
717 value_add( &c->rvalue_vals, cf->c_dseFiles );
725 c->value_string = ch_strdup( logfileName );
730 c->value_int = (SLAP_NOLASTMOD(c->be) == 0);
732 case CFG_SSTR_IF_MAX:
733 c->value_int = index_substr_if_maxlen;
735 case CFG_SSTR_IF_MIN:
736 c->value_int = index_substr_if_minlen;
740 ConfigFile *cf = (ConfigFile *)c->line;
742 for (i=0, mp=&cf->c_modpaths; mp; mp=mp->mp_next, i++) {
744 if (!mp->mp_loads) continue;
745 for (j=0; !BER_BVISNULL(&mp->mp_loads[j]); j++) {
748 bv.bv_len = sprintf( bv.bv_val, "{%d}{%d}%s", i, j,
749 mp->mp_loads[j].bv_val );
750 value_add_one( &c->rvalue_vals, &bv );
753 rc = c->rvalue_vals ? 0 : 1;
757 ConfigFile *cf = (ConfigFile *)c->line;
759 for (i=0, mp=&cf->c_modpaths; mp; mp=mp->mp_next, i++) {
761 if ( BER_BVISNULL( &mp->mp_path ) && !mp->mp_loads )
764 bv.bv_len = sprintf( bv.bv_val, "{%d}%s", i,
765 mp->mp_path.bv_val );
766 value_add_one( &c->rvalue_vals, &bv );
768 rc = c->rvalue_vals ? 0 : 1;
774 slapi_int_plugin_unparse( c->be, &c->rvalue_vals );
775 if ( !c->rvalue_vals ) rc = 1;
778 #ifdef SLAP_AUTH_REWRITE
780 if ( authz_rewrites ) {
781 struct berval bv, idx;
786 for ( i=0; !BER_BVISNULL( &authz_rewrites[i] ); i++ ) {
787 idx.bv_len = sprintf( idx.bv_val, "{%d}", i );
788 bv.bv_len = idx.bv_len + authz_rewrites[i].bv_len;
789 bv.bv_val = ch_malloc( bv.bv_len + 1 );
790 strcpy( bv.bv_val, idx.bv_val );
791 strcpy( bv.bv_val+idx.bv_len, authz_rewrites[i].bv_val );
792 ber_bvarray_add( &c->rvalue_vals, &bv );
795 if ( !c->rvalue_vals ) rc = 1;
804 p = strchr(c->line,'(' /*')'*/);
807 if(!(c->bi = backend_info(c->argv[1]))) {
808 Debug(LDAP_DEBUG_ANY, "%s: "
809 "backend %s failed init!\n", c->log, c->argv[1], 0);
816 /* NOTE: config is always the first backend!
818 if ( !strcasecmp( c->argv[1], "config" )) {
820 } else if(!(c->be = backend_db_init(c->argv[1]))) {
821 Debug(LDAP_DEBUG_ANY, "%s: "
822 "database %s failed init!\n", c->log, c->argv[1], 0);
828 ldap_pvt_thread_set_concurrency(c->value_int);
832 ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int);
833 connection_pool_max = c->value_int; /* save for reference */
837 if ( passwd_salt ) ch_free( passwd_salt );
838 passwd_salt = c->value_string;
839 lutil_salt_format(passwd_salt);
843 if(limits_parse(c->be, c->fname, c->lineno, c->argc, c->argv))
849 c->be->be_restrictops |= SLAP_RESTRICT_OP_WRITES;
851 c->be->be_restrictops &= ~SLAP_RESTRICT_OP_WRITES;
855 ch_free(c->value_string);
856 if (slap_sasl_setpolicy( c->argv[1] )) {
857 Debug(LDAP_DEBUG_ANY, "%s: unable to parse value \"%s\" in"
858 " \"authz-policy <policy>\"\n",
859 c->log, c->argv[1], 0 );
865 if (slap_sasl_regexp_config( c->argv[1], c->argv[2] ))
869 #ifdef HAVE_CYRUS_SASL
872 char *txt = slap_sasl_secprops( c->argv[1] );
874 Debug(LDAP_DEBUG_ANY, "%s: sasl-secprops: %s\n",
883 c->be->be_max_deref_depth = c->value_int;
887 if(parse_oidm(c->fname, c->lineno, c->argc, c->argv)) return(1);
891 if(parse_oc(c->fname, c->lineno, p, c->argv)) return(1);
895 if(parse_cr(c->fname, c->lineno, p, c->argv)) return(1);
899 if(parse_at(c->fname, c->lineno, p, c->argv)) return(1);
903 ad_define_option(NULL, NULL, 0);
904 for(i = 1; i < c->argc; i++)
905 if(ad_define_option(c->argv[i], c->fname, c->lineno))
910 global_schemacheck = c->value_int;
911 if(!global_schemacheck) Debug(LDAP_DEBUG_ANY, "%s: "
912 "schema checking disabled! your mileage may vary!\n",
917 parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv);
921 if(SLAP_MONITOR(c->be)) {
922 Debug(LDAP_DEBUG_ANY, "%s: "
923 "\"replogfile\" should not be used "
924 "inside monitor database\n",
926 return(0); /* FIXME: should this be an error? */
929 c->be->be_replogfile = c->value_string;
933 if(read_root_dse_file(c->argv[1])) {
934 Debug(LDAP_DEBUG_ANY, "%s: "
935 "could not read \"rootDSE <filename>\" line\n",
941 ber_str2bv( c->argv[1], 0, 1, &bv );
942 ber_bvarray_add( &cfn->c_dseFiles, &bv );
948 if ( logfileName ) ch_free( logfileName );
949 logfileName = c->value_string;
950 logfile = fopen(logfileName, "w");
951 if(logfile) lutil_debug_file(logfile);
955 if(SLAP_NOLASTMODCMD(c->be)) {
956 Debug(LDAP_DEBUG_ANY, "%s: "
957 "lastmod not available for %s databases\n",
958 c->log, c->be->bd_info->bi_type, 0);
962 SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_NOLASTMOD;
964 SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_NOLASTMOD;
967 case CFG_SSTR_IF_MAX:
968 if (c->value_int < index_substr_if_minlen) {
969 Debug(LDAP_DEBUG_ANY, "%s: "
970 "invalid max value (%d)\n",
971 c->log, c->value_int, 0 );
974 index_substr_if_maxlen = c->value_int;
977 case CFG_SSTR_IF_MIN:
978 if (c->value_int > index_substr_if_maxlen) {
979 Debug(LDAP_DEBUG_ANY, "%s: "
980 "invalid min value (%d)\n",
981 c->log, c->value_int, 0 );
984 index_substr_if_minlen = c->value_int;
989 if(module_load(c->argv[1], c->argc - 2, (c->argc > 2) ? c->argv + 2 : NULL))
991 /* Record this load on the current path */
994 ber_str2bv(c->line, 0, 1, &bv);
995 ber_bvarray_add( &cfn->c_modlast->mp_loads, &bv );
1000 if(module_path(c->argv[1])) return(1);
1001 /* Record which path was used with each module */
1005 if (!cfn->c_modpaths.mp_loads) {
1006 mp = &cfn->c_modpaths;
1008 mp = ch_malloc( sizeof( ModPaths ));
1009 cfn->c_modlast->mp_next = mp;
1011 ber_str2bv(c->argv[1], 0, 1, &mp->mp_path);
1013 mp->mp_loads = NULL;
1014 cfn->c_modlast = mp;
1022 if(slapi_int_read_config(c->be, c->fname, c->lineno, c->argc, c->argv) != LDAP_SUCCESS)
1024 slapi_plugins_used++;
1028 #ifdef SLAP_AUTH_REWRITE
1031 if(slap_sasl_rewrite_config(c->fname, c->lineno, c->argc, c->argv))
1033 ber_str2bv( c->line, 0, 1, &bv );
1034 ber_bvarray_add( &authz_rewrites, &bv );
1041 Debug(LDAP_DEBUG_ANY, "%s: unknown CFG_TYPE %d"
1042 "(ignored)\n", c->log, c->type, 0);
1050 config_fname(ConfigArgs *c) {
1051 if(c->op == SLAP_CONFIG_EMIT && c->line) {
1052 ConfigFile *cf = (ConfigFile *)c->line;
1053 value_add_one( &c->rvalue_vals, &cf->c_file );
1060 config_cfdir(ConfigArgs *c) {
1061 if(c->op == SLAP_CONFIG_EMIT) {
1062 value_add_one( &c->rvalue_vals, &cfdir );
1069 config_search_base(ConfigArgs *c) {
1072 if(c->op == SLAP_CONFIG_EMIT) {
1074 if (!BER_BVISEMPTY(&default_search_base)) {
1075 value_add_one(&c->rvalue_vals, &default_search_base);
1076 value_add_one(&c->rvalue_nvals, &default_search_nbase);
1082 if(c->bi || c->be != frontendDB) {
1083 Debug(LDAP_DEBUG_ANY, "%s: defaultSearchBase line must appear "
1084 "prior to any backend or database definition\n",
1089 if(default_search_nbase.bv_len) {
1090 Debug(LDAP_DEBUG_ANY, "%s: "
1091 "default search base \"%s\" already defined "
1092 "(discarding old)\n",
1093 c->log, default_search_base.bv_val, 0);
1094 free(default_search_base.bv_val);
1095 free(default_search_nbase.bv_val);
1098 default_search_base = c->value_dn;
1099 default_search_nbase = c->value_ndn;
1104 config_passwd_hash(ConfigArgs *c) {
1106 if (c->op == SLAP_CONFIG_EMIT) {
1108 for (i=0; default_passwd_hash && default_passwd_hash[i]; i++) {
1109 ber_str2bv(default_passwd_hash[i], 0, 0, &bv);
1110 value_add_one(&c->rvalue_vals, &bv);
1114 if(default_passwd_hash) {
1115 Debug(LDAP_DEBUG_ANY, "%s: "
1116 "already set default password_hash\n",
1120 for(i = 1; i < c->argc; i++) {
1121 if(!lutil_passwd_scheme(c->argv[i])) {
1122 Debug(LDAP_DEBUG_ANY, "%s: "
1123 "password scheme \"%s\" not available\n",
1124 c->log, c->argv[i], 0);
1126 ldap_charray_add(&default_passwd_hash, c->argv[i]);
1128 if(!default_passwd_hash) {
1129 Debug(LDAP_DEBUG_ANY, "%s: no valid hashes found\n",
1138 config_schema_dn(ConfigArgs *c) {
1139 if ( c->op == SLAP_CONFIG_EMIT ) {
1141 if ( !BER_BVISEMPTY( &c->be->be_schemadn )) {
1142 value_add_one(&c->rvalue_vals, &c->be->be_schemadn);
1143 value_add_one(&c->rvalue_nvals, &c->be->be_schemandn);
1148 c->be->be_schemadn = c->value_dn;
1149 c->be->be_schemandn = c->value_ndn;
1154 config_sizelimit(ConfigArgs *c) {
1157 struct slap_limits_set *lim = &c->be->be_def_limit;
1158 if (c->op == SLAP_CONFIG_EMIT) {
1163 limits_unparse_one( lim, SLAP_LIMIT_SIZE, &bv );
1164 if ( !BER_BVISEMPTY( &bv ))
1165 value_add_one( &c->rvalue_vals, &bv );
1170 for(i = 1; i < c->argc; i++) {
1171 if(!strncasecmp(c->argv[i], "size", 4)) {
1172 rc = limits_parse_one(c->argv[i], lim);
1174 Debug(LDAP_DEBUG_ANY, "%s: "
1175 "unable to parse value \"%s\" in \"sizelimit <limit>\" line\n",
1176 c->log, c->argv[i], 0);
1180 if(!strcasecmp(c->argv[i], "unlimited")) {
1181 lim->lms_s_soft = -1;
1183 lim->lms_s_soft = strtol(c->argv[i], &next, 0);
1184 if(next == c->argv[i]) {
1185 Debug(LDAP_DEBUG_ANY, "%s: "
1186 "unable to parse limit \"%s\" in \"sizelimit <limit>\" line\n",
1187 c->log, c->argv[i], 0);
1189 } else if(next[0] != '\0') {
1190 Debug(LDAP_DEBUG_ANY, "%s: "
1191 "trailing chars \"%s\" in \"sizelimit <limit>\" line (ignored)\n",
1195 lim->lms_s_hard = 0;
1202 config_timelimit(ConfigArgs *c) {
1205 struct slap_limits_set *lim = &c->be->be_def_limit;
1206 if (c->op == SLAP_CONFIG_EMIT) {
1211 limits_unparse_one( lim, SLAP_LIMIT_TIME, &bv );
1212 if ( !BER_BVISEMPTY( &bv ))
1213 value_add_one( &c->rvalue_vals, &bv );
1218 for(i = 1; i < c->argc; i++) {
1219 if(!strncasecmp(c->argv[i], "time", 4)) {
1220 rc = limits_parse_one(c->argv[i], lim);
1222 Debug(LDAP_DEBUG_ANY, "%s: "
1223 "unable to parse value \"%s\" in \"timelimit <limit>\" line\n",
1224 c->log, c->argv[i], 0);
1228 if(!strcasecmp(c->argv[i], "unlimited")) {
1229 lim->lms_t_soft = -1;
1231 lim->lms_t_soft = strtol(c->argv[i], &next, 0);
1232 if(next == c->argv[i]) {
1233 Debug(LDAP_DEBUG_ANY, "%s: "
1234 "unable to parse limit \"%s\" in \"timelimit <limit>\" line\n",
1235 c->log, c->argv[i], 0);
1237 } else if(next[0] != '\0') {
1238 Debug(LDAP_DEBUG_ANY, "%s: "
1239 "trailing chars \"%s\" in \"timelimit <limit>\" line (ignored)\n",
1243 lim->lms_t_hard = 0;
1250 config_overlay(ConfigArgs *c) {
1251 if (c->op == SLAP_CONFIG_EMIT) {
1254 if(c->argv[1][0] == '-' && overlay_config(c->be, &c->argv[1][1])) {
1256 Debug(LDAP_DEBUG_ANY, "%s: (optional) %s overlay \"%s\" configuration failed (ignored)\n",
1257 c->log, c->be == frontendDB ? "global " : "", c->argv[1][1]);
1258 } else if(overlay_config(c->be, c->argv[1])) {
1265 config_suffix(ConfigArgs *c) {
1267 struct berval pdn, ndn;
1269 if (c->op == SLAP_CONFIG_EMIT) {
1270 if ( !BER_BVISNULL( &c->be->be_suffix[0] )) {
1271 value_add( &c->rvalue_vals, c->be->be_suffix );
1272 value_add( &c->rvalue_nvals, c->be->be_nsuffix );
1278 #ifdef SLAPD_MONITOR_DN
1279 if(!strcasecmp(c->argv[1], SLAPD_MONITOR_DN)) {
1280 Debug(LDAP_DEBUG_ANY, "%s: "
1281 "\"%s\" is reserved for monitoring slapd\n",
1282 c->log, SLAPD_MONITOR_DN, 0);
1289 tbe = select_backend(&ndn, 0, 0);
1291 Debug(LDAP_DEBUG_ANY, "%s: suffix already served by this backend! (ignored)\n",
1296 Debug(LDAP_DEBUG_ANY, "%s: suffix already served by a preceding backend \"%s\"\n",
1297 c->log, tbe->be_suffix[0].bv_val, 0);
1301 } else if(pdn.bv_len == 0 && default_search_nbase.bv_len) {
1302 Debug(LDAP_DEBUG_ANY, "%s: suffix DN empty and default search "
1303 "base provided \"%s\" (assuming okay)\n",
1304 c->log, default_search_base.bv_val, 0);
1306 ber_bvarray_add(&c->be->be_suffix, &pdn);
1307 ber_bvarray_add(&c->be->be_nsuffix, &ndn);
1312 config_rootdn(ConfigArgs *c) {
1313 if (c->op == SLAP_CONFIG_EMIT) {
1314 if ( !BER_BVISNULL( &c->be->be_rootdn )) {
1315 value_add_one(&c->rvalue_vals, &c->be->be_rootdn);
1316 value_add_one(&c->rvalue_nvals, &c->be->be_rootndn);
1322 c->be->be_rootdn = c->value_dn;
1323 c->be->be_rootndn = c->value_ndn;
1328 config_rootpw(ConfigArgs *c) {
1330 if (c->op == SLAP_CONFIG_EMIT) {
1331 if (!BER_BVISEMPTY(&c->be->be_rootpw)) {
1332 c->value_string=ch_strdup("*");
1338 tbe = select_backend(&c->be->be_rootndn, 0, 0);
1340 Debug(LDAP_DEBUG_ANY, "%s: "
1341 "rootpw can only be set when rootdn is under suffix\n",
1345 ber_str2bv(c->value_string, 0, 0, &c->be->be_rootpw);
1350 config_restrict(ConfigArgs *c) {
1351 slap_mask_t restrictops = 0;
1353 slap_verbmasks restrictable_ops[] = {
1354 { BER_BVC("bind"), SLAP_RESTRICT_OP_BIND },
1355 { BER_BVC("add"), SLAP_RESTRICT_OP_ADD },
1356 { BER_BVC("modify"), SLAP_RESTRICT_OP_MODIFY },
1357 { BER_BVC("rename"), SLAP_RESTRICT_OP_RENAME },
1358 { BER_BVC("modrdn"), 0 },
1359 { BER_BVC("delete"), SLAP_RESTRICT_OP_DELETE },
1360 { BER_BVC("search"), SLAP_RESTRICT_OP_SEARCH },
1361 { BER_BVC("compare"), SLAP_RESTRICT_OP_COMPARE },
1362 { BER_BVC("read"), SLAP_RESTRICT_OP_READS },
1363 { BER_BVC("write"), SLAP_RESTRICT_OP_WRITES },
1364 { BER_BVC("extended"), SLAP_RESTRICT_OP_EXTENDED },
1365 { BER_BVC("extended=" LDAP_EXOP_START_TLS ), SLAP_RESTRICT_EXOP_START_TLS },
1366 { BER_BVC("extended=" LDAP_EXOP_MODIFY_PASSWD ), SLAP_RESTRICT_EXOP_MODIFY_PASSWD },
1367 { BER_BVC("extended=" LDAP_EXOP_X_WHO_AM_I ), SLAP_RESTRICT_EXOP_WHOAMI },
1368 { BER_BVC("extended=" LDAP_EXOP_X_CANCEL ), SLAP_RESTRICT_EXOP_CANCEL },
1372 if (c->op == SLAP_CONFIG_EMIT) {
1373 return mask_to_verbs( restrictable_ops, c->be->be_restrictops,
1376 i = verbs_to_mask( c->argc, c->argv, restrictable_ops, &restrictops );
1378 Debug(LDAP_DEBUG_ANY, "%s: "
1379 "unknown operation %s in \"restrict <features>\" line\n",
1380 c->log, c->argv[i], 0);
1383 if ( restrictops & SLAP_RESTRICT_OP_EXTENDED )
1384 restrictops &= ~SLAP_RESTRICT_EXOP_MASK;
1385 c->be->be_restrictops |= restrictops;
1390 config_allows(ConfigArgs *c) {
1391 slap_mask_t allows = 0;
1393 slap_verbmasks allowable_ops[] = {
1394 { BER_BVC("bind_v2"), SLAP_ALLOW_BIND_V2 },
1395 { BER_BVC("bind_anon_cred"), SLAP_ALLOW_BIND_ANON_CRED },
1396 { BER_BVC("bind_anon_dn"), SLAP_ALLOW_BIND_ANON_DN },
1397 { BER_BVC("update_anon"), SLAP_ALLOW_UPDATE_ANON },
1400 if (c->op == SLAP_CONFIG_EMIT) {
1401 return mask_to_verbs( allowable_ops, global_allows, &c->rvalue_vals );
1403 i = verbs_to_mask(c->argc, c->argv, allowable_ops, &allows);
1405 Debug(LDAP_DEBUG_ANY, "%s: "
1406 "unknown feature %s in \"allow <features>\" line\n",
1407 c->log, c->argv[i], 0);
1410 global_allows |= allows;
1415 config_disallows(ConfigArgs *c) {
1416 slap_mask_t disallows = 0;
1418 slap_verbmasks disallowable_ops[] = {
1419 { BER_BVC("bind_anon"), SLAP_DISALLOW_BIND_ANON },
1420 { BER_BVC("bind_simple"), SLAP_DISALLOW_BIND_SIMPLE },
1421 { BER_BVC("bind_krb4"), SLAP_DISALLOW_BIND_KRBV4 },
1422 { BER_BVC("tls_2_anon"), SLAP_DISALLOW_TLS_2_ANON },
1423 { BER_BVC("tls_authc"), SLAP_DISALLOW_TLS_AUTHC },
1426 if (c->op == SLAP_CONFIG_EMIT) {
1427 return mask_to_verbs( disallowable_ops, global_disallows, &c->rvalue_vals );
1429 i = verbs_to_mask(c->argc, c->argv, disallowable_ops, &disallows);
1431 Debug(LDAP_DEBUG_ANY, "%s: "
1432 "unknown feature %s in \"disallow <features>\" line\n",
1433 c->log, c->argv[i], 0);
1436 global_disallows |= disallows;
1441 config_requires(ConfigArgs *c) {
1442 slap_mask_t requires = 0;
1444 slap_verbmasks requires_ops[] = {
1445 { BER_BVC("bind"), SLAP_REQUIRE_BIND },
1446 { BER_BVC("LDAPv3"), SLAP_REQUIRE_LDAP_V3 },
1447 { BER_BVC("authc"), SLAP_REQUIRE_AUTHC },
1448 { BER_BVC("sasl"), SLAP_REQUIRE_SASL },
1449 { BER_BVC("strong"), SLAP_REQUIRE_STRONG },
1452 if (c->op == SLAP_CONFIG_EMIT) {
1453 return mask_to_verbs( requires_ops, c->be->be_requires, &c->rvalue_vals );
1455 i = verbs_to_mask(c->argc, c->argv, requires_ops, &requires);
1457 Debug(LDAP_DEBUG_ANY, "%s: "
1458 "unknown feature %s in \"require <features>\" line\n",
1459 c->log, c->argv[i], 0);
1462 c->be->be_requires = requires;
1467 config_loglevel(ConfigArgs *c) {
1470 slap_verbmasks loglevel_ops[] = {
1471 { BER_BVC("Trace"), LDAP_DEBUG_TRACE },
1472 { BER_BVC("Packets"), LDAP_DEBUG_PACKETS },
1473 { BER_BVC("Args"), LDAP_DEBUG_ARGS },
1474 { BER_BVC("Conns"), LDAP_DEBUG_CONNS },
1475 { BER_BVC("BER"), LDAP_DEBUG_BER },
1476 { BER_BVC("Filter"), LDAP_DEBUG_FILTER },
1477 { BER_BVC("Config"), LDAP_DEBUG_CONFIG },
1478 { BER_BVC("ACL"), LDAP_DEBUG_ACL },
1479 { BER_BVC("Stats"), LDAP_DEBUG_STATS },
1480 { BER_BVC("Stats2"), LDAP_DEBUG_STATS2 },
1481 { BER_BVC("Shell"), LDAP_DEBUG_SHELL },
1482 { BER_BVC("Parse"), LDAP_DEBUG_PARSE },
1483 { BER_BVC("Cache"), LDAP_DEBUG_CACHE },
1484 { BER_BVC("Index"), LDAP_DEBUG_INDEX },
1485 { BER_BVC("Any"), -1 },
1489 if (c->op == SLAP_CONFIG_EMIT) {
1490 return mask_to_verbs( loglevel_ops, ldap_syslog, &c->rvalue_vals );
1495 for( i=1; i < c->argc; i++ ) {
1498 if ( isdigit( c->argv[i][0] ) ) {
1499 level = strtol( c->argv[i], &next, 10 );
1500 if ( next == NULL || next[0] != '\0' ) {
1501 Debug( LDAP_DEBUG_ANY,
1502 "%s: unable to parse level \"%s\" "
1503 "in \"loglevel <level> [...]\" line.\n",
1504 c->log, c->argv[i], 0);
1508 int j = verb_to_mask(c->argv[i], loglevel_ops);
1509 if(BER_BVISNULL(&loglevel_ops[j].word)) {
1510 Debug( LDAP_DEBUG_ANY,
1511 "%s: unknown level \"%s\" "
1512 "in \"loglevel <level> [...]\" line.\n",
1513 c->log, c->argv[i], 0);
1516 level = loglevel_ops[j].mask;
1518 ldap_syslog |= level;
1524 config_syncrepl(ConfigArgs *c) {
1525 if (c->op == SLAP_CONFIG_EMIT) {
1526 if ( c->be->be_syncinfo ) {
1528 syncrepl_unparse( c->be->be_syncinfo, &bv );
1529 ber_bvarray_add( &c->rvalue_vals, &bv );
1534 if(SLAP_SHADOW(c->be)) {
1535 Debug(LDAP_DEBUG_ANY, "%s: "
1536 "syncrepl: database already shadowed.\n",
1539 } else if(add_syncrepl(c->be, c->argv, c->argc)) {
1542 SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SYNC_SHADOW);
1547 config_referral(ConfigArgs *c) {
1548 struct berval vals[2];
1549 if (c->op == SLAP_CONFIG_EMIT) {
1550 if ( default_referral ) {
1551 value_add( &c->rvalue_vals, default_referral );
1557 if(validate_global_referral(c->argv[1])) {
1558 Debug(LDAP_DEBUG_ANY, "%s: "
1559 "invalid URL (%s) in \"referral\" line.\n",
1560 c->log, c->argv[1], 0);
1564 ber_str2bv(c->argv[1], 0, 0, &vals[0]);
1565 vals[1].bv_val = NULL; vals[1].bv_len = 0;
1566 if(value_add(&default_referral, vals)) return(LDAP_OTHER);
1574 { BER_BVC("ssf="), offsetof(slap_ssf_set_t, sss_ssf) },
1575 { BER_BVC("transport="), offsetof(slap_ssf_set_t, sss_transport) },
1576 { BER_BVC("tls="), offsetof(slap_ssf_set_t, sss_tls) },
1577 { BER_BVC("sasl="), offsetof(slap_ssf_set_t, sss_sasl) },
1578 { BER_BVC("update_ssf="), offsetof(slap_ssf_set_t, sss_update_ssf) },
1579 { BER_BVC("update_transport="), offsetof(slap_ssf_set_t, sss_update_transport) },
1580 { BER_BVC("update_tls="), offsetof(slap_ssf_set_t, sss_update_tls) },
1581 { BER_BVC("update_sasl="), offsetof(slap_ssf_set_t, sss_update_sasl) },
1582 { BER_BVC("simple_bind="), offsetof(slap_ssf_set_t, sss_simple_bind) },
1587 config_security(ConfigArgs *c) {
1588 slap_ssf_set_t *set = &c->be->be_ssf_set;
1591 if (c->op == SLAP_CONFIG_EMIT) {
1597 for (i=0; !BER_BVISNULL( &sec_keys[i].key ); i++) {
1598 tgt = (slap_ssf_t *)((char *)set + sec_keys[i].off);
1601 bv.bv_len = sprintf( numbuf, "%u", *tgt );
1602 bv.bv_len += sec_keys[i].key.bv_len;
1603 bv.bv_val = ch_malloc( bv.bv_len + 1);
1604 next = lutil_strcopy( bv.bv_val, sec_keys[i].key.bv_val );
1605 strcpy( next, numbuf );
1606 ber_bvarray_add( &c->rvalue_vals, &bv );
1611 for(i = 1; i < c->argc; i++) {
1612 slap_ssf_t *tgt = NULL;
1614 for ( j=0; !BER_BVISNULL( &sec_keys[j].key ); j++ ) {
1615 if(!strncasecmp(c->argv[i], sec_keys[j].key.bv_val,
1616 sec_keys[j].key.bv_len)) {
1617 src = c->argv[i] + sec_keys[j].key.bv_len;
1618 tgt = (slap_ssf_t *)((char *)set + sec_keys[j].off);
1623 Debug(LDAP_DEBUG_ANY, "%s: "
1624 "unknown factor %s in \"security <factors>\" line\n",
1625 c->log, c->argv[i], 0);
1629 *tgt = strtol(src, &next, 10);
1630 if(next == NULL || next[0] != '\0' ) {
1631 Debug(LDAP_DEBUG_ANY, "%s: "
1632 "unable to parse factor \"%s\" in \"security <factors>\" line\n",
1633 c->log, c->argv[i], 0);
1641 anlist_unparse( AttributeName *an, char *ptr ) {
1644 for (; !BER_BVISNULL( &an->an_name ); an++) {
1645 if ( comma ) *ptr++ = ',';
1646 ptr = lutil_strcopy( ptr, an->an_name.bv_val );
1653 replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv )
1657 struct berval bc = {0};
1660 len = sprintf(numbuf, "{%d}", i );
1662 len += strlen( ri->ri_uri ) + STRLENOF("uri=");
1663 if ( ri->ri_nsuffix ) {
1664 for (i=0; !BER_BVISNULL( &ri->ri_nsuffix[i] ); i++) {
1665 len += ri->ri_nsuffix[i].bv_len + STRLENOF(" suffix=\"\"");
1668 if ( ri->ri_attrs ) {
1669 len += STRLENOF("attr");
1670 if ( ri->ri_exclude ) len++;
1671 for (i=0; !BER_BVISNULL( &ri->ri_attrs[i].an_name ); i++) {
1672 len += 1 + ri->ri_attrs[i].an_name.bv_len;
1675 bindconf_unparse( &ri->ri_bindconf, &bc );
1678 bv->bv_val = ch_malloc(len + 1);
1681 ptr = lutil_strcopy( bv->bv_val, numbuf );
1682 ptr = lutil_strcopy( ptr, "uri=" );
1683 ptr = lutil_strcopy( ptr, ri->ri_uri );
1685 if ( ri->ri_nsuffix ) {
1686 for (i=0; !BER_BVISNULL( &ri->ri_nsuffix[i] ); i++) {
1687 ptr = lutil_strcopy( ptr, " suffix=\"" );
1688 ptr = lutil_strcopy( ptr, ri->ri_nsuffix[i].bv_val );
1692 if ( ri->ri_attrs ) {
1693 ptr = lutil_strcopy( ptr, "attr" );
1694 if ( ri->ri_exclude ) *ptr++ = '!';
1696 ptr = anlist_unparse( ri->ri_attrs, ptr );
1699 strcpy( ptr, bc.bv_val );
1700 ch_free( bc.bv_val );
1705 config_replica(ConfigArgs *c) {
1706 int i, nr = -1, len;
1707 char *replicahost, *replicauri;
1710 if (c->op == SLAP_CONFIG_EMIT) {
1711 if (c->be->be_replica) {
1713 for (i=0;c->be->be_replica[i]; i++) {
1714 replica_unparse( c->be->be_replica[i], i, &bv );
1715 ber_bvarray_add( &c->rvalue_vals, &bv );
1721 if(SLAP_MONITOR(c->be)) {
1722 Debug(LDAP_DEBUG_ANY, "%s: "
1723 "\"replica\" should not be used inside monitor database\n",
1725 return(0); /* FIXME: should this be an error? */
1728 for(i = 1; i < c->argc; i++) {
1729 if(!strncasecmp(c->argv[i], "host=", STRLENOF("host="))) {
1730 replicahost = c->argv[i] + STRLENOF("host=");
1731 len = strlen( replicahost );
1732 replicauri = ch_malloc( len + STRLENOF("ldap://") + 1 );
1733 sprintf( replicauri, "ldap://%s", replicahost );
1734 replicahost = replicauri + STRLENOF( "ldap://");
1735 nr = add_replica_info(c->be, replicauri, replicahost);
1737 } else if(!strncasecmp(c->argv[i], "uri=", STRLENOF("uri="))) {
1738 if(ldap_url_parse(c->argv[i] + STRLENOF("uri="), &ludp) != LDAP_SUCCESS) {
1739 Debug(LDAP_DEBUG_ANY, "%s: "
1740 "replica line contains invalid "
1741 "uri definition.\n", c->log, 0, 0);
1744 if(!ludp->lud_host) {
1745 Debug(LDAP_DEBUG_ANY, "%s: "
1746 "replica line contains invalid "
1747 "uri definition - missing hostname.\n",
1751 ldap_free_urldesc(ludp);
1752 replicauri = c->argv[i] + STRLENOF("uri=");
1753 replicauri = ch_strdup( replicauri );
1754 replicahost = strchr( replicauri, '/' );
1756 nr = add_replica_info(c->be, replicauri, replicahost);
1761 Debug(LDAP_DEBUG_ANY, "%s: "
1762 "missing host or uri in \"replica\" line\n",
1765 } else if(nr == -1) {
1766 Debug(LDAP_DEBUG_ANY, "%s: "
1767 "unable to add replica \"%s\"\n",
1768 c->log, replicauri, 0);
1771 for(i = 1; i < c->argc; i++) {
1772 if(!strncasecmp(c->argv[i], "suffix=", STRLENOF( "suffix="))) {
1773 switch(add_replica_suffix(c->be, nr, c->argv[i] + STRLENOF("suffix="))) {
1775 Debug(LDAP_DEBUG_ANY, "%s: "
1776 "suffix \"%s\" in \"replica\" line is not valid for backend (ignored)\n",
1777 c->log, c->argv[i] + STRLENOF("suffix="), 0);
1780 Debug(LDAP_DEBUG_ANY, "%s: "
1781 "unable to normalize suffix in \"replica\" line (ignored)\n",
1786 } else if(!strncasecmp(c->argv[i], "attr", STRLENOF("attr"))) {
1788 char *arg = c->argv[i] + STRLENOF("attr");
1796 if(add_replica_attrs(c->be, nr, arg + 1, exclude)) {
1797 Debug(LDAP_DEBUG_ANY, "%s: "
1798 "attribute \"%s\" in \"replica\" line is unknown\n",
1799 c->log, arg + 1, 0);
1802 } else if ( bindconf_parse( c->argv[i],
1803 &c->be->be_replica[nr]->ri_bindconf ) ) {
1812 config_updatedn(ConfigArgs *c) {
1815 if (c->op == SLAP_CONFIG_EMIT) {
1816 if (!BER_BVISEMPTY(&c->be->be_update_ndn)) {
1817 value_add_one(&c->rvalue_vals, &c->be->be_update_ndn);
1818 value_add_one(&c->rvalue_nvals, &c->be->be_update_ndn);
1823 if(SLAP_SHADOW(c->be)) {
1824 Debug(LDAP_DEBUG_ANY, "%s: "
1825 "updatedn: database already shadowed.\n",
1830 ber_str2bv(c->argv[1], 0, 0, &dn);
1832 rc = dnNormalize(0, NULL, NULL, &dn, &c->be->be_update_ndn, NULL);
1834 if(rc != LDAP_SUCCESS) {
1835 Debug(LDAP_DEBUG_ANY, "%s: "
1836 "updatedn DN is invalid: %d (%s)\n",
1837 c->log, rc, ldap_err2string( rc ));
1841 SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SLURP_SHADOW);
1846 config_updateref(ConfigArgs *c) {
1847 struct berval vals[2];
1848 if (c->op == SLAP_CONFIG_EMIT) {
1849 if ( c->be->be_update_refs ) {
1850 value_add( &c->rvalue_vals, c->be->be_update_refs );
1856 if(!SLAP_SHADOW(c->be)) {
1857 Debug(LDAP_DEBUG_ANY, "%s: "
1858 "updateref line must come after syncrepl or updatedn.\n",
1863 if(validate_global_referral(c->argv[1])) {
1864 Debug(LDAP_DEBUG_ANY, "%s: "
1865 "invalid URL (%s) in \"updateref\" line.\n",
1866 c->log, c->argv[1], 0);
1869 ber_str2bv(c->argv[1], 0, 0, &vals[0]);
1870 vals[1].bv_val = NULL;
1871 if(value_add(&c->be->be_update_refs, vals)) return(LDAP_OTHER);
1876 config_include(ConfigArgs *c) {
1877 unsigned long savelineno = c->lineno;
1880 ConfigFile *cfsave = cfn;
1881 ConfigFile *cf2 = NULL;
1882 if (c->op == SLAP_CONFIG_EMIT) {
1885 cf = ch_calloc( 1, sizeof(ConfigFile));
1886 #ifdef SLAPD_MODULES
1887 cf->c_modlast = &cf->c_modpaths;
1889 if ( cfn->c_kids ) {
1890 for (cf2=cfn->c_kids; cf2 && cf2->c_sibs; cf2=cf2->c_sibs) ;
1896 rc = read_config_file(c->argv[1], c->depth + 1, c);
1897 c->lineno = savelineno - 1;
1900 if ( cf2 ) cf2->c_sibs = NULL;
1901 else cfn->c_kids = NULL;
1904 ber_str2bv( c->argv[1], 0, 1, &cf->c_file );
1911 config_tls_option(ConfigArgs *c) {
1914 case CFG_TLS_RAND: flag = LDAP_OPT_X_TLS_RANDOM_FILE; break;
1915 case CFG_TLS_CIPHER: flag = LDAP_OPT_X_TLS_CIPHER_SUITE; break;
1916 case CFG_TLS_CERT_FILE: flag = LDAP_OPT_X_TLS_CERTFILE; break;
1917 case CFG_TLS_CERT_KEY: flag = LDAP_OPT_X_TLS_KEYFILE; break;
1918 case CFG_TLS_CA_PATH: flag = LDAP_OPT_X_TLS_CACERTDIR; break;
1919 case CFG_TLS_CA_FILE: flag = LDAP_OPT_X_TLS_CACERTFILE; break;
1920 default: Debug(LDAP_DEBUG_ANY, "%s: "
1921 "unknown tls_option <%x>\n",
1922 c->log, c->type, 0);
1924 if (c->op == SLAP_CONFIG_EMIT) {
1925 return ldap_pvt_tls_get_option( NULL, flag, &c->value_string );
1927 ch_free(c->value_string);
1928 return(ldap_pvt_tls_set_option(NULL, flag, c->argv[1]));
1931 /* FIXME: this ought to be provided by libldap */
1933 config_tls_config(ConfigArgs *c) {
1935 slap_verbmasks crlkeys[] = {
1936 { BER_BVC("none"), LDAP_OPT_X_TLS_CRL_NONE },
1937 { BER_BVC("peer"), LDAP_OPT_X_TLS_CRL_PEER },
1938 { BER_BVC("all"), LDAP_OPT_X_TLS_CRL_ALL },
1941 slap_verbmasks vfykeys[] = {
1942 { BER_BVC("never"), LDAP_OPT_X_TLS_NEVER },
1943 { BER_BVC("demand"), LDAP_OPT_X_TLS_DEMAND },
1944 { BER_BVC("try"), LDAP_OPT_X_TLS_TRY },
1945 { BER_BVC("hard"), LDAP_OPT_X_TLS_HARD },
1949 #ifdef HAVE_OPENSSL_CRL
1950 case CFG_TLS_CRLCHECK: flag = LDAP_OPT_X_TLS_CRLCHECK; keys = crlkeys;
1953 case CFG_TLS_VERIFY: flag = LDAP_OPT_X_TLS_REQUIRE_CERT; keys = vfykeys;
1955 default: Debug(LDAP_DEBUG_ANY, "%s: "
1956 "unknown tls_option <%x>\n",
1957 c->log, c->type, 0);
1959 if (c->op == SLAP_CONFIG_EMIT) {
1960 ldap_pvt_tls_get_option( NULL, flag, &c->value_int );
1961 for (i=0; !BER_BVISNULL(&keys[i].word); i++) {
1962 if (keys[i].mask == c->value_int) {
1963 c->value_string = ch_strdup( keys[i].word.bv_val );
1969 ch_free( c->value_string );
1970 if(isdigit((unsigned char)c->argv[1][0])) {
1971 i = atoi(c->argv[1]);
1972 return(ldap_pvt_tls_set_option(NULL, flag, &i));
1974 return(ldap_int_tls_config(NULL, flag, c->argv[1]));
1989 si = (syncinfo_t *) ch_calloc( 1, sizeof( syncinfo_t ) );
1992 Debug( LDAP_DEBUG_ANY, "out of memory in add_syncrepl\n", 0, 0, 0 );
1996 si->si_bindconf.sb_tls = SB_TLS_OFF;
1997 si->si_bindconf.sb_method = LDAP_AUTH_SIMPLE;
1998 si->si_schemachecking = 0;
1999 ber_str2bv( "(objectclass=*)", STRLENOF("(objectclass=*)"), 1,
2000 &si->si_filterstr );
2001 si->si_base.bv_val = NULL;
2002 si->si_scope = LDAP_SCOPE_SUBTREE;
2003 si->si_attrsonly = 0;
2004 si->si_anlist = (AttributeName *) ch_calloc( 1, sizeof( AttributeName ));
2005 si->si_exanlist = (AttributeName *) ch_calloc( 1, sizeof( AttributeName ));
2006 si->si_attrs = NULL;
2007 si->si_allattrs = 0;
2008 si->si_allopattrs = 0;
2009 si->si_exattrs = NULL;
2010 si->si_type = LDAP_SYNC_REFRESH_ONLY;
2011 si->si_interval = 86400;
2012 si->si_retryinterval = NULL;
2013 si->si_retrynum_init = NULL;
2014 si->si_retrynum = NULL;
2015 si->si_manageDSAit = 0;
2019 si->si_presentlist = NULL;
2020 LDAP_LIST_INIT( &si->si_nonpresentlist );
2021 ldap_pvt_thread_mutex_init( &si->si_mutex );
2023 rc = parse_syncrepl_line( cargv, cargc, si );
2026 Debug( LDAP_DEBUG_ANY, "failed to add syncinfo\n", 0, 0, 0 );
2027 syncinfo_free( si );
2030 Debug( LDAP_DEBUG_CONFIG,
2031 "Config: ** successfully added syncrepl \"%s\"\n",
2032 BER_BVISNULL( &si->si_provideruri ) ?
2033 "(null)" : si->si_provideruri.bv_val, 0, 0 );
2034 if ( !si->si_schemachecking ) {
2035 SLAP_DBFLAGS(be) |= SLAP_DBFLAG_NO_SCHEMA_CHECK;
2038 be->be_syncinfo = si;
2043 /* NOTE: used & documented in slapd.conf(5) */
2045 #define PROVIDERSTR "provider"
2046 #define TYPESTR "type"
2047 #define INTERVALSTR "interval"
2048 #define SEARCHBASESTR "searchbase"
2049 #define FILTERSTR "filter"
2050 #define SCOPESTR "scope"
2051 #define ATTRSSTR "attrs"
2052 #define ATTRSONLYSTR "attrsonly"
2053 #define SLIMITSTR "sizelimit"
2054 #define TLIMITSTR "timelimit"
2055 #define SCHEMASTR "schemachecking"
2057 /* FIXME: undocumented */
2058 #define OLDAUTHCSTR "bindprincipal"
2059 #define EXATTRSSTR "exattrs"
2060 #define RETRYSTR "retry"
2063 #define LASTMODSTR "lastmod"
2064 #define LMGENSTR "gen"
2065 #define LMNOSTR "no"
2066 #define LMREQSTR "req"
2067 #define SRVTABSTR "srvtab"
2068 #define SUFFIXSTR "suffix"
2069 #define MANAGEDSAITSTR "manageDSAit"
2072 #define GOT_ID 0x0001
2073 #define GOT_PROVIDER 0x0002
2076 #define GOT_ALL (GOT_ID|GOT_PROVIDER)
2082 { BER_BVC("base"), LDAP_SCOPE_BASE },
2083 { BER_BVC("one"), LDAP_SCOPE_ONELEVEL },
2084 #ifdef LDAP_SCOPE_SUBORDINATE
2085 { BER_BVC("children"), LDAP_SCOPE_SUBORDINATE },
2086 { BER_BVC("subordinate"), 0 },
2088 { BER_BVC("sub"), LDAP_SCOPE_SUBTREE },
2093 parse_syncrepl_line(
2103 for ( i = 1; i < cargc; i++ ) {
2104 if ( !strncasecmp( cargv[ i ], IDSTR "=",
2105 STRLENOF( IDSTR "=" ) ) )
2108 /* '\0' string terminator accounts for '=' */
2109 val = cargv[ i ] + STRLENOF( IDSTR "=" );
2111 if ( tmp >= 1000 || tmp < 0 ) {
2112 fprintf( stderr, "Error: parse_syncrepl_line: "
2113 "syncrepl id %d is out of range [0..999]\n", tmp );
2118 } else if ( !strncasecmp( cargv[ i ], PROVIDERSTR "=",
2119 STRLENOF( PROVIDERSTR "=" ) ) )
2121 val = cargv[ i ] + STRLENOF( PROVIDERSTR "=" );
2122 ber_str2bv( val, 0, 1, &si->si_provideruri );
2123 gots |= GOT_PROVIDER;
2124 } else if ( !strncasecmp( cargv[ i ], SCHEMASTR "=",
2125 STRLENOF( SCHEMASTR "=" ) ) )
2127 val = cargv[ i ] + STRLENOF( SCHEMASTR "=" );
2128 if ( !strncasecmp( val, "on", STRLENOF( "on" ) )) {
2129 si->si_schemachecking = 1;
2130 } else if ( !strncasecmp( val, "off", STRLENOF( "off" ) ) ) {
2131 si->si_schemachecking = 0;
2133 si->si_schemachecking = 1;
2135 } else if ( !strncasecmp( cargv[ i ], FILTERSTR "=",
2136 STRLENOF( FILTERSTR "=" ) ) )
2138 val = cargv[ i ] + STRLENOF( FILTERSTR "=" );
2139 ber_str2bv( val, 0, 1, &si->si_filterstr );
2140 } else if ( !strncasecmp( cargv[ i ], SEARCHBASESTR "=",
2141 STRLENOF( SEARCHBASESTR "=" ) ) )
2146 val = cargv[ i ] + STRLENOF( SEARCHBASESTR "=" );
2147 if ( si->si_base.bv_val ) {
2148 ch_free( si->si_base.bv_val );
2150 ber_str2bv( val, 0, 0, &bv );
2151 rc = dnNormalize( 0, NULL, NULL, &bv, &si->si_base, NULL );
2152 if ( rc != LDAP_SUCCESS ) {
2153 fprintf( stderr, "Invalid base DN \"%s\": %d (%s)\n",
2154 val, rc, ldap_err2string( rc ) );
2157 } else if ( !strncasecmp( cargv[ i ], SCOPESTR "=",
2158 STRLENOF( SCOPESTR "=" ) ) )
2161 val = cargv[ i ] + STRLENOF( SCOPESTR "=" );
2162 for ( j=0; !BER_BVISNULL(&scopes[j].key); j++ ) {
2163 if (!strncasecmp( val, scopes[j].key.bv_val,
2164 scopes[j].key.bv_len )) {
2165 while (!scopes[j].val) j--;
2166 si->si_scope = scopes[j].val;
2170 if ( BER_BVISNULL(&scopes[j].key) ) {
2171 fprintf( stderr, "Error: parse_syncrepl_line: "
2172 "unknown scope \"%s\"\n", val);
2175 } else if ( !strncasecmp( cargv[ i ], ATTRSONLYSTR "=",
2176 STRLENOF( ATTRSONLYSTR "=" ) ) )
2178 si->si_attrsonly = 1;
2179 } else if ( !strncasecmp( cargv[ i ], ATTRSSTR "=",
2180 STRLENOF( ATTRSSTR "=" ) ) )
2182 val = cargv[ i ] + STRLENOF( ATTRSSTR "=" );
2183 if ( !strncasecmp( val, ":include:", STRLENOF(":include:") ) ) {
2185 attr_fname = ch_strdup( val + STRLENOF(":include:") );
2186 si->si_anlist = file2anlist( si->si_anlist, attr_fname, " ,\t" );
2187 if ( si->si_anlist == NULL ) {
2188 ch_free( attr_fname );
2191 si->si_anfile = attr_fname;
2193 char *str, *s, *next;
2194 char delimstr[] = " ,\t";
2195 str = ch_strdup( val );
2196 for ( s = ldap_pvt_strtok( str, delimstr, &next );
2198 s = ldap_pvt_strtok( NULL, delimstr, &next ) )
2200 if ( strlen(s) == 1 && *s == '*' ) {
2201 si->si_allattrs = 1;
2202 *(val + ( s - str )) = delimstr[0];
2204 if ( strlen(s) == 1 && *s == '+' ) {
2205 si->si_allopattrs = 1;
2206 *(val + ( s - str )) = delimstr[0];
2210 si->si_anlist = str2anlist( si->si_anlist, val, " ,\t" );
2211 if ( si->si_anlist == NULL ) {
2215 } else if ( !strncasecmp( cargv[ i ], EXATTRSSTR "=",
2216 STRLENOF( EXATTRSSTR "=" ) ) )
2218 val = cargv[ i ] + STRLENOF( EXATTRSSTR "=" );
2219 if ( !strncasecmp( val, ":include:", STRLENOF(":include:") )) {
2221 attr_fname = ch_strdup( val + STRLENOF(":include:") );
2222 si->si_exanlist = file2anlist(
2223 si->si_exanlist, attr_fname, " ,\t" );
2224 if ( si->si_exanlist == NULL ) {
2225 ch_free( attr_fname );
2228 ch_free( attr_fname );
2230 si->si_exanlist = str2anlist( si->si_exanlist, val, " ,\t" );
2231 if ( si->si_exanlist == NULL ) {
2235 } else if ( !strncasecmp( cargv[ i ], TYPESTR "=",
2236 STRLENOF( TYPESTR "=" ) ) )
2238 val = cargv[ i ] + STRLENOF( TYPESTR "=" );
2239 if ( !strncasecmp( val, "refreshOnly",
2240 STRLENOF("refreshOnly") ))
2242 si->si_type = LDAP_SYNC_REFRESH_ONLY;
2243 } else if ( !strncasecmp( val, "refreshAndPersist",
2244 STRLENOF("refreshAndPersist") ))
2246 si->si_type = LDAP_SYNC_REFRESH_AND_PERSIST;
2247 si->si_interval = 60;
2249 fprintf( stderr, "Error: parse_syncrepl_line: "
2250 "unknown sync type \"%s\"\n", val);
2253 } else if ( !strncasecmp( cargv[ i ], INTERVALSTR "=",
2254 STRLENOF( INTERVALSTR "=" ) ) )
2256 val = cargv[ i ] + STRLENOF( INTERVALSTR "=" );
2257 if ( si->si_type == LDAP_SYNC_REFRESH_AND_PERSIST ) {
2258 si->si_interval = 0;
2266 hstr = strchr( dstr, ':' );
2267 if ( hstr == NULL ) {
2268 fprintf( stderr, "Error: parse_syncrepl_line: "
2269 "invalid interval \"%s\"\n", val );
2273 mstr = strchr( hstr, ':' );
2274 if ( mstr == NULL ) {
2275 fprintf( stderr, "Error: parse_syncrepl_line: "
2276 "invalid interval \"%s\"\n", val );
2280 sstr = strchr( mstr, ':' );
2281 if ( sstr == NULL ) {
2282 fprintf( stderr, "Error: parse_syncrepl_line: "
2283 "invalid interval \"%s\"\n", val );
2292 if (( hh > 24 ) || ( hh < 0 ) ||
2293 ( mm > 60 ) || ( mm < 0 ) ||
2294 ( ss > 60 ) || ( ss < 0 ) || ( dd < 0 )) {
2295 fprintf( stderr, "Error: parse_syncrepl_line: "
2296 "invalid interval \"%s\"\n", val );
2299 si->si_interval = (( dd * 24 + hh ) * 60 + mm ) * 60 + ss;
2301 if ( si->si_interval < 0 ) {
2302 fprintf( stderr, "Error: parse_syncrepl_line: "
2303 "invalid interval \"%ld\"\n",
2304 (long) si->si_interval);
2307 } else if ( !strncasecmp( cargv[ i ], RETRYSTR "=",
2308 STRLENOF( RETRYSTR "=" ) ) )
2313 val = cargv[ i ] + STRLENOF( RETRYSTR "=" );
2314 retry_list = (char **) ch_calloc( 1, sizeof( char * ));
2315 retry_list[0] = NULL;
2317 slap_str2clist( &retry_list, val, " ,\t" );
2319 for ( k = 0; retry_list && retry_list[k]; k++ ) ;
2323 "Error: incomplete syncrepl retry list\n" );
2324 for ( k = 0; retry_list && retry_list[k]; k++ ) {
2325 ch_free( retry_list[k] );
2327 ch_free( retry_list );
2328 exit( EXIT_FAILURE );
2330 si->si_retryinterval = (time_t *) ch_calloc( n + 1, sizeof( time_t ));
2331 si->si_retrynum = (int *) ch_calloc( n + 1, sizeof( int ));
2332 si->si_retrynum_init = (int *) ch_calloc( n + 1, sizeof( int ));
2333 for ( j = 0; j < n; j++ ) {
2334 si->si_retryinterval[j] = atoi( retry_list[j*2] );
2335 if ( *retry_list[j*2+1] == '+' ) {
2336 si->si_retrynum_init[j] = -1;
2337 si->si_retrynum[j] = -1;
2341 si->si_retrynum_init[j] = atoi( retry_list[j*2+1] );
2342 si->si_retrynum[j] = atoi( retry_list[j*2+1] );
2345 si->si_retrynum_init[j] = -2;
2346 si->si_retrynum[j] = -2;
2347 si->si_retryinterval[j] = 0;
2349 for ( k = 0; retry_list && retry_list[k]; k++ ) {
2350 ch_free( retry_list[k] );
2352 ch_free( retry_list );
2353 } else if ( !strncasecmp( cargv[ i ], MANAGEDSAITSTR "=",
2354 STRLENOF( MANAGEDSAITSTR "=" ) ) )
2356 val = cargv[ i ] + STRLENOF( MANAGEDSAITSTR "=" );
2357 si->si_manageDSAit = atoi( val );
2358 } else if ( !strncasecmp( cargv[ i ], SLIMITSTR "=",
2359 STRLENOF( SLIMITSTR "=") ) )
2361 val = cargv[ i ] + STRLENOF( SLIMITSTR "=" );
2362 si->si_slimit = atoi( val );
2363 } else if ( !strncasecmp( cargv[ i ], TLIMITSTR "=",
2364 STRLENOF( TLIMITSTR "=" ) ) )
2366 val = cargv[ i ] + STRLENOF( TLIMITSTR "=" );
2367 si->si_tlimit = atoi( val );
2368 } else if ( bindconf_parse( cargv[i], &si->si_bindconf )) {
2369 fprintf( stderr, "Error: parse_syncrepl_line: "
2370 "unknown keyword \"%s\"\n", cargv[ i ] );
2375 if ( gots != GOT_ALL ) {
2377 "Error: Malformed \"syncrepl\" line in slapd config file" );
2385 syncrepl_unparse( syncinfo_t *si, struct berval *bv )
2388 char buf[BUFSIZ*2], *ptr;
2391 bindconf_unparse( &si->si_bindconf, &bc );
2393 ptr += sprintf( ptr, IDSTR "=%03d " PROVIDERSTR "=%s",
2394 si->si_rid, si->si_provideruri.bv_val );
2395 if ( !BER_BVISNULL( &bc )) {
2396 ptr = lutil_strcopy( ptr, bc.bv_val );
2399 if ( !BER_BVISEMPTY( &si->si_filterstr )) {
2400 ptr = lutil_strcopy( ptr, " " FILTERSTR "=\"" );
2401 ptr = lutil_strcopy( ptr, si->si_filterstr.bv_val );
2404 if ( !BER_BVISNULL( &si->si_base )) {
2405 ptr = lutil_strcopy( ptr, " " SEARCHBASESTR "=\"" );
2406 ptr = lutil_strcopy( ptr, si->si_base.bv_val );
2409 for (i=0; !BER_BVISNULL(&scopes[i].key);i++) {
2410 if ( si->si_scope == scopes[i].val ) {
2411 ptr = lutil_strcopy( ptr, " " SCOPESTR "=" );
2412 ptr = lutil_strcopy( ptr, scopes[i].key.bv_val );
2416 if ( si->si_attrsonly ) {
2417 ptr = lutil_strcopy( ptr, " " ATTRSONLYSTR "=yes" );
2419 if ( si->si_anfile ) {
2420 ptr = lutil_strcopy( ptr, " " ATTRSSTR "=:include:" );
2421 ptr = lutil_strcopy( ptr, si->si_anfile );
2422 } else if ( si->si_allattrs || si->si_allopattrs ||
2423 ( si->si_anlist && !BER_BVISNULL(&si->si_anlist[0].an_name) )) {
2425 ptr = lutil_strcopy( ptr, " " ATTRSSTR "=\"" );
2427 ptr = anlist_unparse( si->si_anlist, ptr );
2428 if ( si->si_allattrs ) {
2429 if ( old != ptr ) *ptr++ = ',';
2432 if ( si->si_allopattrs ) {
2433 if ( old != ptr ) *ptr++ = ',';
2438 if ( si->si_exanlist && !BER_BVISNULL(&si->si_exanlist[0].an_name) ) {
2439 ptr = lutil_strcopy( ptr, " " EXATTRSSTR "=" );
2440 ptr = anlist_unparse( si->si_exanlist, ptr );
2442 ptr = lutil_strcopy( ptr, " " SCHEMASTR "=" );
2443 ptr = lutil_strcopy( ptr, si->si_schemachecking ? "on" : "off" );
2445 ptr = lutil_strcopy( ptr, " " TYPESTR "=" );
2446 ptr = lutil_strcopy( ptr, si->si_type == LDAP_SYNC_REFRESH_AND_PERSIST ?
2447 "refreshAndPersist" : "refreshOnly" );
2449 if ( si->si_type == LDAP_SYNC_REFRESH_ONLY ) {
2452 dd = si->si_interval;
2459 ptr = lutil_strcopy( ptr, " " INTERVALSTR "=" );
2460 ptr += sprintf( ptr, "%02d:%02d:%02d:%02d", dd, hh, mm, ss );
2461 } else if ( si->si_retryinterval ) {
2463 ptr = lutil_strcopy( ptr, " " RETRYSTR "=\"" );
2464 for (i=0; si->si_retryinterval[i]; i++) {
2465 if ( space ) *ptr++ = ' ';
2467 ptr += sprintf( ptr, "%d", si->si_retryinterval[i] );
2468 if ( si->si_retrynum_init[i] == -1 )
2471 ptr += sprintf( ptr, "%d", si->si_retrynum_init );
2476 #if 0 /* FIXME: unused in syncrepl.c, should remove it */
2477 ptr = lutil_strcopy( ptr, " " MANAGEDSAITSTR "=" );
2478 ptr += sprintf( ptr, "%d", si->si_manageDSAit );
2481 if ( si->si_slimit ) {
2482 ptr = lutil_strcopy( ptr, " " SLIMITSTR "=" );
2483 ptr += sprintf( ptr, "%d", si->si_slimit );
2486 if ( si->si_tlimit ) {
2487 ptr = lutil_strcopy( ptr, " " TLIMITSTR "=" );
2488 ptr += sprintf( ptr, "%d", si->si_tlimit );
2490 bc.bv_len = ptr - buf;
2492 ber_dupbv( bv, &bc );
2495 static CfEntryInfo *
2496 config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last )
2501 if ( dn_match( &root->ce_entry->e_nname, dn ))
2504 c = dn->bv_val+dn->bv_len;
2505 for (;*c != ',';c--);
2509 for (--c;c>dn->bv_val && *c != ',';c--);
2513 cdn.bv_len = dn->bv_len - (c-dn->bv_val);
2515 root = root->ce_kids;
2517 for (;root;root=root->ce_sibs) {
2518 if ( dn_match( &root->ce_entry->e_nname, &cdn )) {
2519 if ( cdn.bv_val == dn->bv_val ) {
2530 config_ldif_resp( Operation *op, SlapReply *rs )
2532 if ( rs->sr_type == REP_SEARCH ) {
2533 CfBackInfo *cfb = op->o_callback->sc_private;
2534 CfEntryInfo *ce, *last;
2536 cfb->cb_got_ldif = 1;
2537 config_find_base( cfb->cb_root, &rs->sr_entry->e_nname, &last );
2538 ce = ch_calloc( 1, sizeof(CfEntryInfo) );
2539 ce->ce_entry = entry_dup( rs->sr_entry );
2540 ce->ce_entry->e_private = ce;
2543 } else if ( last->ce_kids ) {
2546 for (c2=last->ce_kids; c2 && c2->ce_sibs; c2 = c2->ce_sibs);
2555 /* Configure and read the underlying back-ldif store */
2557 config_setup_ldif( BackendDB *be, const char *dir ) {
2558 CfBackInfo *cfb = be->be_private;
2563 slap_callback cb = { NULL, config_ldif_resp, NULL, NULL };
2564 Connection conn = {0};
2565 char opbuf[OPERATION_BUFFER_SIZE];
2567 SlapReply rs = {REP_RESULT};
2568 Filter filter = { LDAP_FILTER_PRESENT };
2569 struct berval filterstr = BER_BVC("(objectclass=*)");
2571 cfb->cb_db.bd_info = backend_info( "ldif" );
2572 if ( !cfb->cb_db.bd_info )
2575 if ( cfb->cb_db.bd_info->bi_db_init( &cfb->cb_db )) return 1;
2577 /* Mark that back-ldif type is in use */
2578 cfb->cb_db.bd_info->bi_nDB++;
2580 cfb->cb_db.be_suffix = be->be_suffix;
2581 cfb->cb_db.be_nsuffix = be->be_nsuffix;
2582 cfb->cb_db.be_rootdn = be->be_rootdn;
2583 cfb->cb_db.be_rootndn = be->be_rootndn;
2585 ber_str2bv( dir, 0, 1, &cfdir );
2590 argv[0] = "directory";
2591 argv[1] = (char *)dir;
2595 ct = config_find_keyword( c.be->be_cf_table, &c );
2599 if ( config_add_vals( ct, &c ))
2602 if ( backend_startup_one( &cfb->cb_db ))
2606 op = (Operation *)opbuf;
2607 connection_fake_init( &conn, op, cfb );
2609 filter.f_desc = slap_schema.si_ad_objectClass;
2611 op->o_tag = LDAP_REQ_SEARCH;
2613 op->ors_filter = &filter;
2614 op->ors_filterstr = filterstr;
2615 op->ors_scope = LDAP_SCOPE_SUBTREE;
2617 op->o_dn = be->be_rootdn;
2618 op->o_ndn = be->be_rootndn;
2620 op->o_req_dn = be->be_suffix[0];
2621 op->o_req_ndn = be->be_nsuffix[0];
2623 op->ors_tlimit = SLAP_NO_LIMIT;
2624 op->ors_slimit = SLAP_NO_LIMIT;
2626 op->ors_attrs = slap_anlist_all_attributes;
2627 op->ors_attrsonly = 0;
2629 op->o_callback = &cb;
2630 cb.sc_private = cfb;
2632 op->o_bd = &cfb->cb_db;
2633 op->o_bd->be_search( op, &rs );
2640 read_config(const char *fname, const char *dir) {
2643 /* Setup the config backend */
2644 be = backend_db_init( "config" );
2648 /* Setup the underlying back-ldif backend */
2649 if ( config_setup_ldif( be, dir ))
2652 ber_str2bv( fname, 0, 1, &cf_prv.c_file );
2654 return read_config_file(fname, 0, NULL);
2658 config_back_bind( Operation *op, SlapReply *rs )
2660 if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
2661 ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ));
2662 /* frontend sends result */
2663 return LDAP_SUCCESS;
2666 rs->sr_err = LDAP_INVALID_CREDENTIALS;
2667 send_ldap_result( op, rs );
2673 config_send( Operation *op, SlapReply *rs, CfEntryInfo *ce, int depth )
2677 if ( test_filter( op, ce->ce_entry, op->ors_filter ) == LDAP_COMPARE_TRUE )
2679 rs->sr_attrs = op->ors_attrs;
2680 rs->sr_entry = ce->ce_entry;
2681 rc = send_search_entry( op, rs );
2683 if ( op->ors_scope == LDAP_SCOPE_SUBTREE ) {
2684 if ( ce->ce_kids ) {
2685 rc = config_send( op, rs, ce->ce_kids, 1 );
2686 if ( rc ) return rc;
2689 for (ce=ce->ce_sibs; ce; ce=ce->ce_sibs) {
2690 rc = config_send( op, rs, ce, 0 );
2699 config_back_modify( Operation *op, SlapReply *rs )
2702 CfEntryInfo *ce, *last;
2704 if ( !be_isroot( op ) ) {
2705 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
2706 send_ldap_result( op, rs );
2709 cfb = (CfBackInfo *)op->o_bd->be_private;
2711 ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
2714 rs->sr_matched = last->ce_entry->e_name.bv_val;
2715 rs->sr_err = LDAP_NO_SUCH_OBJECT;
2718 ldap_pvt_thread_pool_pause( &connection_pool );
2721 * 1) perform the Modify on the cached Entry.
2722 * 2) verify that the Entry still satisfies the schema.
2723 * 3) perform the individual config operations.
2724 * 4) store Modified entry in underlying LDIF backend.
2726 ldap_pvt_thread_pool_resume( &connection_pool );
2728 send_ldap_result( op, rs );
2733 config_back_search( Operation *op, SlapReply *rs )
2736 CfEntryInfo *ce, *last;
2739 if ( !be_isroot( op ) ) {
2740 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
2741 send_ldap_result( op, rs );
2744 cfb = (CfBackInfo *)op->o_bd->be_private;
2746 ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
2749 rs->sr_matched = last->ce_entry->e_name.bv_val;
2750 rs->sr_err = LDAP_NO_SUCH_OBJECT;
2753 switch ( op->ors_scope ) {
2754 case LDAP_SCOPE_BASE:
2755 case LDAP_SCOPE_SUBTREE:
2756 config_send( op, rs, ce, 0 );
2759 case LDAP_SCOPE_ONELEVEL:
2760 for (ce = ce->ce_kids; ce; ce=ce->ce_sibs) {
2761 config_send( op, rs, ce, 1 );
2766 rs->sr_err = LDAP_SUCCESS;
2768 send_ldap_result( op, rs );
2773 config_alloc_entry( struct berval *pdn, struct berval *rdn )
2775 Entry *e = ch_calloc( 1, sizeof(Entry) );
2776 CfEntryInfo *ce = ch_calloc( 1, sizeof(CfEntryInfo) );
2779 build_new_dn( &e->e_name, pdn, rdn, NULL );
2780 ber_dupbv( &e->e_nname, &e->e_name );
2789 config_build_entry( ConfigArgs *c, Entry *e, ObjectClass *oc,
2790 struct berval *rdn, ConfigTable *ct, int table )
2792 struct berval vals[2];
2793 struct berval ad_name;
2794 AttributeDescription *ad = NULL;
2800 BER_BVZERO( &vals[1] );
2802 vals[0] = oc->soc_cname;
2803 attr_merge(e, slap_schema.si_ad_objectClass, vals, NULL );
2804 attr_merge(e, slap_schema.si_ad_structuralObjectClass, vals, NULL );
2805 ptr = strchr(rdn->bv_val, '=');
2806 ad_name.bv_val = rdn->bv_val;
2807 ad_name.bv_len = ptr - rdn->bv_val;
2808 rc = slap_bv2ad( &ad_name, &ad, &text );
2812 vals[0].bv_val = ptr+1;
2813 vals[0].bv_len = rdn->bv_len - (vals[0].bv_val - rdn->bv_val);
2814 attr_merge(e, ad, vals, NULL );
2816 for (at=oc->soc_required; at && *at; at++) {
2817 /* Skip the naming attr */
2818 if ((*at)->sat_ad == ad || (*at)->sat_ad == slap_schema.si_ad_cn )
2820 for (i=0;ct[i].name;i++) {
2821 if (ct[i].ad == (*at)->sat_ad) {
2822 rc = config_get_vals(&ct[i], c);
2823 if (rc == LDAP_SUCCESS) {
2824 attr_merge(e, ct[i].ad, c->rvalue_vals, c->rvalue_nvals);
2825 ber_bvarray_free( c->rvalue_nvals );
2826 ber_bvarray_free( c->rvalue_vals );
2833 for (at=oc->soc_allowed; at && *at; at++) {
2834 /* Skip the naming attr */
2835 if ((*at)->sat_ad == ad || (*at)->sat_ad == slap_schema.si_ad_cn )
2837 for (i=0;ct[i].name;i++) {
2838 if (ct[i].ad == (*at)->sat_ad) {
2839 rc = config_get_vals(&ct[i], c);
2840 if (rc == LDAP_SUCCESS) {
2841 attr_merge(e, ct[i].ad, c->rvalue_vals, c->rvalue_nvals);
2842 ber_bvarray_free( c->rvalue_nvals );
2843 ber_bvarray_free( c->rvalue_vals );
2851 if ( table == BI_TABLE )
2852 ct = c->bi->bi_cf_table;
2854 ct = c->be->be_cf_table;
2855 for (;ct && ct->name;ct++) {
2856 if (!ct->ad) continue;
2857 rc = config_get_vals(ct, c);
2858 if (rc == LDAP_SUCCESS) {
2859 attr_merge(e, ct->ad, c->rvalue_vals, c->rvalue_nvals);
2867 static CfEntryInfo *
2868 config_build_includes( ConfigArgs *c, Entry *parent,
2869 Operation *op, SlapReply *rs )
2873 ConfigFile *cf = (ConfigFile *)c->line;
2874 CfEntryInfo *ce, *ceparent, *ceprev;
2876 ceparent = parent->e_private;
2878 for (i=0; cf; cf=cf->c_sibs, i++) {
2879 c->value_dn.bv_val = c->log;
2880 c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=include{%d}", i);
2881 e = config_alloc_entry( &parent->e_nname, &c->value_dn );
2882 c->line = (char *)cf;
2883 config_build_entry( c, e, cfOc_include, &c->value_dn,
2884 c->bi->bi_cf_table, NO_TABLE );
2886 op->o_bd->be_add( op, rs );
2888 if ( !ceparent->ce_kids ) {
2889 ceparent->ce_kids = ce;
2891 ceprev->ce_sibs = ce;
2895 c->line = (char *)cf->c_kids;
2896 config_build_includes( c, e, op, rs );
2903 config_back_db_open( BackendDB *be )
2905 CfBackInfo *cfb = be->be_private;
2908 CfEntryInfo *ce, *ceparent, *ceprev;
2914 Connection conn = {0};
2915 char opbuf[OPERATION_BUFFER_SIZE];
2917 slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
2918 SlapReply rs = {REP_RESULT};
2920 /* If we read the config from back-ldif, nothing to do here */
2921 if ( cfb->cb_got_ldif )
2924 op = (Operation *)opbuf;
2925 connection_fake_init( &conn, op, cfb );
2927 op->o_dn = be->be_rootdn;
2928 op->o_ndn = be->be_rootndn;
2930 op->o_tag = LDAP_REQ_ADD;
2931 op->o_callback = &cb;
2932 op->o_bd = &cfb->cb_db;
2934 /* create root of tree */
2936 e = config_alloc_entry( NULL, &rdn );
2941 c.line = (char *)cfb->cb_config;
2942 ct = c.bi->bi_cf_table;
2943 config_build_entry( &c, e, cfOc_global, &rdn, ct, NO_TABLE );
2945 op->o_bd->be_add( op, &rs );
2950 /* Create includeFile nodes... */
2951 if ( cfb->cb_config->c_kids ) {
2952 c.line = (char *)cfb->cb_config->c_kids;
2953 ceprev = config_build_includes( &c, parent, op, &rs );
2956 /* Create backend nodes. Skip if they don't provide a cf_table.
2957 * There usually aren't any of these.
2962 for (i=0; i<nBackendInfo; i++, bi++) {
2963 if (!bi->bi_cf_table) continue;
2964 if (!bi->bi_private) continue;
2967 rdn.bv_len = sprintf(rdn.bv_val, "%s=%s", cfAd_backend->ad_cname.bv_val, bi->bi_type);
2968 e = config_alloc_entry( &parent->e_nname, &rdn );
2972 config_build_entry( &c, e, cfOc_backend, &rdn, ct, BI_TABLE );
2974 op->o_bd->be_add( op, &rs );
2975 if ( !ceparent->ce_kids ) {
2976 ceparent->ce_kids = ce;
2978 ceprev->ce_sibs = ce;
2983 /* Create database nodes... */
2984 for (i=0; i<nBackendDB; i++) {
2985 slap_overinfo *oi = NULL;
2989 bptr = &backendDB[i];
2991 if ( overlay_is_over( bptr )) {
2992 oi = bptr->bd_info->bi_private;
2998 rdn.bv_len = sprintf(rdn.bv_val, "%s={%0x}%s", cfAd_database->ad_cname.bv_val,
3000 e = config_alloc_entry( &parent->e_nname, &rdn );
3006 config_build_entry( &c, e, cfOc_database, &rdn, ct, BE_TABLE );
3008 op->o_bd->be_add( op, &rs );
3009 if ( !ceparent->ce_kids ) {
3010 ceparent->ce_kids = ce;
3012 ceprev->ce_sibs = ce;
3015 /* Iterate through overlays */
3019 CfEntryInfo *opar = ce, *oprev = NULL;
3022 for (j=0,on=oi->oi_list; on; j++,on=on->on_next) {
3024 rdn.bv_len = sprintf(rdn.bv_val, "%s={%0x}%s",
3025 cfAd_overlay->ad_cname.bv_val, j, on->on_bi.bi_type );
3026 oe = config_alloc_entry( &e->e_nname, &rdn );
3032 config_build_entry( &c, oe, cfOc_overlay, &rdn, ct, BI_TABLE );
3034 op->o_bd->be_add( op, &rs );
3035 if ( !opar->ce_kids ) {
3038 oprev->ce_sibs = ce;
3049 config_back_db_destroy( Backend *be )
3051 free( be->be_private );
3056 config_back_db_init( Backend *be )
3061 cfb = ch_calloc( 1, sizeof(CfBackInfo));
3062 cfb->cb_config = &cf_prv;
3063 be->be_private = cfb;
3065 ber_dupbv( &be->be_rootdn, &config_rdn );
3066 ber_dupbv( &be->be_rootndn, &be->be_rootdn );
3067 ber_dupbv( &dn, &be->be_rootdn );
3068 ber_bvarray_add( &be->be_suffix, &dn );
3069 ber_dupbv( &dn, &be->be_rootdn );
3070 ber_bvarray_add( &be->be_nsuffix, &dn );
3072 /* Hide from namingContexts */
3073 SLAP_BFLAGS(be) |= SLAP_BFLAG_CONFIG;
3080 AttributeDescription **desc;
3081 AttributeDescription *sub;
3083 { "attribute", NULL, NULL },
3084 { "backend", &cfAd_backend, NULL },
3085 { "database", &cfAd_database, NULL },
3086 { "ditcontentrule", NULL, NULL },
3087 { "include", &cfAd_include, NULL },
3088 { "objectclass", NULL, NULL },
3089 { "overlay", &cfAd_overlay, NULL },
3090 { NULL, NULL, NULL }
3094 config_back_initialize( BackendInfo *bi )
3096 ConfigTable *ct = config_back_cf_table;
3105 bi->bi_db_init = config_back_db_init;
3106 bi->bi_db_config = 0;
3107 bi->bi_db_open = config_back_db_open;
3108 bi->bi_db_close = 0;
3109 bi->bi_db_destroy = config_back_db_destroy;
3111 bi->bi_op_bind = config_back_bind;
3112 bi->bi_op_unbind = 0;
3113 bi->bi_op_search = config_back_search;
3114 bi->bi_op_compare = 0;
3115 bi->bi_op_modify = config_back_modify;
3116 bi->bi_op_modrdn = 0;
3118 bi->bi_op_delete = 0;
3119 bi->bi_op_abandon = 0;
3121 bi->bi_extended = 0;
3123 bi->bi_chk_referrals = 0;
3125 bi->bi_connection_init = 0;
3126 bi->bi_connection_destroy = 0;
3129 for (i=0; OidMacros[i].name; i++ ) {
3130 argv[1] = OidMacros[i].name;
3131 argv[2] = OidMacros[i].oid;
3132 parse_oidm( "slapd", i, 3, argv );
3135 i = init_config_attrs( ct );
3138 /* set up the notable AttributeDescriptions */
3139 ads[0].sub = slap_schema.si_ad_attributeTypes;
3140 ads[3].sub = slap_schema.si_ad_ditContentRules;
3141 ads[5].sub = slap_schema.si_ad_objectClasses;
3143 bi->bi_cf_table = ct;
3146 for (;ct->name;ct++) {
3147 if (strcmp(ct->name, ads[i].name)) continue;
3149 ct->ad = ads[i].sub;
3151 *ads[i].desc = ct->ad;
3154 if (!ads[i].name) break;
3157 /* set up the objectclasses */
3158 i = init_config_ocs( cf_ocs );