]> git.sur5r.net Git - openldap/blob - servers/slapd/saslauthz.c
DB_RMW flag to dn2id and id2entry
[openldap] / servers / slapd / saslauthz.c
1 /*
2  * Copyright (c) 2000, Mark Adamson, Carnegie Mellon.  All rights reserved.
3  * This software is not subject to any license of Carnegie Mellon University.
4  *
5  * Redistribution and use in source and binary forms are permitted without 
6  * restriction or fee of any kind as long as this notice is preserved.
7  *
8  * The name "Carnegie Mellon" must not be used to endorse or promote
9  * products derived from this software without prior written permission.
10  *
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16
17 #include <ac/stdlib.h>
18 #include <ac/string.h>
19
20 #include "slap.h"
21
22 #ifdef HAVE_CYRUS_SASL
23 #include <limits.h>
24
25 #ifdef HAVE_SASL_SASL_H
26 #include <sasl/sasl.h>
27 #else
28 #include <sasl.h>
29 #endif
30
31 #include <ldap_pvt.h>
32
33 /* URI format: ldap://<host>/<base>[?[<attrs>][?[<scope>][?[<filter>]]]] */
34
35 static int slap_parseURI( struct berval *uri,
36         struct berval *searchbase, int *scope, Filter **filter,
37         struct berval *fstr )
38 {
39         struct berval bv;
40         int rc;
41         LDAPURLDesc *ludp;
42
43         assert( uri != NULL && uri->bv_val != NULL );
44         searchbase->bv_val = NULL;
45         searchbase->bv_len = 0;
46         *scope = -1;
47         *filter = NULL;
48
49         if ( fstr ) {
50                 fstr->bv_val = NULL;
51                 fstr->bv_len = 0;
52         }
53
54 #ifdef NEW_LOGGING
55         LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
56                 "slap_parseURI: parsing %s\n", uri->bv_val ));
57 #else
58         Debug( LDAP_DEBUG_TRACE, "slap_parseURI: parsing %s\n", uri->bv_val, 0, 0 );
59 #endif
60
61         /* If it does not look like a URI, assume it is a DN */
62         if( !strncasecmp( uri->bv_val, "dn:", sizeof("dn:")-1 ) ) {
63                 bv.bv_val = uri->bv_val + sizeof("dn:")-1;
64                 bv.bv_val += strspn( bv.bv_val, " " );
65
66 is_dn:          bv.bv_len = uri->bv_len - (bv.bv_val - uri->bv_val);
67                 rc = dnNormalize2( NULL, &bv, searchbase );
68                 if (rc == LDAP_SUCCESS) {
69                         *scope = LDAP_SCOPE_BASE;
70                 }
71                 return( rc );
72         }
73
74         rc = ldap_url_parse( uri->bv_val, &ludp );
75         if ( rc == LDAP_URL_ERR_BADSCHEME ) {
76                 bv.bv_val = uri->bv_val;
77                 goto is_dn;
78         }
79
80         if ( rc != LDAP_URL_SUCCESS ) {
81                 return( LDAP_PROTOCOL_ERROR );
82         }
83
84         /* could check the hostname here */
85
86         /* Grab the scope */
87         *scope = ludp->lud_scope;
88
89         /* Grab the filter */
90         if ( ludp->lud_filter ) {
91                 *filter = str2filter( ludp->lud_filter );
92                 if ( *filter == NULL )
93                         rc = LDAP_PROTOCOL_ERROR;
94                 else if ( fstr )
95                         ber_str2bv( ludp->lud_filter, 0, 1, fstr );
96         }
97
98         /* Grab the searchbase */
99         if ( rc == LDAP_URL_SUCCESS ) {
100                 bv.bv_val = ludp->lud_dn;
101                 bv.bv_len = strlen( bv.bv_val );
102                 rc = dnNormalize2( NULL, &bv, searchbase );
103         }
104
105         ldap_free_urldesc( ludp );
106
107         return( rc );
108 }
109
110 static int slap_sasl_rx_off(char *rep, int *off)
111 {
112         const char *c;
113         int n;
114
115         /* Precompile replace pattern. Find the $<n> placeholders */
116         off[0] = -2;
117         n = 1;
118         for ( c = rep;   *c;  c++ ) {
119                 if ( *c == '\\' && c[1] ) {
120                         c++;
121                         continue;
122                 }
123                 if ( *c == '$' ) {
124                         if ( n == SASLREGEX_REPLACE ) {
125 #ifdef NEW_LOGGING
126                                 LDAP_LOG(( "sasl", LDAP_LEVEL_ERR,
127                                         "slap_sasl_regexp_config: \"%s\" has too many $n "
128                                                 "placeholders (max %d)\n",
129                                         rep, SASLREGEX_REPLACE ));
130 #else
131                                 Debug( LDAP_DEBUG_ANY,
132                                         "SASL replace pattern %s has too many $n "
133                                                 "placeholders (max %d)\n",
134                                         rep, SASLREGEX_REPLACE, 0 );
135 #endif
136
137                                 return( LDAP_OPERATIONS_ERROR );
138                         }
139                         off[n] = c - rep;
140                         n++;
141                 }
142         }
143
144         /* Final placeholder, after the last $n */
145         off[n] = c - rep;
146         n++;
147         off[n] = -1;
148         return( LDAP_SUCCESS );
149 }
150 #endif /* HAVE_CYRUS_SASL */
151
152 int slap_sasl_regexp_config( const char *match, const char *replace )
153 {
154 #ifdef HAVE_CYRUS_SASL
155         const char *c;
156         int rc, n;
157         SaslRegexp_t *reg;
158         struct berval bv, nbv;
159         Filter *filter;
160
161         SaslRegexp = (SaslRegexp_t *) ch_realloc( (char *) SaslRegexp,
162           (nSaslRegexp + 1) * sizeof(SaslRegexp_t) );
163         reg = &( SaslRegexp[nSaslRegexp] );
164         ber_str2bv( match, 0, 0, &bv );
165         rc = dnNormalize2( NULL, &bv, &nbv );
166         if ( rc ) {
167 #ifdef NEW_LOGGING
168                 LDAP_LOG(( "sasl", LDAP_LEVEL_ERR,
169                            "slap_sasl_regexp_config: \"%s\" could not be normalized.\n",
170                            match ));
171 #else
172                 Debug( LDAP_DEBUG_ANY,
173                 "SASL match pattern %s could not be normalized.\n",
174                 match, 0, 0 );
175 #endif
176                 return( rc );
177         }
178         reg->sr_match = nbv.bv_val;
179
180         ber_str2bv( replace, 0, 0, &bv );
181         rc = slap_parseURI( &bv, &reg->sr_replace.dn, &reg->sr_replace.scope,
182                 &filter, &reg->sr_replace.filter );
183         if ( filter ) filter_free( filter );
184         if ( rc ) {
185 #ifdef NEW_LOGGING
186                 LDAP_LOG(( "sasl", LDAP_LEVEL_ERR,
187                            "slap_sasl_regexp_config: \"%s\" could not be parsed.\n",
188                            replace ));
189 #else
190                 Debug( LDAP_DEBUG_ANY,
191                 "SASL replace pattern %s could not be parsed.\n",
192                 replace, 0, 0 );
193 #endif
194                 return( rc );
195         }
196
197         /* Precompile matching pattern */
198         rc = regcomp( &reg->sr_workspace, reg->sr_match, REG_EXTENDED|REG_ICASE );
199         if ( rc ) {
200 #ifdef NEW_LOGGING
201                 LDAP_LOG(( "sasl", LDAP_LEVEL_ERR,
202                            "slap_sasl_regexp_config: \"%s\" could not be compiled.\n",
203                            reg->sr_match ));
204 #else
205                 Debug( LDAP_DEBUG_ANY,
206                 "SASL match pattern %s could not be compiled by regexp engine\n",
207                 reg->sr_match, 0, 0 );
208 #endif
209
210                 return( LDAP_OPERATIONS_ERROR );
211         }
212
213         rc = slap_sasl_rx_off( reg->sr_replace.dn.bv_val, reg->sr_dn_offset );
214         if ( rc != LDAP_SUCCESS ) return rc;
215
216         if (reg->sr_replace.filter.bv_val ) {
217                 rc = slap_sasl_rx_off( reg->sr_replace.filter.bv_val, reg->sr_fi_offset );
218                 if ( rc != LDAP_SUCCESS ) return rc;
219         }
220
221         nSaslRegexp++;
222 #endif
223         return( LDAP_SUCCESS );
224 }
225
226
227 #ifdef HAVE_CYRUS_SASL
228
229 /* Perform replacement on regexp matches */
230 static void slap_sasl_rx_exp( char *rep, int *off, regmatch_t *str,
231         char *saslname, struct berval *out )
232 {
233         int i, n, len, insert;
234
235         /* Get the total length of the final URI */
236
237         n=1;
238         len = 0;
239         while( off[n] >= 0 ) {
240                 /* Len of next section from replacement string (x,y,z above) */
241                 len += off[n] - off[n-1] - 2;
242                 if( off[n+1] < 0)
243                         break;
244
245                 /* Len of string from saslname that matched next $i  (b,d above) */
246                 i = rep[ off[n] + 1 ]   - '0';
247                 len += str[i].rm_eo - str[i].rm_so;
248                 n++;
249         }
250         out->bv_val = ch_malloc( len + 1 );
251         out->bv_len = len;
252
253         /* Fill in URI with replace string, replacing $i as we go */
254         n=1;
255         insert = 0;
256         while( off[n] >= 0) {
257                 /* Paste in next section from replacement string (x,y,z above) */
258                 len = off[n] - off[n-1] - 2;
259                 strncpy( out->bv_val+insert, rep + off[n-1] + 2, len);
260                 insert += len;
261                 if( off[n+1] < 0)
262                         break;
263
264                 /* Paste in string from saslname that matched next $i  (b,d above) */
265                 i = rep[ off[n] + 1 ]   - '0';
266                 len = str[i].rm_eo - str[i].rm_so;
267                 strncpy( out->bv_val+insert, saslname + str[i].rm_so, len );
268                 insert += len;
269
270                 n++;
271         }
272
273         out->bv_val[insert] = '\0';
274 }
275
276 /* Take the passed in SASL name and attempt to convert it into an
277    LDAP URI to find the matching LDAP entry, using the pattern matching
278    strings given in the saslregexp config file directive(s) */
279
280 static int slap_sasl_regexp( struct berval *in, SaslUri_t *out )
281 {
282         char *saslname = in->bv_val;
283         char *scope[] = { "base", "one", "sub" };
284         SaslRegexp_t *reg;
285         int i;
286
287         memset( out, 0, sizeof( *out ) );
288
289 #ifdef NEW_LOGGING
290         LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
291                 "slap_sasl_regexp: converting SASL name %s\n", saslname ));
292 #else
293         Debug( LDAP_DEBUG_TRACE, "slap_sasl_regexp: converting SASL name %s\n",
294            saslname, 0, 0 );
295 #endif
296
297         if (( saslname == NULL ) || ( nSaslRegexp == 0 ))
298                 return( 0 );
299
300         /* Match the normalized SASL name to the saslregexp patterns */
301         for( reg = SaslRegexp,i=0;  i<nSaslRegexp;  i++,reg++ ) {
302                 if ( regexec( &reg->sr_workspace, saslname, SASLREGEX_REPLACE,
303                   reg->sr_strings, 0)  == 0 )
304                         break;
305         }
306
307         if( i >= nSaslRegexp )
308                 return( 0 );
309
310         /*
311          * The match pattern may have been of the form "a(b.*)c(d.*)e" and the
312          * replace pattern of the form "x$1y$2z". The returned string needs
313          * to replace the $1,$2 with the strings that matched (b.*) and (d.*)
314          */
315         slap_sasl_rx_exp( reg->sr_replace.dn.bv_val, reg->sr_dn_offset,
316                 reg->sr_strings, saslname, &out->dn );
317
318         if ( reg->sr_replace.filter.bv_val )
319                 slap_sasl_rx_exp( reg->sr_replace.filter.bv_val,
320                         reg->sr_fi_offset, reg->sr_strings, saslname, &out->filter );
321         
322         out->scope = reg->sr_replace.scope;
323
324 #ifdef NEW_LOGGING
325         LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
326                 "slap_sasl_regexp: converted SASL name to ldap:///%s??%s?%s\n",
327                 out->dn.bv_val, scope[out->scope], out->filter.bv_val ?
328                 out->filter.bv_val : "" ));
329 #else
330         Debug( LDAP_DEBUG_TRACE,
331            "slap_sasl_regexp: converted SASL name to ldap:///%s??%s?%s\n",
332                 out->dn.bv_val, scope[out->scope], out->filter.bv_val ?
333                 out->filter.bv_val : "" );
334 #endif
335
336         return( 1 );
337 }
338
339 /* Two empty callback functions to avoid sending results */
340 static void sasl_sc_r( Connection *conn, Operation *o, ber_tag_t tag,
341         ber_int_t msgid, ber_int_t err, const char *matched,
342         const char *text, BerVarray ref, const char *resoid,
343         struct berval *resdata, struct berval *sasldata, LDAPControl **c)
344 {
345 }
346
347 static void sasl_sc_s( Connection *conn, Operation *o, ber_int_t err,
348         const char *matched, const char *text, BerVarray refs, LDAPControl **c,
349         int nentries)
350 {
351 }
352
353 /* This callback actually does some work...*/
354 static int sasl_sc_sasl2dn( BackendDB *be, Connection *conn, Operation *o,
355         Entry *e, AttributeName *an, int ao, LDAPControl **c)
356 {
357         struct berval *ndn = o->o_callback->sc_private;
358
359         /* We only want to be called once */
360         if (ndn->bv_val) {
361                 free(ndn->bv_val);
362                 ndn->bv_val = NULL;
363 #ifdef NEW_LOGGING
364         LDAP_LOG(( "sasl", LDAP_LEVEL_DETAIL1,
365                    "slap_sasl2dn: search DN returned more than 1 entry\n" ));
366 #else
367         Debug( LDAP_DEBUG_TRACE,
368            "slap_sasl2dn: search DN returned more than 1 entry\n", 0,0,0 );
369 #endif
370                 return -1;
371         } else {
372                 ber_dupbv(ndn, &e->e_nname);
373                 return 0;
374         }
375 }
376
377 /*
378  * Given a SASL name (e.g. "UID=name,cn=REALM,cn=MECH,cn=AUTH")
379  * return the LDAP DN to which it matches. The SASL regexp rules in the config
380  * file turn the SASL name into an LDAP URI. If the URI is just a DN (or a
381  * search with scope=base), just return the URI (or its searchbase). Otherwise
382  * an internal search must be done, and if that search returns exactly one
383  * entry, return the DN of that one entry.
384  */
385
386 void slap_sasl2dn( Connection *conn, struct berval *saslname, struct berval *dn )
387 {
388         int rc;
389         Backend *be;
390         Filter *filter=NULL;
391         slap_callback cb = {sasl_sc_r, sasl_sc_s, sasl_sc_sasl2dn, NULL};
392         Operation op = {0};
393         SaslUri_t uri;
394
395 #ifdef NEW_LOGGING
396         LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
397                 "slap_sasl2dn: converting SASL name %s to DN.\n", saslname->bv_val ));
398 #else
399         Debug( LDAP_DEBUG_TRACE,
400                 "==>slap_sasl2dn: Converting SASL name %s to a DN\n", saslname->bv_val, 0,0 );
401 #endif
402         dn->bv_val = NULL;
403         dn->bv_len = 0;
404         cb.sc_private = dn;
405
406         /* Convert the SASL name into a minimal URI */
407         if( !slap_sasl_regexp( saslname, &uri ) )
408                 goto FINISHED;
409
410         if ( uri.filter.bv_val )
411                 filter = str2filter( uri.filter.bv_val );
412
413         /* Must do an internal search */
414
415         be = select_backend( &uri.dn, 0, 1 );
416
417         conn->c_authz_backend = be;
418
419         /* Massive shortcut: search scope == base */
420         if( uri.scope == LDAP_SCOPE_BASE ) {
421                 *dn = uri.dn;
422                 uri.dn.bv_len = 0;
423                 uri.dn.bv_val = NULL;
424                 goto FINISHED;
425         }
426
427 #ifdef NEW_LOGGING
428         LDAP_LOG(( "sasl", LDAP_LEVEL_DETAIL1,
429                    "slap_sasl2dn: performing internal search (base=%s, scope=%d)\n",
430                    uri.dn.bv_val, uri.scope ));
431 #else
432         Debug( LDAP_DEBUG_TRACE,
433            "slap_sasl2dn: performing internal search (base=%s, scope=%d)\n",
434            uri.dn.bv_val, uri.scope, 0 );
435 #endif
436
437         if(( be == NULL ) || ( be->be_search == NULL))
438                 goto FINISHED;
439         suffix_alias( be, &uri.dn );
440
441         op.o_tag = LDAP_REQ_SEARCH;
442         op.o_protocol = LDAP_VERSION3;
443         op.o_ndn = *saslname;
444         op.o_callback = &cb;
445         op.o_time = slap_get_time();
446
447         (*be->be_search)( be, /*conn*/NULL, &op, /*base*/NULL, &uri.dn,
448            uri.scope, /*deref=*/1, /*sizelimit=*/1, /*time=*/0, filter, /*fstr=*/NULL,
449            /*attrs=*/NULL, /*attrsonly=*/0 );
450         
451 FINISHED:
452         if( uri.dn.bv_len ) ch_free( uri.dn.bv_val );
453         if( uri.filter.bv_len ) ch_free( uri.filter.bv_val );
454         if( filter ) filter_free( filter );
455
456 #ifdef NEW_LOGGING
457         LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
458                 "slap_sasl2dn: Converted SASL name to %s\n",
459                 dn->bv_len ? dn->bv_val : "<nothing>" ));
460 #else
461         Debug( LDAP_DEBUG_TRACE, "<==slap_sasl2dn: Converted SASL name to %s\n",
462                 dn->bv_len ? dn->bv_val : "<nothing>", 0, 0 );
463 #endif
464
465         return;
466 }
467
468 typedef struct smatch_info {
469         struct berval *dn;
470         int match;
471 } smatch_info;
472
473 static int sasl_sc_smatch( BackendDB *be, Connection *conn, Operation *o,
474         Entry *e, AttributeName *an, int ao, LDAPControl **c)
475 {
476         smatch_info *sm = o->o_callback->sc_private;
477
478         if (dn_match(sm->dn, &e->e_nname)) {
479                 sm->match = 1;
480                 return -1;      /* short-circuit the search */
481         } else {
482                 return 1;
483         }
484 }
485
486 /*
487  * Map a SASL regexp rule to a DN. If the rule is just a DN or a scope=base
488  * URI, just strcmp the rule (or its searchbase) to the *assertDN. Otherwise,
489  * the rule must be used as an internal search for entries. If that search
490  * returns the *assertDN entry, the match is successful.
491  *
492  * The assertDN should not have the dn: prefix
493  */
494
495 static
496 int slap_sasl_match( struct berval *rule, struct berval *assertDN, struct berval *authc )
497 {
498         struct berval searchbase = {0, NULL};
499         int rc, scope;
500         Backend *be;
501         Filter *filter=NULL;
502         regex_t reg;
503         smatch_info sm;
504         slap_callback cb = { sasl_sc_r, sasl_sc_s, sasl_sc_smatch, NULL };
505         Operation op = {0};
506
507 #ifdef NEW_LOGGING
508         LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
509                 "slap_sasl_match: comparing DN %s to rule %s\n", assertDN->bv_val, rule->bv_val ));
510 #else
511         Debug( LDAP_DEBUG_TRACE,
512            "===>slap_sasl_match: comparing DN %s to rule %s\n", assertDN->bv_val, rule->bv_val, 0 );
513 #endif
514
515         rc = slap_parseURI( rule, &searchbase, &scope, &filter, NULL );
516         if( rc != LDAP_SUCCESS )
517                 goto CONCLUDED;
518
519         /* Massive shortcut: search scope == base */
520         if( scope == LDAP_SCOPE_BASE ) {
521                 rc = regcomp(&reg, searchbase.bv_val,
522                         REG_EXTENDED|REG_ICASE|REG_NOSUB);
523                 if ( rc == 0 ) {
524                         rc = regexec(&reg, assertDN->bv_val, 0, NULL, 0);
525                         regfree( &reg );
526                 }
527                 if ( rc == 0 )
528                         rc = LDAP_SUCCESS;
529                 else
530                         rc = LDAP_INAPPROPRIATE_AUTH;
531                 goto CONCLUDED;
532         }
533
534         /* Must run an internal search. */
535
536 #ifdef NEW_LOGGING
537         LDAP_LOG(( "sasl", LDAP_LEVEL_DETAIL1,
538                 "slap_sasl_match: performing internal search (base=%s, scope=%d)\n",
539                 searchbase.bv_val, scope ));
540 #else
541         Debug( LDAP_DEBUG_TRACE,
542            "slap_sasl_match: performing internal search (base=%s, scope=%d)\n",
543            searchbase.bv_val, scope, 0 );
544 #endif
545
546         be = select_backend( &searchbase, 0, 1 );
547         if(( be == NULL ) || ( be->be_search == NULL)) {
548                 rc = LDAP_INAPPROPRIATE_AUTH;
549                 goto CONCLUDED;
550         }
551         suffix_alias( be, &searchbase );
552
553         sm.dn = assertDN;
554         sm.match = 0;
555         cb.sc_private = &sm;
556
557         op.o_tag = LDAP_REQ_SEARCH;
558         op.o_protocol = LDAP_VERSION3;
559         op.o_ndn = *authc;
560         op.o_callback = &cb;
561         op.o_time = slap_get_time();
562
563         (*be->be_search)( be, /*conn=*/NULL, &op, /*base=*/NULL, &searchbase,
564            scope, /*deref=*/1, /*sizelimit=*/0, /*time=*/0, filter, /*fstr=*/NULL,
565            /*attrs=*/NULL, /*attrsonly=*/0 );
566
567         if (sm.match)
568                 rc = LDAP_SUCCESS;
569         else
570                 rc = LDAP_INAPPROPRIATE_AUTH;
571
572 CONCLUDED:
573         if( searchbase.bv_len ) ch_free( searchbase.bv_val );
574         if( filter ) filter_free( filter );
575 #ifdef NEW_LOGGING
576         LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
577                    "slap_sasl_match: comparison returned %d\n", rc ));
578 #else
579         Debug( LDAP_DEBUG_TRACE,
580            "<===slap_sasl_match: comparison returned %d\n", rc, 0, 0);
581 #endif
582
583         return( rc );
584 }
585
586
587 /*
588  * This function answers the question, "Can this ID authorize to that ID?",
589  * based on authorization rules. The rules are stored in the *searchDN, in the
590  * attribute named by *attr. If any of those rules map to the *assertDN, the
591  * authorization is approved.
592  *
593  * The DNs should not have the dn: prefix
594  */
595 static int
596 slap_sasl_check_authz(struct berval *searchDN, struct berval *assertDN, struct berval *attr, struct berval *authc)
597 {
598         const char *errmsg;
599         int i, rc;
600         BerVarray vals=NULL;
601         AttributeDescription *ad=NULL;
602
603 #ifdef NEW_LOGGING
604         LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
605                    "slap_sasl_check_authz: does %s match %s rule in %s?\n",
606                    assertDN->bv_val, attr->bv_val, searchDN->bv_val ));
607 #else
608         Debug( LDAP_DEBUG_TRACE,
609            "==>slap_sasl_check_authz: does %s match %s rule in %s?\n",
610            assertDN->bv_val, attr->bv_val, searchDN->bv_val);
611 #endif
612
613         rc = slap_bv2ad( attr, &ad, &errmsg );
614         if( rc != LDAP_SUCCESS )
615                 goto COMPLETE;
616
617         rc = backend_attribute( NULL, NULL, NULL, NULL, searchDN, ad, &vals );
618         if( rc != LDAP_SUCCESS )
619                 goto COMPLETE;
620
621         /* Check if the *assertDN matches any **vals */
622         for( i=0; vals[i].bv_val != NULL; i++ ) {
623                 rc = slap_sasl_match( &vals[i], assertDN, authc );
624                 if ( rc == LDAP_SUCCESS )
625                         goto COMPLETE;
626         }
627         rc = LDAP_INAPPROPRIATE_AUTH;
628
629 COMPLETE:
630         if( vals ) ber_bvarray_free( vals );
631
632 #ifdef NEW_LOGGING
633         LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
634                    "slap_sasl_check_authz: %s check returning %s\n", attr->bv_val, rc ));
635 #else
636         Debug( LDAP_DEBUG_TRACE,
637            "<==slap_sasl_check_authz: %s check returning %d\n", attr->bv_val, rc, 0);
638 #endif
639
640         return( rc );
641 }
642 #endif  /* HAVE_CYRUS_SASL */
643
644
645 /* Check if a bind can SASL authorize to another identity.
646  * The DNs should not have the dn: prefix
647  */
648
649 static struct berval sasl_authz_src = {
650         sizeof(SASL_AUTHZ_SOURCE_ATTR)-1, SASL_AUTHZ_SOURCE_ATTR };
651
652 static struct berval sasl_authz_dst = {
653         sizeof(SASL_AUTHZ_DEST_ATTR)-1, SASL_AUTHZ_DEST_ATTR };
654
655 int slap_sasl_authorized( struct berval *authcDN, struct berval *authzDN )
656 {
657         int rc = LDAP_INAPPROPRIATE_AUTH;
658
659 #ifdef HAVE_CYRUS_SASL
660         /* User binding as anonymous */
661         if ( authzDN == NULL ) {
662                 rc = LDAP_SUCCESS;
663                 goto DONE;
664         }
665
666 #ifdef NEW_LOGGING
667         LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
668                 "slap_sasl_authorized: can %s become %s?\n", authcDN->bv_val, authzDN->bv_val ));
669 #else
670         Debug( LDAP_DEBUG_TRACE,
671            "==>slap_sasl_authorized: can %s become %s?\n", authcDN->bv_val, authzDN->bv_val, 0 );
672 #endif
673
674         /* If person is authorizing to self, succeed */
675         if ( dn_match( authcDN, authzDN ) ) {
676                 rc = LDAP_SUCCESS;
677                 goto DONE;
678         }
679
680         /* Check source rules */
681         rc = slap_sasl_check_authz( authcDN, authzDN, &sasl_authz_src,
682            authcDN );
683         if( rc == LDAP_SUCCESS ) {
684                 goto DONE;
685         }
686
687         /* Check destination rules */
688         rc = slap_sasl_check_authz( authzDN, authcDN, &sasl_authz_dst,
689            authcDN );
690         if( rc == LDAP_SUCCESS ) {
691                 goto DONE;
692         }
693
694         rc = LDAP_INAPPROPRIATE_AUTH;
695
696 DONE:
697 #endif
698
699 #ifdef NEW_LOGGING
700         LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
701                 "slap_sasl_authorized: return %d\n", rc ));
702 #else
703         Debug( LDAP_DEBUG_TRACE,
704                 "<== slap_sasl_authorized: return %d\n", rc, 0, 0 );
705 #endif
706
707         return( rc );
708 }