2 * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to ITSD, Government of BC. The name of ITSD
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
15 #ifdef SLAPD_ALIAS_DEREF
19 #include <ac/socket.h> /* Get struct sockaddr for slap.h */
21 #include "back-ldbm.h"
22 #include "proto-back-ldbm.h"
25 * given an alias object, dereference it to its end point.
26 * entry returned has reader lock
28 Entry *derefAlias_r ( Backend *be,
38 Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", e->e_dn, 0, 0 );
41 * try to deref fully, up to a maximum depth. If the max depth exceeded
45 ( ( a = attr_find( e->e_attrs, "aliasedobjectname" ) ) != NULL) &&
46 ( depth < be->be_maxDerefDepth );
51 * make sure there is a defined aliasedobjectname.
52 * can only have one value so just use first value (0) in the attr list.
54 if (a->a_vals[0] && a->a_vals[0]->bv_val) {
57 Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n",
58 e->e_dn, a->a_vals[0]->bv_val, 0 );
59 newDN = ch_strdup (a->a_vals[0]->bv_val);
60 oldDN = ch_strdup (e->e_dn);
63 * ok, so what happens if there is an alias in the DN of a dereferenced
66 if ( (e = dn2entry_r( be, newDN, &matched )) == NULL ) {
68 /* could not deref return error */
69 Debug( LDAP_DEBUG_TRACE,
70 "<= %s is a dangling alias to %s\n",
72 send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
75 if(matched != NULL) free(matched);
82 * there was an aliasedobjectname defined but no data.
83 * this can't happen, right?
85 Debug( LDAP_DEBUG_TRACE,
86 "<= %s has no data in aliasedobjectname attribute\n",
88 send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
89 "Alias missing aliasedobjectname" );
94 * warn if we pulled out due to exceeding the maximum deref depth
96 if ( depth >= be->be_maxDerefDepth ) {
97 Debug( LDAP_DEBUG_TRACE,
98 "<= %s exceeded maximum deref depth %d\n",
99 e->e_dn, be->be_maxDerefDepth, 0 );
100 send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
101 "Maximum alias dereference depth exceeded" );
108 * given a DN fully deref it and return the real DN or original DN if it fails
110 char *derefDN ( Backend *be,
116 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
125 Debug( LDAP_DEBUG_TRACE,
126 "<= dereferencing dn: \"%s\"\n",
129 newDN = ch_strdup ( dn );
131 /* while we don't have a matched dn, deref the DN */
133 ( (eMatched = dn2entry_r( be, newDN, &matched )) == NULL) &&
134 (depth < be->be_maxDerefDepth);
137 if ((matched != NULL) && *matched) {
141 * make sure there actually is an entry for the matched part
143 if ( (eMatched = dn2entry_r( be, matched, &submatch )) != NULL) {
144 char *remainder; /* part before the aliased part */
145 int rlen = strlen(newDN) - strlen(matched);
147 Debug( LDAP_DEBUG_TRACE, "<= matched %s\n", matched, 0, 0 );
149 remainder = ch_malloc (rlen + 1);
150 strncpy ( remainder, newDN, rlen );
151 remainder[rlen] = '\0';
153 Debug( LDAP_DEBUG_TRACE, "<= remainder %s\n", remainder, 0, 0 );
155 if ((eNew = derefAlias_r( be, conn, op, eMatched )) == NULL) {
162 break; /* no associated entry, dont deref */
166 Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 );
168 i = strcasecmp (matched, eNew->e_dn);
169 /* free reader lock */
170 cache_return_entry_r(&li->li_cache, eNew);
172 /* newDN same as old so not an alias, no need to go further */
182 * we have dereferenced the aliased part so put
183 * the new dn together
186 newDN = ch_malloc (strlen(eMatched->e_dn) + rlen + 1);
187 strcpy (newDN, remainder);
188 strcat (newDN, eMatched->e_dn);
189 Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 );
195 /* free reader lock */
196 cache_return_entry_r(&li->li_cache, eMatched);
199 if(submatch != NULL) free(submatch);
200 break; /* there was no entry for the matched part */
204 break; /* there was no matched part */
208 if(eMatched != NULL) {
209 /* free reader lock */
210 cache_return_entry_r(&li->li_cache, eMatched);
214 * the final part of the DN might be an alias
215 * so try to dereference it.
217 if ( (eNew = dn2entry_r( be, newDN, &matched )) != NULL) {
218 if ((eDeref = derefAlias_r( be, conn, op, eNew )) != NULL) {
220 newDN = ch_strdup (eDeref->e_dn);
221 /* free reader lock */
222 cache_return_entry_r(&li->li_cache, eDeref);
224 /* free reader lock */
225 cache_return_entry_r(&li->li_cache, eNew);
229 * warn if we exceeded the max depth as the resulting DN may not be dereferenced
231 if (depth >= be->be_maxDerefDepth) {
232 Debug( LDAP_DEBUG_TRACE,
233 "<= max deref depth exceeded in derefDN for \"%s\", result \"%s\"\n",
235 send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
236 "Maximum alias dereference depth exceeded for base" );
240 newDN = ch_strdup ( dn );
243 Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 );
244 if (matched != NULL) free(matched);
249 #endif /* SLAPD_ALIAS_DEREF */