1 /* bconfig.c - the config backend */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/bconfig.c,v 1.202.2.37 2008/07/09 23:52:27 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2005-2008 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 #define CONFIG_RDN "cn=config"
41 #define SCHEMA_RDN "cn=schema"
43 static struct berval config_rdn
= BER_BVC(CONFIG_RDN
);
44 static struct berval schema_rdn
= BER_BVC(SCHEMA_RDN
);
46 extern int slap_DN_strict
; /* dn.c */
49 typedef struct modpath_s
{
50 struct modpath_s
*mp_next
;
51 struct berval mp_path
;
55 static ModPaths modpaths
, *modlast
= &modpaths
, *modcur
= &modpaths
;
58 typedef struct ConfigFile
{
59 struct ConfigFile
*c_sibs
;
60 struct ConfigFile
*c_kids
;
62 AttributeType
*c_at_head
, *c_at_tail
;
63 ContentRule
*c_cr_head
, *c_cr_tail
;
64 ObjectClass
*c_oc_head
, *c_oc_tail
;
65 OidMacro
*c_om_head
, *c_om_tail
;
70 ConfigFile
*cb_config
;
72 BackendDB cb_db
; /* underlying database */
77 static CfBackInfo cfBackInfo
;
79 static char *passwd_salt
;
81 static char *logfileName
;
82 #ifdef SLAP_AUTH_REWRITE
83 static BerVarray authz_rewrites
;
86 static struct berval cfdir
;
89 static AttributeDescription
*cfAd_backend
, *cfAd_database
, *cfAd_overlay
,
90 *cfAd_include
, *cfAd_attr
, *cfAd_oc
, *cfAd_om
;
92 static ConfigFile
*cfn
;
94 static Avlnode
*CfOcTree
;
96 /* System schema state */
97 extern AttributeType
*at_sys_tail
; /* at.c */
98 extern ObjectClass
*oc_sys_tail
; /* oc.c */
99 extern OidMacro
*om_sys_tail
; /* oidm.c */
100 static AttributeType
*cf_at_tail
;
101 static ObjectClass
*cf_oc_tail
;
102 static OidMacro
*cf_om_tail
;
104 static int config_add_internal( CfBackInfo
*cfb
, Entry
*e
, ConfigArgs
*ca
,
105 SlapReply
*rs
, int *renumber
, Operation
*op
);
107 static int config_check_schema( Operation
*op
, CfBackInfo
*cfb
);
109 static ConfigDriver config_fname
;
110 static ConfigDriver config_cfdir
;
111 static ConfigDriver config_generic
;
112 static ConfigDriver config_search_base
;
113 static ConfigDriver config_passwd_hash
;
114 static ConfigDriver config_schema_dn
;
115 static ConfigDriver config_sizelimit
;
116 static ConfigDriver config_timelimit
;
117 static ConfigDriver config_overlay
;
118 static ConfigDriver config_subordinate
;
119 static ConfigDriver config_suffix
;
120 static ConfigDriver config_rootdn
;
121 static ConfigDriver config_rootpw
;
122 static ConfigDriver config_restrict
;
123 static ConfigDriver config_allows
;
124 static ConfigDriver config_disallows
;
125 static ConfigDriver config_requires
;
126 static ConfigDriver config_security
;
127 static ConfigDriver config_referral
;
128 static ConfigDriver config_loglevel
;
129 static ConfigDriver config_updatedn
;
130 static ConfigDriver config_updateref
;
131 static ConfigDriver config_include
;
132 static ConfigDriver config_obsolete
;
134 static ConfigDriver config_tls_option
;
135 static ConfigDriver config_tls_config
;
137 extern ConfigDriver syncrepl_config
;
191 static OidRec OidMacros
[] = {
192 /* OpenLDAProot:1.12.2 */
193 { "OLcfg", "1.3.6.1.4.1.4203.1.12.2" },
194 { "OLcfgAt", "OLcfg:3" },
195 { "OLcfgGlAt", "OLcfgAt:0" },
196 { "OLcfgBkAt", "OLcfgAt:1" },
197 { "OLcfgDbAt", "OLcfgAt:2" },
198 { "OLcfgOvAt", "OLcfgAt:3" },
199 { "OLcfgCtAt", "OLcfgAt:4" }, /* contrib modules */
200 { "OLcfgOc", "OLcfg:4" },
201 { "OLcfgGlOc", "OLcfgOc:0" },
202 { "OLcfgBkOc", "OLcfgOc:1" },
203 { "OLcfgDbOc", "OLcfgOc:2" },
204 { "OLcfgOvOc", "OLcfgOc:3" },
205 { "OLcfgCtOc", "OLcfgOc:4" }, /* contrib modules */
207 /* Syntaxes. We should just start using the standard names and
208 * document that they are predefined and available for users
209 * to reference in their own schema. Defining schema without
210 * OID macros is for masochists...
212 { "OMsyn", "1.3.6.1.4.1.1466.115.121.1" },
213 { "OMsBoolean", "OMsyn:7" },
214 { "OMsDN", "OMsyn:12" },
215 { "OMsDirectoryString", "OMsyn:15" },
216 { "OMsIA5String", "OMsyn:26" },
217 { "OMsInteger", "OMsyn:27" },
218 { "OMsOID", "OMsyn:38" },
219 { "OMsOctetString", "OMsyn:40" },
224 * Backend/Database registry
226 * OLcfg{Bk|Db}{Oc|At}:0 -> common
227 * OLcfg{Bk|Db}{Oc|At}:1 -> back-bdb(/back-hdb)
228 * OLcfg{Bk|Db}{Oc|At}:2 -> back-ldif
229 * OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap
230 * OLcfg{Bk|Db}{Oc|At}:4 -> back-monitor
231 * OLcfg{Bk|Db}{Oc|At}:5 -> back-relay
232 * OLcfg{Bk|Db}{Oc|At}:6 -> back-sql
233 * OLcfg{Bk|Db}{Oc|At}:7 -> back-sock
239 * OLcfgOv{Oc|At}:1 -> syncprov
240 * OLcfgOv{Oc|At}:2 -> pcache
241 * OLcfgOv{Oc|At}:3 -> chain
242 * OLcfgOv{Oc|At}:4 -> accesslog
243 * OLcfgOv{Oc|At}:5 -> valsort
244 * OLcfgOv{Oc|At}:7 -> distproc
245 * OLcfgOv{Oc|At}:8 -> dynlist
246 * OLcfgOv{Oc|At}:9 -> dds
247 * OLcfgOv{Oc|At}:10 -> unique
248 * OLcfgOv{Oc|At}:11 -> refint
249 * OLcfgOv{Oc|At}:12 -> ppolicy
250 * OLcfgOv{Oc|At}:13 -> constraint
251 * OLcfgOv{Oc|At}:14 -> translucent
252 * OLcfgOv{Oc|At}:15 -> auditlog
253 * OLcfgOv{Oc|At}:16 -> rwm
254 * OLcfgOv{Oc|At}:17 -> dyngroup
255 * OLcfgOv{Oc|At}:18 -> memberof
256 * OLcfgOv{Oc|At}:19 -> collect
259 /* alphabetical ordering */
261 static ConfigTable config_back_cf_table
[] = {
262 /* This attr is read-only */
263 { "", "", 0, 0, 0, ARG_MAGIC
,
264 &config_fname
, "( OLcfgGlAt:78 NAME 'olcConfigFile' "
265 "DESC 'File for slapd configuration directives' "
266 "EQUALITY caseIgnoreMatch "
267 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
268 { "", "", 0, 0, 0, ARG_MAGIC
,
269 &config_cfdir
, "( OLcfgGlAt:79 NAME 'olcConfigDir' "
270 "DESC 'Directory for slapd configuration backend' "
271 "EQUALITY caseIgnoreMatch "
272 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
273 { "access", NULL
, 0, 0, 0, ARG_MAY_DB
|ARG_MAGIC
|CFG_ACL
,
274 &config_generic
, "( OLcfgGlAt:1 NAME 'olcAccess' "
275 "DESC 'Access Control List' "
276 "EQUALITY caseIgnoreMatch "
277 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL
, NULL
},
278 { "allows", "features", 2, 0, 5, ARG_PRE_DB
|ARG_MAGIC
,
279 &config_allows
, "( OLcfgGlAt:2 NAME 'olcAllows' "
280 "DESC 'Allowed set of deprecated features' "
281 "EQUALITY caseIgnoreMatch "
282 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
283 { "argsfile", "file", 2, 2, 0, ARG_STRING
,
284 &slapd_args_file
, "( OLcfgGlAt:3 NAME 'olcArgsFile' "
285 "DESC 'File for slapd command line options' "
286 "EQUALITY caseIgnoreMatch "
287 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
288 { "attributeoptions", NULL
, 0, 0, 0, ARG_MAGIC
|CFG_ATOPT
,
289 &config_generic
, "( OLcfgGlAt:5 NAME 'olcAttributeOptions' "
290 "EQUALITY caseIgnoreMatch "
291 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
292 { "attribute", "attribute", 2, 0, STRLENOF( "attribute" ),
293 ARG_PAREN
|ARG_MAGIC
|CFG_ATTR
,
294 &config_generic
, "( OLcfgGlAt:4 NAME 'olcAttributeTypes' "
295 "DESC 'OpenLDAP attributeTypes' "
296 "EQUALITY caseIgnoreMatch "
297 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
299 { "authid-rewrite", NULL
, 2, 0, STRLENOF( "authid-rewrite" ),
300 #ifdef SLAP_AUTH_REWRITE
301 ARG_MAGIC
|CFG_REWRITE
|ARG_NO_INSERT
, &config_generic
,
305 "( OLcfgGlAt:6 NAME 'olcAuthIDRewrite' "
306 "EQUALITY caseIgnoreMatch "
307 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL
, NULL
},
308 { "authz-policy", "policy", 2, 2, 0, ARG_STRING
|ARG_MAGIC
|CFG_AZPOLICY
,
309 &config_generic
, "( OLcfgGlAt:7 NAME 'olcAuthzPolicy' "
310 "EQUALITY caseIgnoreMatch "
311 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
312 { "authz-regexp", NULL
, 3, 3, 0, ARG_MAGIC
|CFG_AZREGEXP
|ARG_NO_INSERT
,
313 &config_generic
, "( OLcfgGlAt:8 NAME 'olcAuthzRegexp' "
314 "EQUALITY caseIgnoreMatch "
315 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL
, NULL
},
316 { "backend", "type", 2, 2, 0, ARG_PRE_DB
|ARG_MAGIC
|CFG_BACKEND
,
317 &config_generic
, "( OLcfgGlAt:9 NAME 'olcBackend' "
318 "DESC 'A type of backend' "
319 "EQUALITY caseIgnoreMatch "
320 "SYNTAX OMsDirectoryString SINGLE-VALUE X-ORDERED 'SIBLINGS' )",
322 { "concurrency", "level", 2, 2, 0, ARG_INT
|ARG_MAGIC
|CFG_CONCUR
,
323 &config_generic
, "( OLcfgGlAt:10 NAME 'olcConcurrency' "
324 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
325 { "conn_max_pending", "max", 2, 2, 0, ARG_INT
,
326 &slap_conn_max_pending
, "( OLcfgGlAt:11 NAME 'olcConnMaxPending' "
327 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
328 { "conn_max_pending_auth", "max", 2, 2, 0, ARG_INT
,
329 &slap_conn_max_pending_auth
, "( OLcfgGlAt:12 NAME 'olcConnMaxPendingAuth' "
330 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
331 { "database", "type", 2, 2, 0, ARG_MAGIC
|CFG_DATABASE
,
332 &config_generic
, "( OLcfgGlAt:13 NAME 'olcDatabase' "
333 "DESC 'The backend type for a database instance' "
334 "SUP olcBackend SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL
, NULL
},
335 { "defaultSearchBase", "dn", 2, 2, 0, ARG_PRE_BI
|ARG_PRE_DB
|ARG_DN
|ARG_QUOTE
|ARG_MAGIC
,
336 &config_search_base
, "( OLcfgGlAt:14 NAME 'olcDefaultSearchBase' "
337 "SYNTAX OMsDN SINGLE-VALUE )", NULL
, NULL
},
338 { "disallows", "features", 2, 0, 8, ARG_PRE_DB
|ARG_MAGIC
,
339 &config_disallows
, "( OLcfgGlAt:15 NAME 'olcDisallows' "
340 "EQUALITY caseIgnoreMatch "
341 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
342 { "ditcontentrule", NULL
, 0, 0, 0, ARG_MAGIC
|CFG_DIT
|ARG_NO_DELETE
|ARG_NO_INSERT
,
343 &config_generic
, "( OLcfgGlAt:16 NAME 'olcDitContentRules' "
344 "DESC 'OpenLDAP DIT content rules' "
345 "EQUALITY caseIgnoreMatch "
346 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
348 { "gentlehup", "on|off", 2, 2, 0,
350 ARG_ON_OFF
, &global_gentlehup
,
354 "( OLcfgGlAt:17 NAME 'olcGentleHUP' "
355 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL
, NULL
},
356 { "hidden", "on|off", 2, 2, 0, ARG_DB
|ARG_ON_OFF
|ARG_MAGIC
|CFG_HIDDEN
,
357 &config_generic
, "( OLcfgDbAt:0.17 NAME 'olcHidden' "
358 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL
, NULL
},
359 { "idletimeout", "timeout", 2, 2, 0, ARG_INT
,
360 &global_idletimeout
, "( OLcfgGlAt:18 NAME 'olcIdleTimeout' "
361 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
362 { "include", "file", 2, 2, 0, ARG_MAGIC
,
363 &config_include
, "( OLcfgGlAt:19 NAME 'olcInclude' "
364 "SUP labeledURI )", NULL
, NULL
},
365 { "index_substr_if_minlen", "min", 2, 2, 0, ARG_INT
|ARG_NONZERO
|ARG_MAGIC
|CFG_SSTR_IF_MIN
,
366 &config_generic
, "( OLcfgGlAt:20 NAME 'olcIndexSubstrIfMinLen' "
367 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
368 { "index_substr_if_maxlen", "max", 2, 2, 0, ARG_INT
|ARG_NONZERO
|ARG_MAGIC
|CFG_SSTR_IF_MAX
,
369 &config_generic
, "( OLcfgGlAt:21 NAME 'olcIndexSubstrIfMaxLen' "
370 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
371 { "index_substr_any_len", "len", 2, 2, 0, ARG_INT
|ARG_NONZERO
,
372 &index_substr_any_len
, "( OLcfgGlAt:22 NAME 'olcIndexSubstrAnyLen' "
373 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
374 { "index_substr_any_step", "step", 2, 2, 0, ARG_INT
|ARG_NONZERO
,
375 &index_substr_any_step
, "( OLcfgGlAt:23 NAME 'olcIndexSubstrAnyStep' "
376 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
377 { "index_intlen", "len", 2, 2, 0, ARG_INT
|ARG_MAGIC
|CFG_IX_INTLEN
,
378 &config_generic
, "( OLcfgGlAt:84 NAME 'olcIndexIntLen' "
379 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
380 { "lastmod", "on|off", 2, 2, 0, ARG_DB
|ARG_ON_OFF
|ARG_MAGIC
|CFG_LASTMOD
,
381 &config_generic
, "( OLcfgDbAt:0.4 NAME 'olcLastMod' "
382 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL
, NULL
},
383 { "limits", "limits", 2, 0, 0, ARG_DB
|ARG_MAGIC
|CFG_LIMITS
,
384 &config_generic
, "( OLcfgDbAt:0.5 NAME 'olcLimits' "
385 "EQUALITY caseIgnoreMatch "
386 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL
, NULL
},
387 { "localSSF", "ssf", 2, 2, 0, ARG_INT
,
388 &local_ssf
, "( OLcfgGlAt:26 NAME 'olcLocalSSF' "
389 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
390 { "logfile", "file", 2, 2, 0, ARG_STRING
|ARG_MAGIC
|CFG_LOGFILE
,
391 &config_generic
, "( OLcfgGlAt:27 NAME 'olcLogFile' "
392 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
393 { "loglevel", "level", 2, 0, 0, ARG_MAGIC
,
394 &config_loglevel
, "( OLcfgGlAt:28 NAME 'olcLogLevel' "
395 "EQUALITY caseIgnoreMatch "
396 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
397 { "maxDerefDepth", "depth", 2, 2, 0, ARG_DB
|ARG_INT
|ARG_MAGIC
|CFG_DEPTH
,
398 &config_generic
, "( OLcfgDbAt:0.6 NAME 'olcMaxDerefDepth' "
399 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
400 { "mirrormode", "on|off", 2, 2, 0, ARG_DB
|ARG_ON_OFF
|ARG_MAGIC
|CFG_MIRRORMODE
,
401 &config_generic
, "( OLcfgDbAt:0.16 NAME 'olcMirrorMode' "
402 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL
, NULL
},
403 { "moduleload", "file", 2, 0, 0,
405 ARG_MAGIC
|CFG_MODLOAD
|ARG_NO_DELETE
, &config_generic
,
409 "( OLcfgGlAt:30 NAME 'olcModuleLoad' "
410 "EQUALITY caseIgnoreMatch "
411 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL
, NULL
},
412 { "modulepath", "path", 2, 2, 0,
414 ARG_MAGIC
|CFG_MODPATH
|ARG_NO_DELETE
|ARG_NO_INSERT
, &config_generic
,
418 "( OLcfgGlAt:31 NAME 'olcModulePath' "
419 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
420 { "monitoring", "TRUE|FALSE", 2, 2, 0,
421 ARG_MAGIC
|CFG_MONITORING
|ARG_DB
|ARG_ON_OFF
, &config_generic
,
422 "( OLcfgDbAt:0.18 NAME 'olcMonitoring' "
423 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL
, NULL
},
424 { "objectclass", "objectclass", 2, 0, 0, ARG_PAREN
|ARG_MAGIC
|CFG_OC
,
425 &config_generic
, "( OLcfgGlAt:32 NAME 'olcObjectClasses' "
426 "DESC 'OpenLDAP object classes' "
427 "EQUALITY caseIgnoreMatch "
428 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
430 { "objectidentifier", "name> <oid", 3, 3, 0, ARG_MAGIC
|CFG_OID
,
431 &config_generic
, "( OLcfgGlAt:33 NAME 'olcObjectIdentifier' "
432 "EQUALITY caseIgnoreMatch "
433 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL
, NULL
},
434 { "overlay", "overlay", 2, 2, 0, ARG_MAGIC
,
435 &config_overlay
, "( OLcfgGlAt:34 NAME 'olcOverlay' "
436 "SUP olcDatabase SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL
, NULL
},
437 { "password-crypt-salt-format", "salt", 2, 2, 0, ARG_STRING
|ARG_MAGIC
|CFG_SALT
,
438 &config_generic
, "( OLcfgGlAt:35 NAME 'olcPasswordCryptSaltFormat' "
439 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
440 { "password-hash", "hash", 2, 2, 0, ARG_MAGIC
,
441 &config_passwd_hash
, "( OLcfgGlAt:36 NAME 'olcPasswordHash' "
442 "EQUALITY caseIgnoreMatch "
443 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
444 { "pidfile", "file", 2, 2, 0, ARG_STRING
,
445 &slapd_pid_file
, "( OLcfgGlAt:37 NAME 'olcPidFile' "
446 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
447 { "plugin", NULL
, 0, 0, 0,
449 ARG_MAGIC
|CFG_PLUGIN
, &config_generic
,
453 "( OLcfgGlAt:38 NAME 'olcPlugin' "
454 "EQUALITY caseIgnoreMatch "
455 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
456 { "pluginlog", "filename", 2, 2, 0,
458 ARG_STRING
, &slapi_log_file
,
462 "( OLcfgGlAt:39 NAME 'olcPluginLogFile' "
463 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
464 { "readonly", "on|off", 2, 2, 0, ARG_MAY_DB
|ARG_ON_OFF
|ARG_MAGIC
|CFG_RO
,
465 &config_generic
, "( OLcfgGlAt:40 NAME 'olcReadOnly' "
466 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL
, NULL
},
467 { "referral", "url", 2, 2, 0, ARG_MAGIC
,
468 &config_referral
, "( OLcfgGlAt:41 NAME 'olcReferral' "
469 "SUP labeledURI SINGLE-VALUE )", NULL
, NULL
},
470 { "replica", "host or uri", 2, 0, 0, ARG_DB
|ARG_MAGIC
,
471 &config_obsolete
, "( OLcfgDbAt:0.7 NAME 'olcReplica' "
472 "EQUALITY caseIgnoreMatch "
473 "SUP labeledURI X-ORDERED 'VALUES' )", NULL
, NULL
},
474 { "replica-argsfile", NULL
, 0, 0, 0, ARG_MAY_DB
|ARG_MAGIC
,
475 &config_obsolete
, "( OLcfgGlAt:43 NAME 'olcReplicaArgsFile' "
476 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
477 { "replica-pidfile", NULL
, 0, 0, 0, ARG_MAY_DB
|ARG_MAGIC
,
478 &config_obsolete
, "( OLcfgGlAt:44 NAME 'olcReplicaPidFile' "
479 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
480 { "replicationInterval", NULL
, 0, 0, 0, ARG_MAY_DB
|ARG_MAGIC
,
481 &config_obsolete
, "( OLcfgGlAt:45 NAME 'olcReplicationInterval' "
482 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
483 { "replogfile", "filename", 2, 2, 0, ARG_MAY_DB
|ARG_MAGIC
,
484 &config_obsolete
, "( OLcfgGlAt:46 NAME 'olcReplogFile' "
485 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
486 { "require", "features", 2, 0, 7, ARG_MAY_DB
|ARG_MAGIC
,
487 &config_requires
, "( OLcfgGlAt:47 NAME 'olcRequires' "
488 "EQUALITY caseIgnoreMatch "
489 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
490 { "restrict", "op_list", 2, 0, 0, ARG_MAY_DB
|ARG_MAGIC
,
491 &config_restrict
, "( OLcfgGlAt:48 NAME 'olcRestrict' "
492 "EQUALITY caseIgnoreMatch "
493 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
494 { "reverse-lookup", "on|off", 2, 2, 0,
495 #ifdef SLAPD_RLOOKUPS
496 ARG_ON_OFF
, &use_reverse_lookup
,
500 "( OLcfgGlAt:49 NAME 'olcReverseLookup' "
501 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL
, NULL
},
502 { "rootdn", "dn", 2, 2, 0, ARG_DB
|ARG_DN
|ARG_QUOTE
|ARG_MAGIC
,
503 &config_rootdn
, "( OLcfgDbAt:0.8 NAME 'olcRootDN' "
504 "EQUALITY distinguishedNameMatch "
505 "SYNTAX OMsDN SINGLE-VALUE )", NULL
, NULL
},
506 { "rootDSE", "file", 2, 2, 0, ARG_MAGIC
|CFG_ROOTDSE
,
507 &config_generic
, "( OLcfgGlAt:51 NAME 'olcRootDSE' "
508 "EQUALITY caseIgnoreMatch "
509 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
510 { "rootpw", "password", 2, 2, 0, ARG_BERVAL
|ARG_DB
|ARG_MAGIC
,
511 &config_rootpw
, "( OLcfgDbAt:0.9 NAME 'olcRootPW' "
512 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
513 { "sasl-authz-policy", NULL
, 2, 2, 0, ARG_MAGIC
|CFG_AZPOLICY
,
514 &config_generic
, NULL
, NULL
, NULL
},
515 { "sasl-host", "host", 2, 2, 0,
516 #ifdef HAVE_CYRUS_SASL
517 ARG_STRING
|ARG_UNIQUE
, &sasl_host
,
521 "( OLcfgGlAt:53 NAME 'olcSaslHost' "
522 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
523 { "sasl-realm", "realm", 2, 2, 0,
524 #ifdef HAVE_CYRUS_SASL
525 ARG_STRING
|ARG_UNIQUE
, &global_realm
,
529 "( OLcfgGlAt:54 NAME 'olcSaslRealm' "
530 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
531 { "sasl-regexp", NULL
, 3, 3, 0, ARG_MAGIC
|CFG_AZREGEXP
,
532 &config_generic
, NULL
, NULL
, NULL
},
533 { "sasl-secprops", "properties", 2, 2, 0,
534 #ifdef HAVE_CYRUS_SASL
535 ARG_MAGIC
|CFG_SASLSECP
, &config_generic
,
539 "( OLcfgGlAt:56 NAME 'olcSaslSecProps' "
540 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
541 { "saslRegexp", NULL
, 3, 3, 0, ARG_MAGIC
|CFG_AZREGEXP
,
542 &config_generic
, NULL
, NULL
, NULL
},
543 { "schemadn", "dn", 2, 2, 0, ARG_MAY_DB
|ARG_DN
|ARG_QUOTE
|ARG_MAGIC
,
544 &config_schema_dn
, "( OLcfgGlAt:58 NAME 'olcSchemaDN' "
545 "EQUALITY distinguishedNameMatch "
546 "SYNTAX OMsDN SINGLE-VALUE )", NULL
, NULL
},
547 { "security", "factors", 2, 0, 0, ARG_MAY_DB
|ARG_MAGIC
,
548 &config_security
, "( OLcfgGlAt:59 NAME 'olcSecurity' "
549 "EQUALITY caseIgnoreMatch "
550 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
551 { "serverID", "number> <[URI]", 2, 3, 0, ARG_MAGIC
|CFG_SERVERID
,
552 &config_generic
, "( OLcfgGlAt:81 NAME 'olcServerID' "
553 "EQUALITY caseIgnoreMatch "
554 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
555 { "sizelimit", "limit", 2, 0, 0, ARG_MAY_DB
|ARG_MAGIC
,
556 &config_sizelimit
, "( OLcfgGlAt:60 NAME 'olcSizeLimit' "
557 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
558 { "sockbuf_max_incoming", "max", 2, 2, 0, ARG_BER_LEN_T
,
559 &sockbuf_max_incoming
, "( OLcfgGlAt:61 NAME 'olcSockbufMaxIncoming' "
560 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
561 { "sockbuf_max_incoming_auth", "max", 2, 2, 0, ARG_BER_LEN_T
,
562 &sockbuf_max_incoming_auth
, "( OLcfgGlAt:62 NAME 'olcSockbufMaxIncomingAuth' "
563 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
564 { "sortvals", "attr", 2, 0, 0, ARG_MAGIC
|CFG_SORTVALS
,
565 &config_generic
, "( OLcfgGlAt:83 NAME 'olcSortVals' "
566 "DESC 'Attributes whose values will always be sorted' "
567 "EQUALITY caseIgnoreMatch "
568 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
569 { "subordinate", "[advertise]", 1, 2, 0, ARG_DB
|ARG_MAGIC
,
570 &config_subordinate
, "( OLcfgDbAt:0.15 NAME 'olcSubordinate' "
571 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
572 { "suffix", "suffix", 2, 2, 0, ARG_DB
|ARG_DN
|ARG_QUOTE
|ARG_MAGIC
,
573 &config_suffix
, "( OLcfgDbAt:0.10 NAME 'olcSuffix' "
574 "EQUALITY distinguishedNameMatch "
575 "SYNTAX OMsDN )", NULL
, NULL
},
576 { "syncrepl", NULL
, 0, 0, 0, ARG_DB
|ARG_MAGIC
,
577 &syncrepl_config
, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
578 "EQUALITY caseIgnoreMatch "
579 "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL
, NULL
},
580 { "threads", "count", 2, 2, 0,
584 ARG_INT
|ARG_MAGIC
|CFG_THREADS
, &config_generic
,
586 "( OLcfgGlAt:66 NAME 'olcThreads' "
587 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
588 { "timelimit", "limit", 2, 0, 0, ARG_MAY_DB
|ARG_MAGIC
,
589 &config_timelimit
, "( OLcfgGlAt:67 NAME 'olcTimeLimit' "
590 "SYNTAX OMsDirectoryString )", NULL
, NULL
},
591 { "TLSCACertificateFile", NULL
, 0, 0, 0,
593 CFG_TLS_CA_FILE
|ARG_STRING
|ARG_MAGIC
, &config_tls_option
,
597 "( OLcfgGlAt:68 NAME 'olcTLSCACertificateFile' "
598 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
599 { "TLSCACertificatePath", NULL
, 0, 0, 0,
601 CFG_TLS_CA_PATH
|ARG_STRING
|ARG_MAGIC
, &config_tls_option
,
605 "( OLcfgGlAt:69 NAME 'olcTLSCACertificatePath' "
606 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
607 { "TLSCertificateFile", NULL
, 0, 0, 0,
609 CFG_TLS_CERT_FILE
|ARG_STRING
|ARG_MAGIC
, &config_tls_option
,
613 "( OLcfgGlAt:70 NAME 'olcTLSCertificateFile' "
614 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
615 { "TLSCertificateKeyFile", NULL
, 0, 0, 0,
617 CFG_TLS_CERT_KEY
|ARG_STRING
|ARG_MAGIC
, &config_tls_option
,
621 "( OLcfgGlAt:71 NAME 'olcTLSCertificateKeyFile' "
622 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
623 { "TLSCipherSuite", NULL
, 0, 0, 0,
625 CFG_TLS_CIPHER
|ARG_STRING
|ARG_MAGIC
, &config_tls_option
,
629 "( OLcfgGlAt:72 NAME 'olcTLSCipherSuite' "
630 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
631 { "TLSCRLCheck", NULL
, 0, 0, 0,
632 #if defined(HAVE_TLS) && defined(HAVE_OPENSSL_CRL)
633 CFG_TLS_CRLCHECK
|ARG_STRING
|ARG_MAGIC
, &config_tls_config
,
637 "( OLcfgGlAt:73 NAME 'olcTLSCRLCheck' "
638 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
639 { "TLSCRLFile", NULL
, 0, 0, 0,
640 #if defined(HAVE_GNUTLS)
641 CFG_TLS_CRL_FILE
|ARG_STRING
|ARG_MAGIC
, &config_tls_option
,
645 "( OLcfgGlAt:82 NAME 'olcTLSCRLFile' "
646 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
647 { "TLSRandFile", NULL
, 0, 0, 0,
649 CFG_TLS_RAND
|ARG_STRING
|ARG_MAGIC
, &config_tls_option
,
653 "( OLcfgGlAt:74 NAME 'olcTLSRandFile' "
654 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
655 { "TLSVerifyClient", NULL
, 0, 0, 0,
657 CFG_TLS_VERIFY
|ARG_STRING
|ARG_MAGIC
, &config_tls_config
,
661 "( OLcfgGlAt:75 NAME 'olcTLSVerifyClient' "
662 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
663 { "TLSDHParamFile", NULL
, 0, 0, 0,
665 CFG_TLS_DH_FILE
|ARG_STRING
|ARG_MAGIC
, &config_tls_option
,
669 "( OLcfgGlAt:77 NAME 'olcTLSDHParamFile' "
670 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL
, NULL
},
671 { "tool-threads", "count", 2, 2, 0, ARG_INT
|ARG_MAGIC
|CFG_TTHREADS
,
672 &config_generic
, "( OLcfgGlAt:80 NAME 'olcToolThreads' "
673 "SYNTAX OMsInteger SINGLE-VALUE )", NULL
, NULL
},
674 { "ucdata-path", "path", 2, 2, 0, ARG_IGNORED
,
675 NULL
, NULL
, NULL
, NULL
},
676 { "updatedn", "dn", 2, 2, 0, ARG_DB
|ARG_DN
|ARG_QUOTE
|ARG_MAGIC
,
677 &config_updatedn
, "( OLcfgDbAt:0.12 NAME 'olcUpdateDN' "
678 "SYNTAX OMsDN SINGLE-VALUE )", NULL
, NULL
},
679 { "updateref", "url", 2, 2, 0, ARG_DB
|ARG_MAGIC
,
680 &config_updateref
, "( OLcfgDbAt:0.13 NAME 'olcUpdateRef' "
681 "EQUALITY caseIgnoreMatch "
682 "SUP labeledURI )", NULL
, NULL
},
683 { NULL
, NULL
, 0, 0, 0, ARG_IGNORED
,
684 NULL
, NULL
, NULL
, NULL
}
687 /* Routines to check if a child can be added to this type */
688 static ConfigLDAPadd cfAddSchema
, cfAddInclude
, cfAddDatabase
,
689 cfAddBackend
, cfAddModule
, cfAddOverlay
;
691 /* NOTE: be careful when defining array members
692 * that can be conditionally compiled */
693 #define CFOC_GLOBAL cf_ocs[1]
694 #define CFOC_SCHEMA cf_ocs[2]
695 #define CFOC_BACKEND cf_ocs[3]
696 #define CFOC_DATABASE cf_ocs[4]
697 #define CFOC_OVERLAY cf_ocs[5]
698 #define CFOC_INCLUDE cf_ocs[6]
699 #define CFOC_FRONTEND cf_ocs[7]
701 #define CFOC_MODULE cf_ocs[8]
702 #endif /* SLAPD_MODULES */
704 static ConfigOCs cf_ocs
[] = {
707 "DESC 'OpenLDAP configuration object' "
708 "ABSTRACT SUP top )", Cft_Abstract
, NULL
},
711 "DESC 'OpenLDAP Global configuration options' "
712 "SUP olcConfig STRUCTURAL "
713 "MAY ( cn $ olcConfigFile $ olcConfigDir $ olcAllows $ olcArgsFile $ "
714 "olcAttributeOptions $ olcAuthIDRewrite $ "
715 "olcAuthzPolicy $ olcAuthzRegexp $ olcConcurrency $ "
716 "olcConnMaxPending $ olcConnMaxPendingAuth $ "
717 "olcDisallows $ olcGentleHUP $ olcIdleTimeout $ "
718 "olcIndexSubstrIfMaxLen $ olcIndexSubstrIfMinLen $ "
719 "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcIndexIntLen $ "
720 "olcLocalSSF $ olcLogLevel $ "
721 "olcPasswordCryptSaltFormat $ olcPasswordHash $ olcPidFile $ "
722 "olcPluginLogFile $ olcReadOnly $ olcReferral $ "
723 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
725 "olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
726 "olcSecurity $ olcServerID $ olcSizeLimit $ "
727 "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ "
728 "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
729 "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
730 "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
731 "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ "
732 "olcTLSCRLFile $ olcToolThreads $ "
733 "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ "
734 "olcDitContentRules ) )", Cft_Global
},
736 "NAME 'olcSchemaConfig' "
737 "DESC 'OpenLDAP schema object' "
738 "SUP olcConfig STRUCTURAL "
739 "MAY ( cn $ olcObjectIdentifier $ olcAttributeTypes $ "
740 "olcObjectClasses $ olcDitContentRules ) )",
741 Cft_Schema
, NULL
, cfAddSchema
},
743 "NAME 'olcBackendConfig' "
744 "DESC 'OpenLDAP Backend-specific options' "
745 "SUP olcConfig STRUCTURAL "
746 "MUST olcBackend )", Cft_Backend
, NULL
, cfAddBackend
},
748 "NAME 'olcDatabaseConfig' "
749 "DESC 'OpenLDAP Database-specific options' "
750 "SUP olcConfig STRUCTURAL "
752 "MAY ( olcHidden $ olcSuffix $ olcSubordinate $ olcAccess $ "
753 "olcLastMod $ olcLimits $ "
754 "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
755 "olcReplicaArgsFile $ olcReplicaPidFile $ olcReplicationInterval $ "
756 "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
757 "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncrepl $ "
758 "olcTimeLimit $ olcUpdateDN $ olcUpdateRef $ olcMirrorMode $ "
760 Cft_Database
, NULL
, cfAddDatabase
},
762 "NAME 'olcOverlayConfig' "
763 "DESC 'OpenLDAP Overlay-specific options' "
764 "SUP olcConfig STRUCTURAL "
765 "MUST olcOverlay )", Cft_Overlay
, NULL
, cfAddOverlay
},
767 "NAME 'olcIncludeFile' "
768 "DESC 'OpenLDAP configuration include file' "
769 "SUP olcConfig STRUCTURAL "
771 "MAY ( cn $ olcRootDSE ) )",
772 /* Used to be Cft_Include, that def has been removed */
773 Cft_Abstract
, NULL
, cfAddInclude
},
774 /* This should be STRUCTURAL like all the other database classes, but
775 * that would mean inheriting all of the olcDatabaseConfig attributes,
776 * which causes them to be merged twice in config_build_entry.
779 "NAME 'olcFrontendConfig' "
780 "DESC 'OpenLDAP frontend configuration' "
782 "MAY ( olcDefaultSearchBase $ olcPasswordHash $ olcSortVals ) )",
783 Cft_Database
, NULL
, NULL
},
786 "NAME 'olcModuleList' "
787 "DESC 'OpenLDAP dynamic module info' "
788 "SUP olcConfig STRUCTURAL "
789 "MAY ( cn $ olcModulePath $ olcModuleLoad ) )",
790 Cft_Module
, NULL
, cfAddModule
},
795 typedef struct ServerID
{
796 struct ServerID
*si_next
;
797 struct berval si_url
;
801 static ServerID
*sid_list
;
803 typedef struct voidList
{
804 struct voidList
*vl_next
;
808 typedef struct ADlist
{
809 struct ADlist
*al_next
;
810 AttributeDescription
*al_desc
;
813 static ADlist
*sortVals
;
816 config_generic(ConfigArgs
*c
) {
819 if ( c
->op
== SLAP_CONFIG_EMIT
) {
823 c
->value_int
= ldap_pvt_thread_get_concurrency();
826 c
->value_int
= connection_pool_max
;
829 c
->value_int
= slap_tool_thread_max
;
833 c
->value_string
= ch_strdup( passwd_salt
);
838 if ( c
->be
->be_limits
) {
842 for ( i
=0; c
->be
->be_limits
[i
]; i
++ ) {
843 bv
.bv_len
= snprintf( buf
, sizeof( buf
), SLAP_X_ORDERED_FMT
, i
);
844 if ( bv
.bv_len
>= sizeof( buf
) ) {
845 ber_bvarray_free_x( c
->rvalue_vals
, NULL
);
846 c
->rvalue_vals
= NULL
;
850 bv
.bv_val
= buf
+ bv
.bv_len
;
851 limits_unparse( c
->be
->be_limits
[i
], &bv
,
852 sizeof( buf
) - ( bv
.bv_val
- buf
) );
853 bv
.bv_len
+= bv
.bv_val
- buf
;
855 value_add_one( &c
->rvalue_vals
, &bv
);
858 if ( !c
->rvalue_vals
) rc
= 1;
861 c
->value_int
= (c
->be
->be_restrictops
& SLAP_RESTRICT_OP_WRITES
) ==
862 SLAP_RESTRICT_OP_WRITES
;
865 c
->value_string
= ch_strdup( slap_sasl_getpolicy());
868 slap_sasl_regexp_unparse( &c
->rvalue_vals
);
869 if ( !c
->rvalue_vals
) rc
= 1;
871 #ifdef HAVE_CYRUS_SASL
873 struct berval bv
= BER_BVNULL
;
874 slap_sasl_secprops_unparse( &bv
);
875 if ( !BER_BVISNULL( &bv
)) {
876 ber_bvarray_add( &c
->rvalue_vals
, &bv
);
884 c
->value_int
= c
->be
->be_max_deref_depth
;
887 if ( SLAP_DBHIDDEN( c
->be
)) {
894 ConfigFile
*cf
= c
->ca_private
;
896 oidm_unparse( &c
->rvalue_vals
, NULL
, NULL
, 1 );
897 else if ( cf
->c_om_head
)
898 oidm_unparse( &c
->rvalue_vals
, cf
->c_om_head
,
900 if ( !c
->rvalue_vals
)
905 ad_unparse_options( &c
->rvalue_vals
);
908 ConfigFile
*cf
= c
->ca_private
;
910 oc_unparse( &c
->rvalue_vals
, NULL
, NULL
, 1 );
911 else if ( cf
->c_oc_head
)
912 oc_unparse( &c
->rvalue_vals
, cf
->c_oc_head
,
914 if ( !c
->rvalue_vals
)
919 ConfigFile
*cf
= c
->ca_private
;
921 at_unparse( &c
->rvalue_vals
, NULL
, NULL
, 1 );
922 else if ( cf
->c_at_head
)
923 at_unparse( &c
->rvalue_vals
, cf
->c_at_head
,
925 if ( !c
->rvalue_vals
)
930 ConfigFile
*cf
= c
->ca_private
;
932 cr_unparse( &c
->rvalue_vals
, NULL
, NULL
, 1 );
933 else if ( cf
->c_cr_head
)
934 cr_unparse( &c
->rvalue_vals
, cf
->c_cr_head
,
936 if ( !c
->rvalue_vals
)
943 char *src
, *dst
, ibuf
[11];
944 struct berval bv
, abv
;
946 if ( c
->be
== frontendDB
)
949 end
= frontendDB
->be_acl
;
950 for (i
=0, a
=c
->be
->be_acl
; a
&& a
!= end
; i
++,a
=a
->acl_next
) {
951 abv
.bv_len
= snprintf( ibuf
, sizeof( ibuf
), SLAP_X_ORDERED_FMT
, i
);
952 if ( abv
.bv_len
>= sizeof( ibuf
) ) {
953 ber_bvarray_free_x( c
->rvalue_vals
, NULL
);
954 c
->rvalue_vals
= NULL
;
958 acl_unparse( a
, &bv
);
959 abv
.bv_val
= ch_malloc( abv
.bv_len
+ bv
.bv_len
+ 1 );
960 AC_MEMCPY( abv
.bv_val
, ibuf
, abv
.bv_len
);
961 /* Turn TAB / EOL into plain space */
962 for (src
=bv
.bv_val
,dst
=abv
.bv_val
+abv
.bv_len
; *src
; src
++) {
963 if (isspace((unsigned char)*src
)) *dst
++ = ' ';
967 if (dst
[-1] == ' ') {
971 abv
.bv_len
= dst
- abv
.bv_val
;
972 ber_bvarray_add( &c
->rvalue_vals
, &abv
);
978 ConfigFile
*cf
= c
->ca_private
;
979 if ( cf
->c_dseFiles
) {
980 value_add( &c
->rvalue_vals
, cf
->c_dseFiles
);
991 for ( si
= sid_list
; si
; si
=si
->si_next
) {
992 assert( si
->si_num
>= 0 && si
->si_num
<= SLAP_SYNC_SID_MAX
);
993 if ( !BER_BVISEMPTY( &si
->si_url
)) {
994 bv
.bv_len
= si
->si_url
.bv_len
+ 6;
995 bv
.bv_val
= ch_malloc( bv
.bv_len
);
996 sprintf( bv
.bv_val
, "%d %s", si
->si_num
,
998 ber_bvarray_add( &c
->rvalue_vals
, &bv
);
1002 bv
.bv_len
= sprintf( buf
, "%d", si
->si_num
);
1003 value_add_one( &c
->rvalue_vals
, &bv
);
1012 c
->value_string
= ch_strdup( logfileName
);
1017 c
->value_int
= (SLAP_NOLASTMOD(c
->be
) == 0);
1019 case CFG_MIRRORMODE
:
1020 if ( SLAP_SHADOW(c
->be
))
1021 c
->value_int
= (SLAP_SINGLE_SHADOW(c
->be
) == 0);
1025 case CFG_MONITORING
:
1026 c
->value_int
= (SLAP_DBMONITORING(c
->be
) != 0);
1028 case CFG_SSTR_IF_MAX
:
1029 c
->value_int
= index_substr_if_maxlen
;
1031 case CFG_SSTR_IF_MIN
:
1032 c
->value_int
= index_substr_if_minlen
;
1035 c
->value_int
= index_intlen
;
1037 case CFG_SORTVALS
: {
1040 for ( sv
= sortVals
; sv
; sv
= sv
->al_next
) {
1041 value_add_one( &c
->rvalue_vals
, &sv
->al_desc
->ad_cname
);
1045 #ifdef SLAPD_MODULES
1047 ModPaths
*mp
= c
->ca_private
;
1050 for (i
=0; !BER_BVISNULL(&mp
->mp_loads
[i
]); i
++) {
1053 bv
.bv_len
= snprintf( bv
.bv_val
, sizeof( c
->log
),
1054 SLAP_X_ORDERED_FMT
"%s", i
,
1055 mp
->mp_loads
[i
].bv_val
);
1056 if ( bv
.bv_len
>= sizeof( c
->log
) ) {
1057 ber_bvarray_free_x( c
->rvalue_vals
, NULL
);
1058 c
->rvalue_vals
= NULL
;
1061 value_add_one( &c
->rvalue_vals
, &bv
);
1065 rc
= c
->rvalue_vals
? 0 : 1;
1069 ModPaths
*mp
= c
->ca_private
;
1070 if ( !BER_BVISNULL( &mp
->mp_path
))
1071 value_add_one( &c
->rvalue_vals
, &mp
->mp_path
);
1073 rc
= c
->rvalue_vals
? 0 : 1;
1079 slapi_int_plugin_unparse( c
->be
, &c
->rvalue_vals
);
1080 if ( !c
->rvalue_vals
) rc
= 1;
1083 #ifdef SLAP_AUTH_REWRITE
1085 if ( authz_rewrites
) {
1086 struct berval bv
, idx
;
1091 for ( i
=0; !BER_BVISNULL( &authz_rewrites
[i
] ); i
++ ) {
1092 idx
.bv_len
= snprintf( idx
.bv_val
, sizeof( ibuf
), SLAP_X_ORDERED_FMT
, i
);
1093 if ( idx
.bv_len
>= sizeof( ibuf
) ) {
1094 ber_bvarray_free_x( c
->rvalue_vals
, NULL
);
1095 c
->rvalue_vals
= NULL
;
1098 bv
.bv_len
= idx
.bv_len
+ authz_rewrites
[i
].bv_len
;
1099 bv
.bv_val
= ch_malloc( bv
.bv_len
+ 1 );
1100 AC_MEMCPY( bv
.bv_val
, idx
.bv_val
, idx
.bv_len
);
1101 AC_MEMCPY( &bv
.bv_val
[ idx
.bv_len
],
1102 authz_rewrites
[i
].bv_val
,
1103 authz_rewrites
[i
].bv_len
+ 1 );
1104 ber_bvarray_add( &c
->rvalue_vals
, &bv
);
1107 if ( !c
->rvalue_vals
) rc
= 1;
1114 } else if ( c
->op
== LDAP_MOD_DELETE
) {
1117 /* single-valued attrs, no-ops */
1125 case CFG_MIRRORMODE
:
1126 case CFG_MONITORING
:
1128 case CFG_SSTR_IF_MAX
:
1129 case CFG_SSTR_IF_MIN
:
1132 /* no-ops, requires slapd restart */
1137 snprintf(c
->log
, sizeof( c
->log
), "change requires slapd restart");
1141 ch_free( passwd_salt
);
1146 ch_free( logfileName
);
1154 case CFG_SERVERID
: {
1155 ServerID
*si
, **sip
;
1157 for ( i
=0, si
= sid_list
, sip
= &sid_list
;
1158 si
; si
= *sip
, i
++ ) {
1159 if ( c
->valx
== -1 || i
== c
->valx
) {
1171 c
->be
->be_flags
&= ~SLAP_DBFLAG_HIDDEN
;
1175 index_intlen
= SLAP_INDEX_INTLEN_DEFAULT
;
1176 index_intlen_strlen
= SLAP_INDEX_INTLEN_STRLEN(
1177 SLAP_INDEX_INTLEN_DEFAULT
);
1181 if ( c
->valx
< 0 ) {
1183 if ( c
->be
== frontendDB
)
1186 end
= frontendDB
->be_acl
;
1187 acl_destroy( c
->be
->be_acl
, end
);
1188 c
->be
->be_acl
= end
;
1191 AccessControl
**prev
, *a
;
1193 for (i
=0, prev
= &c
->be
->be_acl
; i
< c
->valx
;
1196 prev
= &a
->acl_next
;
1199 *prev
= a
->acl_next
;
1206 /* Can be NULL when undoing a failed add */
1207 if ( c
->ca_entry
) {
1208 ce
= c
->ca_entry
->e_private
;
1209 /* can't modify the hardcoded schema */
1210 if ( ce
->ce_parent
->ce_type
== Cft_Global
)
1214 cfn
= c
->ca_private
;
1215 if ( c
->valx
< 0 ) {
1218 for( oc
= cfn
->c_oc_head
; oc
; oc_next( &oc
)) {
1220 if ( oc
== cfn
->c_oc_tail
)
1223 cfn
->c_oc_head
= cfn
->c_oc_tail
= NULL
;
1225 ObjectClass
*oc
, *prev
= NULL
;
1227 for ( i
=0, oc
=cfn
->c_oc_head
; i
<c
->valx
; i
++) {
1232 if ( cfn
->c_oc_tail
== oc
) {
1233 cfn
->c_oc_tail
= prev
;
1235 if ( cfn
->c_oc_head
== oc
) {
1237 cfn
->c_oc_head
= oc
;
1244 /* Can be NULL when undoing a failed add */
1245 if ( c
->ca_entry
) {
1246 ce
= c
->ca_entry
->e_private
;
1247 /* can't modify the hardcoded schema */
1248 if ( ce
->ce_parent
->ce_type
== Cft_Global
)
1252 cfn
= c
->ca_private
;
1253 if ( c
->valx
< 0 ) {
1256 for( at
= cfn
->c_at_head
; at
; at_next( &at
)) {
1258 if ( at
== cfn
->c_at_tail
)
1261 cfn
->c_at_head
= cfn
->c_at_tail
= NULL
;
1263 AttributeType
*at
, *prev
= NULL
;
1265 for ( i
=0, at
=cfn
->c_at_head
; i
<c
->valx
; i
++) {
1270 if ( cfn
->c_at_tail
== at
) {
1271 cfn
->c_at_tail
= prev
;
1273 if ( cfn
->c_at_head
== at
) {
1275 cfn
->c_at_head
= at
;
1280 if ( c
->valx
< 0 ) {
1282 for ( sv
= sortVals
; sv
; sv
= sortVals
) {
1283 sortVals
= sv
->al_next
;
1284 sv
->al_desc
->ad_type
->sat_flags
&= ~SLAP_AT_SORTED_VAL
;
1291 for ( prev
= &sortVals
, sv
= sortVals
; i
< c
->valx
; i
++ ) {
1292 prev
= &sv
->al_next
;
1295 sv
->al_desc
->ad_type
->sat_flags
&= ~SLAP_AT_SORTED_VAL
;
1296 *prev
= sv
->al_next
;
1302 /* FIXME: there is no limits_free function */
1304 /* FIXME: there is no ad_option_free function */
1306 /* FIXME: there is no way to remove attributes added by
1320 if(!(c
->bi
= backend_info(c
->argv
[1]))) {
1321 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> failed init", c
->argv
[0] );
1322 Debug(LDAP_DEBUG_ANY
, "%s: %s (%s)!\n",
1323 c
->log
, c
->cr_msg
, c
->argv
[1] );
1330 /* NOTE: config is always the first backend!
1332 if ( !strcasecmp( c
->argv
[1], "config" )) {
1333 c
->be
= LDAP_STAILQ_FIRST(&backendDB
);
1334 } else if ( !strcasecmp( c
->argv
[1], "frontend" )) {
1337 c
->be
= backend_db_init(c
->argv
[1], NULL
, c
->valx
, &c
->reply
);
1339 if ( c
->cr_msg
[0] == 0 )
1340 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> failed init", c
->argv
[0] );
1341 Debug(LDAP_DEBUG_ANY
, "%s: %s (%s)\n", c
->log
, c
->cr_msg
, c
->argv
[1] );
1348 ldap_pvt_thread_set_concurrency(c
->value_int
);
1352 if ( c
->value_int
< 2 ) {
1353 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1354 "threads=%d smaller than minimum value 2",
1356 Debug(LDAP_DEBUG_ANY
, "%s: %s.\n",
1357 c
->log
, c
->cr_msg
, 0 );
1360 } else if ( c
->value_int
> 2 * SLAP_MAX_WORKER_THREADS
) {
1361 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1362 "warning, threads=%d larger than twice the default (2*%d=%d); YMMV",
1363 c
->value_int
, SLAP_MAX_WORKER_THREADS
, 2 * SLAP_MAX_WORKER_THREADS
);
1364 Debug(LDAP_DEBUG_ANY
, "%s: %s.\n",
1365 c
->log
, c
->cr_msg
, 0 );
1367 if ( slapMode
& SLAP_SERVER_MODE
)
1368 ldap_pvt_thread_pool_maxthreads(&connection_pool
, c
->value_int
);
1369 connection_pool_max
= c
->value_int
; /* save for reference */
1373 if ( slapMode
& SLAP_TOOL_MODE
)
1374 ldap_pvt_thread_pool_maxthreads(&connection_pool
, c
->value_int
);
1375 slap_tool_thread_max
= c
->value_int
; /* save for reference */
1379 if ( passwd_salt
) ch_free( passwd_salt
);
1380 passwd_salt
= c
->value_string
;
1381 lutil_salt_format(passwd_salt
);
1385 if(limits_parse(c
->be
, c
->fname
, c
->lineno
, c
->argc
, c
->argv
))
1391 c
->be
->be_restrictops
|= SLAP_RESTRICT_OP_WRITES
;
1393 c
->be
->be_restrictops
&= ~SLAP_RESTRICT_OP_WRITES
;
1397 ch_free(c
->value_string
);
1398 if (slap_sasl_setpolicy( c
->argv
[1] )) {
1399 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unable to parse value", c
->argv
[0] );
1400 Debug(LDAP_DEBUG_ANY
, "%s: %s \"%s\"\n",
1401 c
->log
, c
->cr_msg
, c
->argv
[1] );
1407 if (slap_sasl_regexp_config( c
->argv
[1], c
->argv
[2] ))
1411 #ifdef HAVE_CYRUS_SASL
1414 char *txt
= slap_sasl_secprops( c
->argv
[1] );
1416 snprintf( c
->cr_msg
, sizeof(c
->cr_msg
), "<%s> %s",
1418 Debug(LDAP_DEBUG_ANY
, "%s: %s\n", c
->log
, c
->cr_msg
, 0 );
1426 c
->be
->be_max_deref_depth
= c
->value_int
;
1432 if ( c
->op
== LDAP_MOD_ADD
&& c
->ca_private
&& cfn
!= c
->ca_private
)
1433 cfn
= c
->ca_private
;
1434 if(parse_oidm(c
, 1, &om
))
1436 if (!cfn
->c_om_head
) cfn
->c_om_head
= om
;
1437 cfn
->c_om_tail
= om
;
1442 ObjectClass
*oc
, *prev
;
1444 if ( c
->op
== LDAP_MOD_ADD
&& c
->ca_private
&& cfn
!= c
->ca_private
)
1445 cfn
= c
->ca_private
;
1446 if ( c
->valx
< 0 ) {
1447 prev
= cfn
->c_oc_tail
;
1450 /* If adding anything after the first, prev is easy */
1453 for (i
=0, oc
= cfn
->c_oc_head
; i
<c
->valx
; i
++) {
1458 /* If adding the first, and head exists, find its prev */
1459 if (cfn
->c_oc_head
) {
1460 for ( oc_start( &oc
); oc
!= cfn
->c_oc_head
; ) {
1465 /* else prev is NULL, append to end of global list */
1467 if(parse_oc(c
, &oc
, prev
)) return(1);
1468 if (!cfn
->c_oc_head
) cfn
->c_oc_head
= oc
;
1469 if (cfn
->c_oc_tail
== prev
) cfn
->c_oc_tail
= oc
;
1474 AttributeType
*at
, *prev
;
1476 if ( c
->op
== LDAP_MOD_ADD
&& c
->ca_private
&& cfn
!= c
->ca_private
)
1477 cfn
= c
->ca_private
;
1478 if ( c
->valx
< 0 ) {
1479 prev
= cfn
->c_at_tail
;
1482 /* If adding anything after the first, prev is easy */
1485 for (i
=0, at
= cfn
->c_at_head
; i
<c
->valx
; i
++) {
1490 /* If adding the first, and head exists, find its prev */
1491 if (cfn
->c_at_head
) {
1492 for ( at_start( &at
); at
!= cfn
->c_at_head
; ) {
1497 /* else prev is NULL, append to end of global list */
1499 if(parse_at(c
, &at
, prev
)) return(1);
1500 if (!cfn
->c_at_head
) cfn
->c_at_head
= at
;
1501 if (cfn
->c_at_tail
== prev
) cfn
->c_at_tail
= at
;
1508 if ( c
->op
== LDAP_MOD_ADD
&& c
->ca_private
&& cfn
!= c
->ca_private
)
1509 cfn
= c
->ca_private
;
1510 if(parse_cr(c
, &cr
)) return(1);
1511 if (!cfn
->c_cr_head
) cfn
->c_cr_head
= cr
;
1512 cfn
->c_cr_tail
= cr
;
1517 ad_define_option(NULL
, NULL
, 0);
1518 for(i
= 1; i
< c
->argc
; i
++)
1519 if(ad_define_option(c
->argv
[i
], c
->fname
, c
->lineno
))
1524 if ( c
->value_int
< SLAP_INDEX_INTLEN_DEFAULT
)
1525 c
->value_int
= SLAP_INDEX_INTLEN_DEFAULT
;
1526 else if ( c
->value_int
> 255 )
1528 index_intlen
= c
->value_int
;
1529 index_intlen_strlen
= SLAP_INDEX_INTLEN_STRLEN(
1533 case CFG_SORTVALS
: {
1534 ADlist
*svnew
= NULL
, *svtail
, *sv
;
1536 for ( i
= 1; i
< c
->argc
; i
++ ) {
1537 AttributeDescription
*ad
= NULL
;
1541 rc
= slap_str2ad( c
->argv
[i
], &ad
, &text
);
1543 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unknown attribute type #%d",
1546 Debug(LDAP_DEBUG_ANY
, "%s: %s %s\n",
1547 c
->log
, c
->cr_msg
, c
->argv
[i
] );
1548 for ( sv
= svnew
; sv
; sv
= svnew
) {
1549 svnew
= sv
->al_next
;
1554 if (( ad
->ad_type
->sat_flags
& SLAP_AT_ORDERED
) ||
1555 ad
->ad_type
->sat_single_value
) {
1556 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> inappropriate attribute type #%d",
1558 goto sortval_reject
;
1560 sv
= ch_malloc( sizeof( ADlist
));
1565 svtail
->al_next
= sv
;
1570 for ( sv
= svnew
; sv
; sv
= sv
->al_next
)
1571 sv
->al_desc
->ad_type
->sat_flags
|= SLAP_AT_SORTED_VAL
;
1572 for ( sv
= sortVals
; sv
&& sv
->al_next
; sv
= sv
->al_next
);
1574 sv
->al_next
= svnew
;
1581 /* Don't append to the global ACL if we're on a specific DB */
1583 if ( c
->be
!= frontendDB
&& frontendDB
->be_acl
&& c
->valx
== -1 ) {
1586 for ( a
=c
->be
->be_acl
; a
&& a
!= frontendDB
->be_acl
;
1590 if ( parse_acl(c
->be
, c
->fname
, c
->lineno
, c
->argc
, c
->argv
, i
) ) {
1596 if(root_dse_read_file(c
->argv
[1])) {
1597 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> could not read file", c
->argv
[0] );
1598 Debug(LDAP_DEBUG_ANY
, "%s: %s %s\n",
1599 c
->log
, c
->cr_msg
, c
->argv
[1] );
1604 ber_str2bv( c
->argv
[1], 0, 1, &bv
);
1605 if ( c
->op
== LDAP_MOD_ADD
&& c
->ca_private
&& cfn
!= c
->ca_private
)
1606 cfn
= c
->ca_private
;
1607 ber_bvarray_add( &cfn
->c_dseFiles
, &bv
);
1613 ServerID
*si
, **sip
;
1616 if ( lutil_atoi( &num
, c
->argv
[1] ) ||
1617 num
< 0 || num
> SLAP_SYNC_SID_MAX
)
1619 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1620 "<%s> illegal server ID", c
->argv
[0] );
1621 Debug(LDAP_DEBUG_ANY
, "%s: %s %s\n",
1622 c
->log
, c
->cr_msg
, c
->argv
[1] );
1625 /* only one value allowed if no URL is given */
1626 if ( c
->argc
> 2 ) {
1629 if ( sid_list
&& BER_BVISEMPTY( &sid_list
->si_url
)) {
1630 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1631 "<%s> only one server ID allowed now", c
->argv
[0] );
1632 Debug(LDAP_DEBUG_ANY
, "%s: %s %s\n",
1633 c
->log
, c
->cr_msg
, c
->argv
[1] );
1637 if ( ldap_url_parse( c
->argv
[2], &lud
)) {
1638 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1639 "<%s> invalid URL", c
->argv
[0] );
1640 Debug(LDAP_DEBUG_ANY
, "%s: %s %s\n",
1641 c
->log
, c
->cr_msg
, c
->argv
[2] );
1644 len
= strlen( c
->argv
[2] );
1645 si
= ch_malloc( sizeof(ServerID
) + len
+ 1 );
1646 si
->si_url
.bv_val
= (char *)(si
+1);
1647 si
->si_url
.bv_len
= len
;
1648 strcpy( si
->si_url
.bv_val
, c
->argv
[2] );
1651 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
),
1652 "<%s> unqualified server ID not allowed now", c
->argv
[0] );
1653 Debug(LDAP_DEBUG_ANY
, "%s: %s %s\n",
1654 c
->log
, c
->cr_msg
, c
->argv
[1] );
1657 si
= ch_malloc( sizeof(ServerID
) );
1658 BER_BVZERO( &si
->si_url
);
1659 slap_serverID
= num
;
1660 Debug( LDAP_DEBUG_CONFIG
,
1662 c
->log
, slap_serverID
, 0 );
1666 for ( sip
= &sid_list
; *sip
; sip
= &(*sip
)->si_next
);
1669 if (( slapMode
& SLAP_SERVER_MODE
) && c
->argc
> 2 ) {
1670 /* If hostname is empty, or is localhost, or matches
1671 * our hostname, this serverID refers to this host.
1672 * Compare it against listeners and ports.
1674 if ( !lud
->lud_host
|| !lud
->lud_host
[0] ||
1675 !strncasecmp("localhost", lud
->lud_host
,
1676 STRLENOF("localhost")) ||
1677 !strcasecmp( global_host
, lud
->lud_host
)) {
1678 Listener
**l
= slapd_get_listeners();
1681 for ( i
=0; l
&& l
[i
]; i
++ ) {
1684 ldap_url_parse( l
[i
]->sl_url
.bv_val
, &lu2
);
1686 if ( strcasecmp( lud
->lud_scheme
,
1689 if ( lud
->lud_port
!= lu2
->lud_port
)
1691 /* Listener on ANY address */
1692 if ( !lu2
->lud_host
|| !lu2
->lud_host
[0] ) {
1696 /* URL on ANY address */
1697 if ( !lud
->lud_host
|| !lud
->lud_host
[0] ) {
1701 /* Listener has specific host, must
1704 if ( !strcasecmp( lud
->lud_host
,
1710 ldap_free_urldesc( lu2
);
1712 slap_serverID
= si
->si_num
;
1713 Debug( LDAP_DEBUG_CONFIG
,
1714 "%s: SID=%d (listener=%s)\n",
1715 c
->log
, slap_serverID
,
1716 l
[i
]->sl_url
.bv_val
);
1723 ldap_free_urldesc( lud
);
1727 if ( logfileName
) ch_free( logfileName
);
1728 logfileName
= c
->value_string
;
1729 logfile
= fopen(logfileName
, "w");
1730 if(logfile
) lutil_debug_file(logfile
);
1734 if(SLAP_NOLASTMODCMD(c
->be
)) {
1735 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> not available for %s database",
1736 c
->argv
[0], c
->be
->bd_info
->bi_type
);
1737 Debug(LDAP_DEBUG_ANY
, "%s: %s\n",
1738 c
->log
, c
->cr_msg
, 0 );
1742 SLAP_DBFLAGS(c
->be
) &= ~SLAP_DBFLAG_NOLASTMOD
;
1744 SLAP_DBFLAGS(c
->be
) |= SLAP_DBFLAG_NOLASTMOD
;
1747 case CFG_MIRRORMODE
:
1748 if(!SLAP_SHADOW(c
->be
)) {
1749 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> database is not a shadow",
1751 Debug(LDAP_DEBUG_ANY
, "%s: %s\n",
1752 c
->log
, c
->cr_msg
, 0 );
1756 SLAP_DBFLAGS(c
->be
) &= ~SLAP_DBFLAG_SINGLE_SHADOW
;
1758 SLAP_DBFLAGS(c
->be
) |= SLAP_DBFLAG_SINGLE_SHADOW
;
1761 case CFG_MONITORING
:
1763 SLAP_DBFLAGS(c
->be
) |= SLAP_DBFLAG_MONITORING
;
1765 SLAP_DBFLAGS(c
->be
) &= ~SLAP_DBFLAG_MONITORING
;
1770 SLAP_DBFLAGS(c
->be
) |= SLAP_DBFLAG_HIDDEN
;
1772 SLAP_DBFLAGS(c
->be
) &= ~SLAP_DBFLAG_HIDDEN
;
1775 case CFG_SSTR_IF_MAX
:
1776 if (c
->value_int
< index_substr_if_minlen
) {
1777 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> invalid value", c
->argv
[0] );
1778 Debug(LDAP_DEBUG_ANY
, "%s: %s (%d)\n",
1779 c
->log
, c
->cr_msg
, c
->value_int
);
1782 index_substr_if_maxlen
= c
->value_int
;
1785 case CFG_SSTR_IF_MIN
:
1786 if (c
->value_int
> index_substr_if_maxlen
) {
1787 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> invalid value", c
->argv
[0] );
1788 Debug(LDAP_DEBUG_ANY
, "%s: %s (%d)\n",
1789 c
->log
, c
->cr_msg
, c
->value_int
);
1792 index_substr_if_minlen
= c
->value_int
;
1795 #ifdef SLAPD_MODULES
1797 /* If we're just adding a module on an existing modpath,
1798 * make sure we've selected the current path.
1800 if ( c
->op
== LDAP_MOD_ADD
&& c
->ca_private
&& modcur
!= c
->ca_private
) {
1801 modcur
= c
->ca_private
;
1802 /* This should never fail */
1803 if ( module_path( modcur
->mp_path
.bv_val
)) {
1804 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> module path no longer valid",
1806 Debug(LDAP_DEBUG_ANY
, "%s: %s (%s)\n",
1807 c
->log
, c
->cr_msg
, modcur
->mp_path
.bv_val
);
1811 if(module_load(c
->argv
[1], c
->argc
- 2, (c
->argc
> 2) ? c
->argv
+ 2 : NULL
))
1813 /* Record this load on the current path */
1817 if ( c
->op
== SLAP_CONFIG_ADD
) {
1818 ptr
= c
->line
+ STRLENOF("moduleload");
1819 while (!isspace((unsigned char) *ptr
)) ptr
++;
1820 while (isspace((unsigned char) *ptr
)) ptr
++;
1824 ber_str2bv(ptr
, 0, 1, &bv
);
1825 ber_bvarray_add( &modcur
->mp_loads
, &bv
);
1827 /* Check for any new hardcoded schema */
1828 if ( c
->op
== LDAP_MOD_ADD
&& CONFIG_ONLINE_ADD( c
)) {
1829 config_check_schema( NULL
, &cfBackInfo
);
1834 if(module_path(c
->argv
[1])) return(1);
1835 /* Record which path was used with each module */
1839 if (!modpaths
.mp_loads
) {
1842 mp
= ch_malloc( sizeof( ModPaths
));
1843 modlast
->mp_next
= mp
;
1845 ber_str2bv(c
->argv
[1], 0, 1, &mp
->mp_path
);
1847 mp
->mp_loads
= NULL
;
1858 if(slapi_int_read_config(c
->be
, c
->fname
, c
->lineno
, c
->argc
, c
->argv
) != LDAP_SUCCESS
)
1860 slapi_plugins_used
++;
1864 #ifdef SLAP_AUTH_REWRITE
1869 if(slap_sasl_rewrite_config(c
->fname
, c
->lineno
, c
->argc
, c
->argv
))
1872 if ( c
->argc
> 1 ) {
1875 /* quote all args but the first */
1876 line
= ldap_charray2str( c
->argv
, "\" \"" );
1877 ber_str2bv( line
, 0, 0, &bv
);
1878 s
= ber_bvchr( &bv
, '"' );
1879 assert( s
!= NULL
);
1880 /* move the trailing quote of argv[0] to the end */
1881 AC_MEMCPY( s
, s
+ 1, bv
.bv_len
- ( s
- bv
.bv_val
) );
1882 bv
.bv_val
[ bv
.bv_len
- 1 ] = '"';
1885 ber_str2bv( c
->argv
[ 0 ], 0, 1, &bv
);
1888 ber_bvarray_add( &authz_rewrites
, &bv
);
1895 Debug( LDAP_DEBUG_ANY
,
1896 "%s: unknown CFG_TYPE %d.\n",
1897 c
->log
, c
->type
, 0 );
1906 config_fname(ConfigArgs
*c
) {
1907 if(c
->op
== SLAP_CONFIG_EMIT
) {
1908 if (c
->ca_private
) {
1909 ConfigFile
*cf
= c
->ca_private
;
1910 value_add_one( &c
->rvalue_vals
, &cf
->c_file
);
1919 config_cfdir(ConfigArgs
*c
) {
1920 if(c
->op
== SLAP_CONFIG_EMIT
) {
1921 if ( !BER_BVISEMPTY( &cfdir
)) {
1922 value_add_one( &c
->rvalue_vals
, &cfdir
);
1931 config_search_base(ConfigArgs
*c
) {
1932 if(c
->op
== SLAP_CONFIG_EMIT
) {
1934 if (!BER_BVISEMPTY(&default_search_base
)) {
1935 value_add_one(&c
->rvalue_vals
, &default_search_base
);
1936 value_add_one(&c
->rvalue_nvals
, &default_search_nbase
);
1940 } else if( c
->op
== LDAP_MOD_DELETE
) {
1941 ch_free( default_search_base
.bv_val
);
1942 ch_free( default_search_nbase
.bv_val
);
1943 BER_BVZERO( &default_search_base
);
1944 BER_BVZERO( &default_search_nbase
);
1948 if(c
->bi
|| c
->be
!= frontendDB
) {
1949 Debug(LDAP_DEBUG_ANY
, "%s: defaultSearchBase line must appear "
1950 "prior to any backend or database definition\n",
1955 if(default_search_nbase
.bv_len
) {
1956 free(default_search_base
.bv_val
);
1957 free(default_search_nbase
.bv_val
);
1960 default_search_base
= c
->value_dn
;
1961 default_search_nbase
= c
->value_ndn
;
1965 /* For RE23 compatibility we allow this in the global entry
1966 * but we now defer it to the frontend entry to allow modules
1967 * to load new hash types.
1970 config_passwd_hash(ConfigArgs
*c
) {
1972 if (c
->op
== SLAP_CONFIG_EMIT
) {
1974 /* Don't generate it in the global entry */
1975 if ( c
->table
== Cft_Global
)
1977 for (i
=0; default_passwd_hash
&& default_passwd_hash
[i
]; i
++) {
1978 ber_str2bv(default_passwd_hash
[i
], 0, 0, &bv
);
1979 value_add_one(&c
->rvalue_vals
, &bv
);
1982 } else if ( c
->op
== LDAP_MOD_DELETE
) {
1983 /* Deleting from global is a no-op, only the frontendDB entry matters */
1984 if ( c
->table
== Cft_Global
)
1986 if ( c
->valx
< 0 ) {
1987 ldap_charray_free( default_passwd_hash
);
1988 default_passwd_hash
= NULL
;
1991 ch_free( default_passwd_hash
[i
] );
1992 for (; default_passwd_hash
[i
]; i
++ )
1993 default_passwd_hash
[i
] = default_passwd_hash
[i
+1];
1997 for(i
= 1; i
< c
->argc
; i
++) {
1998 if(!lutil_passwd_scheme(c
->argv
[i
])) {
1999 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> scheme not available", c
->argv
[0] );
2000 Debug(LDAP_DEBUG_ANY
, "%s: %s (%s)\n",
2001 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2003 ldap_charray_add(&default_passwd_hash
, c
->argv
[i
]);
2006 if(!default_passwd_hash
) {
2007 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> no valid hashes found", c
->argv
[0] );
2008 Debug(LDAP_DEBUG_ANY
, "%s: %s\n",
2009 c
->log
, c
->cr_msg
, 0 );
2016 config_schema_dn(ConfigArgs
*c
) {
2017 if ( c
->op
== SLAP_CONFIG_EMIT
) {
2019 if ( !BER_BVISEMPTY( &c
->be
->be_schemadn
)) {
2020 value_add_one(&c
->rvalue_vals
, &c
->be
->be_schemadn
);
2021 value_add_one(&c
->rvalue_nvals
, &c
->be
->be_schemandn
);
2025 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2026 ch_free( c
->be
->be_schemadn
.bv_val
);
2027 ch_free( c
->be
->be_schemandn
.bv_val
);
2028 BER_BVZERO( &c
->be
->be_schemadn
);
2029 BER_BVZERO( &c
->be
->be_schemandn
);
2032 ch_free( c
->be
->be_schemadn
.bv_val
);
2033 ch_free( c
->be
->be_schemandn
.bv_val
);
2034 c
->be
->be_schemadn
= c
->value_dn
;
2035 c
->be
->be_schemandn
= c
->value_ndn
;
2040 config_sizelimit(ConfigArgs
*c
) {
2042 struct slap_limits_set
*lim
= &c
->be
->be_def_limit
;
2043 if (c
->op
== SLAP_CONFIG_EMIT
) {
2048 limits_unparse_one( lim
, SLAP_LIMIT_SIZE
, &bv
, sizeof( buf
) );
2049 if ( !BER_BVISEMPTY( &bv
))
2050 value_add_one( &c
->rvalue_vals
, &bv
);
2054 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2055 /* Reset to defaults */
2056 lim
->lms_s_soft
= SLAPD_DEFAULT_SIZELIMIT
;
2057 lim
->lms_s_hard
= 0;
2058 lim
->lms_s_unchecked
= -1;
2060 lim
->lms_s_pr_hide
= 0;
2061 lim
->lms_s_pr_total
= 0;
2064 for(i
= 1; i
< c
->argc
; i
++) {
2065 if(!strncasecmp(c
->argv
[i
], "size", 4)) {
2066 rc
= limits_parse_one(c
->argv
[i
], lim
);
2068 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unable to parse value", c
->argv
[0] );
2069 Debug(LDAP_DEBUG_ANY
, "%s: %s \"%s\"\n",
2070 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2074 if(!strcasecmp(c
->argv
[i
], "unlimited")) {
2075 lim
->lms_s_soft
= -1;
2077 if ( lutil_atoix( &lim
->lms_s_soft
, c
->argv
[i
], 0 ) != 0 ) {
2078 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unable to parse limit", c
->argv
[0]);
2079 Debug(LDAP_DEBUG_ANY
, "%s: %s \"%s\"\n",
2080 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2084 lim
->lms_s_hard
= 0;
2091 config_timelimit(ConfigArgs
*c
) {
2093 struct slap_limits_set
*lim
= &c
->be
->be_def_limit
;
2094 if (c
->op
== SLAP_CONFIG_EMIT
) {
2099 limits_unparse_one( lim
, SLAP_LIMIT_TIME
, &bv
, sizeof( buf
) );
2100 if ( !BER_BVISEMPTY( &bv
))
2101 value_add_one( &c
->rvalue_vals
, &bv
);
2105 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2106 /* Reset to defaults */
2107 lim
->lms_t_soft
= SLAPD_DEFAULT_TIMELIMIT
;
2108 lim
->lms_t_hard
= 0;
2111 for(i
= 1; i
< c
->argc
; i
++) {
2112 if(!strncasecmp(c
->argv
[i
], "time", 4)) {
2113 rc
= limits_parse_one(c
->argv
[i
], lim
);
2115 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unable to parse value", c
->argv
[0] );
2116 Debug(LDAP_DEBUG_ANY
, "%s: %s \"%s\"\n",
2117 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2121 if(!strcasecmp(c
->argv
[i
], "unlimited")) {
2122 lim
->lms_t_soft
= -1;
2124 if ( lutil_atoix( &lim
->lms_t_soft
, c
->argv
[i
], 0 ) != 0 ) {
2125 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unable to parse limit", c
->argv
[0]);
2126 Debug(LDAP_DEBUG_ANY
, "%s: %s \"%s\"\n",
2127 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2131 lim
->lms_t_hard
= 0;
2138 config_overlay(ConfigArgs
*c
) {
2139 if (c
->op
== SLAP_CONFIG_EMIT
) {
2141 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2144 if(c
->argv
[1][0] == '-' && overlay_config(c
->be
, &c
->argv
[1][1],
2145 c
->valx
, &c
->bi
, &c
->reply
)) {
2147 Debug( LDAP_DEBUG_ANY
,
2148 "%s: (optional) %s overlay \"%s\" configuration failed.\n",
2149 c
->log
, c
->be
== frontendDB
? "global " : "", &c
->argv
[1][1]);
2151 } else if(overlay_config(c
->be
, c
->argv
[1], c
->valx
, &c
->bi
, &c
->reply
)) {
2158 config_subordinate(ConfigArgs
*c
)
2164 case SLAP_CONFIG_EMIT
:
2165 if ( SLAP_GLUE_SUBORDINATE( c
->be
)) {
2168 bv
.bv_val
= SLAP_GLUE_ADVERTISE( c
->be
) ? "advertise" : "TRUE";
2169 bv
.bv_len
= SLAP_GLUE_ADVERTISE( c
->be
) ? STRLENOF("advertise") :
2172 value_add_one( &c
->rvalue_vals
, &bv
);
2176 case LDAP_MOD_DELETE
:
2177 if ( !c
->line
|| strcasecmp( c
->line
, "advertise" )) {
2178 glue_sub_del( c
->be
);
2180 SLAP_DBFLAGS( c
->be
) &= ~SLAP_DBFLAG_GLUE_ADVERTISE
;
2185 case SLAP_CONFIG_ADD
:
2186 advertise
= ( c
->argc
== 2 && !strcasecmp( c
->argv
[1], "advertise" ));
2187 rc
= glue_sub_add( c
->be
, advertise
, CONFIG_ONLINE_ADD( c
));
2194 config_suffix(ConfigArgs
*c
)
2197 struct berval pdn
, ndn
;
2198 char *notallowed
= NULL
;
2200 if ( c
->be
== frontendDB
) {
2201 notallowed
= "frontend";
2203 } else if ( SLAP_MONITOR(c
->be
) ) {
2204 notallowed
= "monitor";
2206 } else if ( SLAP_CONFIG(c
->be
) ) {
2207 notallowed
= "config";
2210 if ( notallowed
!= NULL
) {
2211 char buf
[ SLAP_TEXT_BUFLEN
] = { '\0' };
2215 case LDAP_MOD_DELETE
:
2216 case LDAP_MOD_REPLACE
:
2217 case LDAP_MOD_INCREMENT
:
2218 case SLAP_CONFIG_ADD
:
2219 if ( !BER_BVISNULL( &c
->value_dn
) ) {
2220 snprintf( buf
, sizeof( buf
), "<%s> ",
2221 c
->value_dn
.bv_val
);
2224 Debug(LDAP_DEBUG_ANY
,
2225 "%s: suffix %snot allowed in %s database.\n",
2226 c
->log
, buf
, notallowed
);
2229 case SLAP_CONFIG_EMIT
:
2230 /* don't complain when emitting... */
2234 /* FIXME: don't know what values may be valid;
2235 * please remove assertion, or add legal values
2236 * to either block */
2244 if (c
->op
== SLAP_CONFIG_EMIT
) {
2245 if ( c
->be
->be_suffix
== NULL
2246 || BER_BVISNULL( &c
->be
->be_suffix
[0] ) )
2250 value_add( &c
->rvalue_vals
, c
->be
->be_suffix
);
2251 value_add( &c
->rvalue_nvals
, c
->be
->be_nsuffix
);
2254 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2255 if ( c
->valx
< 0 ) {
2256 ber_bvarray_free( c
->be
->be_suffix
);
2257 ber_bvarray_free( c
->be
->be_nsuffix
);
2258 c
->be
->be_suffix
= NULL
;
2259 c
->be
->be_nsuffix
= NULL
;
2262 ch_free( c
->be
->be_suffix
[i
].bv_val
);
2263 ch_free( c
->be
->be_nsuffix
[i
].bv_val
);
2265 c
->be
->be_suffix
[i
] = c
->be
->be_suffix
[i
+1];
2266 c
->be
->be_nsuffix
[i
] = c
->be
->be_nsuffix
[i
+1];
2268 } while ( !BER_BVISNULL( &c
->be
->be_suffix
[i
] ) );
2273 #ifdef SLAPD_MONITOR_DN
2274 if(!strcasecmp(c
->argv
[1], SLAPD_MONITOR_DN
)) {
2275 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> DN is reserved for monitoring slapd",
2277 Debug(LDAP_DEBUG_ANY
, "%s: %s (%s)\n",
2278 c
->log
, c
->cr_msg
, SLAPD_MONITOR_DN
);
2283 if (SLAP_DB_ONE_SUFFIX( c
->be
) && c
->be
->be_suffix
) {
2284 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> Only one suffix is allowed on this %s backend",
2285 c
->argv
[0], c
->be
->bd_info
->bi_type
);
2286 Debug(LDAP_DEBUG_ANY
, "%s: %s\n",
2287 c
->log
, c
->cr_msg
, 0);
2294 if (SLAP_DBHIDDEN( c
->be
))
2297 tbe
= select_backend(&ndn
, 0);
2299 Debug( LDAP_DEBUG_ANY
, "%s: suffix already served by this backend!.\n",
2305 BackendDB
*b2
= tbe
;
2307 /* Does tbe precede be? */
2308 while (( b2
= LDAP_STAILQ_NEXT(b2
, be_next
)) && b2
&& b2
!= c
->be
);
2311 char *type
= tbe
->bd_info
->bi_type
;
2313 if ( overlay_is_over( tbe
) ) {
2314 slap_overinfo
*oi
= (slap_overinfo
*)tbe
->bd_info
->bi_private
;
2315 type
= oi
->oi_orig
->bi_type
;
2318 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> namingContext \"%s\" "
2319 "already served by a preceding %s database",
2320 c
->argv
[0], pdn
.bv_val
, type
);
2321 Debug(LDAP_DEBUG_ANY
, "%s: %s serving namingContext \"%s\"\n",
2322 c
->log
, c
->cr_msg
, tbe
->be_suffix
[0].bv_val
);
2328 if(pdn
.bv_len
== 0 && default_search_nbase
.bv_len
) {
2329 Debug(LDAP_DEBUG_ANY
, "%s: suffix DN empty and default search "
2330 "base provided \"%s\" (assuming okay)\n",
2331 c
->log
, default_search_base
.bv_val
, 0);
2333 ber_bvarray_add(&c
->be
->be_suffix
, &pdn
);
2334 ber_bvarray_add(&c
->be
->be_nsuffix
, &ndn
);
2339 config_rootdn(ConfigArgs
*c
) {
2340 if (c
->op
== SLAP_CONFIG_EMIT
) {
2341 if ( !BER_BVISNULL( &c
->be
->be_rootdn
)) {
2342 value_add_one(&c
->rvalue_vals
, &c
->be
->be_rootdn
);
2343 value_add_one(&c
->rvalue_nvals
, &c
->be
->be_rootndn
);
2348 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2349 ch_free( c
->be
->be_rootdn
.bv_val
);
2350 ch_free( c
->be
->be_rootndn
.bv_val
);
2351 BER_BVZERO( &c
->be
->be_rootdn
);
2352 BER_BVZERO( &c
->be
->be_rootndn
);
2355 if ( !BER_BVISNULL( &c
->be
->be_rootdn
)) {
2356 ch_free( c
->be
->be_rootdn
.bv_val
);
2357 ch_free( c
->be
->be_rootndn
.bv_val
);
2359 c
->be
->be_rootdn
= c
->value_dn
;
2360 c
->be
->be_rootndn
= c
->value_ndn
;
2365 config_rootpw(ConfigArgs
*c
) {
2368 if (c
->op
== SLAP_CONFIG_EMIT
) {
2369 if (!BER_BVISEMPTY(&c
->be
->be_rootpw
)) {
2370 /* don't copy, because "rootpw" is marked
2372 c
->value_bv
= c
->be
->be_rootpw
;
2376 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2377 ch_free( c
->be
->be_rootpw
.bv_val
);
2378 BER_BVZERO( &c
->be
->be_rootpw
);
2382 tbe
= select_backend(&c
->be
->be_rootndn
, 0);
2384 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> can only be set when rootdn is under suffix",
2386 Debug(LDAP_DEBUG_ANY
, "%s: %s\n",
2387 c
->log
, c
->cr_msg
, 0);
2390 if ( !BER_BVISNULL( &c
->be
->be_rootpw
))
2391 ch_free( c
->be
->be_rootpw
.bv_val
);
2392 c
->be
->be_rootpw
= c
->value_bv
;
2397 config_restrict(ConfigArgs
*c
) {
2398 slap_mask_t restrictops
= 0;
2400 slap_verbmasks restrictable_ops
[] = {
2401 { BER_BVC("bind"), SLAP_RESTRICT_OP_BIND
},
2402 { BER_BVC("add"), SLAP_RESTRICT_OP_ADD
},
2403 { BER_BVC("modify"), SLAP_RESTRICT_OP_MODIFY
},
2404 { BER_BVC("rename"), SLAP_RESTRICT_OP_RENAME
},
2405 { BER_BVC("modrdn"), 0 },
2406 { BER_BVC("delete"), SLAP_RESTRICT_OP_DELETE
},
2407 { BER_BVC("search"), SLAP_RESTRICT_OP_SEARCH
},
2408 { BER_BVC("compare"), SLAP_RESTRICT_OP_COMPARE
},
2409 { BER_BVC("read"), SLAP_RESTRICT_OP_READS
},
2410 { BER_BVC("write"), SLAP_RESTRICT_OP_WRITES
},
2411 { BER_BVC("extended"), SLAP_RESTRICT_OP_EXTENDED
},
2412 { BER_BVC("extended=" LDAP_EXOP_START_TLS
), SLAP_RESTRICT_EXOP_START_TLS
},
2413 { BER_BVC("extended=" LDAP_EXOP_MODIFY_PASSWD
), SLAP_RESTRICT_EXOP_MODIFY_PASSWD
},
2414 { BER_BVC("extended=" LDAP_EXOP_X_WHO_AM_I
), SLAP_RESTRICT_EXOP_WHOAMI
},
2415 { BER_BVC("extended=" LDAP_EXOP_X_CANCEL
), SLAP_RESTRICT_EXOP_CANCEL
},
2416 { BER_BVC("all"), SLAP_RESTRICT_OP_ALL
},
2420 if (c
->op
== SLAP_CONFIG_EMIT
) {
2421 return mask_to_verbs( restrictable_ops
, c
->be
->be_restrictops
,
2423 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2425 c
->be
->be_restrictops
= 0;
2427 restrictops
= verb_to_mask( c
->line
, restrictable_ops
);
2428 c
->be
->be_restrictops
^= restrictops
;
2432 i
= verbs_to_mask( c
->argc
, c
->argv
, restrictable_ops
, &restrictops
);
2434 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unknown operation", c
->argv
[0] );
2435 Debug(LDAP_DEBUG_ANY
, "%s: %s %s\n",
2436 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2439 if ( restrictops
& SLAP_RESTRICT_OP_EXTENDED
)
2440 restrictops
&= ~SLAP_RESTRICT_EXOP_MASK
;
2441 c
->be
->be_restrictops
|= restrictops
;
2446 config_allows(ConfigArgs
*c
) {
2447 slap_mask_t allows
= 0;
2449 slap_verbmasks allowable_ops
[] = {
2450 { BER_BVC("bind_v2"), SLAP_ALLOW_BIND_V2
},
2451 { BER_BVC("bind_anon_cred"), SLAP_ALLOW_BIND_ANON_CRED
},
2452 { BER_BVC("bind_anon_dn"), SLAP_ALLOW_BIND_ANON_DN
},
2453 { BER_BVC("update_anon"), SLAP_ALLOW_UPDATE_ANON
},
2454 { BER_BVC("proxy_authz_anon"), SLAP_ALLOW_PROXY_AUTHZ_ANON
},
2457 if (c
->op
== SLAP_CONFIG_EMIT
) {
2458 return mask_to_verbs( allowable_ops
, global_allows
, &c
->rvalue_vals
);
2459 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2463 allows
= verb_to_mask( c
->line
, allowable_ops
);
2464 global_allows
^= allows
;
2468 i
= verbs_to_mask(c
->argc
, c
->argv
, allowable_ops
, &allows
);
2470 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unknown feature", c
->argv
[0] );
2471 Debug(LDAP_DEBUG_ANY
, "%s: %s %s\n",
2472 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2475 global_allows
|= allows
;
2480 config_disallows(ConfigArgs
*c
) {
2481 slap_mask_t disallows
= 0;
2483 slap_verbmasks disallowable_ops
[] = {
2484 { BER_BVC("bind_anon"), SLAP_DISALLOW_BIND_ANON
},
2485 { BER_BVC("bind_simple"), SLAP_DISALLOW_BIND_SIMPLE
},
2486 { BER_BVC("tls_2_anon"), SLAP_DISALLOW_TLS_2_ANON
},
2487 { BER_BVC("tls_authc"), SLAP_DISALLOW_TLS_AUTHC
},
2490 if (c
->op
== SLAP_CONFIG_EMIT
) {
2491 return mask_to_verbs( disallowable_ops
, global_disallows
, &c
->rvalue_vals
);
2492 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2494 global_disallows
= 0;
2496 disallows
= verb_to_mask( c
->line
, disallowable_ops
);
2497 global_disallows
^= disallows
;
2501 i
= verbs_to_mask(c
->argc
, c
->argv
, disallowable_ops
, &disallows
);
2503 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unknown feature", c
->argv
[0] );
2504 Debug(LDAP_DEBUG_ANY
, "%s: %s %s\n",
2505 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2508 global_disallows
|= disallows
;
2513 config_requires(ConfigArgs
*c
) {
2514 slap_mask_t requires
= frontendDB
->be_requires
;
2515 int i
, argc
= c
->argc
;
2516 char **argv
= c
->argv
;
2518 slap_verbmasks requires_ops
[] = {
2519 { BER_BVC("bind"), SLAP_REQUIRE_BIND
},
2520 { BER_BVC("LDAPv3"), SLAP_REQUIRE_LDAP_V3
},
2521 { BER_BVC("authc"), SLAP_REQUIRE_AUTHC
},
2522 { BER_BVC("sasl"), SLAP_REQUIRE_SASL
},
2523 { BER_BVC("strong"), SLAP_REQUIRE_STRONG
},
2526 if (c
->op
== SLAP_CONFIG_EMIT
) {
2527 return mask_to_verbs( requires_ops
, c
->be
->be_requires
, &c
->rvalue_vals
);
2528 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2530 c
->be
->be_requires
= 0;
2532 requires
= verb_to_mask( c
->line
, requires_ops
);
2533 c
->be
->be_requires
^= requires
;
2537 /* "none" can only be first, to wipe out default/global values */
2538 if ( strcasecmp( c
->argv
[ 1 ], "none" ) == 0 ) {
2543 i
= verbs_to_mask(argc
, argv
, requires_ops
, &requires
);
2545 if (strcasecmp( c
->argv
[ i
], "none" ) == 0 ) {
2546 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> \"none\" (#%d) must be listed first", c
->argv
[0], i
- 1 );
2547 Debug(LDAP_DEBUG_ANY
, "%s: %s\n",
2548 c
->log
, c
->cr_msg
, 0);
2550 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unknown feature #%d", c
->argv
[0], i
- 1 );
2551 Debug(LDAP_DEBUG_ANY
, "%s: %s \"%s\"\n",
2552 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2556 c
->be
->be_requires
= requires
;
2560 static slap_verbmasks
*loglevel_ops
;
2563 loglevel_init( void )
2565 slap_verbmasks lo
[] = {
2566 { BER_BVC("Any"), -1 },
2567 { BER_BVC("Trace"), LDAP_DEBUG_TRACE
},
2568 { BER_BVC("Packets"), LDAP_DEBUG_PACKETS
},
2569 { BER_BVC("Args"), LDAP_DEBUG_ARGS
},
2570 { BER_BVC("Conns"), LDAP_DEBUG_CONNS
},
2571 { BER_BVC("BER"), LDAP_DEBUG_BER
},
2572 { BER_BVC("Filter"), LDAP_DEBUG_FILTER
},
2573 { BER_BVC("Config"), LDAP_DEBUG_CONFIG
},
2574 { BER_BVC("ACL"), LDAP_DEBUG_ACL
},
2575 { BER_BVC("Stats"), LDAP_DEBUG_STATS
},
2576 { BER_BVC("Stats2"), LDAP_DEBUG_STATS2
},
2577 { BER_BVC("Shell"), LDAP_DEBUG_SHELL
},
2578 { BER_BVC("Parse"), LDAP_DEBUG_PARSE
},
2579 #if 0 /* no longer used (nor supported) */
2580 { BER_BVC("Cache"), LDAP_DEBUG_CACHE
},
2581 { BER_BVC("Index"), LDAP_DEBUG_INDEX
},
2583 { BER_BVC("Sync"), LDAP_DEBUG_SYNC
},
2584 { BER_BVC("None"), LDAP_DEBUG_NONE
},
2588 return slap_verbmasks_init( &loglevel_ops
, lo
);
2592 loglevel_destroy( void )
2594 if ( loglevel_ops
) {
2595 (void)slap_verbmasks_destroy( loglevel_ops
);
2597 loglevel_ops
= NULL
;
2600 static slap_mask_t loglevel_ignore
[] = { -1, 0 };
2603 slap_loglevel_register( slap_mask_t m
, struct berval
*s
)
2607 if ( loglevel_ops
== NULL
) {
2611 rc
= slap_verbmasks_append( &loglevel_ops
, m
, s
, loglevel_ignore
);
2614 Debug( LDAP_DEBUG_ANY
, "slap_loglevel_register(%lu, \"%s\") failed\n",
2622 slap_loglevel_get( struct berval
*s
, int *l
)
2627 if ( loglevel_ops
== NULL
) {
2631 for ( m
= 0, i
= 1; !BER_BVISNULL( &loglevel_ops
[ i
].word
); i
++ ) {
2632 m
|= loglevel_ops
[ i
].mask
;
2635 for ( i
= 1; m
& i
; i
<<= 1 )
2642 rc
= slap_verbmasks_append( &loglevel_ops
, i
, s
, loglevel_ignore
);
2645 Debug( LDAP_DEBUG_ANY
, "slap_loglevel_get(%lu, \"%s\") failed\n",
2656 str2loglevel( const char *s
, int *l
)
2660 if ( loglevel_ops
== NULL
) {
2664 i
= verb_to_mask( s
, loglevel_ops
);
2666 if ( BER_BVISNULL( &loglevel_ops
[ i
].word
) ) {
2670 *l
= loglevel_ops
[ i
].mask
;
2676 loglevel2str( int l
)
2678 struct berval bv
= BER_BVNULL
;
2680 loglevel2bv( l
, &bv
);
2686 loglevel2bv( int l
, struct berval
*bv
)
2688 if ( loglevel_ops
== NULL
) {
2694 return enum_to_verb( loglevel_ops
, l
, bv
) == -1;
2698 loglevel2bvarray( int l
, BerVarray
*bva
)
2700 if ( loglevel_ops
== NULL
) {
2704 return mask_to_verbs( loglevel_ops
, l
, bva
);
2708 loglevel_print( FILE *out
)
2712 if ( loglevel_ops
== NULL
) {
2716 fprintf( out
, "Installed log subsystems:\n\n" );
2717 for ( i
= 0; !BER_BVISNULL( &loglevel_ops
[ i
].word
); i
++ ) {
2718 fprintf( out
, "\t%-30s (%lu)\n",
2719 loglevel_ops
[ i
].word
.bv_val
,
2720 loglevel_ops
[ i
].mask
);
2723 fprintf( out
, "\nNOTE: custom log subsystems may be later installed "
2724 "by specific code\n\n" );
2729 static int config_syslog
;
2732 config_loglevel(ConfigArgs
*c
) {
2735 if ( loglevel_ops
== NULL
) {
2739 if (c
->op
== SLAP_CONFIG_EMIT
) {
2740 /* Get default or commandline slapd setting */
2741 if ( ldap_syslog
&& !config_syslog
)
2742 config_syslog
= ldap_syslog
;
2743 return loglevel2bvarray( config_syslog
, &c
->rvalue_vals
);
2745 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2749 int level
= verb_to_mask( c
->line
, loglevel_ops
);
2750 config_syslog
^= level
;
2752 if ( slapMode
& SLAP_SERVER_MODE
) {
2753 ldap_syslog
= config_syslog
;
2758 for( i
=1; i
< c
->argc
; i
++ ) {
2761 if ( isdigit((unsigned char)c
->argv
[i
][0]) || c
->argv
[i
][0] == '-' ) {
2762 if( lutil_atoi( &level
, c
->argv
[i
] ) != 0 ) {
2763 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unable to parse level", c
->argv
[0] );
2764 Debug( LDAP_DEBUG_ANY
, "%s: %s \"%s\"\n",
2765 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2769 if ( str2loglevel( c
->argv
[i
], &level
) ) {
2770 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unknown level", c
->argv
[0] );
2771 Debug( LDAP_DEBUG_ANY
, "%s: %s \"%s\"\n",
2772 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2776 /* Explicitly setting a zero clears all the levels */
2778 config_syslog
|= level
;
2782 if ( slapMode
& SLAP_SERVER_MODE
) {
2783 ldap_syslog
= config_syslog
;
2789 config_referral(ConfigArgs
*c
) {
2791 if (c
->op
== SLAP_CONFIG_EMIT
) {
2792 if ( default_referral
) {
2793 value_add( &c
->rvalue_vals
, default_referral
);
2798 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2799 if ( c
->valx
< 0 ) {
2800 ber_bvarray_free( default_referral
);
2801 default_referral
= NULL
;
2804 ch_free( default_referral
[i
].bv_val
);
2805 for (; default_referral
[i
].bv_val
; i
++ )
2806 default_referral
[i
] = default_referral
[i
+1];
2810 if(validate_global_referral(c
->argv
[1])) {
2811 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> invalid URL", c
->argv
[0] );
2812 Debug(LDAP_DEBUG_ANY
, "%s: %s (%s)\n",
2813 c
->log
, c
->cr_msg
, c
->argv
[1]);
2817 ber_str2bv(c
->argv
[1], 0, 0, &val
);
2818 if(value_add_one(&default_referral
, &val
)) return(LDAP_OTHER
);
2826 { BER_BVC("ssf="), offsetof(slap_ssf_set_t
, sss_ssf
) },
2827 { BER_BVC("transport="), offsetof(slap_ssf_set_t
, sss_transport
) },
2828 { BER_BVC("tls="), offsetof(slap_ssf_set_t
, sss_tls
) },
2829 { BER_BVC("sasl="), offsetof(slap_ssf_set_t
, sss_sasl
) },
2830 { BER_BVC("update_ssf="), offsetof(slap_ssf_set_t
, sss_update_ssf
) },
2831 { BER_BVC("update_transport="), offsetof(slap_ssf_set_t
, sss_update_transport
) },
2832 { BER_BVC("update_tls="), offsetof(slap_ssf_set_t
, sss_update_tls
) },
2833 { BER_BVC("update_sasl="), offsetof(slap_ssf_set_t
, sss_update_sasl
) },
2834 { BER_BVC("simple_bind="), offsetof(slap_ssf_set_t
, sss_simple_bind
) },
2839 config_security(ConfigArgs
*c
) {
2840 slap_ssf_set_t
*set
= &c
->be
->be_ssf_set
;
2843 if (c
->op
== SLAP_CONFIG_EMIT
) {
2849 for (i
=0; !BER_BVISNULL( &sec_keys
[i
].key
); i
++) {
2850 tgt
= (slap_ssf_t
*)((char *)set
+ sec_keys
[i
].off
);
2853 bv
.bv_len
= snprintf( numbuf
, sizeof( numbuf
), "%u", *tgt
);
2854 if ( bv
.bv_len
>= sizeof( numbuf
) ) {
2855 ber_bvarray_free_x( c
->rvalue_vals
, NULL
);
2856 c
->rvalue_vals
= NULL
;
2860 bv
.bv_len
+= sec_keys
[i
].key
.bv_len
;
2861 bv
.bv_val
= ch_malloc( bv
.bv_len
+ 1);
2862 next
= lutil_strcopy( bv
.bv_val
, sec_keys
[i
].key
.bv_val
);
2863 strcpy( next
, numbuf
);
2864 ber_bvarray_add( &c
->rvalue_vals
, &bv
);
2869 for(i
= 1; i
< c
->argc
; i
++) {
2870 slap_ssf_t
*tgt
= NULL
;
2872 for ( j
=0; !BER_BVISNULL( &sec_keys
[j
].key
); j
++ ) {
2873 if(!strncasecmp(c
->argv
[i
], sec_keys
[j
].key
.bv_val
,
2874 sec_keys
[j
].key
.bv_len
)) {
2875 src
= c
->argv
[i
] + sec_keys
[j
].key
.bv_len
;
2876 tgt
= (slap_ssf_t
*)((char *)set
+ sec_keys
[j
].off
);
2881 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unknown factor", c
->argv
[0] );
2882 Debug(LDAP_DEBUG_ANY
, "%s: %s %s\n",
2883 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2887 if ( lutil_atou( tgt
, src
) != 0 ) {
2888 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> unable to parse factor", c
->argv
[0] );
2889 Debug(LDAP_DEBUG_ANY
, "%s: %s \"%s\"\n",
2890 c
->log
, c
->cr_msg
, c
->argv
[i
]);
2898 anlist_unparse( AttributeName
*an
, char *ptr
, ber_len_t buflen
) {
2902 for (; !BER_BVISNULL( &an
->an_name
); an
++) {
2903 /* if buflen == 0, assume the buffer size has been
2904 * already checked otherwise */
2905 if ( buflen
> 0 && buflen
- ( ptr
- start
) < comma
+ an
->an_name
.bv_len
) return NULL
;
2906 if ( comma
) *ptr
++ = ',';
2907 ptr
= lutil_strcopy( ptr
, an
->an_name
.bv_val
);
2914 config_updatedn(ConfigArgs
*c
) {
2915 if (c
->op
== SLAP_CONFIG_EMIT
) {
2916 if (!BER_BVISEMPTY(&c
->be
->be_update_ndn
)) {
2917 value_add_one(&c
->rvalue_vals
, &c
->be
->be_update_ndn
);
2918 value_add_one(&c
->rvalue_nvals
, &c
->be
->be_update_ndn
);
2922 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2923 ch_free( c
->be
->be_update_ndn
.bv_val
);
2924 BER_BVZERO( &c
->be
->be_update_ndn
);
2925 SLAP_DBFLAGS(c
->be
) ^= (SLAP_DBFLAG_SHADOW
| SLAP_DBFLAG_SLURP_SHADOW
);
2928 if(SLAP_SHADOW(c
->be
)) {
2929 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> database already shadowed", c
->argv
[0] );
2930 Debug(LDAP_DEBUG_ANY
, "%s: %s\n",
2931 c
->log
, c
->cr_msg
, 0);
2935 ber_memfree_x( c
->value_dn
.bv_val
, NULL
);
2936 if ( !BER_BVISNULL( &c
->be
->be_update_ndn
) ) {
2937 ber_memfree_x( c
->be
->be_update_ndn
.bv_val
, NULL
);
2939 c
->be
->be_update_ndn
= c
->value_ndn
;
2940 BER_BVZERO( &c
->value_dn
);
2941 BER_BVZERO( &c
->value_ndn
);
2943 return config_slurp_shadow( c
);
2947 config_shadow( ConfigArgs
*c
, int flag
)
2949 char *notallowed
= NULL
;
2951 if ( c
->be
== frontendDB
) {
2952 notallowed
= "frontend";
2954 } else if ( SLAP_MONITOR(c
->be
) ) {
2955 notallowed
= "monitor";
2958 if ( notallowed
!= NULL
) {
2959 Debug( LDAP_DEBUG_ANY
, "%s: %s database cannot be shadow.\n", c
->log
, notallowed
, 0 );
2963 SLAP_DBFLAGS(c
->be
) |= (SLAP_DBFLAG_SHADOW
| SLAP_DBFLAG_SINGLE_SHADOW
| flag
);
2969 config_updateref(ConfigArgs
*c
) {
2971 if (c
->op
== SLAP_CONFIG_EMIT
) {
2972 if ( c
->be
->be_update_refs
) {
2973 value_add( &c
->rvalue_vals
, c
->be
->be_update_refs
);
2978 } else if ( c
->op
== LDAP_MOD_DELETE
) {
2979 if ( c
->valx
< 0 ) {
2980 ber_bvarray_free( c
->be
->be_update_refs
);
2981 c
->be
->be_update_refs
= NULL
;
2984 ch_free( c
->be
->be_update_refs
[i
].bv_val
);
2985 for (; c
->be
->be_update_refs
[i
].bv_val
; i
++)
2986 c
->be
->be_update_refs
[i
] = c
->be
->be_update_refs
[i
+1];
2990 if(!SLAP_SHADOW(c
->be
) && !c
->be
->be_syncinfo
) {
2991 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> must appear after syncrepl or updatedn",
2993 Debug(LDAP_DEBUG_ANY
, "%s: %s\n",
2994 c
->log
, c
->cr_msg
, 0);
2998 if(validate_global_referral(c
->argv
[1])) {
2999 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> invalid URL", c
->argv
[0] );
3000 Debug(LDAP_DEBUG_ANY
, "%s: %s (%s)\n",
3001 c
->log
, c
->cr_msg
, c
->argv
[1]);
3004 ber_str2bv(c
->argv
[1], 0, 0, &val
);
3005 if(value_add_one(&c
->be
->be_update_refs
, &val
)) return(LDAP_OTHER
);
3010 config_obsolete(ConfigArgs
*c
) {
3011 if (c
->op
== SLAP_CONFIG_EMIT
)
3014 snprintf( c
->cr_msg
, sizeof( c
->cr_msg
), "<%s> keyword is obsolete (ignored)",
3016 Debug(LDAP_DEBUG_ANY
, "%s: %s\n", c
->log
, c
->cr_msg
, 0);
3021 config_include(ConfigArgs
*c
) {
3022 int savelineno
= c
->lineno
;
3025 ConfigFile
*cfsave
= cfn
;
3026 ConfigFile
*cf2
= NULL
;
3028 /* Leftover from RE23. No dynamic config for include files */
3029 if ( c
->op
== SLAP_CONFIG_EMIT
|| c
->op
== LDAP_MOD_DELETE
)
3032 cf
= ch_calloc( 1, sizeof(ConfigFile
));
3033 if ( cfn
->c_kids
) {
3034 for (cf2
=cfn
->c_kids
; cf2
&& cf2
->c_sibs
; cf2
=cf2
->c_sibs
) ;
3040 ber_str2bv( c
->argv
[1], 0, 1, &cf
->c_file
);
3041 rc
= read_config_file(c
->argv
[1], c
->depth
+ 1, c
, config_back_cf_table
);
3042 c
->lineno
= savelineno
- 1;
3045 if ( cf2
) cf2
->c_sibs
= NULL
;
3046 else cfn
->c_kids
= NULL
;
3047 ch_free( cf
->c_file
.bv_val
);
3057 config_tls_option(ConfigArgs
*c
) {
3059 LDAP
*ld
= slap_tls_ld
;
3061 case CFG_TLS_RAND
: flag
= LDAP_OPT_X_TLS_RANDOM_FILE
; ld
= NULL
; break;
3062 case CFG_TLS_CIPHER
: flag
= LDAP_OPT_X_TLS_CIPHER_SUITE
; break;
3063 case CFG_TLS_CERT_FILE
: flag
= LDAP_OPT_X_TLS_CERTFILE
; break;
3064 case CFG_TLS_CERT_KEY
: flag
= LDAP_OPT_X_TLS_KEYFILE
; break;
3065 case CFG_TLS_CA_PATH
: flag
= LDAP_OPT_X_TLS_CACERTDIR
; break;
3066 case CFG_TLS_CA_FILE
: flag
= LDAP_OPT_X_TLS_CACERTFILE
; break;
3067 case CFG_TLS_DH_FILE
: flag
= LDAP_OPT_X_TLS_DHFILE
; break;
3069 case CFG_TLS_CRL_FILE
: flag
= LDAP_OPT_X_TLS_CRLFILE
; break;
3071 default: Debug(LDAP_DEBUG_ANY
, "%s: "
3072 "unknown tls_option <0x%x>\n",
3073 c
->log
, c
->type
, 0);
3076 if (c
->op
== SLAP_CONFIG_EMIT
) {
3077 return ldap_pvt_tls_get_option( ld
, flag
, &c
->value_string
);
3078 } else if ( c
->op
== LDAP_MOD_DELETE
) {
3079 return ldap_pvt_tls_set_option( ld
, flag
, NULL
);
3081 ch_free(c
->value_string
);
3082 return(ldap_pvt_tls_set_option(ld
, flag
, c
->argv
[1]));
3085 /* FIXME: this ought to be provided by libldap */
3087 config_tls_config(ConfigArgs
*c
) {
3090 case CFG_TLS_CRLCHECK
: flag
= LDAP_OPT_X_TLS_CRLCHECK
; break;
3091 case CFG_TLS_VERIFY
: flag
= LDAP_OPT_X_TLS_REQUIRE_CERT
; break;
3093 Debug(LDAP_DEBUG_ANY
, "%s: "
3094 "unknown tls_option <0x%x>\n",
3095 c
->log
, c
->type
, 0);
3098 if (c
->op
== SLAP_CONFIG_EMIT
) {
3099 return slap_tls_get_config( slap_tls_ld
, flag
, &c
->value_string
);
3100 } else if ( c
->op
== LDAP_MOD_DELETE
) {
3102 return ldap_pvt_tls_set_option( slap_tls_ld
, flag
, &i
);
3104 ch_free( c
->value_string
);
3105 if ( isdigit( (unsigned char)c
->argv
[1][0] ) ) {
3106 if ( lutil_atoi( &i
, c
->argv
[1] ) != 0 ) {
3107 Debug(LDAP_DEBUG_ANY
, "%s: "
3108 "unable to parse %s \"%s\"\n",
3109 c
->log
, c
->argv
[0], c
->argv
[1] );
3112 return(ldap_pvt_tls_set_option(slap_tls_ld
, flag
, &i
));
3114 return(ldap_int_tls_config(slap_tls_ld
, flag
, c
->argv
[1]));
3119 static CfEntryInfo
*
3120 config_find_base( CfEntryInfo
*root
, struct berval
*dn
, CfEntryInfo
**last
)
3130 if ( dn_match( &root
->ce_entry
->e_nname
, dn
))
3133 c
= dn
->bv_val
+dn
->bv_len
;
3134 for (;*c
!= ',';c
--);
3138 for (--c
;c
>dn
->bv_val
&& *c
!= ',';c
--);
3142 cdn
.bv_len
= dn
->bv_len
- (cdn
.bv_val
- dn
->bv_val
);
3144 root
= root
->ce_kids
;
3146 for (;root
;root
=root
->ce_sibs
) {
3147 if ( dn_match( &root
->ce_entry
->e_nname
, &cdn
)) {
3148 if ( cdn
.bv_val
== dn
->bv_val
) {
3158 typedef struct setup_cookie
{
3168 config_ldif_resp( Operation
*op
, SlapReply
*rs
)
3170 if ( rs
->sr_type
== REP_SEARCH
) {
3171 setup_cookie
*sc
= op
->o_callback
->sc_private
;
3173 sc
->cfb
->cb_got_ldif
= 1;
3174 /* Does the frontend exist? */
3175 if ( !sc
->got_frontend
) {
3176 if ( !strncmp( rs
->sr_entry
->e_nname
.bv_val
,
3177 "olcDatabase", STRLENOF( "olcDatabase" ))) {
3178 if ( strncmp( rs
->sr_entry
->e_nname
.bv_val
+
3179 STRLENOF( "olcDatabase" ), "={-1}frontend",
3180 STRLENOF( "={-1}frontend" ))) {
3183 sc
->ca
->be
= frontendDB
;
3184 sc
->ca
->bi
= frontendDB
->bd_info
;
3185 frontendDB
->be_cf_ocs
= &CFOC_FRONTEND
;
3186 rdn
.bv_val
= sc
->ca
->log
;
3187 rdn
.bv_len
= snprintf(rdn
.bv_val
, sizeof( sc
->ca
->log
),
3188 "%s=" SLAP_X_ORDERED_FMT
"%s",
3189 cfAd_database
->ad_cname
.bv_val
, -1,
3190 sc
->ca
->bi
->bi_type
);
3192 sc
->frontend
= config_build_entry( op
, rs
,
3193 sc
->cfb
->cb_root
, sc
->ca
, &rdn
, &CFOC_DATABASE
,
3194 sc
->ca
->be
->be_cf_ocs
);
3203 /* Does the configDB exist? */
3204 if ( sc
->got_frontend
&& !sc
->got_config
&&
3205 !strncmp( rs
->sr_entry
->e_nname
.bv_val
,
3206 "olcDatabase", STRLENOF( "olcDatabase" ))) {
3207 if ( strncmp( rs
->sr_entry
->e_nname
.bv_val
+
3208 STRLENOF( "olcDatabase" ), "={0}config",
3209 STRLENOF( "={0}config" ))) {
3212 sc
->ca
->be
= LDAP_STAILQ_FIRST( &backendDB
);
3213 sc
->ca
->bi
= sc
->ca
->be
->bd_info
;
3214 rdn
.bv_val
= sc
->ca
->log
;
3215 rdn
.bv_len
= snprintf(rdn
.bv_val
, sizeof( sc
->ca
->log
),
3216 "%s=" SLAP_X_ORDERED_FMT
"%s",
3217 cfAd_database
->ad_cname
.bv_val
, 0,
3218 sc
->ca
->bi
->bi_type
);
3220 sc
->config
= config_build_entry( op
, rs
, sc
->cfb
->cb_root
,
3221 sc
->ca
, &rdn
, &CFOC_DATABASE
, sc
->ca
->be
->be_cf_ocs
);
3228 rs
->sr_err
= config_add_internal( sc
->cfb
, rs
->sr_entry
, sc
->ca
, NULL
, NULL
, NULL
);
3229 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
3230 Debug( LDAP_DEBUG_ANY
, "config error processing %s: %s\n",
3231 rs
->sr_entry
->e_name
.bv_val
, sc
->ca
->cr_msg
, 0 );
3237 /* Configure and read the underlying back-ldif store */
3239 config_setup_ldif( BackendDB
*be
, const char *dir
, int readit
) {
3240 CfBackInfo
*cfb
= be
->be_private
;
3246 slap_callback cb
= { NULL
, config_ldif_resp
, NULL
, NULL
};
3247 Connection conn
= {0};
3248 OperationBuffer opbuf
;
3250 SlapReply rs
= {REP_RESULT
};
3251 Filter filter
= { LDAP_FILTER_PRESENT
};
3252 struct berval filterstr
= BER_BVC("(objectclass=*)");
3255 /* Is the config directory available? */
3256 if ( stat( dir
, &st
) < 0 ) {
3257 /* No, so don't bother using the backing store.
3258 * All changes will be in-memory only.
3263 cfb
->cb_db
.bd_info
= backend_info( "ldif" );
3264 if ( !cfb
->cb_db
.bd_info
)
3265 return 0; /* FIXME: eventually this will be a fatal error */
3267 if ( backend_db_init( "ldif", &cfb
->cb_db
, -1, NULL
) == NULL
)
3270 cfb
->cb_db
.be_suffix
= be
->be_suffix
;
3271 cfb
->cb_db
.be_nsuffix
= be
->be_nsuffix
;
3273 /* The suffix is always "cn=config". The underlying DB's rootdn
3274 * is always the same as the suffix.
3276 cfb
->cb_db
.be_rootdn
= be
->be_suffix
[0];
3277 cfb
->cb_db
.be_rootndn
= be
->be_nsuffix
[0];
3279 ber_str2bv( dir
, 0, 1, &cfdir
);
3284 argv
[0] = "directory";
3285 argv
[1] = (char *)dir
;
3290 c
.table
= Cft_Database
;
3292 ct
= config_find_keyword( c
.be
->be_cf_ocs
->co_table
, &c
);
3296 if ( config_add_vals( ct
, &c
))
3299 if ( backend_startup_one( &cfb
->cb_db
, &c
.reply
))
3303 void *thrctx
= ldap_pvt_thread_pool_context();
3306 connection_fake_init( &conn
, &opbuf
, thrctx
);
3309 filter
.f_desc
= slap_schema
.si_ad_objectClass
;
3311 op
->o_tag
= LDAP_REQ_SEARCH
;
3313 op
->ors_filter
= &filter
;
3314 op
->ors_filterstr
= filterstr
;
3315 op
->ors_scope
= LDAP_SCOPE_SUBTREE
;
3317 op
->o_dn
= c
.be
->be_rootdn
;
3318 op
->o_ndn
= c
.be
->be_rootndn
;
3320 op
->o_req_dn
= be
->be_suffix
[0];
3321 op
->o_req_ndn
= be
->be_nsuffix
[0];
3323 op
->ors_tlimit
= SLAP_NO_LIMIT
;
3324 op
->ors_slimit
= SLAP_NO_LIMIT
;
3326 op
->ors_attrs
= slap_anlist_all_attributes
;
3327 op
->ors_attrsonly
= 0;
3329 op
->o_callback
= &cb
;
3332 cb
.sc_private
= &sc
;
3333 sc
.got_frontend
= 0;
3338 op
->o_bd
= &cfb
->cb_db
;
3340 /* Allow unknown attrs in DNs */
3341 prev_DN_strict
= slap_DN_strict
;
3344 rc
= op
->o_bd
->be_search( op
, &rs
);
3346 /* Restore normal DN validation */
3347 slap_DN_strict
= prev_DN_strict
;
3349 op
->o_tag
= LDAP_REQ_ADD
;
3350 if ( rc
== LDAP_SUCCESS
&& sc
.frontend
) {
3351 op
->ora_e
= sc
.frontend
;
3352 rc
= op
->o_bd
->be_add( op
, &rs
);
3354 if ( rc
== LDAP_SUCCESS
&& sc
.config
) {
3355 op
->ora_e
= sc
.config
;
3356 rc
= op
->o_bd
->be_add( op
, &rs
);
3358 ldap_pvt_thread_pool_context_reset( thrctx
);
3361 /* ITS#4194 - only use if it's present, or we're converting. */
3362 if ( !readit
|| rc
== LDAP_SUCCESS
)
3363 cfb
->cb_use_ldif
= 1;
3369 CfOc_cmp( const void *c1
, const void *c2
) {
3370 const ConfigOCs
*co1
= c1
;
3371 const ConfigOCs
*co2
= c2
;
3373 return ber_bvcmp( co1
->co_name
, co2
->co_name
);
3377 config_register_schema(ConfigTable
*ct
, ConfigOCs
*ocs
) {
3380 i
= init_config_attrs( ct
);
3383 /* set up the objectclasses */
3384 i
= init_config_ocs( ocs
);
3387 for (i
=0; ocs
[i
].co_def
; i
++) {
3388 if ( ocs
[i
].co_oc
) {
3389 ocs
[i
].co_name
= &ocs
[i
].co_oc
->soc_cname
;
3390 if ( !ocs
[i
].co_table
)
3391 ocs
[i
].co_table
= ct
;
3392 avl_insert( &CfOcTree
, &ocs
[i
], CfOc_cmp
, avl_dup_error
);
3399 read_config(const char *fname
, const char *dir
) {
3402 const char *cfdir
, *cfname
;
3405 /* Setup the config backend */
3406 be
= backend_db_init( "config", NULL
, 0, NULL
);
3410 cfb
= be
->be_private
;
3411 be
->be_dfltaccess
= ACL_NONE
;
3413 /* If no .conf, or a dir was specified, setup the dir */
3414 if ( !fname
|| dir
) {
3416 /* If explicitly given, check for existence */
3419 if ( stat( dir
, &st
) < 0 ) {
3420 Debug( LDAP_DEBUG_ANY
,
3421 "invalid config directory %s, error %d\n",
3427 cfdir
= SLAPD_DEFAULT_CONFIGDIR
;
3429 /* if fname is defaulted, try reading .d */
3430 rc
= config_setup_ldif( be
, cfdir
, !fname
);
3433 /* It may be OK if the base object doesn't exist yet. */
3434 if ( rc
!= LDAP_NO_SUCH_OBJECT
)
3436 /* ITS#4194: But if dir was specified and no fname,
3437 * then we were supposed to read the dir. Unless we're
3438 * trying to slapadd the dir...
3440 if ( dir
&& !fname
) {
3441 if ( slapMode
& (SLAP_SERVER_MODE
|SLAP_TOOL_READMAIN
|SLAP_TOOL_READONLY
))
3443 /* Assume it's slapadd with a config dir, let it continue */
3445 cfb
->cb_got_ldif
= 1;
3446 cfb
->cb_use_ldif
= 1;
3451 /* If we read the config from back-ldif, nothing to do here */
3452 if ( cfb
->cb_got_ldif
) {
3461 cfname
= SLAPD_DEFAULT_CONFIGFILE
;
3463 rc
= read_config_file(cfname
, 0, NULL
, config_back_cf_table
);
3466 ber_str2bv( cfname
, 0, 1, &cfb
->cb_config
->c_file
);
3469 if ( rc
== 0 && BER_BVISNULL( &frontendDB
->be_schemadn
) ) {
3470 ber_str2bv( SLAPD_SCHEMA_DN
, STRLENOF( SLAPD_SCHEMA_DN
), 1,
3471 &frontendDB
->be_schemadn
);
3472 rc
= dnNormalize( 0, NULL
, NULL
, &frontendDB
->be_schemadn
, &frontendDB
->be_schemandn
, NULL
);
3473 if ( rc
!= LDAP_SUCCESS
) {
3474 Debug(LDAP_DEBUG_ANY
, "read_config: "
3475 "unable to normalize default schema DN \"%s\"\n",
3476 frontendDB
->be_schemadn
.bv_val
, 0, 0 );
3477 /* must not happen */
3485 config_back_bind( Operation
*op
, SlapReply
*rs
)
3487 if ( be_isroot_pw( op
) ) {
3488 ber_dupbv( &op
->orb_edn
, be_root_dn( op
->o_bd
));
3489 /* frontend sends result */
3490 return LDAP_SUCCESS
;
3493 rs
->sr_err
= LDAP_INVALID_CREDENTIALS
;
3494 send_ldap_result( op
, rs
);
3500 config_send( Operation
*op
, SlapReply
*rs
, CfEntryInfo
*ce
, int depth
)
3504 if ( test_filter( op
, ce
->ce_entry
, op
->ors_filter
) == LDAP_COMPARE_TRUE
)
3506 rs
->sr_attrs
= op
->ors_attrs
;
3507 rs
->sr_entry
= ce
->ce_entry
;
3509 rc
= send_search_entry( op
, rs
);
3511 if ( op
->ors_scope
== LDAP_SCOPE_SUBTREE
) {
3512 if ( ce
->ce_kids
) {
3513 rc
= config_send( op
, rs
, ce
->ce_kids
, 1 );
3514 if ( rc
) return rc
;
3517 for (ce
=ce
->ce_sibs
; ce
; ce
=ce
->ce_sibs
) {
3518 rc
= config_send( op
, rs
, ce
, 0 );
3526 static ConfigTable
*
3527 config_find_table( ConfigOCs
**colst
, int nocs
, AttributeDescription
*ad
,
3532 for (j
=0; j
<nocs
; j
++) {
3533 for (i
=0; colst
[j
]->co_table
[i
].name
; i
++)
3534 if ( colst
[j
]->co_table
[i
].ad
== ad
) {
3535 ca
->table
= colst
[j
]->co_type
;
3536 return &colst
[j
]->co_table
[i
];
3542 /* Sort the attributes of the entry according to the order defined
3543 * in the objectclass, with required attributes occurring before
3544 * allowed attributes. For any attributes with sequencing dependencies
3545 * (e.g., rootDN must be defined after suffix) the objectclass must
3546 * list the attributes in the desired sequence.
3549 sort_attrs( Entry
*e
, ConfigOCs
**colst
, int nocs
)
3551 Attribute
*a
, *head
= NULL
, *tail
= NULL
, **prev
;
3554 for (i
=0; i
<nocs
; i
++) {
3555 if ( colst
[i
]->co_oc
->soc_required
) {
3556 AttributeType
**at
= colst
[i
]->co_oc
->soc_required
;
3557 for (j
=0; at
[j
]; j
++) {
3558 for (a
=e
->e_attrs
, prev
=&e
->e_attrs
; a
;
3559 prev
= &(*prev
)->a_next
, a
=a
->a_next
) {
3560 if ( a
->a_desc
== at
[j
]->sat_ad
) {
3574 if ( colst
[i
]->co_oc
->soc_allowed
) {
3575 AttributeType
**at
= colst
[i
]->co_oc
->soc_allowed
;
3576 for (j
=0; at
[j
]; j
++) {
3577 for (a
=e
->e_attrs
, prev
=&e
->e_attrs
; a
;
3578 prev
= &(*prev
)->a_next
, a
=a
->a_next
) {
3579 if ( a
->a_desc
== at
[j
]->sat_ad
) {
3595 tail
->a_next
= e
->e_attrs
;
3601 check_vals( ConfigTable
*ct
, ConfigArgs
*ca
, void *ptr
, int isAttr
)
3603 Attribute
*a
= NULL
;
3604 AttributeDescription
*ad
;
3614 Modifications
*ml
= ptr
;
3616 vals
= ml
->sml_values
;
3619 if ( a
&& ( ad
->ad_type
->sat_flags
& SLAP_AT_ORDERED_VAL
)) {
3620 rc
= ordered_value_sort( a
, 1 );
3622 snprintf(ca
->cr_msg
, sizeof( ca
->cr_msg
), "ordered_value_sort failed on attr %s\n",
3623 ad
->ad_cname
.bv_val
);
3627 for ( i
=0; vals
[i
].bv_val
; i
++ ) {
3628 ca
->line
= vals
[i
].bv_val
;
3629 if (( ad
->ad_type
->sat_flags
& SLAP_AT_ORDERED_VAL
) &&
3630 ca
->line
[0] == '{' ) {
3631 char *idx
= strchr( ca
->line
, '}' );
3632 if ( idx
) ca
->line
= idx
+1;
3634 rc
= config_parse_vals( ct
, ca
, i
);
3643 config_rename_attr( SlapReply
*rs
, Entry
*e
, struct berval
*rdn
,
3646 struct berval rtype
, rval
;
3648 AttributeDescription
*ad
= NULL
;
3650 dnRdn( &e
->e_name
, rdn
);
3651 rval
.bv_val
= strchr(rdn
->bv_val
, '=' ) + 1;
3652 rval
.bv_len
= rdn
->bv_len
- (rval
.bv_val
- rdn
->bv_val
);
3653 rtype
.bv_val
= rdn
->bv_val
;
3654 rtype
.bv_len
= rval
.bv_val
- rtype
.bv_val
- 1;
3657 slap_bv2ad( &rtype
, &ad
, &rs
->sr_text
);
3658 a
= attr_find( e
->e_attrs
, ad
);
3659 if (!a
) return LDAP_NAMING_VIOLATION
;
3666 config_rename_kids( CfEntryInfo
*ce
)
3669 struct berval rdn
, nrdn
;
3671 for (ce2
= ce
->ce_kids
; ce2
; ce2
= ce2
->ce_sibs
) {
3672 dnRdn ( &ce2
->ce_entry
->e_name
, &rdn
);
3673 dnRdn ( &ce2
->ce_entry
->e_nname
, &nrdn
);
3674 free( ce2
->ce_entry
->e_name
.bv_val
);
3675 free( ce2
->ce_entry
->e_nname
.bv_val
);
3676 build_new_dn( &ce2
->ce_entry
->e_name
, &ce
->ce_entry
->e_name
,
3678 build_new_dn( &ce2
->ce_entry
->e_nname
, &ce
->ce_entry
->e_nname
,
3680 config_rename_kids( ce2
);
3685 config_rename_one( Operation
*op
, SlapReply
*rs
, Entry
*e
,
3686 CfEntryInfo
*parent
, Attribute
*a
, struct berval
*newrdn
,
3687 struct berval
*nnewrdn
, int use_ldif
)
3691 struct berval odn
, ondn
;
3695 build_new_dn( &e
->e_name
, &parent
->ce_entry
->e_name
, newrdn
, NULL
);
3696 build_new_dn( &e
->e_nname
, &parent
->ce_entry
->e_nname
, nnewrdn
, NULL
);
3699 free( a
->a_vals
[0].bv_val
);
3700 ptr1
= strchr( newrdn
->bv_val
, '=' ) + 1;
3701 a
->a_vals
[0].bv_len
= newrdn
->bv_len
- (ptr1
- newrdn
->bv_val
);
3702 a
->a_vals
[0].bv_val
= ch_malloc( a
->a_vals
[0].bv_len
+ 1 );
3703 strcpy( a
->a_vals
[0].bv_val
, ptr1
);
3705 if ( a
->a_nvals
!= a
->a_vals
) {
3706 free( a
->a_nvals
[0].bv_val
);
3707 ptr1
= strchr( nnewrdn
->bv_val
, '=' ) + 1;
3708 a
->a_nvals
[0].bv_len
= nnewrdn
->bv_len
- (ptr1
- nnewrdn
->bv_val
);
3709 a
->a_nvals
[0].bv_val
= ch_malloc( a
->a_nvals
[0].bv_len
+ 1 );
3710 strcpy( a
->a_nvals
[0].bv_val
, ptr1
);
3713 CfBackInfo
*cfb
= (CfBackInfo
*)op
->o_bd
->be_private
;
3714 BackendDB
*be
= op
->o_bd
;
3715 slap_callback sc
= { NULL
, slap_null_cb
, NULL
, NULL
}, *scp
;
3716 struct berval dn
, ndn
, xdn
, xndn
;
3718 op
->o_bd
= &cfb
->cb_db
;
3720 /* Save current rootdn; use the underlying DB's rootdn */
3724 xndn
= op
->o_req_ndn
;
3725 op
->o_dn
= op
->o_bd
->be_rootdn
;
3726 op
->o_ndn
= op
->o_bd
->be_rootndn
;
3728 op
->o_req_ndn
= ondn
;
3730 scp
= op
->o_callback
;
3731 op
->o_callback
= &sc
;
3732 op
->orr_newrdn
= *newrdn
;
3733 op
->orr_nnewrdn
= *nnewrdn
;
3734 op
->orr_newSup
= NULL
;
3735 op
->orr_nnewSup
= NULL
;
3736 op
->orr_deleteoldrdn
= 1;
3737 op
->orr_modlist
= NULL
;
3738 slap_modrdn2mods( op
, rs
);
3739 slap_mods_opattrs( op
, &op
->orr_modlist
, 1 );
3740 rc
= op
->o_bd
->be_modrdn( op
, rs
);
3741 slap_mods_free( op
->orr_modlist
, 1 );
3744 op
->o_callback
= scp
;
3748 op
->o_req_ndn
= xndn
;
3751 free( ondn
.bv_val
);
3753 config_rename_kids( e
->e_private
);
3758 config_renumber_one( Operation
*op
, SlapReply
*rs
, CfEntryInfo
*parent
,
3759 Entry
*e
, int idx
, int tailindex
, int use_ldif
)
3761 struct berval ival
, newrdn
, nnewrdn
;
3764 char ibuf
[32], *ptr1
, *ptr2
= NULL
;
3767 rc
= config_rename_attr( rs
, e
, &rdn
, &a
);
3768 if ( rc
) return rc
;
3771 ival
.bv_len
= snprintf( ibuf
, sizeof( ibuf
), SLAP_X_ORDERED_FMT
, idx
);
3772 if ( ival
.bv_len
>= sizeof( ibuf
) ) {
3773 return LDAP_NAMING_VIOLATION
;
3776 newrdn
.bv_len
= rdn
.bv_len
+ ival
.bv_len
;
3777 newrdn
.bv_val
= ch_malloc( newrdn
.bv_len
+1 );
3780 ptr1
= lutil_strncopy( newrdn
.bv_val
, rdn
.bv_val
, rdn
.bv_len
);
3781 ptr1
= lutil_strcopy( ptr1
, ival
.bv_val
);
3784 ptr2
= ber_bvchr( &rdn
, '}' );
3788 ptr2
= rdn
.bv_val
+ a
->a_desc
->ad_cname
.bv_len
+ 1;
3790 xlen
= rdn
.bv_len
- (ptr2
- rdn
.bv_val
);
3791 ptr1
= lutil_strncopy( newrdn
.bv_val
, a
->a_desc
->ad_cname
.bv_val
,
3792 a
->a_desc
->ad_cname
.bv_len
);
3794 ptr1
= lutil_strcopy( ptr1
, ival
.bv_val
);
3795 ptr1
= lutil_strncopy( ptr1
, ptr2
, xlen
);
3799 /* Do the equivalent of ModRDN */
3800 /* Replace DN / NDN */
3801 newrdn
.bv_len
= ptr1
- newrdn
.bv_val
;
3802 rdnNormalize( 0, NULL
, NULL
, &newrdn
, &nnewrdn
, NULL
);
3803 rc
= config_rename_one( op
, rs
, e
, parent
, a
, &newrdn
, &nnewrdn
, use_ldif
);
3805 free( nnewrdn
.bv_val
);
3806 free( newrdn
.bv_val
);
3811 check_name_index( CfEntryInfo
*parent
, ConfigType ce_type
, Entry
*e
,
3812 SlapReply
*rs
, int *renum
, int *ibase
)
3815 int index
= -1, gotindex
= 0, nsibs
, rc
= 0;
3816 int renumber
= 0, tailindex
= 0, isfrontend
= 0, isconfig
= 0;
3817 char *ptr1
, *ptr2
= NULL
;
3820 if ( renum
) *renum
= 0;
3822 /* These entries don't get indexed/renumbered */
3823 if ( ce_type
== Cft_Global
) return 0;
3824 if ( ce_type
== Cft_Schema
&& parent
->ce_type
== Cft_Global
) return 0;
3826 if ( ce_type
== Cft_Module
)
3829 /* See if the rdn has an index already */
3830 dnRdn( &e
->e_name
, &rdn
);
3831 if ( ce_type
== Cft_Database
) {
3832 if ( !strncmp( rdn
.bv_val
+ rdn
.bv_len
- STRLENOF("frontend"),
3833 "frontend", STRLENOF("frontend") ))
3835 else if ( !strncmp( rdn
.bv_val
+ rdn
.bv_len
- STRLENOF("config"),
3836 "config", STRLENOF("config") ))
3839 ptr1
= ber_bvchr( &e
->e_name
, '{' );
3840 if ( ptr1
&& ptr1
- e
->e_name
.bv_val
< rdn
.bv_len
) {
3842 ptr2
= strchr( ptr1
, '}' );
3843 if (!ptr2
|| ptr2
- e
->e_name
.bv_val
> rdn
.bv_len
)
3844 return LDAP_NAMING_VIOLATION
;
3845 if ( ptr2
-ptr1
== 1)
3846 return LDAP_NAMING_VIOLATION
;
3848 index
= strtol( ptr1
+ 1, &next
, 10 );
3849 if ( next
== ptr1
+ 1 || next
[ 0 ] != '}' ) {
3850 return LDAP_NAMING_VIOLATION
;
3853 /* Special case, we allow -1 for the frontendDB */
3854 if ( index
!= -1 || !isfrontend
)
3855 return LDAP_NAMING_VIOLATION
;
3857 if ( isconfig
&& index
!= 0 ){
3858 return LDAP_NAMING_VIOLATION
;
3862 /* count related kids */
3863 for (nsibs
=0, ce
=parent
->ce_kids
; ce
; ce
=ce
->ce_sibs
) {
3864 if ( ce
->ce_type
== ce_type
) nsibs
++;
3867 /* account for -1 frontend */
3868 if ( ce_type
== Cft_Database
)
3871 if ( index
!= nsibs
) {
3873 if ( index
< nsibs
) {
3874 if ( tailindex
) return LDAP_NAMING_VIOLATION
;
3875 /* Siblings need to be renumbered */
3876 if ( index
!= -1 || !isfrontend
)
3880 /* config DB is always "0" */
3881 if ( isconfig
&& index
== -1 ) {
3884 if ( !isfrontend
&& index
== -1 ) {
3888 /* just make index = nsibs */
3890 rc
= config_renumber_one( NULL
, rs
, parent
, e
, index
, tailindex
, 0 );
3893 if ( ibase
) *ibase
= index
;
3894 if ( renum
) *renum
= renumber
;
3899 count_oc( ObjectClass
*oc
, ConfigOCs
***copp
, int *nocs
)
3904 co
.co_name
= &oc
->soc_cname
;
3905 cop
= avl_find( CfOcTree
, &co
, CfOc_cmp
);
3909 /* check for duplicates */
3910 for ( i
= 0; i
< *nocs
; i
++ ) {
3911 if ( *copp
&& (*copp
)[i
] == cop
) {
3917 ConfigOCs
**tmp
= ch_realloc( *copp
, (*nocs
+ 1)*sizeof( ConfigOCs
* ) );
3918 if ( tmp
== NULL
) {
3922 (*copp
)[*nocs
] = cop
;
3927 for ( sups
= oc
->soc_sups
; sups
&& *sups
; sups
++ ) {
3928 if ( count_oc( *sups
, copp
, nocs
) ) {
3937 count_ocs( Attribute
*oc_at
, int *nocs
)
3940 ConfigOCs
**colst
= NULL
;
3944 for ( i
= 0; !BER_BVISNULL( &oc_at
->a_nvals
[i
] ); i
++ )
3948 ObjectClass
*oc
= oc_bvfind( &oc_at
->a_nvals
[i
] );
3950 assert( oc
!= NULL
);
3951 if ( count_oc( oc
, &colst
, nocs
) ) {
3961 cfAddInclude( CfEntryInfo
*p
, Entry
*e
, ConfigArgs
*ca
)
3963 /* Leftover from RE23. Never parse this entry */
3964 return LDAP_COMPARE_TRUE
;
3968 cfAddSchema( CfEntryInfo
*p
, Entry
*e
, ConfigArgs
*ca
)
3972 /* This entry is hardcoded, don't re-parse it */
3973 if ( p
->ce_type
== Cft_Global
) {
3974 cfn
= p
->ce_private
;
3975 ca
->ca_private
= cfn
;
3976 return LDAP_COMPARE_TRUE
;
3978 if ( p
->ce_type
!= Cft_Schema
)
3979 return LDAP_CONSTRAINT_VIOLATION
;
3981 cfn
= ch_calloc( 1, sizeof(ConfigFile
) );
3982 ca
->ca_private
= cfn
;
3983 cfo
= p
->ce_private
;
3984 cfn
->c_sibs
= cfo
->c_kids
;
3986 return LDAP_SUCCESS
;
3990 cfAddDatabase( CfEntryInfo
*p
, Entry
*e
, struct config_args_s
*ca
)
3992 if ( p
->ce_type
!= Cft_Global
) {
3993 return LDAP_CONSTRAINT_VIOLATION
;
3995 /* config must be {0}, nothing else allowed */
3996 if ( !strncmp( e
->e_nname
.bv_val
, "olcDatabase={0}", STRLENOF("olcDatabase={0}")) &&
3997 strncmp( e
->e_nname
.bv_val
+ STRLENOF("olcDatabase={0}"), "config,", STRLENOF("config,") )) {
3998 return LDAP_CONSTRAINT_VIOLATION
;
4000 ca
->be
= frontendDB
; /* just to get past check_vals */
4001 return LDAP_SUCCESS
;
4005 cfAddBackend( CfEntryInfo
*p
, Entry
*e
, struct config_args_s
*ca
)
4007 if ( p
->ce_type
!= Cft_Global
) {
4008 return LDAP_CONSTRAINT_VIOLATION
;
4010 return LDAP_SUCCESS
;
4014 cfAddModule( CfEntryInfo
*p
, Entry
*e
, struct config_args_s
*ca
)
4016 if ( p
->ce_type
!= Cft_Global
) {
4017 return LDAP_CONSTRAINT_VIOLATION
;
4019 return LDAP_SUCCESS
;
4023 cfAddOverlay( CfEntryInfo
*p
, Entry
*e
, struct config_args_s
*ca
)
4025 if ( p
->ce_type
!= Cft_Database
) {
4026 return LDAP_CONSTRAINT_VIOLATION
;
4029 return LDAP_SUCCESS
;
4033 schema_destroy_one( ConfigArgs
*ca
, ConfigOCs
**colst
, int nocs
,
4038 AttributeDescription
*ad
;
4043 if ( cfn
->c_cr_head
) {
4044 struct berval bv
= BER_BVC("olcDitContentRules");
4046 slap_bv2ad( &bv
, &ad
, &text
);
4047 ct
= config_find_table( colst
, nocs
, ad
, ca
);
4048 config_del_vals( ct
, ca
);
4050 if ( cfn
->c_oc_head
) {
4051 struct berval bv
= BER_BVC("olcObjectClasses");
4053 slap_bv2ad( &bv
, &ad
, &text
);
4054 ct
= config_find_table( colst
, nocs
, ad
, ca
);
4055 config_del_vals( ct
, ca
);
4057 if ( cfn
->c_at_head
) {
4058 struct berval bv
= BER_BVC("olcAttributeTypes");
4060 slap_bv2ad( &bv
, &ad
, &text
);
4061 ct
= config_find_table( colst
, nocs
, ad
, ca
);
4062 config_del_vals( ct
, ca
);
4064 if ( cfn
->c_om_head
) {
4065 struct berval bv
= BER_BVC("olcObjectIdentifier");
4067 slap_bv2ad( &bv
, &ad
, &text
);
4068 ct
= config_find_table( colst
, nocs
, ad
, ca
);
4069 config_del_vals( ct
, ca
);
4071 cfo
= p
->ce_private
;
4072 cfo
->c_kids
= cfn
->c_sibs
;
4077 config_add_oc( ConfigOCs
**cop
, CfEntryInfo
*last
, Entry
*e
, ConfigArgs
*ca
)
4079 int rc
= LDAP_CONSTRAINT_VIOLATION
;
4082 if ( (*cop
)->co_ldadd
) {
4083 rc
= (*cop
)->co_ldadd( last
, e
, ca
);
4084 if ( rc
!= LDAP_CONSTRAINT_VIOLATION
) {
4089 for ( ocp
= (*cop
)->co_oc
->soc_sups
; ocp
&& *ocp
; ocp
++ ) {
4090 ConfigOCs co
= { 0 };
4092 co
.co_name
= &(*ocp
)->soc_cname
;
4093 *cop
= avl_find( CfOcTree
, &co
, CfOc_cmp
);
4094 if ( *cop
== NULL
) {
4098 rc
= config_add_oc( cop
, last
, e
, ca
);
4099 if ( rc
!= LDAP_CONSTRAINT_VIOLATION
) {
4107 /* Parse an LDAP entry into config directives */
4109 config_add_internal( CfBackInfo
*cfb
, Entry
*e
, ConfigArgs
*ca
, SlapReply
*rs
,
4110 int *renum
, Operation
*op
)
4112 CfEntryInfo
*ce
, *last
= NULL
;
4113 ConfigOCs co
, *coptr
, **colst
;
4114 Attribute
*a
, *oc_at
, *soc_at
;
4115 int i
, ibase
= -1, nocs
, rc
= 0;
4118 char *ptr
, *log_prefix
= op
? op
->o_log_prefix
: "";
4120 memset( ca
, 0, sizeof(ConfigArgs
));
4122 /* Make sure parent exists and entry does not. But allow
4123 * Databases and Overlays to be inserted. Don't do any
4124 * auto-renumbering if manageDSAit control is present.
4126 ce
= config_find_base( cfb
->cb_root
, &e
->e_nname
, &last
);
4128 if ( ( op
&& op
->o_managedsait
) ||
4129 ( ce
->ce_type
!= Cft_Database
&& ce
->ce_type
!= Cft_Overlay
&&
4130 ce
->ce_type
!= Cft_Module
) )
4132 Debug( LDAP_DEBUG_TRACE
, "%s: config_add_internal: "
4133 "DN=\"%s\" already exists\n",
4134 log_prefix
, e
->e_name
.bv_val
, 0 );
4135 return LDAP_ALREADY_EXISTS
;
4139 dnParent( &e
->e_nname
, &pdn
);
4141 /* If last is NULL, the new entry is the root/suffix entry,
4142 * otherwise last should be the parent.
4144 if ( last
&& !dn_match( &last
->ce_entry
->e_nname
, &pdn
) ) {
4146 rs
->sr_matched
= last
->ce_entry
->e_name
.bv_val
;
4148 Debug( LDAP_DEBUG_TRACE
, "%s: config_add_internal: "
4149 "DN=\"%s\" not child of DN=\"%s\"\n",
4150 log_prefix
, e
->e_name
.bv_val
,
4151 last
->ce_entry
->e_name
.bv_val
);
4152 return LDAP_NO_SUCH_OBJECT
;
4156 /* No parent, must be root. This will never happen... */
4157 if ( !last
&& !be_isroot( op
) && !be_shadow_update( op
) ) {
4158 return LDAP_NO_SUCH_OBJECT
;
4161 if ( last
&& !access_allowed( op
, last
->ce_entry
,
4162 slap_schema
.si_ad_children
, NULL
, ACL_WADD
, NULL
) )
4164 Debug( LDAP_DEBUG_TRACE
, "%s: config_add_internal: "
4165 "DN=\"%s\" no write access to \"children\" of parent\n",
4166 log_prefix
, e
->e_name
.bv_val
, 0 );
4167 return LDAP_INSUFFICIENT_ACCESS
;
4171 oc_at
= attr_find( e
->e_attrs
, slap_schema
.si_ad_objectClass
);
4173 Debug( LDAP_DEBUG_TRACE
, "%s: config_add_internal: "
4174 "DN=\"%s\" no objectClass\n",
4175 log_prefix
, e
->e_name
.bv_val
, 0 );
4176 return LDAP_OBJECT_CLASS_VIOLATION
;
4179 soc_at
= attr_find( e
->e_attrs
, slap_schema
.si_ad_structuralObjectClass
);
4181 ObjectClass
*soc
= NULL
;
4182 char textbuf
[ SLAP_TEXT_BUFLEN
];
4183 const char *text
= textbuf
;
4185 /* FIXME: check result */
4186 rc
= structural_class( oc_at
->a_nvals
, &soc
, NULL
,
4187 &text
, textbuf
, sizeof(textbuf
), NULL
);
4188 if ( rc
!= LDAP_SUCCESS
) {
4189 Debug( LDAP_DEBUG_TRACE
, "%s: config_add_internal: "
4190 "DN=\"%s\" no structural objectClass (%s)\n",
4191 log_prefix
, e
->e_name
.bv_val
, text
);
4194 attr_merge_one( e
, slap_schema
.si_ad_structuralObjectClass
, &soc
->soc_cname
, NULL
);
4195 soc_at
= attr_find( e
->e_attrs
, slap_schema
.si_ad_structuralObjectClass
);
4196 if ( soc_at
== NULL
) {
4197 Debug( LDAP_DEBUG_TRACE
, "%s: config_add_internal: "
4198 "DN=\"%s\" no structural objectClass; "
4199 "unable to merge computed class %s\n",
4200 log_prefix
, e
->e_name
.bv_val
,
4201 soc
->soc_cname
.bv_val
);
4202 return LDAP_OBJECT_CLASS_VIOLATION
;
4205 Debug( LDAP_DEBUG_TRACE
, "%s: config_add_internal: "
4206 "DN=\"%s\" no structural objectClass; "
4207 "computed objectClass %s merged\n",
4208 log_prefix
, e
->e_name
.bv_val
,
4209 soc
->soc_cname
.bv_val
);
4212 /* Fake the coordinates based on whether we're part of an
4213 * LDAP Add or if reading the config dir
4216 ca
->fname
= "slapd";
4219 ca
->fname
= cfdir
.bv_val
;
4224 co
.co_name
= &soc_at
->a_nvals
[0];
4225 coptr
= avl_find( CfOcTree
, &co
, CfOc_cmp
);
4226 if ( coptr
== NULL
) {
4227 Debug( LDAP_DEBUG_TRACE
, "%s: config_add_internal: "
4228 "DN=\"%s\" no structural objectClass in configuration table\n",
4229 log_prefix
, e
->e_name
.bv_val
, 0 );
4230 return LDAP_OBJECT_CLASS_VIOLATION
;
4233 /* Only the root can be Cft_Global, everything else must
4234 * have a parent. Only limited nesting arrangements are allowed.
4236 rc
= LDAP_CONSTRAINT_VIOLATION
;
4237 if ( coptr
->co_type
== Cft_Global
&& !last
) {
4238 cfn
= cfb
->cb_config
;
4239 ca
->ca_private
= cfn
;
4240 ca
->be
= frontendDB
; /* just to get past check_vals */
4244 colst
= count_ocs( oc_at
, &nocs
);
4246 /* Check whether the Add is allowed by its parent, and do
4247 * any necessary arg setup
4250 rc
= config_add_oc( &coptr
, last
, e
, ca
);
4251 if ( rc
== LDAP_CONSTRAINT_VIOLATION
) {
4252 for ( i
= 0; i
<nocs
; i
++ ) {
4253 /* Already checked these */
4254 if ( colst
[i
]->co_oc
->soc_kind
== LDAP_SCHEMA_STRUCTURAL
)
4256 if ( colst
[i
]->co_ldadd
&&
4257 ( rc
= colst
[i
]->co_ldadd( last
, e
, ca
))
4258 != LDAP_CONSTRAINT_VIOLATION
) {
4264 if ( rc
== LDAP_CONSTRAINT_VIOLATION
) {
4265 Debug( LDAP_DEBUG_TRACE
, "%s: config_add_internal: "
4266 "DN=\"%s\" no structural objectClass add function\n",
4267 log_prefix
, e
->e_name
.bv_val
, 0 );
4268 return LDAP_OBJECT_CLASS_VIOLATION
;
4272 /* Add the entry but don't parse it, we already have its contents */
4273 if ( rc
== LDAP_COMPARE_TRUE
) {
4278 if ( rc
!= LDAP_SUCCESS
)
4281 /* Parse all the values and check for simple syntax errors before
4282 * performing any set actions.
4284 * If doing an LDAPadd, check for indexed names and any necessary
4285 * renaming/renumbering. Entries that don't need indexed names are
4286 * ignored. Entries that need an indexed name and arrive without one
4287 * are assigned to the end. Entries that arrive with an index may
4288 * cause the following entries to be renumbered/bumped down.
4290 * Note that "pseudo-indexed" entries (cn=Include{xx}, cn=Module{xx})
4291 * don't allow Adding an entry with an index that's already in use.
4292 * This is flagged as an error (LDAP_ALREADY_EXISTS) up above.
4294 * These entries can have auto-assigned indexes (appended to the end)
4295 * but only the other types support auto-renumbering of siblings.
4298 rc
= check_name_index( last
, coptr
->co_type
, e
, rs
, renum
,
4303 if ( renum
&& *renum
&& coptr
->co_type
!= Cft_Database
&&
4304 coptr
->co_type
!= Cft_Overlay
)
4306 snprintf( ca
->cr_msg
, sizeof( ca
->cr_msg
),
4307 "operation requires sibling renumbering" );
4308 rc
= LDAP_UNWILLING_TO_PERFORM
;
4313 init_config_argv( ca
);
4315 /* Make sure we process attrs in the required order */
4316 sort_attrs( e
, colst
, nocs
);
4318 for ( a
= e
->e_attrs
; a
; a
= a
->a_next
) {
4319 if ( a
== oc_at
) continue;
4320 ct
= config_find_table( colst
, nocs
, a
->a_desc
, ca
);
4321 if ( !ct
) continue; /* user data? */
4322 rc
= check_vals( ct
, ca
, a
, 1 );
4323 if ( rc
) goto done_noop
;
4326 /* Basic syntax checks are OK. Do the actual settings. */
4327 for ( a
=e
->e_attrs
; a
; a
=a
->a_next
) {
4328 if ( a
== oc_at
) continue;
4329 ct
= config_find_table( colst
, nocs
, a
->a_desc
, ca
);
4330 if ( !ct
) continue; /* user data? */
4331 for (i
=0; a
->a_vals
[i
].bv_val
; i
++) {
4333 ca
->line
= a
->a_vals
[i
].bv_val
;
4334 if ( a
->a_desc
->ad_type
->sat_flags
& SLAP_AT_ORDERED
) {
4335 ptr
= strchr( ca
->line
, '}' );
4337 iptr
= strchr( ca
->line
, '{' );
4341 if ( a
->a_desc
->ad_type
->sat_flags
& SLAP_AT_ORDERED_SIB
) {
4343 ca
->valx
= strtol( iptr
+1, NULL
, 0 );
4350 rc
= config_parse_add( ct
, ca
, i
);
4358 /* Newly added databases and overlays need to be started up */
4359 if ( CONFIG_ONLINE_ADD( ca
)) {
4360 if ( colst
[0]->co_type
== Cft_Database
) {
4361 rc
= backend_startup_one( ca
->be
, &ca
->reply
);
4363 } else if ( colst
[0]->co_type
== Cft_Overlay
) {
4364 if ( ca
->bi
->bi_db_open
) {
4365 BackendInfo
*bi_orig
= ca
->be
->bd_info
;
4366 ca
->be
->bd_info
= ca
->bi
;
4367 rc
= ca
->bi
->bi_db_open( ca
->be
, &ca
->reply
);
4368 ca
->be
->bd_info
= bi_orig
;
4370 } else if ( ca
->cleanup
) {
4371 rc
= ca
->cleanup( ca
);
4374 if (ca
->cr_msg
[0] == '\0')
4375 snprintf( ca
->cr_msg
, sizeof( ca
->cr_msg
), "<%s> failed startup", ca
->argv
[0] );
4377 Debug(LDAP_DEBUG_ANY
, "%s: %s (%s)!\n",
4378 ca
->log
, ca
->cr_msg
, ca
->argv
[1] );
4385 ce
= ch_calloc( 1, sizeof(CfEntryInfo
) );
4386 ce
->ce_parent
= last
;
4387 ce
->ce_entry
= entry_dup( e
);
4388 ce
->ce_entry
->e_private
= ce
;
4389 ce
->ce_type
= colst
[0]->co_type
;
4392 ce
->ce_private
= ca
->ca_private
;
4393 ca
->ca_entry
= ce
->ce_entry
;
4396 } else if ( last
->ce_kids
) {
4397 CfEntryInfo
*c2
, **cprev
;
4399 /* Advance to first of this type */
4400 cprev
= &last
->ce_kids
;
4401 for ( c2
= *cprev
; c2
&& c2
->ce_type
< ce
->ce_type
; ) {
4402 cprev
= &c2
->ce_sibs
;
4405 /* Account for the (-1) frontendDB entry */
4406 if ( ce
->ce_type
== Cft_Database
) {
4407 if ( ca
->be
== frontendDB
)
4409 else if ( ibase
!= -1 )
4414 for (c2
= *cprev
; c2
&& c2
->ce_type
== ce
->ce_type
;) {
4415 cprev
= &c2
->ce_sibs
;
4421 for ( i
=0; i
<ibase
; i
++ ) {
4423 cprev
= &c2
->ce_sibs
;
4426 ce
->ce_sibs
= *cprev
;
4434 if ( (colst
[0]->co_type
== Cft_Database
) && ca
->be
) {
4435 if ( ca
->be
!= frontendDB
)
4436 backend_destroy_one( ca
->be
, 1 );
4437 } else if ( (colst
[0]->co_type
== Cft_Overlay
) && ca
->bi
) {
4438 overlay_destroy_one( ca
->be
, (slap_overinst
*)ca
->bi
);
4439 } else if ( colst
[0]->co_type
== Cft_Schema
) {
4440 schema_destroy_one( ca
, colst
, nocs
, last
);
4445 ch_free( ca
->argv
);
4446 if ( colst
) ch_free( colst
);
4450 #define BIGTMP 10000
4452 config_rename_add( Operation
*op
, SlapReply
*rs
, CfEntryInfo
*ce
,
4453 int base
, int rebase
, int max
, int use_ldif
)
4455 CfEntryInfo
*ce2
, *ce3
, *cetmp
= NULL
, *cerem
= NULL
;
4456 ConfigType etype
= ce
->ce_type
;
4457 int count
= 0, rc
= 0;
4459 /* Reverse ce list */
4460 for (ce2
= ce
->ce_sibs
;ce2
;ce2
= ce3
) {
4461 if (ce2
->ce_type
!= etype
) {
4466 ce2
->ce_sibs
= cetmp
;
4469 if ( max
&& count
>= max
) {
4475 /* Move original to a temp name until increments are done */
4477 ce
->ce_entry
->e_private
= NULL
;
4478 rc
= config_renumber_one( op
, rs
, ce
->ce_parent
, ce
->ce_entry
,
4479 base
+BIGTMP
, 0, use_ldif
);
4480 ce
->ce_entry
->e_private
= ce
;
4482 /* start incrementing */
4483 for (ce2
=cetmp
; ce2
; ce2
=ce3
) {
4485 ce2
->ce_sibs
= cerem
;
4488 rc
= config_renumber_one( op
, rs
, ce2
->ce_parent
, ce2
->ce_entry
,
4489 count
+base
, 0, use_ldif
);
4493 rc
= config_renumber_one( op
, rs
, ce
->ce_parent
, ce
->ce_entry
,
4494 base
, 0, use_ldif
);
4499 config_rename_del( Operation
*op
, SlapReply
*rs
, CfEntryInfo
*ce
,
4500 CfEntryInfo
*ce2
, int old
, int use_ldif
)
4504 /* Renumber original to a temp value */
4505 ce
->ce_entry
->e_private
= NULL
;
4506 config_renumber_one( op
, rs
, ce
->ce_parent
, ce
->ce_entry
,
4507 old
+BIGTMP
, 0, use_ldif
);
4508 ce
->ce_entry
->e_private
= ce
;
4510 /* start decrementing */
4511 for (; ce2
!= ce
; ce2
=ce2
->ce_sibs
) {
4512 config_renumber_one( op
, rs
, ce2
->ce_parent
, ce2
->ce_entry
,
4513 count
+old
, 0, use_ldif
);
4516 return config_renumber_one( op
, rs
, ce
->ce_parent
, ce
->ce_entry
,
4517 count
+old
, 0, use_ldif
);
4520 /* Parse an LDAP entry into config directives, then store in underlying
4524 config_back_add( Operation
*op
, SlapReply
*rs
)
4530 if ( !access_allowed( op
, op
->ora_e
, slap_schema
.si_ad_entry
,
4531 NULL
, ACL_WADD
, NULL
)) {
4532 rs
->sr_err
= LDAP_INSUFFICIENT_ACCESS
;
4536 cfb
= (CfBackInfo
*)op
->o_bd
->be_private
;
4538 /* add opattrs for syncprov */
4540 char textbuf
[SLAP_TEXT_BUFLEN
];
4541 size_t textlen
= sizeof textbuf
;
4542 rs
->sr_err
= entry_schema_check(op
, op
->ora_e
, NULL
, 0, 1,
4543 &rs
->sr_text
, textbuf
, sizeof( textbuf
) );
4544 if ( rs
->sr_err
!= LDAP_SUCCESS
)
4546 rs
->sr_err
= slap_add_opattrs( op
, &rs
->sr_text
, textbuf
, textlen
, 1 );
4547 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
4548 Debug( LDAP_DEBUG_TRACE
,
4549 LDAP_XSTRING(config_back_add
) ": entry failed op attrs add: "
4550 "%s (%d)\n", rs
->sr_text
, rs
->sr_err
, 0 );
4555 ldap_pvt_thread_pool_pause( &connection_pool
);
4558 * 1) check for existence of entry
4559 * 2) check for sibling renumbering
4560 * 3) perform internal add
4561 * 4) perform any necessary renumbering
4562 * 5) store entry in underlying database
4564 rs
->sr_err
= config_add_internal( cfb
, op
->ora_e
, &ca
, rs
, &renumber
, op
);
4565 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
4566 rs
->sr_text
= ca
.cr_msg
;
4571 CfEntryInfo
*ce
= ca
.ca_entry
->e_private
;
4572 req_add_s addr
= op
->oq_add
;
4573 op
->o_tag
= LDAP_REQ_MODRDN
;
4574 rs
->sr_err
= config_rename_add( op
, rs
, ce
, ca
.valx
, 0, 0, cfb
->cb_use_ldif
);
4575 op
->o_tag
= LDAP_REQ_ADD
;
4577 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
4582 if ( cfb
->cb_use_ldif
) {
4583 BackendDB
*be
= op
->o_bd
;
4584 slap_callback sc
= { NULL
, slap_null_cb
, NULL
, NULL
}, *scp
;
4585 struct berval dn
, ndn
;
4587 op
->o_bd
= &cfb
->cb_db
;
4589 /* Save current rootdn; use the underlying DB's rootdn */
4592 op
->o_dn
= op
->o_bd
->be_rootdn
;
4593 op
->o_ndn
= op
->o_bd
->be_rootndn
;
4595 scp
= op
->o_callback
;
4596 op
->o_callback
= &sc
;
4597 op
->o_bd
->be_add( op
, rs
);
4599 op
->o_callback
= scp
;
4605 ldap_pvt_thread_pool_resume( &connection_pool
);
4608 send_ldap_result( op
, rs
);
4609 slap_graduate_commit_csn( op
);
4613 typedef struct delrec
{
4614 struct delrec
*next
;
4620 config_modify_add( ConfigTable
*ct
, ConfigArgs
*ca
, AttributeDescription
*ad
,
4625 if (ad
->ad_type
->sat_flags
& SLAP_AT_ORDERED
&&
4626 ca
->line
[0] == '{' )
4628 char *ptr
= strchr( ca
->line
+ 1, '}' );
4632 ca
->valx
= strtol( ca
->line
+ 1, &next
, 0 );
4633 if ( next
== ca
->line
+ 1 || next
[ 0 ] != '}' ) {
4639 rc
= config_parse_add( ct
, ca
, i
);
4647 config_modify_internal( CfEntryInfo
*ce
, Operation
*op
, SlapReply
*rs
,
4650 int rc
= LDAP_UNWILLING_TO_PERFORM
;
4652 Entry
*e
= ce
->ce_entry
;
4653 Attribute
*save_attrs
= e
->e_attrs
, *oc_at
, *s
, *a
;
4658 delrec
*dels
= NULL
, *deltail
= NULL
;
4660 oc_at
= attr_find( e
->e_attrs
, slap_schema
.si_ad_objectClass
);
4661 if ( !oc_at
) return LDAP_OBJECT_CLASS_VIOLATION
;
4663 colst
= count_ocs( oc_at
, &nocs
);
4665 /* make sure add/del flags are clear; should always be true */
4666 for ( s
= save_attrs
; s
; s
= s
->a_next
) {
4667 s
->a_flags
&= ~(SLAP_ATTR_IXADD
|SLAP_ATTR_IXDEL
);
4670 e
->e_attrs
= attrs_dup( e
->e_attrs
);
4672 init_config_argv( ca
);
4675 ca
->ca_private
= ce
->ce_private
;
4677 ca
->fname
= "slapd";
4679 strcpy( ca
->log
, "back-config" );
4681 for (ml
= op
->orm_modlist
; ml
; ml
=ml
->sml_next
) {
4682 ct
= config_find_table( colst
, nocs
, ml
->sml_desc
, ca
);
4683 switch (ml
->sml_op
) {
4684 case LDAP_MOD_DELETE
:
4685 case LDAP_MOD_REPLACE
: {
4686 BerVarray vals
= NULL
, nvals
= NULL
;
4688 if ( ct
&& ( ct
->arg_type
& ARG_NO_DELETE
)) {
4690 snprintf(ca
->cr_msg
, sizeof(ca
->cr_msg
), "cannot delete %s",
4691 ml
->sml_desc
->ad_cname
.bv_val
);
4694 if ( ml
->sml_op
== LDAP_MOD_REPLACE
) {
4695 vals
= ml
->sml_values
;
4696 nvals
= ml
->sml_nvalues
;
4697 ml
->sml_values
= NULL
;
4698 ml
->sml_nvalues
= NULL
;
4700 /* If we're deleting by values, remember the indexes of the
4701 * values we deleted.
4703 if ( ct
&& ml
->sml_values
) {
4705 i
= ml
->sml_numvals
;
4706 d
= ch_malloc( sizeof(delrec
) + (i
- 1)* sizeof(int));
4717 rc
= modify_delete_vindex(e
, &ml
->sml_mod
,
4718 get_permissiveModify(op
),
4719 &rs
->sr_text
, ca
->cr_msg
, sizeof(ca
->cr_msg
), idx
);
4720 if ( ml
->sml_op
== LDAP_MOD_REPLACE
) {
4721 ml
->sml_values
= vals
;
4722 ml
->sml_nvalues
= nvals
;
4727 /* FALLTHRU: LDAP_MOD_REPLACE && vals */
4730 case SLAP_MOD_SOFTADD
: {
4731 int mop
= ml
->sml_op
;
4733 ml
->sml_op
= LDAP_MOD_ADD
;
4735 if ( ct
->arg_type
& ARG_NO_INSERT
) {
4736 Attribute
*a
= attr_find( e
->e_attrs
, ml
->sml_desc
);
4738 navals
= a
->a_numvals
;
4741 for ( i
=0; !BER_BVISNULL( &ml
->sml_values
[i
] ); i
++ ) {
4742 if ( ml
->sml_values
[i
].bv_val
[0] == '{' &&
4745 char *next
, *val
= ml
->sml_values
[i
].bv_val
+ 1;
4748 j
= strtol( val
, &next
, 0 );
4749 if ( next
== val
|| next
[ 0 ] != '}' || j
< navals
) {
4751 snprintf(ca
->cr_msg
, sizeof(ca
->cr_msg
), "cannot insert %s",
4752 ml
->sml_desc
->ad_cname
.bv_val
);
4756 rc
= check_vals( ct
, ca
, ml
, 0 );
4757 if ( rc
) goto out_noop
;
4760 rc
= modify_add_values(e
, &ml
->sml_mod
,
4761 get_permissiveModify(op
),
4762 &rs
->sr_text
, ca
->cr_msg
, sizeof(ca
->cr_msg
) );
4764 /* If value already exists, show success here
4765 * and ignore this operation down below.
4767 if ( mop
== SLAP_MOD_SOFTADD
) {
4768 if ( rc
== LDAP_TYPE_OR_VALUE_EXISTS
)
4778 case LDAP_MOD_INCREMENT
: /* FIXME */
4783 if(rc
!= LDAP_SUCCESS
) break;
4786 if ( rc
== LDAP_SUCCESS
) {
4787 /* check that the entry still obeys the schema */
4788 rc
= entry_schema_check(op
, e
, NULL
, 0, 0,
4789 &rs
->sr_text
, ca
->cr_msg
, sizeof(ca
->cr_msg
) );
4791 if ( rc
) goto out_noop
;
4793 /* Basic syntax checks are OK. Do the actual settings. */
4794 for ( ml
= op
->orm_modlist
; ml
; ml
= ml
->sml_next
) {
4795 ct
= config_find_table( colst
, nocs
, ml
->sml_desc
, ca
);
4796 if ( !ct
) continue;
4798 s
= attr_find( save_attrs
, ml
->sml_desc
);
4799 a
= attr_find( e
->e_attrs
, ml
->sml_desc
);
4801 switch (ml
->sml_op
) {
4802 case LDAP_MOD_DELETE
:
4803 case LDAP_MOD_REPLACE
: {
4804 BerVarray vals
= NULL
, nvals
= NULL
;
4807 if ( ml
->sml_op
== LDAP_MOD_REPLACE
) {
4808 vals
= ml
->sml_values
;
4809 nvals
= ml
->sml_nvalues
;
4810 ml
->sml_values
= NULL
;
4811 ml
->sml_nvalues
= NULL
;
4814 if ( ml
->sml_values
)
4817 /* If we didn't delete the whole attribute */
4818 if ( ml
->sml_values
&& a
) {
4819 struct berval
*mvals
;
4822 if ( ml
->sml_nvalues
)
4823 mvals
= ml
->sml_nvalues
;
4825 mvals
= ml
->sml_values
;
4827 /* use the indexes we saved up above */
4828 for (i
=0; i
< d
->nidx
; i
++) {
4829 struct berval bv
= *mvals
++;
4830 if ( a
->a_desc
->ad_type
->sat_flags
& SLAP_AT_ORDERED
&&
4831 bv
.bv_val
[0] == '{' ) {
4832 ptr
= strchr( bv
.bv_val
, '}' ) + 1;
4833 bv
.bv_len
-= ptr
- bv
.bv_val
;
4836 ca
->line
= bv
.bv_val
;
4837 ca
->valx
= d
->idx
[i
];
4838 rc
= config_del_vals( ct
, ca
);
4839 if ( rc
!= LDAP_SUCCESS
) break;
4841 s
->a_flags
|= SLAP_ATTR_IXDEL
;
4842 for (j
=i
+1; j
< d
->nidx
; j
++)
4843 if ( d
->idx
[j
] >d
->idx
[i
] )
4849 rc
= config_del_vals( ct
, ca
);
4850 if ( rc
) rc
= LDAP_OTHER
;
4852 s
->a_flags
|= SLAP_ATTR_IXDEL
;
4854 if ( ml
->sml_values
) {
4859 if ( ml
->sml_op
== LDAP_MOD_REPLACE
) {
4860 ml
->sml_values
= vals
;
4861 ml
->sml_nvalues
= nvals
;
4863 if ( !vals
|| rc
!= LDAP_SUCCESS
)
4866 /* FALLTHRU: LDAP_MOD_REPLACE && vals */
4869 for (i
=0; ml
->sml_values
[i
].bv_val
; i
++) {
4870 ca
->line
= ml
->sml_values
[i
].bv_val
;
4872 rc
= config_modify_add( ct
, ca
, ml
->sml_desc
, i
);
4875 a
->a_flags
|= SLAP_ATTR_IXADD
;
4882 /* Undo for a failed operation */
4883 if ( rc
!= LDAP_SUCCESS
) {
4884 ConfigReply msg
= ca
->reply
;
4885 for ( s
= save_attrs
; s
; s
= s
->a_next
) {
4886 if ( s
->a_flags
& SLAP_ATTR_IXDEL
) {
4887 s
->a_flags
&= ~(SLAP_ATTR_IXDEL
|SLAP_ATTR_IXADD
);
4888 ct
= config_find_table( colst
, nocs
, s
->a_desc
, ca
);
4889 a
= attr_find( e
->e_attrs
, s
->a_desc
);
4891 /* clear the flag so the add check below will skip it */
4892 a
->a_flags
&= ~(SLAP_ATTR_IXDEL
|SLAP_ATTR_IXADD
);
4895 config_del_vals( ct
, ca
);
4897 for ( i
=0; !BER_BVISNULL( &s
->a_vals
[i
] ); i
++ ) {
4898 ca
->line
= s
->a_vals
[i
].bv_val
;
4900 config_modify_add( ct
, ca
, s
->a_desc
, i
);
4904 for ( a
= e
->e_attrs
; a
; a
= a
->a_next
) {
4905 if ( a
->a_flags
& SLAP_ATTR_IXADD
) {
4906 ct
= config_find_table( colst
, nocs
, a
->a_desc
, ca
);
4909 config_del_vals( ct
, ca
);
4910 s
= attr_find( save_attrs
, a
->a_desc
);
4912 s
->a_flags
&= ~(SLAP_ATTR_IXDEL
|SLAP_ATTR_IXADD
);
4913 for ( i
=0; !BER_BVISNULL( &s
->a_vals
[i
] ); i
++ ) {
4914 ca
->line
= s
->a_vals
[i
].bv_val
;
4916 config_modify_add( ct
, ca
, s
->a_desc
, i
);
4927 if ( rc
== LDAP_SUCCESS
) {
4928 attrs_free( save_attrs
);
4930 attrs_free( e
->e_attrs
);
4931 e
->e_attrs
= save_attrs
;
4933 ch_free( ca
->argv
);
4934 if ( colst
) ch_free( colst
);
4936 deltail
= dels
->next
;
4945 config_back_modify( Operation
*op
, SlapReply
*rs
)
4948 CfEntryInfo
*ce
, *last
;
4950 ConfigArgs ca
= {0};
4953 AttributeDescription
*rad
= NULL
;
4956 cfb
= (CfBackInfo
*)op
->o_bd
->be_private
;
4958 ce
= config_find_base( cfb
->cb_root
, &op
->o_req_ndn
, &last
);
4961 rs
->sr_matched
= last
->ce_entry
->e_name
.bv_val
;
4962 rs
->sr_err
= LDAP_NO_SUCH_OBJECT
;
4966 if ( !acl_check_modlist( op
, ce
->ce_entry
, op
->orm_modlist
)) {
4967 rs
->sr_err
= LDAP_INSUFFICIENT_ACCESS
;
4971 /* Get type of RDN */
4972 rdn
= ce
->ce_entry
->e_nname
;
4973 ptr
= strchr( rdn
.bv_val
, '=' );
4974 rdn
.bv_len
= ptr
- rdn
.bv_val
;
4975 slap_bv2ad( &rdn
, &rad
, &rs
->sr_text
);
4977 /* Some basic validation... */
4978 for ( ml
= op
->orm_modlist
; ml
; ml
= ml
->sml_next
) {
4979 /* Don't allow Modify of RDN; must use ModRdn for that. */
4980 if ( ml
->sml_desc
== rad
) {
4981 rs
->sr_err
= LDAP_NOT_ALLOWED_ON_RDN
;
4982 rs
->sr_text
= "Use modrdn to change the entry name";
4985 /* Internal update of contextCSN? */
4986 if ( ml
->sml_desc
== slap_schema
.si_ad_contextCSN
&& op
->o_conn
->c_conn_idx
== -1 ) {
4992 slap_mods_opattrs( op
, &op
->orm_modlist
, 1 );
4995 ldap_pvt_thread_pool_pause( &connection_pool
);
4998 * 1) perform the Modify on the cached Entry.
4999 * 2) verify that the Entry still satisfies the schema.
5000 * 3) perform the individual config operations.
5001 * 4) store Modified entry in underlying LDIF backend.
5003 rs
->sr_err
= config_modify_internal( ce
, op
, rs
, &ca
);
5005 rs
->sr_text
= ca
.cr_msg
;
5006 } else if ( cfb
->cb_use_ldif
) {
5007 BackendDB
*be
= op
->o_bd
;
5008 slap_callback sc
= { NULL
, slap_null_cb
, NULL
, NULL
}, *scp
;
5009 struct berval dn
, ndn
;
5011 op
->o_bd
= &cfb
->cb_db
;
5015 op
->o_dn
= op
->o_bd
->be_rootdn
;
5016 op
->o_ndn
= op
->o_bd
->be_rootndn
;
5018 scp
= op
->o_callback
;
5019 op
->o_callback
= &sc
;
5020 op
->o_bd
->be_modify( op
, rs
);
5022 op
->o_callback
= scp
;
5028 ldap_pvt_thread_pool_resume( &connection_pool
);
5030 send_ldap_result( op
, rs
);
5031 slap_graduate_commit_csn( op
);
5036 config_back_modrdn( Operation
*op
, SlapReply
*rs
)
5039 CfEntryInfo
*ce
, *last
;
5043 cfb
= (CfBackInfo
*)op
->o_bd
->be_private
;
5045 ce
= config_find_base( cfb
->cb_root
, &op
->o_req_ndn
, &last
);
5048 rs
->sr_matched
= last
->ce_entry
->e_name
.bv_val
;
5049 rs
->sr_err
= LDAP_NO_SUCH_OBJECT
;
5052 if ( !access_allowed( op
, ce
->ce_entry
, slap_schema
.si_ad_entry
,
5053 NULL
, ACL_WRITE
, NULL
)) {
5054 rs
->sr_err
= LDAP_INSUFFICIENT_ACCESS
;
5058 if ( ce
->ce_parent
)
5059 parent
= ce
->ce_parent
->ce_entry
;
5061 parent
= (Entry
*)&slap_entry_root
;
5062 if ( !access_allowed( op
, parent
, slap_schema
.si_ad_children
,
5063 NULL
, ACL_WRITE
, NULL
)) {
5064 rs
->sr_err
= LDAP_INSUFFICIENT_ACCESS
;
5069 /* We don't allow moving objects to new parents.
5070 * Generally we only allow reordering a set of ordered entries.
5072 if ( op
->orr_newSup
) {
5073 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
5077 /* If newRDN == oldRDN, quietly succeed */
5078 dnRdn( &op
->o_req_ndn
, &rdn
);
5079 if ( dn_match( &rdn
, &op
->orr_nnewrdn
)) {
5080 rs
->sr_err
= LDAP_SUCCESS
;
5084 /* Current behavior, subject to change as needed:
5086 * For backends and overlays, we only allow renumbering.
5087 * For schema, we allow renaming with the same number.
5088 * Otherwise, the op is not allowed.
5091 if ( ce
->ce_type
== Cft_Schema
) {
5095 /* Can't alter the main cn=schema entry */
5096 if ( ce
->ce_parent
->ce_type
== Cft_Global
) {
5097 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
5098 rs
->sr_text
= "renaming not allowed for this entry";
5102 /* We could support this later if desired */
5103 ptr1
= ber_bvchr( &rdn
, '}' );
5104 ptr2
= ber_bvchr( &op
->orr_newrdn
, '}' );
5105 len
= ptr1
- rdn
.bv_val
;
5106 if ( len
!= ptr2
- op
->orr_newrdn
.bv_val
||
5107 strncmp( rdn
.bv_val
, op
->orr_newrdn
.bv_val
, len
)) {
5108 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
5109 rs
->sr_text
= "schema reordering not supported";
5112 } else if ( ce
->ce_type
== Cft_Database
||
5113 ce
->ce_type
== Cft_Overlay
) {
5114 char *ptr1
, *ptr2
, *iptr1
, *iptr2
;
5117 iptr2
= ber_bvchr( &op
->orr_newrdn
, '=' ) + 1;
5118 if ( *iptr2
!= '{' ) {
5119 rs
->sr_err
= LDAP_NAMING_VIOLATION
;
5120 rs
->sr_text
= "new ordering index is required";
5124 iptr1
= ber_bvchr( &rdn
, '{' ) + 1;
5125 ptr1
= ber_bvchr( &rdn
, '}' );
5126 ptr2
= ber_bvchr( &op
->orr_newrdn
, '}' );
5128 rs
->sr_err
= LDAP_NAMING_VIOLATION
;
5129 rs
->sr_text
= "new ordering index is required";
5133 len1
= ptr1
- rdn
.bv_val
;
5134 len2
= ptr2
- op
->orr_newrdn
.bv_val
;
5136 if ( rdn
.bv_len
- len1
!= op
->orr_newrdn
.bv_len
- len2
||
5137 strncmp( ptr1
, ptr2
, rdn
.bv_len
- len1
)) {
5138 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
5139 rs
->sr_text
= "changing database/overlay type not allowed";
5142 ixold
= strtol( iptr1
, NULL
, 0 );
5143 ixnew
= strtol( iptr2
, &ptr1
, 0 );
5144 if ( ptr1
!= ptr2
|| ixold
< 0 || ixnew
< 0 ) {
5145 rs
->sr_err
= LDAP_NAMING_VIOLATION
;
5148 /* config DB is always 0, cannot be changed */
5149 if ( ce
->ce_type
== Cft_Database
&& ( ixold
== 0 || ixnew
== 0 )) {
5150 rs
->sr_err
= LDAP_CONSTRAINT_VIOLATION
;
5154 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
5155 rs
->sr_text
= "renaming not supported for this entry";
5159 ldap_pvt_thread_pool_pause( &connection_pool
);
5161 if ( ce
->ce_type
== Cft_Schema
) {
5162 req_modrdn_s modr
= op
->oq_modrdn
;
5165 rs
->sr_err
= config_rename_attr( rs
, ce
->ce_entry
, &rdn
, &a
);
5166 if ( rs
->sr_err
== LDAP_SUCCESS
) {
5167 rs
->sr_err
= config_rename_one( op
, rs
, ce
->ce_entry
,
5168 ce
->ce_parent
, a
, &op
->orr_newrdn
, &op
->orr_nnewrdn
,
5171 op
->oq_modrdn
= modr
;
5173 CfEntryInfo
*ce2
, *cebase
, **cprev
, **cbprev
, *ceold
;
5174 req_modrdn_s modr
= op
->oq_modrdn
;
5177 /* Advance to first of this type */
5178 cprev
= &ce
->ce_parent
->ce_kids
;
5179 for ( ce2
= *cprev
; ce2
&& ce2
->ce_type
!= ce
->ce_type
; ) {
5180 cprev
= &ce2
->ce_sibs
;
5183 /* Skip the -1 entry */
5184 if ( ce
->ce_type
== Cft_Database
) {
5185 cprev
= &ce2
->ce_sibs
;
5191 /* Remove from old slot */
5192 for ( ce2
= *cprev
; ce2
&& ce2
!= ce
; ce2
= ce2
->ce_sibs
)
5193 cprev
= &ce2
->ce_sibs
;
5194 *cprev
= ce
->ce_sibs
;
5195 ceold
= ce
->ce_sibs
;
5197 /* Insert into new slot */
5199 for ( i
=0; i
<ixnew
; i
++ ) {
5203 cprev
= &ce2
->ce_sibs
;
5205 ce
->ce_sibs
= *cprev
;
5210 /* NOTE: These should be encoded in the OC tables, not inline here */
5211 if ( ce
->ce_type
== Cft_Database
)
5212 backend_db_move( ce
->ce_be
, ixnew
);
5213 else if ( ce
->ce_type
== Cft_Overlay
)
5214 overlay_move( ce
->ce_be
, (slap_overinst
*)ce
->ce_bi
, ixnew
);
5216 if ( ixold
< ixnew
) {
5217 rs
->sr_err
= config_rename_del( op
, rs
, ce
, ceold
, ixold
,
5220 rs
->sr_err
= config_rename_add( op
, rs
, ce
, ixnew
, 1,
5221 ixold
- ixnew
, cfb
->cb_use_ldif
);
5223 op
->oq_modrdn
= modr
;
5226 ldap_pvt_thread_pool_resume( &connection_pool
);
5228 send_ldap_result( op
, rs
);
5233 config_back_delete( Operation
*op
, SlapReply
*rs
)
5235 #ifdef SLAP_CONFIG_DELETE
5237 CfEntryInfo
*ce
, *last
, *ce2
;
5241 cfb
= (CfBackInfo
*)op
->o_bd
->be_private
;
5243 ce
= config_find_base( cfb
->cb_root
, &op
->o_req_ndn
, &last
);
5246 rs
->sr_matched
= last
->ce_entry
->e_name
.bv_val
;
5247 rs
->sr_err
= LDAP_NO_SUCH_OBJECT
;
5248 } if ( ce
->ce_kids
) {
5249 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
5250 } else if ( ce
->ce_type
== Cft_Overlay
){
5252 int count
, ixold
, rc
;
5254 ldap_pvt_thread_pool_pause( &connection_pool
);
5256 overlay_remove( ce
->ce_be
, (slap_overinst
*)ce
->ce_bi
);
5258 /* remove CfEntryInfo from the siblings list */
5259 if ( ce
->ce_parent
->ce_kids
== ce
) {
5260 ce
->ce_parent
->ce_kids
= ce
->ce_sibs
;
5262 for ( ce2
= ce
->ce_parent
->ce_kids
; ce2
; ce2
= ce2
->ce_sibs
) {
5263 if ( ce2
->ce_sibs
== ce
) {
5264 ce2
->ce_sibs
= ce
->ce_sibs
;
5270 /* remove from underlying database */
5271 if ( cfb
->cb_use_ldif
) {
5272 BackendDB
*be
= op
->o_bd
;
5273 slap_callback sc
= { NULL
, slap_null_cb
, NULL
, NULL
}, *scp
;
5274 struct berval dn
, ndn
, req_dn
, req_ndn
;
5276 op
->o_bd
= &cfb
->cb_db
;
5280 req_dn
= op
->o_req_dn
;
5281 req_ndn
= op
->o_req_ndn
;
5283 op
->o_dn
= op
->o_bd
->be_rootdn
;
5284 op
->o_ndn
= op
->o_bd
->be_rootndn
;
5285 op
->o_req_dn
= ce
->ce_entry
->e_name
;
5286 op
->o_req_ndn
= ce
->ce_entry
->e_nname
;
5288 scp
= op
->o_callback
;
5289 op
->o_callback
= &sc
;
5290 op
->o_bd
->be_delete( op
, rs
);
5292 op
->o_callback
= scp
;
5295 op
->o_req_dn
= req_dn
;
5296 op
->o_req_ndn
= req_ndn
;
5299 /* renumber siblings */
5300 iptr
= ber_bvchr( &op
->o_req_ndn
, '{' ) + 1;
5301 ixold
= strtol( iptr
, NULL
, 0 );
5302 for (ce2
= ce
->ce_sibs
, count
=0; ce2
; ce2
=ce2
->ce_sibs
) {
5303 config_renumber_one( op
, rs
, ce2
->ce_parent
, ce2
->ce_entry
,
5304 count
+ixold
, 0, cfb
->cb_use_ldif
);
5308 ce
->ce_entry
->e_private
=NULL
;
5309 entry_free(ce
->ce_entry
);
5311 ldap_pvt_thread_pool_resume( &connection_pool
);
5313 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
5316 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
5317 #endif /* SLAP_CONFIG_DELETE */
5318 send_ldap_result( op
, rs
);
5323 config_back_search( Operation
*op
, SlapReply
*rs
)
5326 CfEntryInfo
*ce
, *last
;
5329 cfb
= (CfBackInfo
*)op
->o_bd
->be_private
;
5331 ce
= config_find_base( cfb
->cb_root
, &op
->o_req_ndn
, &last
);
5334 rs
->sr_matched
= last
->ce_entry
->e_name
.bv_val
;
5335 rs
->sr_err
= LDAP_NO_SUCH_OBJECT
;
5338 if ( !access_allowed_mask( op
, ce
->ce_entry
, slap_schema
.si_ad_entry
, NULL
,
5339 ACL_SEARCH
, NULL
, &mask
))
5341 if ( !ACL_GRANT( mask
, ACL_DISCLOSE
)) {
5342 rs
->sr_err
= LDAP_NO_SUCH_OBJECT
;
5344 rs
->sr_err
= LDAP_INSUFFICIENT_ACCESS
;
5348 switch ( op
->ors_scope
) {
5349 case LDAP_SCOPE_BASE
:
5350 case LDAP_SCOPE_SUBTREE
:
5351 config_send( op
, rs
, ce
, 0 );
5354 case LDAP_SCOPE_ONELEVEL
:
5355 for (ce
= ce
->ce_kids
; ce
; ce
=ce
->ce_sibs
) {
5356 config_send( op
, rs
, ce
, 1 );
5361 rs
->sr_err
= LDAP_SUCCESS
;
5363 send_ldap_result( op
, rs
);
5367 /* no-op, we never free entries */
5368 int config_entry_release(
5373 if ( !e
->e_private
) {
5376 return LDAP_SUCCESS
;
5379 /* return LDAP_SUCCESS IFF we can retrieve the specified entry.
5381 int config_back_entry_get(
5385 AttributeDescription
*at
,
5390 CfEntryInfo
*ce
, *last
;
5391 int rc
= LDAP_NO_SUCH_OBJECT
;
5393 cfb
= (CfBackInfo
*)op
->o_bd
->be_private
;
5395 ce
= config_find_base( cfb
->cb_root
, ndn
, &last
);
5397 *ent
= ce
->ce_entry
;
5400 if ( oc
&& !is_entry_objectclass_or_sub( *ent
, oc
) ) {
5401 rc
= LDAP_NO_SUCH_ATTRIBUTE
;
5411 config_build_attrs( Entry
*e
, AttributeType
**at
, AttributeDescription
*ad
,
5412 ConfigTable
*ct
, ConfigArgs
*c
)
5416 for (; at
&& *at
; at
++) {
5417 /* Skip the naming attr */
5418 if ((*at
)->sat_ad
== ad
|| (*at
)->sat_ad
== slap_schema
.si_ad_cn
)
5420 for (i
=0;ct
[i
].name
;i
++) {
5421 if (ct
[i
].ad
== (*at
)->sat_ad
) {
5422 rc
= config_get_vals(&ct
[i
], c
);
5423 /* NOTE: tolerate that config_get_vals()
5424 * returns success with no values */
5425 if (rc
== LDAP_SUCCESS
&& c
->rvalue_vals
!= NULL
) {
5426 if ( c
->rvalue_nvals
)
5427 attr_merge(e
, ct
[i
].ad
, c
->rvalue_vals
,
5430 attr_merge_normalize(e
, ct
[i
].ad
,
5431 c
->rvalue_vals
, NULL
);
5432 ber_bvarray_free( c
->rvalue_nvals
);
5433 ber_bvarray_free( c
->rvalue_vals
);
5442 config_build_entry( Operation
*op
, SlapReply
*rs
, CfEntryInfo
*parent
,
5443 ConfigArgs
*c
, struct berval
*rdn
, ConfigOCs
*main
, ConfigOCs
*extra
)
5445 Entry
*e
= entry_alloc();
5446 CfEntryInfo
*ce
= ch_calloc( 1, sizeof(CfEntryInfo
) );
5448 struct berval ad_name
;
5449 AttributeDescription
*ad
= NULL
;
5456 CfEntryInfo
*ceprev
= NULL
;
5458 Debug( LDAP_DEBUG_TRACE
, "config_build_entry: \"%s\"\n", rdn
->bv_val
, 0, 0);
5461 ce
->ce_type
= main
->co_type
;
5462 ce
->ce_parent
= parent
;
5464 pdn
= parent
->ce_entry
->e_nname
;
5465 if ( parent
->ce_kids
&& parent
->ce_kids
->ce_type
<= ce
->ce_type
)
5466 for ( ceprev
= parent
->ce_kids
; ceprev
->ce_sibs
&&
5467 ceprev
->ce_type
<= ce
->ce_type
;
5468 ceprev
= ceprev
->ce_sibs
);
5473 ce
->ce_private
= c
->ca_private
;
5477 build_new_dn( &e
->e_name
, &pdn
, rdn
, NULL
);
5478 ber_dupbv( &e
->e_nname
, &e
->e_name
);
5480 attr_merge_normalize_one(e
, slap_schema
.si_ad_objectClass
,
5481 main
->co_name
, NULL
);
5483 attr_merge_normalize_one(e
, slap_schema
.si_ad_objectClass
,
5484 extra
->co_name
, NULL
);
5485 ptr
= strchr(rdn
->bv_val
, '=');
5486 ad_name
.bv_val
= rdn
->bv_val
;
5487 ad_name
.bv_len
= ptr
- rdn
->bv_val
;
5488 rc
= slap_bv2ad( &ad_name
, &ad
, &text
);
5493 val
.bv_len
= rdn
->bv_len
- (val
.bv_val
- rdn
->bv_val
);
5494 attr_merge_normalize_one(e
, ad
, &val
, NULL
);
5497 c
->table
= main
->co_type
;
5498 if ( oc
->soc_required
)
5499 config_build_attrs( e
, oc
->soc_required
, ad
, main
->co_table
, c
);
5501 if ( oc
->soc_allowed
)
5502 config_build_attrs( e
, oc
->soc_allowed
, ad
, main
->co_table
, c
);
5506 c
->table
= extra
->co_type
;
5507 if ( oc
->soc_required
)
5508 config_build_attrs( e
, oc
->soc_required
, ad
, extra
->co_table
, c
);
5510 if ( oc
->soc_allowed
)
5511 config_build_attrs( e
, oc
->soc_allowed
, ad
, extra
->co_table
, c
);
5514 oc_at
= attr_find( e
->e_attrs
, slap_schema
.si_ad_objectClass
);
5515 rc
= structural_class(oc_at
->a_vals
, &oc
, NULL
, &text
, c
->cr_msg
,
5516 sizeof(c
->cr_msg
), op
? op
->o_tmpmemctx
: NULL
);
5517 if ( rc
!= LDAP_SUCCESS
) {
5518 Debug( LDAP_DEBUG_ANY
,
5519 "config_build_entry: build \"%s\" failed: \"%s\"\n",
5520 rdn
->bv_val
, text
, 0);
5523 attr_merge_normalize_one(e
, slap_schema
.si_ad_structuralObjectClass
, &oc
->soc_cname
, NULL
);
5526 op
->ora_modlist
= NULL
;
5527 slap_add_opattrs( op
, NULL
, NULL
, 0, 0 );
5528 if ( !op
->o_noop
) {
5529 op
->o_bd
->be_add( op
, rs
);
5530 if ( ( rs
->sr_err
!= LDAP_SUCCESS
)
5531 && (rs
->sr_err
!= LDAP_ALREADY_EXISTS
) ) {
5537 ce
->ce_sibs
= ceprev
->ce_sibs
;
5538 ceprev
->ce_sibs
= ce
;
5539 } else if ( parent
) {
5540 ce
->ce_sibs
= parent
->ce_kids
;
5541 parent
->ce_kids
= ce
;
5548 config_build_schema_inc( ConfigArgs
*c
, CfEntryInfo
*ceparent
,
5549 Operation
*op
, SlapReply
*rs
)
5552 ConfigFile
*cf
= c
->ca_private
;
5556 for (; cf
; cf
=cf
->c_sibs
, c
->depth
++) {
5557 if ( !cf
->c_at_head
&& !cf
->c_cr_head
&& !cf
->c_oc_head
&&
5558 !cf
->c_om_head
) continue;
5559 c
->value_dn
.bv_val
= c
->log
;
5560 LUTIL_SLASHPATH( cf
->c_file
.bv_val
);
5561 bv
.bv_val
= strrchr(cf
->c_file
.bv_val
, LDAP_DIRSEP
[0]);
5566 bv
.bv_len
= cf
->c_file
.bv_len
- (bv
.bv_val
- cf
->c_file
.bv_val
);
5568 ptr
= strchr( bv
.bv_val
, '.' );
5570 bv
.bv_len
= ptr
- bv
.bv_val
;
5571 c
->value_dn
.bv_len
= snprintf(c
->value_dn
.bv_val
, sizeof( c
->log
), "cn=" SLAP_X_ORDERED_FMT
, c
->depth
);
5572 if ( c
->value_dn
.bv_len
>= sizeof( c
->log
) ) {
5573 /* FIXME: how can indicate error? */
5576 strncpy( c
->value_dn
.bv_val
+ c
->value_dn
.bv_len
, bv
.bv_val
,
5578 c
->value_dn
.bv_len
+= bv
.bv_len
;
5579 c
->value_dn
.bv_val
[c
->value_dn
.bv_len
] ='\0';
5582 e
= config_build_entry( op
, rs
, ceparent
, c
, &c
->value_dn
,
5583 &CFOC_SCHEMA
, NULL
);
5586 } else if ( e
&& cf
->c_kids
) {
5587 c
->ca_private
= cf
->c_kids
;
5588 config_build_schema_inc( c
, e
->e_private
, op
, rs
);
5594 #ifdef SLAPD_MODULES
5597 config_build_modules( ConfigArgs
*c
, CfEntryInfo
*ceparent
,
5598 Operation
*op
, SlapReply
*rs
)
5603 for (i
=0, mp
=&modpaths
; mp
; mp
=mp
->mp_next
, i
++) {
5604 if ( BER_BVISNULL( &mp
->mp_path
) && !mp
->mp_loads
)
5606 c
->value_dn
.bv_val
= c
->log
;
5607 c
->value_dn
.bv_len
= snprintf(c
->value_dn
.bv_val
, sizeof( c
->log
), "cn=module" SLAP_X_ORDERED_FMT
, i
);
5608 if ( c
->value_dn
.bv_len
>= sizeof( c
->log
) ) {
5609 /* FIXME: how can indicate error? */
5613 if ( ! config_build_entry( op
, rs
, ceparent
, c
, &c
->value_dn
, &CFOC_MODULE
, NULL
)) {
5622 config_check_schema(Operation
*op
, CfBackInfo
*cfb
)
5624 struct berval schema_dn
= BER_BVC(SCHEMA_RDN
"," CONFIG_RDN
);
5626 CfEntryInfo
*ce
, *last
;
5629 /* If there's no root entry, we must be in the midst of converting */
5630 if ( !cfb
->cb_root
)
5633 /* Make sure the main schema entry exists */
5634 ce
= config_find_base( cfb
->cb_root
, &schema_dn
, &last
);
5641 /* Make sure it's up to date */
5642 if ( cf_om_tail
!= om_sys_tail
) {
5643 a
= attr_find( e
->e_attrs
, cfAd_om
);
5645 if ( a
->a_nvals
!= a
->a_vals
)
5646 ber_bvarray_free( a
->a_nvals
);
5647 ber_bvarray_free( a
->a_vals
);
5652 oidm_unparse( &bv
, NULL
, NULL
, 1 );
5653 attr_merge_normalize( e
, cfAd_om
, bv
, NULL
);
5654 ber_bvarray_free( bv
);
5655 cf_om_tail
= om_sys_tail
;
5657 if ( cf_at_tail
!= at_sys_tail
) {
5658 a
= attr_find( e
->e_attrs
, cfAd_attr
);
5660 if ( a
->a_nvals
!= a
->a_vals
)
5661 ber_bvarray_free( a
->a_nvals
);
5662 ber_bvarray_free( a
->a_vals
);
5667 at_unparse( &bv
, NULL
, NULL
, 1 );
5668 attr_merge_normalize( e
, cfAd_attr
, bv
, NULL
);
5669 ber_bvarray_free( bv
);
5670 cf_at_tail
= at_sys_tail
;
5672 if ( cf_oc_tail
!= oc_sys_tail
) {
5673 a
= attr_find( e
->e_attrs
, cfAd_oc
);
5675 if ( a
->a_nvals
!= a
->a_vals
)
5676 ber_bvarray_free( a
->a_nvals
);
5677 ber_bvarray_free( a
->a_vals
);
5682 oc_unparse( &bv
, NULL
, NULL
, 1 );
5683 attr_merge_normalize( e
, cfAd_oc
, bv
, NULL
);
5684 ber_bvarray_free( bv
);
5685 cf_oc_tail
= oc_sys_tail
;
5688 SlapReply rs
= {REP_RESULT
};
5689 c
.ca_private
= NULL
;
5690 e
= config_build_entry( op
, &rs
, cfb
->cb_root
, &c
, &schema_rdn
,
5691 &CFOC_SCHEMA
, NULL
);
5696 ce
->ce_private
= cfb
->cb_config
;
5697 cf_at_tail
= at_sys_tail
;
5698 cf_oc_tail
= oc_sys_tail
;
5699 cf_om_tail
= om_sys_tail
;
5704 static const char *defacl
[] = {
5705 NULL
, "to", "*", "by", "*", "none", NULL
5709 config_back_db_open( BackendDB
*be
, ConfigReply
*cr
)
5711 CfBackInfo
*cfb
= be
->be_private
;
5714 CfEntryInfo
*ce
, *ceparent
;
5718 Connection conn
= {0};
5719 OperationBuffer opbuf
;
5721 slap_callback cb
= { NULL
, slap_null_cb
, NULL
, NULL
};
5722 SlapReply rs
= {REP_RESULT
};
5723 void *thrctx
= NULL
;
5725 Debug( LDAP_DEBUG_TRACE
, "config_back_db_open\n", 0, 0, 0);
5727 /* If we have no explicitly configured ACLs, don't just use
5728 * the global ACLs. Explicitly deny access to everything.
5730 if ( frontendDB
->be_acl
&& be
->be_acl
== frontendDB
->be_acl
) {
5731 parse_acl(be
, "config_back_db_open", 0, 6, (char **)defacl
, 0 );
5734 thrctx
= ldap_pvt_thread_pool_context();
5735 connection_fake_init( &conn
, &opbuf
, thrctx
);
5738 op
->o_tag
= LDAP_REQ_ADD
;
5739 op
->o_callback
= &cb
;
5740 op
->o_bd
= &cfb
->cb_db
;
5741 op
->o_dn
= op
->o_bd
->be_rootdn
;
5742 op
->o_ndn
= op
->o_bd
->be_rootndn
;
5744 if ( !cfb
->cb_use_ldif
) {
5748 /* If we read the config from back-ldif, do some quick sanity checks */
5749 if ( cfb
->cb_got_ldif
) {
5750 return config_check_schema( op
, cfb
);
5753 /* create root of tree */
5755 c
.ca_private
= cfb
->cb_config
;
5757 e
= config_build_entry( op
, &rs
, NULL
, &c
, &rdn
, &CFOC_GLOBAL
, NULL
);
5767 #ifdef SLAPD_MODULES
5768 /* Create Module nodes... */
5769 if ( modpaths
.mp_loads
) {
5770 if ( config_build_modules( &c
, ceparent
, op
, &rs
) ){
5776 /* Create schema nodes... cn=schema will contain the hardcoded core
5777 * schema, read-only. Child objects will contain runtime loaded schema
5781 c
.ca_private
= NULL
;
5782 e
= config_build_entry( op
, &rs
, ceparent
, &c
, &rdn
, &CFOC_SCHEMA
, NULL
);
5787 ce
->ce_private
= cfb
->cb_config
;
5788 cf_at_tail
= at_sys_tail
;
5789 cf_oc_tail
= oc_sys_tail
;
5790 cf_om_tail
= om_sys_tail
;
5792 /* Create schema nodes for included schema... */
5793 if ( cfb
->cb_config
->c_kids
) {
5795 c
.ca_private
= cfb
->cb_config
->c_kids
;
5796 if (config_build_schema_inc( &c
, ce
, op
, &rs
)) {
5801 /* Create backend nodes. Skip if they don't provide a cf_table.
5802 * There usually aren't any of these.
5806 LDAP_STAILQ_FOREACH( bi
, &backendInfo
, bi_next
) {
5807 if (!bi
->bi_cf_ocs
) {
5808 /* If it only supports the old config mech, complain. */
5809 if ( bi
->bi_config
) {
5810 Debug( LDAP_DEBUG_ANY
,
5811 "WARNING: No dynamic config support for backend %s.\n",
5812 bi
->bi_type
, 0, 0 );
5817 if (!bi
->bi_private
) continue;
5820 rdn
.bv_len
= snprintf(rdn
.bv_val
, sizeof( c
.log
),
5821 "%s=%s", cfAd_backend
->ad_cname
.bv_val
, bi
->bi_type
);
5822 if ( rdn
.bv_len
>= sizeof( c
.log
) ) {
5823 /* FIXME: holler ... */ ;
5826 e
= config_build_entry( op
, &rs
, ceparent
, &c
, &rdn
, &CFOC_BACKEND
,
5833 /* Create database nodes... */
5834 frontendDB
->be_cf_ocs
= &CFOC_FRONTEND
;
5835 LDAP_STAILQ_NEXT(frontendDB
, be_next
) = LDAP_STAILQ_FIRST(&backendDB
);
5836 for ( i
= -1, be
= frontendDB
; be
;
5837 i
++, be
= LDAP_STAILQ_NEXT( be
, be_next
)) {
5838 slap_overinfo
*oi
= NULL
;
5840 if ( overlay_is_over( be
)) {
5841 oi
= be
->bd_info
->bi_private
;
5847 /* If this backend supports the old config mechanism, but not
5848 * the new mech, complain.
5850 if ( !be
->be_cf_ocs
&& bi
->bi_db_config
) {
5851 Debug( LDAP_DEBUG_ANY
,
5852 "WARNING: No dynamic config support for database %s.\n",
5853 bi
->bi_type
, 0, 0 );
5857 rdn
.bv_len
= snprintf(rdn
.bv_val
, sizeof( c
.log
),
5858 "%s=" SLAP_X_ORDERED_FMT
"%s", cfAd_database
->ad_cname
.bv_val
,
5860 if ( rdn
.bv_len
>= sizeof( c
.log
) ) {
5861 /* FIXME: holler ... */ ;
5865 e
= config_build_entry( op
, &rs
, ceparent
, &c
, &rdn
, &CFOC_DATABASE
,
5871 if ( be
->be_cf_ocs
&& be
->be_cf_ocs
->co_cfadd
)
5872 be
->be_cf_ocs
->co_cfadd( op
, &rs
, e
, &c
);
5873 /* Iterate through overlays */
5878 voidList
*vl
, *v0
= NULL
;
5880 /* overlays are in LIFO order, must reverse stack */
5881 for (on
=oi
->oi_list
; on
; on
=on
->on_next
) {
5882 vl
= ch_malloc( sizeof( voidList
));
5887 for (j
=0; vl
; j
++,vl
=v0
) {
5891 if ( on
->on_bi
.bi_db_config
&& !on
->on_bi
.bi_cf_ocs
) {
5892 Debug( LDAP_DEBUG_ANY
,
5893 "WARNING: No dynamic config support for overlay %s.\n",
5894 on
->on_bi
.bi_type
, 0, 0 );
5898 rdn
.bv_len
= snprintf(rdn
.bv_val
, sizeof( c
.log
),
5899 "%s=" SLAP_X_ORDERED_FMT
"%s",
5900 cfAd_overlay
->ad_cname
.bv_val
, j
, on
->on_bi
.bi_type
);
5901 if ( rdn
.bv_len
>= sizeof( c
.log
) ) {
5902 /* FIXME: holler ... */ ;
5906 oe
= config_build_entry( op
, &rs
, ce
, &c
, &rdn
,
5907 &CFOC_OVERLAY
, c
.bi
->bi_cf_ocs
);
5911 if ( c
.bi
->bi_cf_ocs
&& c
.bi
->bi_cf_ocs
->co_cfadd
)
5912 c
.bi
->bi_cf_ocs
->co_cfadd( op
, &rs
, oe
, &c
);
5917 ldap_pvt_thread_pool_context_reset( thrctx
);
5919 if ( unsupp
&& cfb
->cb_use_ldif
) {
5920 Debug( LDAP_DEBUG_ANY
, "\nWARNING: The converted cn=config "
5921 "directory is incomplete and may not work.\n\n", 0, 0, 0 );
5928 cfb_free_cffile( ConfigFile
*cf
)
5932 for (; cf
; cf
=next
) {
5935 cfb_free_cffile( cf
->c_kids
);
5936 ch_free( cf
->c_file
.bv_val
);
5937 ber_bvarray_free( cf
->c_dseFiles
);
5943 cfb_free_entries( CfEntryInfo
*ce
)
5947 for (; ce
; ce
=next
) {
5950 cfb_free_entries( ce
->ce_kids
);
5951 ce
->ce_entry
->e_private
= NULL
;
5952 entry_free( ce
->ce_entry
);
5958 config_back_db_close( BackendDB
*be
, ConfigReply
*cr
)
5960 CfBackInfo
*cfb
= be
->be_private
;
5962 cfb_free_entries( cfb
->cb_root
);
5963 cfb
->cb_root
= NULL
;
5965 if ( cfb
->cb_db
.bd_info
) {
5966 backend_shutdown( &cfb
->cb_db
);
5973 config_back_db_destroy( BackendDB
*be
, ConfigReply
*cr
)
5975 CfBackInfo
*cfb
= be
->be_private
;
5977 cfb_free_cffile( cfb
->cb_config
);
5979 ch_free( cfdir
.bv_val
);
5981 avl_free( CfOcTree
, NULL
);
5983 if ( cfb
->cb_db
.bd_info
) {
5984 cfb
->cb_db
.be_suffix
= NULL
;
5985 cfb
->cb_db
.be_nsuffix
= NULL
;
5986 BER_BVZERO( &cfb
->cb_db
.be_rootdn
);
5987 BER_BVZERO( &cfb
->cb_db
.be_rootndn
);
5989 backend_destroy_one( &cfb
->cb_db
, 0 );
5998 config_back_db_init( BackendDB
*be
, ConfigReply
* cr
)
6004 cfb
->cb_config
= ch_calloc( 1, sizeof(ConfigFile
));
6005 cfn
= cfb
->cb_config
;
6006 be
->be_private
= cfb
;
6008 ber_dupbv( &be
->be_rootdn
, &config_rdn
);
6009 ber_dupbv( &be
->be_rootndn
, &be
->be_rootdn
);
6010 ber_dupbv( &dn
, &be
->be_rootdn
);
6011 ber_bvarray_add( &be
->be_suffix
, &dn
);
6012 ber_dupbv( &dn
, &be
->be_rootdn
);
6013 ber_bvarray_add( &be
->be_nsuffix
, &dn
);
6015 /* Hide from namingContexts */
6016 SLAP_BFLAGS(be
) |= SLAP_BFLAG_CONFIG
;
6022 config_back_destroy( BackendInfo
*bi
)
6024 ldif_must_b64_encode_release();
6029 config_tool_entry_open( BackendDB
*be
, int mode
)
6031 CfBackInfo
*cfb
= be
->be_private
;
6032 BackendInfo
*bi
= cfb
->cb_db
.bd_info
;
6034 if ( bi
&& bi
->bi_tool_entry_open
)
6035 return bi
->bi_tool_entry_open( &cfb
->cb_db
, mode
);
6042 config_tool_entry_close( BackendDB
*be
)
6044 CfBackInfo
*cfb
= be
->be_private
;
6045 BackendInfo
*bi
= cfb
->cb_db
.bd_info
;
6047 if ( bi
&& bi
->bi_tool_entry_close
)
6048 return bi
->bi_tool_entry_close( &cfb
->cb_db
);
6054 config_tool_entry_first( BackendDB
*be
)
6056 CfBackInfo
*cfb
= be
->be_private
;
6057 BackendInfo
*bi
= cfb
->cb_db
.bd_info
;
6059 if ( bi
&& bi
->bi_tool_entry_first
)
6060 return bi
->bi_tool_entry_first( &cfb
->cb_db
);
6066 config_tool_entry_next( BackendDB
*be
)
6068 CfBackInfo
*cfb
= be
->be_private
;
6069 BackendInfo
*bi
= cfb
->cb_db
.bd_info
;
6071 if ( bi
&& bi
->bi_tool_entry_next
)
6072 return bi
->bi_tool_entry_next( &cfb
->cb_db
);
6078 config_tool_entry_get( BackendDB
*be
, ID id
)
6080 CfBackInfo
*cfb
= be
->be_private
;
6081 BackendInfo
*bi
= cfb
->cb_db
.bd_info
;
6083 if ( bi
&& bi
->bi_tool_entry_get
)
6084 return bi
->bi_tool_entry_get( &cfb
->cb_db
, id
);
6089 static int entry_put_got_frontend
=0;
6090 static int entry_put_got_config
=0;
6092 config_tool_entry_put( BackendDB
*be
, Entry
*e
, struct berval
*text
)
6094 CfBackInfo
*cfb
= be
->be_private
;
6095 BackendInfo
*bi
= cfb
->cb_db
.bd_info
;
6097 struct berval rdn
, vals
[ 2 ];
6099 OperationBuffer opbuf
;
6101 Connection conn
= {0};
6102 Operation
*op
= NULL
;
6106 /* Create entry for frontend database if it does not exist already */
6107 if ( !entry_put_got_frontend
) {
6108 if ( !strncmp( e
->e_nname
.bv_val
, "olcDatabase",
6109 STRLENOF( "olcDatabase" ))) {
6110 if ( strncmp( e
->e_nname
.bv_val
+
6111 STRLENOF( "olcDatabase" ), "={-1}frontend",
6112 STRLENOF( "={-1}frontend" )) &&
6113 strncmp( e
->e_nname
.bv_val
+
6114 STRLENOF( "olcDatabase" ), "=frontend",
6115 STRLENOF( "=frontend" ))) {
6117 vals
[1].bv_val
= NULL
;
6118 memset( &ca
, 0, sizeof(ConfigArgs
));
6120 ca
.bi
= frontendDB
->bd_info
;
6121 ca
.be
->be_cf_ocs
= &CFOC_FRONTEND
;
6122 rdn
.bv_val
= ca
.log
;
6123 rdn
.bv_len
= snprintf(rdn
.bv_val
, sizeof( ca
.log
),
6124 "%s=" SLAP_X_ORDERED_FMT
"%s",
6125 cfAd_database
->ad_cname
.bv_val
, -1,
6127 ce
= config_build_entry( NULL
, NULL
, cfb
->cb_root
, &ca
, &rdn
,
6128 &CFOC_DATABASE
, ca
.be
->be_cf_ocs
);
6129 thrctx
= ldap_pvt_thread_pool_context();
6130 connection_fake_init2( &conn
, &opbuf
, thrctx
,0 );
6132 op
->o_bd
= &cfb
->cb_db
;
6133 op
->o_tag
= LDAP_REQ_ADD
;
6135 op
->o_dn
= be
->be_rootdn
;
6136 op
->o_ndn
= be
->be_rootndn
;
6137 rc
= slap_add_opattrs(op
, NULL
, NULL
, 0, 0);
6138 if ( rc
!= LDAP_SUCCESS
) {
6139 text
->bv_val
= "autocreation of \"olcDatabase={-1}frontend\" failed";
6140 text
->bv_len
= STRLENOF("autocreation of \"olcDatabase={-1}frontend\" failed");
6144 if ( ce
&& bi
&& bi
->bi_tool_entry_put
&&
6145 bi
->bi_tool_entry_put( &cfb
->cb_db
, ce
, text
) != NOID
) {
6146 entry_put_got_frontend
++;
6148 text
->bv_val
= "autocreation of \"olcDatabase={-1}frontend\" failed";
6149 text
->bv_len
= STRLENOF("autocreation of \"olcDatabase={-1}frontend\" failed");
6153 entry_put_got_frontend
++;
6158 /* Create entry for config database if it does not exist already */
6159 if ( !entry_put_got_config
&& !isFrontend
) {
6160 if ( !strncmp( e
->e_nname
.bv_val
, "olcDatabase",
6161 STRLENOF( "olcDatabase" ))) {
6162 if ( strncmp( e
->e_nname
.bv_val
+
6163 STRLENOF( "olcDatabase" ), "={0}config",
6164 STRLENOF( "={0}config" )) &&
6165 strncmp( e
->e_nname
.bv_val
+
6166 STRLENOF( "olcDatabase" ), "=config",
6167 STRLENOF( "=config" )) ) {
6169 vals
[1].bv_val
= NULL
;
6170 memset( &ca
, 0, sizeof(ConfigArgs
));
6171 ca
.be
= LDAP_STAILQ_FIRST( &backendDB
);
6172 ca
.bi
= ca
.be
->bd_info
;
6173 rdn
.bv_val
= ca
.log
;
6174 rdn
.bv_len
= snprintf(rdn
.bv_val
, sizeof( ca
.log
),
6175 "%s=" SLAP_X_ORDERED_FMT
"%s",
6176 cfAd_database
->ad_cname
.bv_val
, 0,
6178 ce
= config_build_entry( NULL
, NULL
, cfb
->cb_root
, &ca
, &rdn
, &CFOC_DATABASE
,
6181 thrctx
= ldap_pvt_thread_pool_context();
6182 connection_fake_init2( &conn
, &opbuf
, thrctx
,0 );
6184 op
->o_bd
= &cfb
->cb_db
;
6185 op
->o_tag
= LDAP_REQ_ADD
;
6186 op
->o_dn
= be
->be_rootdn
;
6187 op
->o_ndn
= be
->be_rootndn
;
6190 rc
= slap_add_opattrs(op
, NULL
, NULL
, 0, 0);
6191 if ( rc
!= LDAP_SUCCESS
) {
6192 text
->bv_val
= "autocreation of \"olcDatabase={0}config\" failed";
6193 text
->bv_len
= STRLENOF("autocreation of \"olcDatabase={0}config\" failed");
6196 if (ce
&& bi
&& bi
->bi_tool_entry_put
&&
6197 bi
->bi_tool_entry_put( &cfb
->cb_db
, ce
, text
) != NOID
) {
6198 entry_put_got_config
++;
6200 text
->bv_val
= "autocreation of \"olcDatabase={0}config\" failed";
6201 text
->bv_len
= STRLENOF("autocreation of \"olcDatabase={0}config\" failed");
6205 entry_put_got_config
++;
6209 if ( bi
&& bi
->bi_tool_entry_put
&&
6210 config_add_internal( cfb
, e
, &ca
, NULL
, NULL
, NULL
) == 0 )
6211 return bi
->bi_tool_entry_put( &cfb
->cb_db
, e
, text
);
6218 AttributeDescription
**desc
;
6220 { "attribute", &cfAd_attr
},
6221 { "backend", &cfAd_backend
},
6222 { "database", &cfAd_database
},
6223 { "include", &cfAd_include
},
6224 { "objectclass", &cfAd_oc
},
6225 { "objectidentifier", &cfAd_om
},
6226 { "overlay", &cfAd_overlay
},
6231 * add / delete: all types that may be added or deleted must use an
6232 * X-ORDERED attributeType for their RDN. Adding and deleting entries
6233 * should automatically renumber the index of any siblings as needed,
6234 * so that no gaps in the numbering sequence exist after the add/delete
6236 * What can be added:
6238 * backend objects for backend-specific config directives
6242 * delete: probably no support this time around.
6244 * modrdn: generally not done. Will be invoked automatically by add/
6245 * delete to update numbering sequence. Perform as an explicit operation
6246 * so that the renumbering effect may be replicated. Subtree rename must
6247 * be supported, since renumbering a database will affect all its child
6250 * modify: must be fully supported.
6254 config_back_initialize( BackendInfo
*bi
)
6256 ConfigTable
*ct
= config_back_cf_table
;
6260 AttributeDescription
*ad
= NULL
;
6262 static char *controls
[] = {
6263 LDAP_CONTROL_MANAGEDSAIT
,
6267 /* Make sure we don't exceed the bits reserved for userland */
6268 config_check_userland( CFG_LAST
);
6270 bi
->bi_controls
= controls
;
6275 bi
->bi_destroy
= config_back_destroy
;
6277 bi
->bi_db_init
= config_back_db_init
;
6278 bi
->bi_db_config
= 0;
6279 bi
->bi_db_open
= config_back_db_open
;
6280 bi
->bi_db_close
= config_back_db_close
;
6281 bi
->bi_db_destroy
= config_back_db_destroy
;
6283 bi
->bi_op_bind
= config_back_bind
;
6284 bi
->bi_op_unbind
= 0;
6285 bi
->bi_op_search
= config_back_search
;
6286 bi
->bi_op_compare
= 0;
6287 bi
->bi_op_modify
= config_back_modify
;
6288 bi
->bi_op_modrdn
= config_back_modrdn
;
6289 bi
->bi_op_add
= config_back_add
;
6290 bi
->bi_op_delete
= config_back_delete
;
6291 bi
->bi_op_abandon
= 0;
6293 bi
->bi_extended
= 0;
6295 bi
->bi_chk_referrals
= 0;
6297 bi
->bi_access_allowed
= slap_access_allowed
;
6299 bi
->bi_connection_init
= 0;
6300 bi
->bi_connection_destroy
= 0;
6302 bi
->bi_entry_release_rw
= config_entry_release
;
6303 bi
->bi_entry_get_rw
= config_back_entry_get
;
6305 bi
->bi_tool_entry_open
= config_tool_entry_open
;
6306 bi
->bi_tool_entry_close
= config_tool_entry_close
;
6307 bi
->bi_tool_entry_first
= config_tool_entry_first
;
6308 bi
->bi_tool_entry_next
= config_tool_entry_next
;
6309 bi
->bi_tool_entry_get
= config_tool_entry_get
;
6310 bi
->bi_tool_entry_put
= config_tool_entry_put
;
6313 argv
[ 0 ] = "slapd";
6319 for (i
=0; OidMacros
[i
].name
; i
++ ) {
6320 argv
[1] = OidMacros
[i
].name
;
6321 argv
[2] = OidMacros
[i
].oid
;
6322 parse_oidm( &ca
, 0, NULL
);
6325 bi
->bi_cf_ocs
= cf_ocs
;
6327 i
= config_register_schema( ct
, cf_ocs
);
6330 /* setup olcRootPW to be base64-encoded when written in LDIF form;
6331 * basically, we don't care if it fails */
6332 i
= slap_str2ad( "olcRootPW", &ad
, &text
);
6334 Debug( LDAP_DEBUG_ANY
, "config_back_initialize: "
6335 "warning, unable to get \"olcRootPW\" "
6336 "attribute description: %d: %s\n",
6339 (void)ldif_must_b64_encode_register( ad
->ad_cname
.bv_val
,
6340 ad
->ad_type
->sat_oid
);
6343 /* set up the notable AttributeDescriptions */
6345 for (;ct
->name
;ct
++) {
6346 if (strcmp(ct
->name
, ads
[i
].name
)) continue;
6347 *ads
[i
].desc
= ct
->ad
;
6349 if (!ads
[i
].name
) break;