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