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