3 * Copyright 1999-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
12 #include <ac/socket.h>
13 #include <ac/string.h>
20 #include "ldap_pvt_thread.h"
23 #ifdef HAVE_CYRUS_SASL
27 * Various Cyrus SASL related stuff.
30 int ldap_int_sasl_init( void )
32 /* XXX not threadsafe */
33 static int sasl_initialized = 0;
35 static sasl_callback_t client_callbacks[] = {
36 #ifdef SASL_CB_GETREALM
37 { SASL_CB_GETREALM, NULL, NULL },
39 { SASL_CB_USER, NULL, NULL },
40 { SASL_CB_AUTHNAME, NULL, NULL },
41 { SASL_CB_PASS, NULL, NULL },
42 { SASL_CB_ECHOPROMPT, NULL, NULL },
43 { SASL_CB_NOECHOPROMPT, NULL, NULL },
44 { SASL_CB_LIST_END, NULL, NULL }
47 if ( sasl_initialized ) {
57 #endif /* CSRIMALLOC */
61 ldap_pvt_sasl_mutex_new,
62 ldap_pvt_sasl_mutex_lock,
63 ldap_pvt_sasl_mutex_unlock,
64 ldap_pvt_sasl_mutex_dispose );
67 if ( sasl_client_init( client_callbacks ) == SASL_OK ) {
76 * SASL encryption support for LBER Sockbufs
80 sasl_conn_t *sasl_context;
81 Sockbuf_Buf sec_buf_in;
87 sb_sasl_setup( Sockbuf_IO_Desc *sbiod, void *arg )
89 struct sb_sasl_data *p;
91 assert( sbiod != NULL );
93 p = LBER_MALLOC( sizeof( *p ) );
96 p->sasl_context = (sasl_conn_t *)arg;
97 ber_pvt_sb_buf_init( &p->sec_buf_in );
98 ber_pvt_sb_buf_init( &p->buf_in );
99 ber_pvt_sb_buf_init( &p->buf_out );
100 if ( ber_pvt_sb_grow_buffer( &p->sec_buf_in, SASL_MIN_BUFF_SIZE ) < 0 ) {
105 sbiod->sbiod_pvt = p;
111 sb_sasl_remove( Sockbuf_IO_Desc *sbiod )
113 struct sb_sasl_data *p;
115 assert( sbiod != NULL );
117 p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
118 ber_pvt_sb_buf_destroy( &p->sec_buf_in );
119 ber_pvt_sb_buf_destroy( &p->buf_in );
120 ber_pvt_sb_buf_destroy( &p->buf_out );
122 sbiod->sbiod_pvt = NULL;
127 sb_sasl_pkt_length( const unsigned char *buf, int debuglevel )
131 assert( buf != NULL );
138 /* we really should check against actual buffer size set
141 if ( size > SASL_MAX_BUFF_SIZE ) {
142 /* somebody is trying to mess me up. */
143 ber_log_printf( LDAP_DEBUG_ANY, debuglevel,
144 "sb_sasl_pkt_length: received illegal packet length "
145 "of %lu bytes\n", (unsigned long)size );
146 size = 16; /* this should lead to an error. */
149 return size + 4; /* include the size !!! */
152 /* Drop a processed packet from the input buffer */
154 sb_sasl_drop_packet ( Sockbuf_Buf *sec_buf_in, int debuglevel )
158 len = sec_buf_in->buf_ptr - sec_buf_in->buf_end;
160 memmove( sec_buf_in->buf_base, sec_buf_in->buf_base +
161 sec_buf_in->buf_end, len );
164 sec_buf_in->buf_end = sb_sasl_pkt_length( sec_buf_in->buf_base,
168 sec_buf_in->buf_end = 0;
170 sec_buf_in->buf_ptr = len;
174 sb_sasl_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
176 struct sb_sasl_data *p;
177 ber_slen_t ret, bufptr;
179 assert( sbiod != NULL );
180 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
182 p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
184 /* Are there anything left in the buffer? */
185 ret = ber_pvt_sb_copy_out( &p->buf_in, buf, len );
192 ber_pvt_sb_buf_destroy( &p->buf_in );
194 /* Read the length of the packet */
195 while ( p->sec_buf_in.buf_ptr < 4 ) {
196 ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base,
197 4 - p->sec_buf_in.buf_ptr );
199 if ( ( ret < 0 ) && ( errno == EINTR ) )
205 p->sec_buf_in.buf_ptr += ret;
208 /* The new packet always starts at p->sec_buf_in.buf_base */
209 ret = sb_sasl_pkt_length( p->sec_buf_in.buf_base,
210 sbiod->sbiod_sb->sb_debug );
212 /* Grow the packet buffer if neccessary */
213 if ( ( p->sec_buf_in.buf_size < ret ) &&
214 ber_pvt_sb_grow_buffer( &p->sec_buf_in, ret ) < 0 )
219 p->sec_buf_in.buf_end = ret;
221 /* Did we read the whole encrypted packet? */
222 while ( p->sec_buf_in.buf_ptr < p->sec_buf_in.buf_end ) {
223 /* No, we have got only a part of it */
224 ret = p->sec_buf_in.buf_end - p->sec_buf_in.buf_ptr;
226 ret = LBER_SBIOD_READ_NEXT( sbiod, p->sec_buf_in.buf_base +
227 p->sec_buf_in.buf_ptr, ret );
229 if ( ( ret < 0 ) && ( errno == EINTR ) )
235 p->sec_buf_in.buf_ptr += ret;
238 /* Decode the packet */
239 ret = sasl_decode( p->sasl_context, p->sec_buf_in.buf_base,
240 p->sec_buf_in.buf_end, &p->buf_in.buf_base,
241 (unsigned *)&p->buf_in.buf_end );
242 if ( ret != SASL_OK ) {
243 ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
244 "sb_sasl_read: failed to decode packet: %s\n",
245 sasl_errstring( ret, NULL, NULL ) );
246 sb_sasl_drop_packet( &p->sec_buf_in,
247 sbiod->sbiod_sb->sb_debug );
252 /* Drop the packet from the input buffer */
253 sb_sasl_drop_packet( &p->sec_buf_in, sbiod->sbiod_sb->sb_debug );
255 p->buf_in.buf_size = p->buf_in.buf_end;
257 bufptr += ber_pvt_sb_copy_out( &p->buf_in, (char*) buf + bufptr, len );
263 sb_sasl_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
265 struct sb_sasl_data *p;
268 assert( sbiod != NULL );
269 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
271 p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
273 /* Are there anything left in the buffer? */
274 if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
275 ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
280 /* now encode the next packet. */
281 ber_pvt_sb_buf_destroy( &p->buf_out );
282 ret = sasl_encode( p->sasl_context, buf, len, &p->buf_out.buf_base,
283 (unsigned *)&p->buf_out.buf_size );
284 if ( ret != SASL_OK ) {
285 ber_log_printf( LDAP_DEBUG_ANY, sbiod->sbiod_sb->sb_debug,
286 "sb_sasl_write: failed to encode packet: %s\n",
287 sasl_errstring( ret, NULL, NULL ) );
290 p->buf_out.buf_end = p->buf_out.buf_size;
292 ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
299 sb_sasl_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
301 struct sb_sasl_data *p;
303 p = (struct sb_sasl_data *)sbiod->sbiod_pvt;
305 if ( opt == LBER_SB_OPT_DATA_READY ) {
306 if ( p->buf_in.buf_ptr != p->buf_in.buf_end )
310 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
313 Sockbuf_IO ldap_pvt_sockbuf_io_sasl = {
314 sb_sasl_setup, /* sbi_setup */
315 sb_sasl_remove, /* sbi_remove */
316 sb_sasl_ctrl, /* sbi_ctrl */
317 sb_sasl_read, /* sbi_read */
318 sb_sasl_write, /* sbi_write */
322 int ldap_pvt_sasl_install( Sockbuf *sb, void *ctx_arg )
324 Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_install\n",
327 /* don't install the stuff unless security has been negotiated */
329 if ( !ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO,
330 &ldap_pvt_sockbuf_io_sasl ) )
333 ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug,
334 LBER_SBIOD_LEVEL_APPLICATION, (void *)"sasl_" );
336 ber_sockbuf_add_io( sb, &ldap_pvt_sockbuf_io_sasl,
337 LBER_SBIOD_LEVEL_APPLICATION, ctx_arg );
344 sasl_err2ldap( int saslerr )
350 rc = LDAP_MORE_RESULTS_TO_RETURN;
353 rc = LDAP_LOCAL_ERROR;
359 rc = LDAP_LOCAL_ERROR;
365 rc = LDAP_AUTH_UNKNOWN;
368 rc = LDAP_AUTH_UNKNOWN;
371 rc = LDAP_PARAM_ERROR;
375 rc = LDAP_AUTH_UNKNOWN;
378 rc = LDAP_LOCAL_ERROR;
382 assert( rc == LDAP_SUCCESS || LDAP_API_ERROR( rc ) );
396 sasl_callback_t *session_callbacks =
397 ber_memcalloc( 2, sizeof( sasl_callback_t ) );
399 if( session_callbacks == NULL ) return LDAP_NO_MEMORY;
401 session_callbacks[0].id = SASL_CB_USER;
402 session_callbacks[0].proc = NULL;
403 session_callbacks[0].context = ld;
405 session_callbacks[1].id = SASL_CB_LIST_END;
406 session_callbacks[1].proc = NULL;
407 session_callbacks[1].context = NULL;
409 assert( lc->lconn_sasl_ctx == NULL );
411 if ( host == NULL ) {
412 ld->ld_errno = LDAP_LOCAL_ERROR;
416 rc = sasl_client_new( "ldap", host, session_callbacks,
417 SASL_SECURITY_LAYER, &ctx );
419 if ( rc != SASL_OK ) {
420 ld->ld_errno = sasl_err2ldap( rc );
424 Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_open: %s\n",
427 lc->lconn_sasl_ctx = ctx;
430 sasl_external_properties_t extprops;
431 memset(&extprops, 0L, sizeof(extprops));
434 (void) sasl_setprop( ctx, SASL_SSF_EXTERNAL,
435 (void *) &extprops );
437 Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_open: ssf=%ld\n",
444 int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc )
446 sasl_conn_t *ctx = lc->lconn_sasl_ctx;
449 sasl_dispose( &ctx );
450 lc->lconn_sasl_ctx = NULL;
461 LDAPControl **sctrls,
462 LDAPControl **cctrls,
464 LDAP_SASL_INTERACT_PROC *interact,
468 const char *mech = NULL;
469 const char *pmech = NULL;
471 sasl_ssf_t *ssf = NULL;
473 sasl_interact_t *prompts = NULL;
478 Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_bind: %s\n",
479 mechs ? mechs : "<null>", 0, 0 );
481 /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */
482 if (ld->ld_version < LDAP_VERSION3) {
483 ld->ld_errno = LDAP_NOT_SUPPORTED;
487 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
489 if ( sd == AC_SOCKET_INVALID ) {
490 /* not connected yet */
493 rc = ldap_open_defconn( ld );
494 if( rc < 0 ) return ld->ld_errno;
496 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
498 if( sd == AC_SOCKET_INVALID ) {
499 ld->ld_errno = LDAP_LOCAL_ERROR;
504 ctx = ld->ld_defconn->lconn_sasl_ctx;
507 ld->ld_errno = LDAP_LOCAL_ERROR;
511 /* (re)set security properties */
512 sasl_setprop( ctx, SASL_SEC_PROPS,
513 &ld->ld_options.ldo_sasl_secprops );
519 saslrc = sasl_client_start( ctx,
527 if( pmech == NULL && mech != NULL ) {
530 if( flags != LDAP_SASL_QUIET ) {
532 "SASL/%s authentication started\n",
537 if( saslrc == SASL_INTERACT ) {
539 if( !interact ) break;
540 res = (interact)( ld, flags, defaults, prompts );
541 if( res != LDAP_SUCCESS ) {
545 } while ( saslrc == SASL_INTERACT );
547 ccred.bv_len = credlen;
549 if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
550 ld->ld_errno = sasl_err2ldap( saslrc );
555 struct berval *scred;
560 rc = ldap_sasl_bind_s( ld, dn, mech, &ccred, sctrls, cctrls, &scred );
562 if ( ccred.bv_val != NULL ) {
563 LDAP_FREE( ccred.bv_val );
567 if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) {
568 if( scred && scred->bv_len ) {
569 /* and server provided us with data? */
570 Debug( LDAP_DEBUG_TRACE,
571 "ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
572 rc, saslrc, scred->bv_len );
578 if( rc == LDAP_SUCCESS && saslrc == SASL_OK ) {
579 /* we're done, no need to step */
580 if( scred && scred->bv_len ) {
581 /* but server provided us with data! */
582 Debug( LDAP_DEBUG_TRACE,
583 "ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
584 rc, saslrc, scred->bv_len );
586 return ld->ld_errno = LDAP_LOCAL_ERROR;
592 saslrc = sasl_client_step( ctx,
593 (scred == NULL) ? NULL : scred->bv_val,
594 (scred == NULL) ? 0 : scred->bv_len,
599 Debug( LDAP_DEBUG_TRACE, "sasl_client_start: %d\n",
602 if( saslrc == SASL_INTERACT ) {
604 if( !interact ) break;
605 res = (interact)( ld, flags, defaults, prompts );
606 if( res != LDAP_SUCCESS ) {
610 } while ( saslrc == SASL_INTERACT );
612 ccred.bv_len = credlen;
615 if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
616 ld->ld_errno = sasl_err2ldap( saslrc );
619 } while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
621 if ( rc != LDAP_SUCCESS ) {
625 if ( saslrc != SASL_OK ) {
626 return ld->ld_errno = sasl_err2ldap( saslrc );
629 if( flags != LDAP_SASL_QUIET ) {
630 saslrc = sasl_getprop( ctx, SASL_USERNAME, (void **) &data );
631 if( saslrc == SASL_OK && data && *data ) {
632 fprintf( stderr, "SASL username: %s\n", data );
635 saslrc = sasl_getprop( ctx, SASL_REALM, (void **) &data );
636 if( saslrc == SASL_OK && data && *data ) {
637 fprintf( stderr, "SASL realm: %s\n", data );
641 saslrc = sasl_getprop( ctx, SASL_SSF, (void **) &ssf );
642 if( saslrc == SASL_OK ) {
643 if( flags != LDAP_SASL_QUIET ) {
644 fprintf( stderr, "SASL SSF: %lu\n",
645 (unsigned long) *ssf );
649 if( flags != LDAP_SASL_QUIET ) {
650 fprintf( stderr, "SASL installing layers\n" );
652 ldap_pvt_sasl_install( ld->ld_conns->lconn_sb, ctx );
660 ldap_int_sasl_external(
667 sasl_external_properties_t extprops;
669 if( ld->ld_defconn == NULL ) {
670 return LDAP_LOCAL_ERROR;
673 ctx = ld->ld_defconn->lconn_sasl_ctx;
676 return LDAP_LOCAL_ERROR;
679 memset( &extprops, '\0', sizeof(extprops) );
681 extprops.auth_id = (char *) authid;
683 sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL,
684 (void *) &extprops );
686 if ( sc != SASL_OK ) {
687 return LDAP_LOCAL_ERROR;
694 int ldap_pvt_sasl_secprops(
696 sasl_security_properties_t *secprops )
699 char **props = ldap_str2charray( in, "," );
702 sasl_ssf_t max_ssf = 0;
704 sasl_ssf_t min_ssf = 0;
706 unsigned maxbufsize = 0;
707 int got_maxbufsize = 0;
709 if( props == NULL || secprops == NULL ) {
710 return LDAP_PARAM_ERROR;
713 for( i=0; props[i]; i++ ) {
714 if( !strcasecmp(props[i], "none") ) {
717 } else if( !strcasecmp(props[i], "noplain") ) {
719 sflags |= SASL_SEC_NOPLAINTEXT;
721 } else if( !strcasecmp(props[i], "noactive") ) {
723 sflags |= SASL_SEC_NOACTIVE;
725 } else if( !strcasecmp(props[i], "nodict") ) {
727 sflags |= SASL_SEC_NODICTIONARY;
729 } else if( !strcasecmp(props[i], "forwardsec") ) {
731 sflags |= SASL_SEC_FORWARD_SECRECY;
733 } else if( !strcasecmp(props[i], "noanonymous")) {
735 sflags |= SASL_SEC_NOANONYMOUS;
737 } else if( !strcasecmp(props[i], "passcred") ) {
739 sflags |= SASL_SEC_PASS_CREDENTIALS;
741 } else if( !strncasecmp(props[i],
742 "minssf=", sizeof("minssf")) )
744 if( isdigit( props[i][sizeof("minssf")] ) ) {
746 min_ssf = atoi( &props[i][sizeof("minssf")] );
748 return LDAP_NOT_SUPPORTED;
751 } else if( !strncasecmp(props[i],
752 "maxssf=", sizeof("maxssf")) )
754 if( isdigit( props[i][sizeof("maxssf")] ) ) {
756 max_ssf = atoi( &props[i][sizeof("maxssf")] );
758 return LDAP_NOT_SUPPORTED;
761 } else if( !strncasecmp(props[i],
762 "maxbufsize=", sizeof("maxbufsize")) )
764 if( isdigit( props[i][sizeof("maxbufsize")] ) ) {
766 maxbufsize = atoi( &props[i][sizeof("maxbufsize")] );
768 return LDAP_NOT_SUPPORTED;
771 if( maxbufsize && (( maxbufsize < SASL_MIN_BUFF_SIZE )
772 || (maxbufsize > SASL_MAX_BUFF_SIZE )))
775 return LDAP_PARAM_ERROR;
779 return LDAP_NOT_SUPPORTED;
784 secprops->security_flags = sflags;
787 secprops->min_ssf = min_ssf;
790 secprops->max_ssf = max_ssf;
793 secprops->maxbufsize = maxbufsize;
796 ldap_charray_free( props );
801 ldap_int_sasl_config( struct ldapoptions *lo, int option, const char *arg )
806 case LDAP_OPT_X_SASL_SECPROPS:
807 rc = ldap_pvt_sasl_secprops( arg, &lo->ldo_sasl_secprops );
808 if( rc == LDAP_SUCCESS ) return 0;
815 ldap_int_sasl_get_option( LDAP *ld, int option, void *arg )
821 case LDAP_OPT_X_SASL_MECH: {
822 *(char **)arg = ld->ld_options.ldo_def_sasl_mech
823 ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_mech ) : NULL;
825 case LDAP_OPT_X_SASL_REALM: {
826 *(char **)arg = ld->ld_options.ldo_def_sasl_realm
827 ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_realm ) : NULL;
829 case LDAP_OPT_X_SASL_AUTHCID: {
830 *(char **)arg = ld->ld_options.ldo_def_sasl_authcid
831 ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_authcid ) : NULL;
833 case LDAP_OPT_X_SASL_AUTHZID: {
834 *(char **)arg = ld->ld_options.ldo_def_sasl_authzid
835 ? LDAP_STRDUP( ld->ld_options.ldo_def_sasl_authzid ) : NULL;
838 case LDAP_OPT_X_SASL_SSF: {
843 if( ld->ld_defconn == NULL ) {
847 ctx = ld->ld_defconn->lconn_sasl_ctx;
853 sc = sasl_getprop( ctx, SASL_SSF,
856 if ( sc != SASL_OK ) {
860 *(ber_len_t *)arg = *ssf;
863 case LDAP_OPT_X_SASL_SSF_EXTERNAL:
864 /* this option is write only */
867 case LDAP_OPT_X_SASL_SSF_MIN:
868 *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.min_ssf;
870 case LDAP_OPT_X_SASL_SSF_MAX:
871 *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.max_ssf;
873 case LDAP_OPT_X_SASL_MAXBUFSIZE:
874 *(ber_len_t *)arg = ld->ld_options.ldo_sasl_secprops.maxbufsize;
877 case LDAP_OPT_X_SASL_SECPROPS:
878 /* this option is write only */
888 ldap_int_sasl_set_option( LDAP *ld, int option, void *arg )
894 case LDAP_OPT_X_SASL_SSF:
895 /* This option is read-only */
898 case LDAP_OPT_X_SASL_SSF_EXTERNAL: {
900 sasl_external_properties_t extprops;
903 if( ld->ld_defconn == NULL ) {
907 ctx = ld->ld_defconn->lconn_sasl_ctx;
913 memset(&extprops, 0L, sizeof(extprops));
915 extprops.ssf = * (ber_len_t *) arg;
917 sc = sasl_setprop( ctx, SASL_SSF_EXTERNAL,
918 (void *) &extprops );
920 if ( sc != SASL_OK ) {
925 case LDAP_OPT_X_SASL_SSF_MIN:
926 ld->ld_options.ldo_sasl_secprops.min_ssf = *(ber_len_t *)arg;
928 case LDAP_OPT_X_SASL_SSF_MAX:
929 ld->ld_options.ldo_sasl_secprops.max_ssf = *(ber_len_t *)arg;
931 case LDAP_OPT_X_SASL_MAXBUFSIZE:
932 ld->ld_options.ldo_sasl_secprops.maxbufsize = *(ber_len_t *)arg;
935 case LDAP_OPT_X_SASL_SECPROPS: {
937 sc = ldap_pvt_sasl_secprops( (char *) arg,
938 &ld->ld_options.ldo_sasl_secprops );
940 return sc == LDAP_SUCCESS ? 0 : -1;
949 #ifdef LDAP_R_COMPILE
950 void *ldap_pvt_sasl_mutex_new(void)
952 ldap_pvt_thread_mutex_t *mutex;
954 mutex = (ldap_pvt_thread_mutex_t *) LDAP_MALLOC(
955 sizeof(ldap_pvt_thread_mutex_t) );
957 if ( ldap_pvt_thread_mutex_init( mutex ) == 0 ) {
963 int ldap_pvt_sasl_mutex_lock(void *mutex)
965 return ldap_pvt_thread_mutex_lock( (ldap_pvt_thread_mutex_t *)mutex )
966 ? SASL_FAIL : SASL_OK;
969 int ldap_pvt_sasl_mutex_unlock(void *mutex)
971 return ldap_pvt_thread_mutex_unlock( (ldap_pvt_thread_mutex_t *)mutex )
972 ? SASL_FAIL : SASL_OK;
975 void ldap_pvt_sasl_mutex_dispose(void *mutex)
977 (void) ldap_pvt_thread_mutex_destroy( (ldap_pvt_thread_mutex_t *)mutex );
983 int ldap_int_sasl_init( void )
984 { return LDAP_SUCCESS; }
986 int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc )
987 { return LDAP_SUCCESS; }
994 LDAPControl **sctrls,
995 LDAPControl **cctrls,
997 LDAP_SASL_INTERACT_PROC *interact,
999 { return LDAP_NOT_SUPPORTED; }
1002 ldap_int_sasl_external(
1004 const char * authid,
1006 { return LDAP_SUCCESS; }
1008 #endif /* HAVE_CYRUS_SASL */