]> git.sur5r.net Git - openldap/blob - servers/slapd/referral.c
Added bdb_attribute and bdb_group ACL support routines
[openldap] / servers / slapd / referral.c
1 /* referral.c - muck with referrals */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2001 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/socket.h>
13 #include <ac/errno.h>
14 #include <ac/signal.h>
15 #include <ac/string.h>
16 #include <ac/ctype.h>
17 #include <ac/time.h>
18 #include <ac/unistd.h>
19
20 #include "slap.h"
21
22 /*
23  * This routine generates the DN appropriate to return in
24  * an LDAP referral.
25  */
26 static char * referral_dn_muck(
27         const char * refDN,
28         const char * baseDN,
29         const char * targetDN )
30 {
31         char *tmp;
32         char *nrefDN = NULL;
33         char *nbaseDN = NULL;
34         char *ntargetDN = NULL;
35
36         if( !baseDN ) {
37                 /* no base, return target */
38                 return targetDN ? ch_strdup( targetDN ) : NULL;
39         }
40
41         if( refDN ) {
42                 nrefDN = dn_validate( tmp = ch_strdup( refDN ) );
43                 if( !nrefDN ) {
44                         /* Invalid refDN */
45                         ch_free( tmp );
46                         return NULL;
47                 }
48         }
49
50         if( !targetDN ) {
51                 /* continuation reference
52                  *      if refDN present return refDN
53                  *  else return baseDN
54                  */
55                 return nrefDN ? nrefDN : ch_strdup( baseDN );
56         }
57
58         ntargetDN = dn_validate( tmp = ch_strdup( targetDN ) );
59         if( !ntargetDN ) {
60                 ch_free( tmp );
61                 ch_free( nrefDN );
62                 return NULL;
63         }
64
65         if( nrefDN ) {
66                 nbaseDN = dn_validate( tmp = ch_strdup( baseDN ) );
67                 if( !nbaseDN ) {
68                         /* Invalid baseDN */
69                         ch_free( ntargetDN );
70                         ch_free( nrefDN );
71                         ch_free( tmp );
72                         return NULL;
73                 }
74
75                 if( strcasecmp( nbaseDN, nrefDN ) == 0 ) {
76                         ch_free( nrefDN );
77                         ch_free( nbaseDN );
78                         return ntargetDN;
79                 }
80
81                 {
82                         /*
83                          * FIXME: string based mucking
84                          */
85                         char *muck;
86                         size_t reflen, baselen, targetlen, mucklen;
87
88                         reflen = strlen( nrefDN );
89                         baselen = strlen( nbaseDN );
90                         targetlen = strlen( ntargetDN );
91
92                         if( targetlen < baselen ) {
93                                 ch_free( nrefDN );
94                                 ch_free( nbaseDN );
95                                 return ntargetDN;
96                         }
97
98                         if( strcasecmp( &ntargetDN[targetlen-baselen], nbaseDN ) ) {
99                                 /* target not subordinate to base */
100                                 ch_free( nrefDN );
101                                 ch_free( nbaseDN );
102                                 return ntargetDN;
103                         }
104
105                         mucklen = targetlen + reflen - baselen;
106                         muck = ch_malloc( 1 + mucklen );
107
108                         strncpy( muck, ntargetDN, targetlen-baselen );
109                         strcpy( &muck[targetlen-baselen], nrefDN );
110
111                         ch_free( nrefDN );
112                         ch_free( nbaseDN );
113                         ch_free( ntargetDN );
114
115                         return muck;
116                 }
117         }
118
119         return ntargetDN;
120 }
121
122
123 /* validate URL for global referral use
124  *   LDAP URLs must not have:
125  *     DN, attrs, scope, nor filter
126  *   Any non-LDAP URL is okay
127  *
128  *   XXYYZ: should return an error string
129  */
130 int validate_global_referral( const char *url )
131 {
132         int rc;
133         LDAPURLDesc *lurl;
134
135         rc = ldap_url_parse_ext( url, &lurl );
136
137         switch( rc ) {
138         case LDAP_URL_SUCCESS:
139                 break;
140
141         case LDAP_URL_ERR_BADSCHEME:
142                 /* not LDAP hence valid */
143                 return 0;
144
145         default:
146                 /* other error, bail */
147 #ifdef NEW_LOGGING
148                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
149                         "referral: invalid URL (%s): %s (%d)\n",
150                         url, "" /* ldap_url_error2str(rc) */, rc ));
151 #else
152                 Debug( LDAP_DEBUG_ANY,
153                         "referral: invalid URL (%s): %s (%d)\n",
154                         url, "" /* ldap_url_error2str(rc) */, rc );
155 #endif
156                 return 1;
157         }
158
159         rc = 0;
160
161         if( lurl->lud_dn && *lurl->lud_dn ) {
162 #ifdef NEW_LOGGING
163                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
164                         "referral: URL (%s): contains DN\n",
165                         url ));
166 #else
167                 Debug( LDAP_DEBUG_ANY,
168                         "referral: URL (%s): contains DN\n",
169                         url, 0, 0 );
170 #endif
171                 rc = 1;
172
173         } else if( lurl->lud_attrs ) {
174 #ifdef NEW_LOGGING
175                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
176                         "referral: URL (%s): requests attributes\n",
177                         url ));
178 #else
179                 Debug( LDAP_DEBUG_ANY,
180                         "referral: URL (%s): requests attributes\n",
181                         url, 0, 0 );
182 #endif
183                 rc = 1;
184
185         } else if( lurl->lud_scope != LDAP_SCOPE_DEFAULT ) {
186 #ifdef NEW_LOGGING
187                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
188                         "referral: URL (%s): contains explicit scope\n",
189                         url ));
190 #else
191                 Debug( LDAP_DEBUG_ANY,
192                         "referral: URL (%s): contains explicit scope\n",
193                         url, 0, 0 );
194 #endif
195                 rc = 1;
196
197         } else if( lurl->lud_filter ) {
198 #ifdef NEW_LOGGING
199                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
200                         "referral: URL (%s): contains explicit filter\n",
201                         url ));
202 #else
203                 Debug( LDAP_DEBUG_ANY,
204                         "referral: URL (%s): contains explicit filter\n",
205                         url, 0, 0 );
206 #endif
207                 rc = 1;
208         }
209
210         ldap_free_urldesc( lurl );
211         return rc;
212 }
213
214 struct berval ** referral_rewrite(
215         struct berval **in,
216         const char *base,
217         const char *target,
218         int scope )
219 {
220         int i, j;
221         struct berval **refs;
222
223         if( in == NULL ) return NULL;
224
225         for( i=0; in[i] != NULL ; i++ ) {
226                 /* just count them */
227         }
228
229         if( i < 1 ) return NULL;
230
231         refs = ch_malloc( (i+1) * sizeof( struct berval * ) );
232
233         for( i=0,j=0; in[i] != NULL ; i++ ) {
234                 LDAPURLDesc *url;
235                 int rc = ldap_url_parse_ext( in[i]->bv_val, &url );
236
237                 if( rc == LDAP_URL_ERR_BADSCHEME ) {
238                         refs[j++] = ber_bvdup( in[i] );
239                         continue;
240
241                 } else if( rc != LDAP_URL_SUCCESS ) {
242                         continue;
243                 }
244
245                 {
246                         char *dn = url->lud_dn;
247                         url->lud_dn = referral_dn_muck(
248                                 ( dn && *dn ) ? dn : NULL, base, target ); 
249
250                         ldap_memfree( dn );
251                 }
252
253                 if( url->lud_scope == LDAP_SCOPE_DEFAULT ) {
254                         url->lud_scope = scope;
255                 }
256
257                 refs[j] = ch_malloc( sizeof( struct berval ) );
258
259                 refs[j]->bv_val = ldap_url_desc2str( url );
260                 refs[j]->bv_len = strlen( refs[j]->bv_val );
261
262                 ldap_free_urldesc( url );
263                 j++;
264         }
265
266         if( j == 0 ) {
267                 ch_free( refs );
268                 refs = NULL;
269
270         } else {
271                 refs[j] = NULL;
272         }
273
274         return refs;
275 }
276
277
278 struct berval **get_entry_referrals(
279         Backend *be,
280         Connection *conn,
281         Operation *op,
282         Entry *e,
283         const char *dn,
284         int scope )
285 {
286         Attribute *attr;
287         struct berval **refs;
288         unsigned i, j;
289
290         AttributeDescription *ad_ref = slap_schema.si_ad_ref;
291
292         attr = attr_find( e->e_attrs, ad_ref );
293
294         if( attr == NULL ) return NULL;
295
296         for( i=0; attr->a_vals[i] != NULL; i++ ) {
297                 /* count references */
298         }
299
300         if( i < 1 ) return NULL;
301
302         refs = ch_malloc( (i + 1) * sizeof(struct berval *));
303
304         for( i=0, j=0; attr->a_vals[i] != NULL; i++ ) {
305                 unsigned k;
306                 struct berval *ref = ber_bvdup( attr->a_vals[i] );
307
308                 /* trim the label */
309                 for( k=0; k<ref->bv_len; k++ ) {
310                         if( isspace(ref->bv_val[k]) ) {
311                                 ref->bv_val[k] = '\0';
312                                 ref->bv_len = k;
313                                 break;
314                         }
315                 }
316
317                 if(     ref->bv_len > 0 ) {
318                         refs[j++] = ref;
319
320                 } else {
321                         ber_bvfree( ref );
322                 }
323         }
324
325         if( j == 0 ) {
326                 ber_bvecfree( refs );
327                 refs = NULL;
328
329         } else {
330                 refs[j] = NULL;
331         }
332
333         /* we should check that a referral value exists... */
334         return refs;
335 }
336