1 /* root_dse.c - Provides the Root DSA-Specific Entry */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/root_dse.c,v 1.113.2.8 2008/02/11 23:26:44 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1999-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>.
21 #include <ac/string.h>
28 #include "slapi/slapi.h"
31 static struct berval builtin_supportedFeatures
[] = {
32 BER_BVC(LDAP_FEATURE_MODIFY_INCREMENT
), /* Modify/increment */
33 BER_BVC(LDAP_FEATURE_ALL_OP_ATTRS
), /* All Op Attrs (+) */
34 BER_BVC(LDAP_FEATURE_OBJECTCLASS_ATTRS
), /* OCs in Attrs List (@class) */
35 BER_BVC(LDAP_FEATURE_ABSOLUTE_FILTERS
), /* (&) and (|) search filters */
36 BER_BVC(LDAP_FEATURE_LANGUAGE_TAG_OPTIONS
), /* Language Tag Options */
37 BER_BVC(LDAP_FEATURE_LANGUAGE_RANGE_OPTIONS
), /* Language Range Options */
39 BER_BVC(LDAP_FEATURE_SUBORDINATE_SCOPE
), /* "children" search scope */
43 static struct berval
*supportedFeatures
;
45 static Entry
*usr_attr
= NULL
;
48 * allow modules to register functions that muck with the root DSE entry
51 typedef struct entry_info_t
{
52 SLAP_ENTRY_INFO_FN func
;
54 struct entry_info_t
*next
;
57 static entry_info_t
*extra_info
;
60 entry_info_register( SLAP_ENTRY_INFO_FN func
, void *arg
)
62 entry_info_t
*ei
= ch_calloc( 1, sizeof( entry_info_t
) );
67 ei
->next
= extra_info
;
74 entry_info_unregister( SLAP_ENTRY_INFO_FN func
, void *arg
)
78 for ( eip
= &extra_info
; *eip
!= NULL
; eip
= &(*eip
)->next
) {
79 if ( (*eip
)->func
== func
&& (*eip
)->arg
== arg
) {
80 entry_info_t
*ei
= *eip
;
94 entry_info_destroy( void )
98 for ( eip
= &extra_info
; *eip
!= NULL
; ) {
99 entry_info_t
*ei
= *eip
;
108 * Allow modules to register supported features
112 supported_feature_init( void )
116 if ( supportedFeatures
!= NULL
) {
120 for ( i
= 0; !BER_BVISNULL( &builtin_supportedFeatures
[ i
] ); i
++ )
123 supportedFeatures
= ch_calloc( sizeof( struct berval
), i
+ 1 );
124 if ( supportedFeatures
== NULL
) {
128 for ( i
= 0; !BER_BVISNULL( &builtin_supportedFeatures
[ i
] ); i
++ ) {
129 ber_dupbv( &supportedFeatures
[ i
], &builtin_supportedFeatures
[ i
] );
131 BER_BVZERO( &supportedFeatures
[ i
] );
137 supported_feature_destroy( void )
141 if ( supportedFeatures
== NULL
) {
145 for ( i
= 0; !BER_BVISNULL( &supportedFeatures
[ i
] ); i
++ ) {
146 ch_free( supportedFeatures
[ i
].bv_val
);
149 ch_free( supportedFeatures
);
150 supportedFeatures
= NULL
;
156 supported_feature_load( struct berval
*f
)
161 supported_feature_init();
163 for ( i
= 0; !BER_BVISNULL( &supportedFeatures
[ i
] ); i
++ )
166 tmp
= ch_realloc( supportedFeatures
, sizeof( struct berval
) * ( i
+ 2 ) );
170 supportedFeatures
= tmp
;
172 ber_dupbv( &supportedFeatures
[ i
], f
);
173 BER_BVZERO( &supportedFeatures
[ i
+ 1 ] );
190 char ** supportedSASLMechanisms
;
193 AttributeDescription
*ad_structuralObjectClass
194 = slap_schema
.si_ad_structuralObjectClass
;
195 AttributeDescription
*ad_objectClass
196 = slap_schema
.si_ad_objectClass
;
197 AttributeDescription
*ad_namingContexts
198 = slap_schema
.si_ad_namingContexts
;
200 AttributeDescription
*ad_supportedExtension
201 = slap_schema
.si_ad_supportedExtension
;
203 AttributeDescription
*ad_supportedLDAPVersion
204 = slap_schema
.si_ad_supportedLDAPVersion
;
205 AttributeDescription
*ad_supportedSASLMechanisms
206 = slap_schema
.si_ad_supportedSASLMechanisms
;
207 AttributeDescription
*ad_supportedFeatures
208 = slap_schema
.si_ad_supportedFeatures
;
209 AttributeDescription
*ad_monitorContext
210 = slap_schema
.si_ad_monitorContext
;
211 AttributeDescription
*ad_configContext
212 = slap_schema
.si_ad_configContext
;
213 AttributeDescription
*ad_ref
214 = slap_schema
.si_ad_ref
;
218 Debug( LDAP_DEBUG_ANY
,
219 "root_dse_info: entry_alloc failed", 0, 0, 0 );
224 e
->e_name
.bv_val
= ch_strdup( LDAP_ROOT_DSE
);
225 e
->e_name
.bv_len
= sizeof( LDAP_ROOT_DSE
)-1;
226 e
->e_nname
.bv_val
= ch_strdup( LDAP_ROOT_DSE
);
227 e
->e_nname
.bv_len
= sizeof( LDAP_ROOT_DSE
)-1;
229 /* the DN is an empty string so no pretty/normalization is needed */
230 assert( !e
->e_name
.bv_len
);
231 assert( !e
->e_nname
.bv_len
);
235 /* FIXME: is this really needed? */
236 BER_BVSTR( &val
, "top" );
237 if( attr_merge_one( e
, ad_objectClass
, &val
, NULL
) ) {
243 BER_BVSTR( &val
, "OpenLDAProotDSE" );
244 if( attr_merge_one( e
, ad_objectClass
, &val
, NULL
) ) {
247 if( attr_merge_one( e
, ad_structuralObjectClass
, &val
, NULL
) ) {
251 LDAP_STAILQ_FOREACH( be
, &backendDB
, be_next
) {
252 if ( be
->be_suffix
== NULL
253 || be
->be_nsuffix
== NULL
) {
257 if ( SLAP_MONITOR( be
)) {
258 if( attr_merge_one( e
, ad_monitorContext
,
260 &be
->be_nsuffix
[0] ) )
266 if ( SLAP_CONFIG( be
)) {
267 if( attr_merge_one( e
, ad_configContext
,
269 & be
->be_nsuffix
[0] ) )
275 if ( SLAP_GLUE_SUBORDINATE( be
) && !SLAP_GLUE_ADVERTISE( be
) ) {
278 for ( j
= 0; be
->be_suffix
[j
].bv_val
!= NULL
; j
++ ) {
279 if( attr_merge_one( e
, ad_namingContexts
,
281 &be
->be_nsuffix
[0] ) )
288 /* altServer unsupported */
290 /* supportedControl */
291 if ( controls_root_dse_info( e
) != 0 ) {
295 /* supportedExtension */
296 if ( exop_root_dse_info( e
) != 0 ) {
301 /* netscape supportedExtension */
302 for ( i
= 0; (bv
= slapi_int_get_supported_extop(i
)) != NULL
; i
++ ) {
303 if( attr_merge_one( e
, ad_supportedExtension
, bv
, NULL
) ) {
307 #endif /* LDAP_SLAPI */
309 /* supportedFeatures */
310 if ( supportedFeatures
== NULL
) {
311 supported_feature_init();
314 if( attr_merge( e
, ad_supportedFeatures
, supportedFeatures
, NULL
) ) {
318 /* supportedLDAPVersion */
319 /* don't publish version 2 as we don't really support it
320 * (even when configured to accept version 2 Bind requests)
321 * and the value would never be used by true LDAPv2 (or LDAPv3)
324 for ( i
=LDAP_VERSION3
; i
<=LDAP_VERSION_MAX
; i
++ ) {
325 char buf
[sizeof("255")];
326 snprintf(buf
, sizeof buf
, "%d", i
);
328 val
.bv_len
= strlen( val
.bv_val
);
329 if( attr_merge_one( e
, ad_supportedLDAPVersion
, &val
, NULL
) ) {
334 /* supportedSASLMechanism */
335 supportedSASLMechanisms
= slap_sasl_mechs( conn
);
337 if( supportedSASLMechanisms
!= NULL
) {
338 for ( i
=0; supportedSASLMechanisms
[i
] != NULL
; i
++ ) {
339 val
.bv_val
= supportedSASLMechanisms
[i
];
340 val
.bv_len
= strlen( val
.bv_val
);
341 if( attr_merge_one( e
, ad_supportedSASLMechanisms
, &val
, NULL
) ) {
342 ldap_charray_free( supportedSASLMechanisms
);
346 ldap_charray_free( supportedSASLMechanisms
);
349 if ( default_referral
!= NULL
) {
350 if( attr_merge( e
, ad_ref
, default_referral
, NULL
/* FIXME */ ) ) {
355 if( usr_attr
!= NULL
) {
357 for( a
= usr_attr
->e_attrs
; a
!= NULL
; a
= a
->a_next
) {
358 if( attr_merge( e
, a
->a_desc
, a
->a_vals
,
359 (a
->a_nvals
== a
->a_vals
) ? NULL
: a
->a_nvals
) )
367 entry_info_t
*ei
= extra_info
;
369 for ( ; ei
; ei
= ei
->next
) {
370 ei
->func( ei
->arg
, e
);
379 root_dse_init( void )
385 root_dse_destroy( void )
388 entry_free( usr_attr
);
396 * Read the entries specified in fname and merge the attributes
397 * to the user defined rootDSE. Note thaat if we find any errors
398 * what so ever, we will discard the entire entries, print an
399 * error message and return.
402 root_dse_read_file( const char *fname
)
405 int rc
= 0, lineno
= 0, lmax
= 0;
408 if ( (fp
= ldif_open( fname
, "r" )) == NULL
) {
409 Debug( LDAP_DEBUG_ANY
,
410 "root_dse_read_file: could not open rootdse attr file \"%s\" - absolute path?\n",
416 usr_attr
= entry_alloc();
417 if( usr_attr
== NULL
) {
418 Debug( LDAP_DEBUG_ANY
,
419 "root_dse_read_file: entry_alloc failed", 0, 0, 0 );
423 usr_attr
->e_attrs
= NULL
;
425 while( ldif_read_record( fp
, &lineno
, &buf
, &lmax
) ) {
426 Entry
*e
= str2entry( buf
);
430 Debug( LDAP_DEBUG_ANY
, "root_dse_read_file: "
431 "could not parse entry (file=\"%s\" line=%d)\n",
437 /* make sure the DN is the empty DN */
438 if( e
->e_nname
.bv_len
) {
439 Debug( LDAP_DEBUG_ANY
,
440 "root_dse_read_file: invalid rootDSE "
441 "- dn=\"%s\" (file=\"%s\" line=%d)\n",
442 e
->e_dn
, fname
, lineno
);
449 * we found a valid entry, so walk thru all the attributes in the
450 * entry, and add each attribute type and description to the
454 for(a
= e
->e_attrs
; a
!= NULL
; a
= a
->a_next
) {
455 if( attr_merge( usr_attr
, a
->a_desc
, a
->a_vals
,
456 (a
->a_nvals
== a
->a_vals
) ? NULL
: a
->a_nvals
) )
468 entry_free( usr_attr
);
476 Debug(LDAP_DEBUG_CONFIG
, "rootDSE file=\"%s\" read.\n", fname
, 0, 0);
481 slap_discover_feature(
487 LDAPMessage
*res
= NULL
, *entry
;
489 struct berval bv_val
,
491 char *attrs
[ 2 ] = { NULL
, NULL
};
493 rc
= slap_client_connect( &ld
, sb
);
494 if ( rc
!= LDAP_SUCCESS
) {
498 attrs
[ 0 ] = (char *) attr
;
499 rc
= ldap_search_ext_s( ld
, "", LDAP_SCOPE_BASE
, "(objectClass=*)",
500 attrs
, 0, NULL
, NULL
, NULL
, 0, &res
);
501 if ( rc
!= LDAP_SUCCESS
) {
505 entry
= ldap_first_entry( ld
, res
);
506 if ( entry
== NULL
) {
510 values
= ldap_get_values_len( ld
, entry
, attrs
[ 0 ] );
511 if ( values
== NULL
) {
512 rc
= LDAP_NO_SUCH_ATTRIBUTE
;
516 ber_str2bv( val
, 0, 0, &bv_val
);
517 for ( i
= 0; values
[ i
] != NULL
; i
++ ) {
518 if ( bvmatch( &bv_val
, values
[ i
] ) ) {
519 rc
= LDAP_COMPARE_TRUE
;
524 rc
= LDAP_COMPARE_FALSE
;
527 if ( values
!= NULL
) {
528 ldap_value_free_len( values
);
535 ldap_unbind_ext( ld
, NULL
, NULL
);