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