3 * Copyright 1998-2002 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 );
113 cache_return_entry_r(&li->li_cache, entry );
115 ber_dupbv( &dn, &entry->e_nname );
116 ber_bvarray_add( &dnlist, &dn );
121 cache_return_entry_r(&li->li_cache, entry );
126 /* no newe and no superior, we're done */
129 } else if( sup != NULL ) {
130 /* have superior, may be an alias */
134 struct berval aliasDN;
136 if( !is_entry_alias( sup ) ) {
137 /* entry is not an alias */
144 if( depth > be->be_max_deref_depth ) {
147 *err = LDAP_ALIAS_DEREF_PROBLEM;
148 *text = "maximum deref depth exceeded";
153 if( get_alias_dn( sup, &supDN, err, text )) {
158 new_superior( &dn, &sup->e_nname, &supDN, &aliasDN );
161 /* check if aliasDN is a subordinate of any DN in our list */
162 if( dnlist_subordinate( dnlist, &aliasDN ) ) {
163 free(aliasDN.bv_val);
166 *err = LDAP_ALIAS_PROBLEM;
167 *text = "subordinate circular alias";
171 /* attempt to dereference alias */
172 newe = dn2entry_r( be, &aliasDN, &newSup );
175 free(aliasDN.bv_val);
177 cache_return_entry_r(&li->li_cache, sup );
179 ber_dupbv( &dn, &entry->e_nname );
180 ber_bvarray_add( &dnlist, &dn );
184 if ( newSup != NULL ) {
186 cache_return_entry_r(&li->li_cache, sup );
188 ber_dupbv( &dn, &aliasDN );
195 /* no newe and no superior, we're done */
201 ber_bvarray_free( dnlist );
206 static int get_alias_dn(
210 const char **errmsg )
214 AttributeDescription *aliasedObjectName
215 = slap_schema.si_ad_aliasedObjectName;
217 a = attr_find( e->e_attrs, aliasedObjectName );
221 * there was an aliasedobjectname defined but no data.
223 *err = LDAP_ALIAS_PROBLEM;
224 *errmsg = "alias missing aliasedObjectName attribute";
229 * aliasedObjectName should be SINGLE-VALUED with a single value.
231 if ( a->a_vals[0].bv_val == NULL ) {
233 * there was an aliasedobjectname defined but no data.
235 *err = LDAP_ALIAS_PROBLEM;
236 *errmsg = "alias missing aliasedObjectName value";
240 if( a->a_vals[1].bv_val != NULL ) {
241 *err = LDAP_ALIAS_PROBLEM;
242 *errmsg = "alias has multivalued aliasedObjectName";
246 rc = dnNormalize2( NULL, &a->a_vals[0], ndn );
247 if( rc != LDAP_SUCCESS ) {
248 *err = LDAP_ALIAS_PROBLEM;
249 *errmsg = "alias aliasedObjectName value is invalid";
256 static void new_superior(
258 struct berval *oldSup,
259 struct berval *newSup,
260 struct berval *newDN )
262 size_t dnlen, olen, nlen;
263 assert( dn && oldSup && newSup && newDN );
266 olen = oldSup->bv_len;
267 nlen = newSup->bv_len;
269 newDN->bv_val = ch_malloc( dnlen - olen + nlen + 1 );
271 AC_MEMCPY( newDN->bv_val, dn->bv_val, dnlen - olen );
272 AC_MEMCPY( &newDN->bv_val[dnlen - olen], newSup->bv_val, nlen );
273 newDN->bv_val[dnlen - olen + nlen] = '\0';
278 static int dnlist_subordinate(
284 for( ; dnlist->bv_val != NULL; dnlist++ ) {
285 if( dnIsSuffix( dnlist, dn ) ) {