]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/alias.c
ITS#2440 unmunge init_module names
[openldap] / servers / slapd / back-ldbm / alias.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 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 void new_superior(
18         struct berval *dn,
19         struct berval *oldSup,
20         struct berval *newSup,
21         struct berval *res );
22
23 static int dnlist_subordinate(
24         BerVarray dnlist,
25         struct berval *dn );
26
27 Entry *deref_internal_r(
28         Backend*        be,
29         Entry*          alias,
30         struct berval*  dn_in,
31         int*            err,
32         Entry**         matched,
33         const char**            text )
34 {
35         struct berval dn;
36         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
37         Entry *entry;
38         Entry *sup;
39         unsigned depth;
40         BerVarray dnlist;
41
42         assert( ( alias != NULL && dn_in == NULL )
43                 || ( alias == NULL && dn_in != NULL ) );
44
45         *matched = NULL;
46         *err = LDAP_NO_SUCH_OBJECT;
47         *text = NULL;
48
49         if( alias == NULL ) {
50                 ber_dupbv( &dn, dn_in );
51                 entry = dn2entry_r( be, &dn, &sup );
52
53         } else {
54                 ber_dupbv( &dn, &alias->e_nname );
55                 entry = alias;
56                 sup = NULL;
57         }
58
59         dnlist = NULL;
60         ber_bvarray_add( &dnlist, &dn );
61
62         for( depth=0 ; ; depth++ ) {
63                 if( entry != NULL ) {
64                         Entry *newe;
65                         struct berval 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                         if( get_alias_dn( entry, &aliasDN, err, text )) {
85                                 *matched = entry;
86                                 entry = NULL;
87                                 break;
88                         }
89
90                         /* check if aliasDN is a subordinate of any DN in our list */
91                         if( dnlist_subordinate( dnlist, &aliasDN ) ) {
92                                 ch_free( aliasDN.bv_val );
93                                 *matched = entry;
94                                 entry = NULL;
95                                 *err = LDAP_ALIAS_PROBLEM;
96                                 *text = "circular alias";
97                                 break;
98                         }
99
100                         /* attempt to dereference alias */
101
102                         newe = dn2entry_r( be, &aliasDN, &sup );
103                         ch_free( aliasDN.bv_val );
104
105                         if( newe != NULL ) {
106                                 cache_return_entry_r(&li->li_cache, entry );
107                                 entry = newe;
108                                 ber_dupbv( &dn, &entry->e_nname );
109                                 ber_bvarray_add( &dnlist, &dn );
110                                 continue;
111                         }
112                         
113                         if ( sup != NULL ) {
114                                 cache_return_entry_r(&li->li_cache, entry );
115                                 entry = NULL;
116                                 continue;
117                         }
118
119                         /* no newe and no superior, we're done */
120                         break;
121
122                 } else if( sup != NULL ) {
123                         /* have superior, may be an alias */
124                         Entry *newe;
125                         Entry *newSup;
126                         struct berval supDN;
127                         struct berval aliasDN;
128
129                         if( !is_entry_alias( sup ) ) {
130                                 /* entry is not an alias */
131                                 *matched = sup;
132                                 sup = NULL;
133                                 break;
134                         }
135
136                         /* entry is alias */
137                         if( depth > be->be_max_deref_depth ) {
138                                 *matched = sup;
139                                 entry = NULL;
140                                 *err = LDAP_ALIAS_DEREF_PROBLEM;
141                                 *text = "maximum deref depth exceeded";
142                                 break;
143                         }
144
145                         /* deref entry */
146                         if( get_alias_dn( sup, &supDN, err, text )) {
147                                 *matched = sup;
148                                 break;
149                         }
150
151                         new_superior( &dn, &sup->e_nname, &supDN, &aliasDN );
152                         free(supDN.bv_val);
153
154                         /* check if aliasDN is a subordinate of any DN in our list */
155                         if( dnlist_subordinate( dnlist, &aliasDN ) ) {
156                                 free(aliasDN.bv_val);
157                                 *matched = entry;
158                                 entry = NULL;
159                                 *err = LDAP_ALIAS_PROBLEM;
160                                 *text = "subordinate circular alias";
161                                 break;
162                         }
163
164                         /* attempt to dereference alias */
165                         newe = dn2entry_r( be, &aliasDN, &newSup );
166
167                         if( newe != NULL ) {
168                                 free(aliasDN.bv_val);
169                                 cache_return_entry_r(&li->li_cache, sup );
170                                 entry = newe;
171                                 ber_dupbv( &dn, &entry->e_nname );
172                                 ber_bvarray_add( &dnlist, &dn );
173                                 continue;
174                         }
175                         
176                         if ( newSup != NULL ) {
177                                 cache_return_entry_r(&li->li_cache, sup );
178                                 sup = newSup;
179                                 ber_dupbv( &dn, &aliasDN );
180                                 continue;
181                         }
182
183                         break;
184
185                 } else {
186                         /* no newe and no superior, we're done */
187                         break;
188                 }
189         }
190
191         ber_bvarray_free( dnlist );
192         return entry;
193 }
194
195
196 static void new_superior(
197         struct berval *dn,
198         struct berval *oldSup,
199         struct berval *newSup,
200         struct berval *newDN )
201 {
202         size_t dnlen, olen, nlen;
203         assert( dn && oldSup && newSup && newDN );
204
205         dnlen = dn->bv_len;
206         olen = oldSup->bv_len;
207         nlen = newSup->bv_len;
208
209         newDN->bv_val = ch_malloc( dnlen - olen + nlen + 1 );
210
211         AC_MEMCPY( newDN->bv_val, dn->bv_val, dnlen - olen );
212         AC_MEMCPY( &newDN->bv_val[dnlen - olen], newSup->bv_val, nlen );
213         newDN->bv_val[dnlen - olen + nlen] = '\0';
214
215         return;
216 }
217
218 static int dnlist_subordinate(
219         BerVarray dnlist,
220         struct berval *dn )
221 {
222         assert( dnlist );
223
224         for( ; dnlist->bv_val != NULL; dnlist++ ) {
225                 if( dnIsSuffix( dnlist, dn ) ) {
226                         return 1;
227                 }
228         }
229
230         return 0;
231 }