X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Fsasl.c;h=fc995bee449dee8acf63378e509fc3bedc3222bc;hb=7d13ef7e42f1514dd99878835a13a700da4f4b69;hp=6aa8cce49791cda8720636d6f88c8589c4cee24d;hpb=3dadeb3efe31c72dacc2e0e11ee25c271dffe44d;p=openldap diff --git a/libraries/libldap/sasl.c b/libraries/libldap/sasl.c index 6aa8cce497..fc995bee44 100644 --- a/libraries/libldap/sasl.c +++ b/libraries/libldap/sasl.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2010 The OpenLDAP Foundation. + * Copyright 1998-2012 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 **pmechlist ) } /* - * 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; @@ -444,36 +451,86 @@ ldap_sasl_interactive_bind_s( #endif if( mechs == NULL || *mechs == '\0' ) { + /* FIXME: this needs to be asynchronous too; + * perhaps NULL should be disallowed for async usage? + */ rc = ldap_pvt_sasl_getmechs( ld, &smechs ); if( rc != LDAP_SUCCESS ) { goto done; } Debug( LDAP_DEBUG_TRACE, - "ldap_sasl_interactive_bind_s: server supports: %s\n", + "ldap_sasl_interactive_bind: server supports: %s\n", smechs, 0, 0 ); mechs = smechs; } else { Debug( LDAP_DEBUG_TRACE, - "ldap_sasl_interactive_bind_s: user selected: %s\n", + "ldap_sasl_interactive_bind: 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 ); + + ldap_msgfree( result ); + + 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 +790,9 @@ sb_sasl_generic_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) 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