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