3 * Copyright 1998-2000 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 char* get_alias_dn(
20 const char **errmsg );
22 static char* new_superior(
27 static int dnlist_subordinate(
31 Entry *deref_internal_r(
40 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
46 assert( ( alias != NULL && dn_in == NULL )
47 || ( alias == NULL && dn_in != NULL ) );
50 *err = LDAP_NO_SUCH_OBJECT;
54 dn = ch_strdup( dn_in );
55 entry = dn2entry_r( be, dn, &sup );
58 dn = ch_strdup( alias->e_ndn );
64 charray_add( &dnlist, dn );
66 for( depth=0 ; ; depth++ ) {
71 /* have entry, may be an alias */
73 if( !is_entry_alias( entry ) ) {
74 /* entry is not an alias */
79 if( depth > be->be_max_deref_depth ) {
82 *err = LDAP_ALIAS_DEREF_PROBLEM;
83 *text = "maximum deref depth exceeded";
88 aliasDN = get_alias_dn( entry, err, text );
90 if( aliasDN == NULL ) {
96 /* check if aliasDN is a subordinate of any DN in our list */
97 if( dnlist_subordinate( dnlist, aliasDN ) ) {
101 *err = LDAP_ALIAS_PROBLEM;
102 *text = "circular alias";
106 /* attempt to dereference alias */
108 newe = dn2entry_r( be, aliasDN, &sup );
113 cache_return_entry_r(&li->li_cache, entry );
115 dn = ch_strdup( entry->e_ndn );
116 charray_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 */
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 supDN = get_alias_dn( sup, err, text );
155 if( supDN == NULL ) {
160 aliasDN = new_superior( dn, sup->e_ndn, supDN );
163 if( aliasDN == NULL ) {
166 *err = LDAP_ALIAS_PROBLEM;
167 *text = "superior alias problem";
171 /* check if aliasDN is a subordinate of any DN in our list */
172 if( dnlist_subordinate( dnlist, aliasDN ) ) {
176 *err = LDAP_ALIAS_PROBLEM;
177 *text = "subordinate circular alias";
181 /* attempt to dereference alias */
182 newe = dn2entry_r( be, aliasDN, &newSup );
187 cache_return_entry_r(&li->li_cache, sup );
189 dn = ch_strdup( entry->e_ndn );
190 charray_add( &dnlist, dn );
195 if ( newSup != NULL ) {
197 cache_return_entry_r(&li->li_cache, sup );
206 /* no newe and no superior, we're done */
212 charray_free( dnlist );
217 static char* get_alias_dn(
220 const char **errmsg )
224 AttributeDescription *aliasedObjectName = slap_schema.si_ad_aliasedObjectName;
226 a = attr_find( e->e_attrs, aliasedObjectName );
230 * there was an aliasedobjectname defined but no data.
232 *err = LDAP_ALIAS_PROBLEM;
233 *errmsg = "alias missing aliasedObjectName attribute";
238 * aliasedObjectName should be SINGLE-VALUED with a single value.
240 if ( a->a_vals[0] == NULL || a->a_vals[0]->bv_val == NULL ) {
242 * there was an aliasedobjectname defined but no data.
244 *err = LDAP_ALIAS_PROBLEM;
245 *errmsg = "alias missing aliasedObjectName value";
249 if( a->a_vals[1] != NULL ) {
250 *err = LDAP_ALIAS_PROBLEM;
251 *errmsg = "alias has multivalued aliasedObjectName";
255 dn = ch_strdup( a->a_vals[0]->bv_val );
257 if( dn_normalize(dn) == NULL ) {
259 *err = LDAP_ALIAS_PROBLEM;
260 *errmsg = "alias aliasedObjectName value is invalid";
267 static char* new_superior(
273 size_t dnlen, olen, nlen;
274 assert( dn && oldSup && newSup );
276 dnlen = strlen( dn );
277 olen = strlen( oldSup );
278 nlen = strlen( newSup );
280 newDN = ch_malloc( dnlen - olen + nlen + 1 );
282 AC_MEMCPY( newDN, dn, dnlen - olen );
283 AC_MEMCPY( &newDN[dnlen - olen], newSup, nlen );
284 newDN[dnlen - olen + nlen] = '\0';
289 static int dnlist_subordinate(
296 for( i = 0; dnlist[i] != NULL; i++ ) {
297 if( dn_issuffix( dnlist[i], dn ) ) {