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