]> git.sur5r.net Git - openldap/blob - servers/slapd/saslauthz.c
Fix IRIX sc_mask conflict
[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         char *scope[] = { "base", "one", "sub" };
290         SaslRegexp_t *reg;
291         int i;
292
293         memset( out, 0, sizeof( *out ) );
294
295 #ifdef NEW_LOGGING
296         LDAP_LOG( TRANSPORT, ENTRY, 
297                 "slap_sasl_regexp: converting SASL name %s\n", saslname, 0, 0 );
298 #else
299         Debug( LDAP_DEBUG_TRACE, "slap_sasl_regexp: converting SASL name %s\n",
300            saslname, 0, 0 );
301 #endif
302
303         if (( saslname == NULL ) || ( nSaslRegexp == 0 ))
304                 return( 0 );
305
306         /* Match the normalized SASL name to the saslregexp patterns */
307         for( reg = SaslRegexp,i=0;  i<nSaslRegexp;  i++,reg++ ) {
308                 if ( regexec( &reg->sr_workspace, saslname, SASLREGEX_REPLACE,
309                   reg->sr_strings, 0)  == 0 )
310                         break;
311         }
312
313         if( i >= nSaslRegexp )
314                 return( 0 );
315
316         /*
317          * The match pattern may have been of the form "a(b.*)c(d.*)e" and the
318          * replace pattern of the form "x$1y$2z". The returned string needs
319          * to replace the $1,$2 with the strings that matched (b.*) and (d.*)
320          */
321         slap_sasl_rx_exp( reg->sr_replace, reg->sr_offset,
322                 reg->sr_strings, saslname, out );
323
324 #ifdef NEW_LOGGING
325         LDAP_LOG( TRANSPORT, ENTRY, 
326                 "slap_sasl_regexp: converted SASL name to %s\n",
327                 out->bv_len ? out->bv_val : "", 0, 0 );
328 #else
329         Debug( LDAP_DEBUG_TRACE,
330            "slap_sasl_regexp: converted SASL name to ldap:///%s??%s?%s\n",
331                 out->bv_len ? out->bv_val : "", 0, 0 );
332 #endif
333
334         return( 1 );
335 }
336
337 /* Two empty callback functions to avoid sending results */
338 static void sasl_sc_r( Connection *conn, Operation *o, ber_tag_t tag,
339         ber_int_t msgid, ber_int_t err, const char *matched,
340         const char *text, BerVarray ref, const char *resoid,
341         struct berval *resdata, struct berval *sasldata, LDAPControl **c)
342 {
343 }
344
345 static void sasl_sc_s( Connection *conn, Operation *o, ber_int_t err,
346         const char *matched, const char *text, BerVarray refs, LDAPControl **c,
347         int nentries)
348 {
349 }
350
351 /* This callback actually does some work...*/
352 static int sasl_sc_sasl2dn( BackendDB *be, Connection *conn, Operation *o,
353         Entry *e, AttributeName *an, int ao, LDAPControl **c)
354 {
355         struct berval *ndn = o->o_callback->sc_private;
356
357         /* We only want to be called once */
358         if( ndn->bv_val ) {
359                 free(ndn->bv_val);
360                 ndn->bv_val = NULL;
361
362 #ifdef NEW_LOGGING
363         LDAP_LOG( TRANSPORT, DETAIL1,
364                     "slap_sasl2dn: search DN returned more than 1 entry\n", 0, 0, 0 );
365 #else
366                 Debug( LDAP_DEBUG_TRACE,
367                         "slap_sasl2dn: search DN returned more than 1 entry\n", 0,0,0 );
368 #endif
369                 return -1;
370         }
371
372         ber_dupbv(ndn, &e->e_nname);
373         return 0;
374 }
375
376 /*
377  * Given a SASL name (e.g. "UID=name,cn=REALM,cn=MECH,cn=AUTH")
378  * return the LDAP DN to which it matches. The SASL regexp rules in the config
379  * file turn the SASL name into an LDAP URI. If the URI is just a DN (or a
380  * search with scope=base), just return the URI (or its searchbase). Otherwise
381  * an internal search must be done, and if that search returns exactly one
382  * entry, return the DN of that one entry.
383  */
384
385 void slap_sasl2dn( Connection *conn,
386         struct berval *saslname, struct berval *sasldn )
387 {
388         int rc;
389         Backend *be;
390         struct berval dn = { 0, NULL };
391         int scope = LDAP_SCOPE_BASE;
392         Filter *filter = NULL;
393         slap_callback cb = {sasl_sc_r, sasl_sc_s, sasl_sc_sasl2dn, NULL};
394         Operation op = {0};
395         struct berval regout = { 0, NULL };
396
397 #ifdef NEW_LOGGING
398         LDAP_LOG( TRANSPORT, ENTRY, 
399                 "slap_sasl2dn: converting SASL name %s to DN.\n",
400                 saslname->bv_val, 0, 0 );
401 #else
402         Debug( LDAP_DEBUG_TRACE, "==>slap_sasl2dn: "
403                 "converting SASL name %s to a DN\n",
404                 saslname->bv_val, 0,0 );
405 #endif
406
407         sasldn->bv_val = NULL;
408         sasldn->bv_len = 0;
409         cb.sc_private = sasldn;
410
411         /* Convert the SASL name into a minimal URI */
412         if( !slap_sasl_regexp( saslname, &regout ) ) {
413                 goto FINISHED;
414         }
415
416         rc = slap_parseURI( &regout, &dn, &scope, &filter );
417         if( rc != LDAP_SUCCESS ) {
418                 goto FINISHED;
419         }
420
421         /* Must do an internal search */
422         be = select_backend( &dn, 0, 1 );
423
424         /* Massive shortcut: search scope == base */
425         if( scope == LDAP_SCOPE_BASE ) {
426                 *sasldn = dn;
427                 dn.bv_len = 0;
428                 dn.bv_val = NULL;
429                 goto FINISHED;
430         }
431
432 #ifdef NEW_LOGGING
433         LDAP_LOG( TRANSPORT, DETAIL1, 
434                 "slap_sasl2dn: performing internal search (base=%s, scope=%d)\n",
435                 dn.bv_val, scope, 0 );
436 #else
437         Debug( LDAP_DEBUG_TRACE,
438                 "slap_sasl2dn: performing internal search (base=%s, scope=%d)\n",
439                 dn.bv_val, scope, 0 );
440 #endif
441
442         if(( be == NULL ) || ( be->be_search == NULL)) {
443                 goto FINISHED;
444         }
445         suffix_alias( be, &dn );
446
447         op.o_tag = LDAP_REQ_SEARCH;
448         op.o_protocol = LDAP_VERSION3;
449         op.o_ndn = *saslname;
450         op.o_callback = &cb;
451         op.o_time = slap_get_time();
452         op.o_do_not_cache = 1;
453
454         (*be->be_search)( be, conn, &op, NULL, &dn,
455                 scope, LDAP_DEREF_NEVER, 1, 0,
456                 filter, NULL, NULL, 1 );
457         
458 FINISHED:
459         if( sasldn->bv_len ) {
460                 conn->c_authz_backend = be;
461         }
462         if( dn.bv_len ) ch_free( dn.bv_val );
463         if( filter ) filter_free( filter );
464
465 #ifdef NEW_LOGGING
466         LDAP_LOG( TRANSPORT, ENTRY, 
467                 "slap_sasl2dn: Converted SASL name to %s\n",
468                 sasldn->bv_len ? sasldn->bv_val : "<nothing>", 0, 0 );
469 #else
470         Debug( LDAP_DEBUG_TRACE, "<==slap_sasl2dn: Converted SASL name to %s\n",
471                 sasldn->bv_len ? sasldn->bv_val : "<nothing>", 0, 0 );
472 #endif
473
474         return;
475 }
476
477 typedef struct smatch_info {
478         struct berval *dn;
479         int match;
480 } smatch_info;
481
482 static int sasl_sc_smatch( BackendDB *be, Connection *conn, Operation *o,
483         Entry *e, AttributeName *an, int ao, LDAPControl **c)
484 {
485         smatch_info *sm = o->o_callback->sc_private;
486
487         if (dn_match(sm->dn, &e->e_nname)) {
488                 sm->match = 1;
489                 return -1;      /* short-circuit the search */
490         } else {
491                 return 1;
492         }
493 }
494
495 /*
496  * Map a SASL regexp rule to a DN. If the rule is just a DN or a scope=base
497  * URI, just strcmp the rule (or its searchbase) to the *assertDN. Otherwise,
498  * the rule must be used as an internal search for entries. If that search
499  * returns the *assertDN entry, the match is successful.
500  *
501  * The assertDN should not have the dn: prefix
502  */
503
504 static
505 int slap_sasl_match(Connection *conn, struct berval *rule, struct berval *assertDN, struct berval *authc )
506 {
507         struct berval searchbase = {0, NULL};
508         int rc, scope;
509         Backend *be;
510         Filter *filter=NULL;
511         regex_t reg;
512         smatch_info sm;
513         slap_callback cb = { sasl_sc_r, sasl_sc_s, sasl_sc_smatch, NULL };
514         Operation op = {0};
515
516 #ifdef NEW_LOGGING
517         LDAP_LOG( TRANSPORT, ENTRY, 
518                 "slap_sasl_match: comparing DN %s to rule %s\n", 
519                 assertDN->bv_val, rule->bv_val,0 );
520 #else
521         Debug( LDAP_DEBUG_TRACE,
522            "===>slap_sasl_match: comparing DN %s to rule %s\n", assertDN->bv_val, rule->bv_val, 0 );
523 #endif
524
525         rc = slap_parseURI( rule, &searchbase, &scope, &filter );
526         if( rc != LDAP_SUCCESS )
527                 goto CONCLUDED;
528
529         /* Massive shortcut: search scope == base */
530         if( scope == LDAP_SCOPE_BASE ) {
531                 rc = regcomp(&reg, searchbase.bv_val,
532                         REG_EXTENDED|REG_ICASE|REG_NOSUB);
533                 if ( rc == 0 ) {
534                         rc = regexec(&reg, assertDN->bv_val, 0, NULL, 0);
535                         regfree( &reg );
536                 }
537                 if ( rc == 0 )
538                         rc = LDAP_SUCCESS;
539                 else
540                         rc = LDAP_INAPPROPRIATE_AUTH;
541                 goto CONCLUDED;
542         }
543
544         /* Must run an internal search. */
545
546 #ifdef NEW_LOGGING
547         LDAP_LOG( TRANSPORT, DETAIL1, 
548                 "slap_sasl_match: performing internal search (base=%s, scope=%d)\n",
549                 searchbase.bv_val, scope,0 );
550 #else
551         Debug( LDAP_DEBUG_TRACE,
552            "slap_sasl_match: performing internal search (base=%s, scope=%d)\n",
553            searchbase.bv_val, scope, 0 );
554 #endif
555
556         be = select_backend( &searchbase, 0, 1 );
557         if(( be == NULL ) || ( be->be_search == NULL)) {
558                 rc = LDAP_INAPPROPRIATE_AUTH;
559                 goto CONCLUDED;
560         }
561         suffix_alias( be, &searchbase );
562
563         sm.dn = assertDN;
564         sm.match = 0;
565         cb.sc_private = &sm;
566
567         op.o_tag = LDAP_REQ_SEARCH;
568         op.o_protocol = LDAP_VERSION3;
569         op.o_ndn = *authc;
570         op.o_callback = &cb;
571         op.o_time = slap_get_time();
572         op.o_do_not_cache = 1;
573
574         (*be->be_search)( be, conn, &op, /*base=*/NULL, &searchbase,
575            scope, /*deref=*/1, /*sizelimit=*/0, /*time=*/0, filter, /*fstr=*/NULL,
576            /*attrs=*/NULL, /*attrsonly=*/0 );
577
578         if (sm.match)
579                 rc = LDAP_SUCCESS;
580         else
581                 rc = LDAP_INAPPROPRIATE_AUTH;
582
583 CONCLUDED:
584         if( searchbase.bv_len ) ch_free( searchbase.bv_val );
585         if( filter ) filter_free( filter );
586 #ifdef NEW_LOGGING
587         LDAP_LOG( TRANSPORT, ENTRY, 
588                 "slap_sasl_match: comparison returned %d\n", rc, 0, 0 );
589 #else
590         Debug( LDAP_DEBUG_TRACE,
591            "<===slap_sasl_match: comparison returned %d\n", rc, 0, 0);
592 #endif
593
594         return( rc );
595 }
596
597
598 /*
599  * This function answers the question, "Can this ID authorize to that ID?",
600  * based on authorization rules. The rules are stored in the *searchDN, in the
601  * attribute named by *attr. If any of those rules map to the *assertDN, the
602  * authorization is approved.
603  *
604  * The DNs should not have the dn: prefix
605  */
606 static int
607 slap_sasl_check_authz( Connection *conn,
608         struct berval *searchDN,
609         struct berval *assertDN,
610         AttributeDescription *ad,
611         struct berval *authc )
612 {
613         int i, rc;
614         BerVarray vals=NULL;
615
616 #ifdef NEW_LOGGING
617         LDAP_LOG( TRANSPORT, ENTRY, 
618                    "slap_sasl_check_authz: does %s match %s rule in %s?\n",
619                assertDN->bv_val, ad->ad_cname.bv_val, searchDN->bv_val);
620 #else
621         Debug( LDAP_DEBUG_TRACE,
622            "==>slap_sasl_check_authz: does %s match %s rule in %s?\n",
623            assertDN->bv_val, ad->ad_cname.bv_val, searchDN->bv_val);
624 #endif
625
626         rc = backend_attribute( NULL, NULL, NULL, NULL, searchDN, ad, &vals );
627         if( rc != LDAP_SUCCESS )
628                 goto COMPLETE;
629
630         /* Check if the *assertDN matches any **vals */
631         for( i=0; vals[i].bv_val != NULL; i++ ) {
632                 rc = slap_sasl_match( conn, &vals[i], assertDN, authc );
633                 if ( rc == LDAP_SUCCESS )
634                         goto COMPLETE;
635         }
636         rc = LDAP_INAPPROPRIATE_AUTH;
637
638 COMPLETE:
639         if( vals ) ber_bvarray_free( vals );
640
641 #ifdef NEW_LOGGING
642         LDAP_LOG( TRANSPORT, RESULTS, 
643                    "slap_sasl_check_authz: %s check returning %s\n", 
644                    ad->ad_cname.bv_val, rc, 0 );
645 #else
646         Debug( LDAP_DEBUG_TRACE,
647            "<==slap_sasl_check_authz: %s check returning %d\n", ad->ad_cname.bv_val, rc, 0);
648 #endif
649
650         return( rc );
651 }
652 #endif  /* HAVE_CYRUS_SASL */
653
654
655 /* Check if a bind can SASL authorize to another identity.
656  * The DNs should not have the dn: prefix
657  */
658
659 int slap_sasl_authorized( Connection *conn,
660         struct berval *authcDN, struct berval *authzDN )
661 {
662         int rc = LDAP_INAPPROPRIATE_AUTH;
663
664 #ifdef HAVE_CYRUS_SASL
665         /* User binding as anonymous */
666         if ( authzDN == NULL ) {
667                 rc = LDAP_SUCCESS;
668                 goto DONE;
669         }
670
671 #ifdef NEW_LOGGING
672         LDAP_LOG( TRANSPORT, ENTRY, 
673                 "slap_sasl_authorized: can %s become %s?\n", 
674                 authcDN->bv_val, authzDN->bv_val, 0 );
675 #else
676         Debug( LDAP_DEBUG_TRACE,
677            "==>slap_sasl_authorized: can %s become %s?\n", authcDN->bv_val, authzDN->bv_val, 0 );
678 #endif
679
680         /* If person is authorizing to self, succeed */
681         if ( dn_match( authcDN, authzDN ) ) {
682                 rc = LDAP_SUCCESS;
683                 goto DONE;
684         }
685
686         /* Check source rules */
687         if( authz_policy & SASL_AUTHZ_TO ) {
688                 rc = slap_sasl_check_authz( conn, authcDN, authzDN,
689                         slap_schema.si_ad_saslAuthzTo, authcDN );
690                 if( rc == LDAP_SUCCESS ) {
691                         goto DONE;
692                 }
693         }
694
695         /* Check destination rules */
696         if( authz_policy & SASL_AUTHZ_FROM ) {
697                 rc = slap_sasl_check_authz( conn, authzDN, authcDN,
698                         slap_schema.si_ad_saslAuthzFrom, authcDN );
699                 if( rc == LDAP_SUCCESS ) {
700                         goto DONE;
701                 }
702         }
703
704         rc = LDAP_INAPPROPRIATE_AUTH;
705
706 DONE:
707 #endif
708
709 #ifdef NEW_LOGGING
710         LDAP_LOG( TRANSPORT, RESULTS, "slap_sasl_authorized: return %d\n", rc,0,0 );
711 #else
712         Debug( LDAP_DEBUG_TRACE,
713                 "<== slap_sasl_authorized: return %d\n", rc, 0, 0 );
714 #endif
715
716         return( rc );
717 }