3 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
10 #include <ac/string.h>
11 #include <ac/socket.h>
13 #include "back-ldbm.h"
14 #include "proto-back-ldbm.h"
17 static int get_alias_dn(
21 const char **errmsg );
23 static void new_superior(
25 struct berval *oldSup,
26 struct berval *newSup,
29 static int dnlist_subordinate(
33 Entry *deref_internal_r(
42 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
48 assert( ( alias != NULL && dn_in == NULL )
49 || ( alias == NULL && dn_in != NULL ) );
52 *err = LDAP_NO_SUCH_OBJECT;
56 ber_dupbv( &dn, dn_in );
57 entry = dn2entry_r( be, &dn, &sup );
60 ber_dupbv( &dn, &alias->e_nname );
66 ber_bvarray_add( &dnlist, &dn );
68 for( depth=0 ; ; depth++ ) {
71 struct berval aliasDN;
73 /* have entry, may be an alias */
75 if( !is_entry_alias( entry ) ) {
76 /* entry is not an alias */
81 if( depth > be->be_max_deref_depth ) {
84 *err = LDAP_ALIAS_DEREF_PROBLEM;
85 *text = "maximum deref depth exceeded";
90 if( get_alias_dn( entry, &aliasDN, err, text )) {
96 /* check if aliasDN is a subordinate of any DN in our list */
97 if( dnlist_subordinate( dnlist, &aliasDN ) ) {
98 ch_free( aliasDN.bv_val );
101 *err = LDAP_ALIAS_PROBLEM;
102 *text = "circular alias";
106 /* attempt to dereference alias */
108 newe = dn2entry_r( be, &aliasDN, &sup );
109 ch_free( aliasDN.bv_val );
112 cache_return_entry_r(&li->li_cache, entry );
114 ber_dupbv( &dn, &entry->e_nname );
115 ber_bvarray_add( &dnlist, &dn );
120 cache_return_entry_r(&li->li_cache, entry );
125 /* no newe and no superior, we're done */
128 } else if( sup != NULL ) {
129 /* have superior, may be an alias */
133 struct berval aliasDN;
135 if( !is_entry_alias( sup ) ) {
136 /* entry is not an alias */
143 if( depth > be->be_max_deref_depth ) {
146 *err = LDAP_ALIAS_DEREF_PROBLEM;
147 *text = "maximum deref depth exceeded";
152 if( get_alias_dn( sup, &supDN, err, text )) {
157 new_superior( &dn, &sup->e_nname, &supDN, &aliasDN );
160 /* check if aliasDN is a subordinate of any DN in our list */
161 if( dnlist_subordinate( dnlist, &aliasDN ) ) {
162 free(aliasDN.bv_val);
165 *err = LDAP_ALIAS_PROBLEM;
166 *text = "subordinate circular alias";
170 /* attempt to dereference alias */
171 newe = dn2entry_r( be, &aliasDN, &newSup );
174 free(aliasDN.bv_val);
175 cache_return_entry_r(&li->li_cache, sup );
177 ber_dupbv( &dn, &entry->e_nname );
178 ber_bvarray_add( &dnlist, &dn );
182 if ( newSup != NULL ) {
183 cache_return_entry_r(&li->li_cache, sup );
185 ber_dupbv( &dn, &aliasDN );
192 /* no newe and no superior, we're done */
197 ber_bvarray_free( dnlist );
202 static int get_alias_dn(
206 const char **errmsg )
210 AttributeDescription *aliasedObjectName
211 = slap_schema.si_ad_aliasedObjectName;
213 a = attr_find( e->e_attrs, aliasedObjectName );
217 * there was an aliasedobjectname defined but no data.
219 *err = LDAP_ALIAS_PROBLEM;
220 *errmsg = "alias missing aliasedObjectName attribute";
225 * aliasedObjectName should be SINGLE-VALUED with a single value.
227 if ( a->a_vals[0].bv_val == NULL ) {
229 * there was an aliasedobjectname defined but no data.
231 *err = LDAP_ALIAS_PROBLEM;
232 *errmsg = "alias missing aliasedObjectName value";
236 if( a->a_vals[1].bv_val != NULL ) {
237 *err = LDAP_ALIAS_PROBLEM;
238 *errmsg = "alias has multivalued aliasedObjectName";
242 rc = dnNormalize2( NULL, &a->a_vals[0], ndn );
243 if( rc != LDAP_SUCCESS ) {
244 *err = LDAP_ALIAS_PROBLEM;
245 *errmsg = "alias aliasedObjectName value is invalid";
252 static void new_superior(
254 struct berval *oldSup,
255 struct berval *newSup,
256 struct berval *newDN )
258 size_t dnlen, olen, nlen;
259 assert( dn && oldSup && newSup && newDN );
262 olen = oldSup->bv_len;
263 nlen = newSup->bv_len;
265 newDN->bv_val = ch_malloc( dnlen - olen + nlen + 1 );
267 AC_MEMCPY( newDN->bv_val, dn->bv_val, dnlen - olen );
268 AC_MEMCPY( &newDN->bv_val[dnlen - olen], newSup->bv_val, nlen );
269 newDN->bv_val[dnlen - olen + nlen] = '\0';
274 static int dnlist_subordinate(
280 for( ; dnlist->bv_val != NULL; dnlist++ ) {
281 if( dnIsSuffix( dnlist, dn ) ) {