--- libraries/libldap/sasl.c 2009/10/31 00:11:22 1.64.2.7 +++ libraries/libldap/sasl.c 2010/10/13 23:29:32 1.82 @@ -1,7 +1,7 @@ -/* $OpenLDAP$ */ +/* $OpenLDAP: pkg/ldap/libraries/libldap/sasl.c,v 1.81 2010/10/13 06:43:16 hyc Exp $ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2009 The OpenLDAP Foundation. + * Copyright 1998-2010 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -401,15 +401,16 @@ ldap_pvt_sasl_getmechs ( LDAP *ld, char } /* - * ldap_sasl_interactive_bind_s - interactive SASL authentication + * ldap_sasl_interactive_bind - interactive SASL authentication * * This routine uses interactive callbacks. * * LDAP_SUCCESS is returned upon success, the ldap error code - * otherwise. + * otherwise. LDAP_SASL_BIND_IN_PROGRESS is returned if further + * calls are needed. */ int -ldap_sasl_interactive_bind_s( +ldap_sasl_interactive_bind( LDAP *ld, LDAP_CONST char *dn, /* usually NULL */ LDAP_CONST char *mechs, @@ -417,13 +418,16 @@ ldap_sasl_interactive_bind_s( LDAPControl **clientControls, unsigned flags, LDAP_SASL_INTERACT_PROC *interact, - void *defaults ) + void *defaults, + LDAPMessage *result, + const char **rmech, + int *msgid ) { - int rc; char *smechs = NULL; + int rc; -#if defined( LDAP_R_COMPILE ) && defined( HAVE_CYRUS_SASL ) - ldap_pvt_thread_mutex_lock( &ldap_int_sasl_mutex ); +#if defined( HAVE_CYRUS_SASL ) + LDAP_MUTEX_LOCK( &ldap_int_sasl_mutex ); #endif #ifdef LDAP_CONNECTIONLESS if( LDAP_IS_UDP(ld) ) { @@ -437,6 +441,9 @@ ldap_sasl_interactive_bind_s( } else #endif + /* First time */ + if ( !result ) { + #ifdef HAVE_CYRUS_SASL if( mechs == NULL || *mechs == '\0' ) { mechs = ld->ld_options.ldo_def_sasl_mech; @@ -460,20 +467,65 @@ ldap_sasl_interactive_bind_s( "ldap_sasl_interactive_bind_s: user selected: %s\n", mechs, 0, 0 ); } - + } rc = ldap_int_sasl_bind( ld, dn, mechs, serverControls, clientControls, - flags, interact, defaults ); + flags, interact, defaults, result, rmech, msgid ); done: -#if defined( LDAP_R_COMPILE ) && defined( HAVE_CYRUS_SASL ) - ldap_pvt_thread_mutex_unlock( &ldap_int_sasl_mutex ); +#if defined( HAVE_CYRUS_SASL ) + LDAP_MUTEX_UNLOCK( &ldap_int_sasl_mutex ); #endif if ( smechs ) LDAP_FREE( smechs ); return rc; } +/* + * ldap_sasl_interactive_bind_s - interactive SASL authentication + * + * This routine uses interactive callbacks. + * + * LDAP_SUCCESS is returned upon success, the ldap error code + * otherwise. + */ +int +ldap_sasl_interactive_bind_s( + LDAP *ld, + LDAP_CONST char *dn, /* usually NULL */ + LDAP_CONST char *mechs, + LDAPControl **serverControls, + LDAPControl **clientControls, + unsigned flags, + LDAP_SASL_INTERACT_PROC *interact, + void *defaults ) +{ + const char *rmech = NULL; + LDAPMessage *result = NULL; + int rc, msgid; + + do { + rc = ldap_sasl_interactive_bind( ld, dn, mechs, + serverControls, clientControls, + flags, interact, defaults, result, &rmech, &msgid ); + + if ( rc != LDAP_SASL_BIND_IN_PROGRESS ) + break; + +#ifdef LDAP_CONNECTIONLESS + if (LDAP_IS_UDP(ld)) { + break; + } +#endif + + if ( ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1 || !result ) { + return( ld->ld_errno ); /* ldap_result sets ld_errno */ + } + } while ( rc == LDAP_SASL_BIND_IN_PROGRESS ); + + return rc; +} + #ifdef HAVE_CYRUS_SASL #ifdef HAVE_SASL_SASL_H @@ -733,8 +785,9 @@ sb_sasl_generic_write( Sockbuf_IO_Desc * return ret; } else if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) { /* partial write? pretend nothing got written */ - len2 = 0; p->flags |= LDAP_PVT_SASL_PARTIAL_WRITE; + sock_errset(EAGAIN); + len2 = -1; } /* return number of bytes encoded, not written, to ensure