]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/alias.c
9aabaf12eba742fd12ef0c0dceaac57f169240ef
[openldap] / servers / slapd / back-ldbm / alias.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10 #include <ac/string.h>
11 #include <ac/socket.h>
12 #include "slap.h"
13 #include "back-ldbm.h"
14 #include "proto-back-ldbm.h"
15
16
17 static char* get_alias_dn(
18         Entry *e,
19         int *err,
20         const char **errmsg );
21
22 static char* new_superior(
23         const char *dn,
24         const char *oldSup,
25         const char *newSup );
26
27 static int dnlist_subordinate(
28         char** dnlist,
29         const char *dn );
30
31 Entry *deref_internal_r(
32         Backend*        be,
33         Entry*          alias,
34         const char*             dn_in,
35         int*            err,
36         Entry**         matched,
37         const char**            text )
38 {
39         char *dn;
40         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
41         Entry *entry;
42         Entry *sup;
43         unsigned depth;
44         char **dnlist;
45
46         assert( ( alias != NULL && dn == NULL ) || ( alias == NULL && dn != NULL ) );
47
48         *matched = NULL;
49         *err = LDAP_SUCCESS;
50         *text = NULL;
51
52         if( alias == NULL ) {
53                 dn = ch_strdup( dn_in );
54                 entry = dn2entry_r( be, dn, &sup );
55
56         } else {
57                 dn = ch_strdup( alias->e_ndn );
58                 entry = alias;
59                 sup = NULL;
60         }
61
62         dnlist = NULL;
63         charray_add( &dnlist, dn );
64
65         for( depth=0 ; ; depth++ ) {
66                 if( entry != NULL ) {
67                         Entry *newe;
68                         char *aliasDN;
69
70                         /* have entry, may be an alias */
71
72                         if( !is_entry_alias( entry ) ) {
73                                 /* entry is not an alias */
74                                 break;
75                         }
76
77                         /* entry is alias */
78                         if( depth > be->be_max_deref_depth ) {
79                                 *matched = entry;
80                                 entry = NULL;
81                                 *err = LDAP_ALIAS_DEREF_PROBLEM;
82                                 *text = "maximum deref depth exceeded";
83                                 break;
84                         }
85
86                         /* deref entry */
87                         aliasDN = get_alias_dn( entry, err, text );
88
89                         if( aliasDN == NULL ) {
90                                 *matched = entry;
91                                 entry = NULL;
92                                 break;
93                         }
94
95                         /* check if aliasDN is a subordinate of any DN in our list */
96                         if( dnlist_subordinate( dnlist, aliasDN ) ) {
97                                 *matched = entry;
98                                 entry = NULL;
99                                 *err = LDAP_ALIAS_PROBLEM;
100                                 *text = "circular alias";
101                                 break;
102                         }
103
104                         /* attempt to dereference alias */
105
106                         newe = dn2entry_r( be, aliasDN, &sup );
107
108                         if( newe != NULL ) {
109                                 free( dn );
110                                 cache_return_entry_r(&li->li_cache, entry );
111                                 entry = newe;
112                                 dn = ch_strdup( entry->e_ndn );
113                                 charray_add( &dnlist, dn );
114                                 continue;
115
116                         }
117                         
118                         if ( sup != NULL ) {
119                                 cache_return_entry_r(&li->li_cache, entry );
120                                 entry = NULL;
121                                 continue;
122                         }
123
124                         /* no newe and no superior, we're done */
125                         break;
126
127                 } else if( sup != NULL ) {
128                         /* have superior, may be an alias */
129                         Entry *newe;
130                         Entry *newSup;
131                         char *supDN;
132                         char *aliasDN;
133
134                         if( !is_entry_alias( sup ) ) {
135                                 /* entry is not an alias */
136                                 *matched = sup;
137                                 sup = NULL;
138                                 break;
139                         }
140
141                         /* entry is alias */
142                         if( depth > be->be_max_deref_depth ) {
143                                 *matched = sup;
144                                 entry = NULL;
145                                 *err = LDAP_ALIAS_DEREF_PROBLEM;
146                                 *text = "maximum deref depth exceeded";
147                                 break;
148                         }
149
150                         /* deref entry */
151                         supDN = get_alias_dn( sup, err, text );
152
153                         if( supDN == NULL ) {
154                                 *matched = sup;
155                                 break;
156                         }
157
158                         aliasDN = new_superior( dn, sup->e_ndn, supDN );
159
160                         if( aliasDN == NULL ) {
161                                 free(aliasDN);
162                                 *matched = sup;
163                                 *err = LDAP_ALIAS_PROBLEM;
164                                 *text = "superior alias problem";
165                                 break;
166                         }
167
168                         /* check if aliasDN is a subordinate of any DN in our list */
169                         if( dnlist_subordinate( dnlist, aliasDN ) ) {
170                                 free(aliasDN);
171                                 *matched = entry;
172                                 entry = NULL;
173                                 *err = LDAP_ALIAS_PROBLEM;
174                                 *text = "subordinate circular alias";
175                                 break;
176                         }
177
178                         /* attempt to dereference alias */
179                         newe = dn2entry_r( be, aliasDN, &newSup );
180
181                         if( newe != NULL ) {
182                                 free(aliasDN);
183                                 free( dn );
184                                 cache_return_entry_r(&li->li_cache, sup );
185                                 entry = newe;
186                                 dn = ch_strdup( entry->e_ndn );
187                                 charray_add( &dnlist, dn );
188                                 continue;
189
190                         }
191                         
192                         if ( newSup != NULL ) {
193                                 free( dn );
194                                 cache_return_entry_r(&li->li_cache, sup );
195                                 sup = newSup;
196                                 dn = aliasDN;
197                                 continue;
198                         }
199
200                         break;
201
202                 } else {
203                         /* no newe and no superior, we're done */
204                         break;
205                 }
206         }
207
208         free( dn );
209         charray_free( dnlist );
210         return entry;
211 }
212
213
214 static char* get_alias_dn(
215         Entry *e,
216         int *err,
217         const char **errmsg )
218 {       
219         Attribute *a;
220 #ifdef SLAPD_SCHEMA_NOT_COMPAT
221         AttributeDescription *aliasedObjectName = slap_schema.si_ad_aliasedObjectName;
222 #else
223         static const char *aliasedObjectName = "aliasedObjectName";
224 #endif
225
226         a = attr_find( e->e_attrs, aliasedObjectName );
227
228         if( a == NULL ) {
229                 /*
230                  * there was an aliasedobjectname defined but no data.
231                  */
232                 *err = LDAP_ALIAS_PROBLEM;
233                 *errmsg = "alias missing aliasedObjectName attribute";
234                 return NULL;
235         }
236
237         /* 
238          * aliasedObjectName should be SINGLE-VALUED with a single value. 
239          */                     
240         if ( a->a_vals[0] == NULL || a->a_vals[0]->bv_val == NULL ) {
241                 /*
242                  * there was an aliasedobjectname defined but no data.
243                  */
244                 *err = LDAP_ALIAS_PROBLEM;
245                 *errmsg = "alias missing aliasedObjectName value";
246                 return NULL;
247         }
248
249         if( a->a_vals[1] != NULL ) {
250                 *err = LDAP_ALIAS_PROBLEM;
251                 *errmsg = "alias has multivalued aliasedObjectName";
252                 return NULL;
253         }
254
255         return a->a_vals[0]->bv_val;
256 }
257
258 char* new_superior(
259         const char *dn,
260         const char *oldSup,
261         const char *newSup )
262 {
263         char *newDN;
264         size_t dnlen, olen, nlen;
265         assert( dn && oldSup && newSup );
266
267         dnlen = strlen( dn );
268         olen = strlen( oldSup );
269         nlen = strlen( newSup );
270
271         newDN = ch_malloc( dnlen - olen + nlen + 1 );
272
273         memcpy( newDN, dn, dnlen - olen );
274         memcpy( &newDN[dnlen - olen], newSup, nlen );
275         newDN[dnlen - olen + nlen] = '\0';
276
277         return newDN;
278 }
279
280 static int dnlist_subordinate(
281         char** dnlist,
282         const char *dn )
283 {
284         int i;
285         assert( dnlist );
286
287         for( i = 0; dnlist[i] != NULL; i++ ) {
288                 if( dn_issuffix( dnlist[i], dn ) ) {
289                         return 1;
290                 }
291         }
292
293         return 0;
294 }
295