mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-27 03:20:22 +08:00
Add ldap_sasl_interactive_bind()
This commit is contained in:
parent
0b660dc9f6
commit
fca72f333b
@ -1186,6 +1186,26 @@ ldap_sasl_bind LDAP_P((
|
||||
typedef int (LDAP_SASL_INTERACT_PROC) LDAP_P((
|
||||
LDAP *ld, unsigned flags, void* defaults, void *interact ));
|
||||
|
||||
LDAP_F( int )
|
||||
ldap_sasl_interactive_bind LDAP_P((
|
||||
LDAP *ld,
|
||||
LDAP_CONST char *dn, /* usually NULL */
|
||||
LDAP_CONST char *saslMechanism,
|
||||
LDAPControl **serverControls,
|
||||
LDAPControl **clientControls,
|
||||
|
||||
/* should be client controls */
|
||||
unsigned flags,
|
||||
LDAP_SASL_INTERACT_PROC *proc,
|
||||
void *defaults,
|
||||
|
||||
/* as obtained from ldap_result() */
|
||||
LDAPMessage *result,
|
||||
|
||||
/* returned during bind processing */
|
||||
const char **rmech,
|
||||
int *msgid ));
|
||||
|
||||
LDAP_F( int )
|
||||
ldap_sasl_interactive_bind_s LDAP_P((
|
||||
LDAP *ld,
|
||||
|
@ -386,19 +386,18 @@ ldap_int_sasl_bind(
|
||||
LDAPControl **cctrls,
|
||||
unsigned flags,
|
||||
LDAP_SASL_INTERACT_PROC *interact,
|
||||
void * defaults )
|
||||
void *defaults,
|
||||
LDAPMessage *result,
|
||||
const char **rmech,
|
||||
int *msgid )
|
||||
{
|
||||
char *data;
|
||||
const char *mech = NULL;
|
||||
const char *pmech = NULL;
|
||||
int saslrc, rc;
|
||||
sasl_ssf_t *ssf = NULL;
|
||||
sasl_conn_t *ctx, *oldctx = NULL;
|
||||
const char *mech;
|
||||
sasl_ssf_t *ssf;
|
||||
sasl_conn_t *ctx;
|
||||
sasl_interact_t *prompts = NULL;
|
||||
struct berval ccred;
|
||||
int saslrc, rc;
|
||||
unsigned credlen;
|
||||
struct berval ccred;
|
||||
ber_socket_t sd;
|
||||
void *ssl;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldap_int_sasl_bind: %s\n",
|
||||
mechs ? mechs : "<null>", 0, 0 );
|
||||
@ -409,203 +408,161 @@ ldap_int_sasl_bind(
|
||||
return ld->ld_errno;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
|
||||
/* Starting a Bind */
|
||||
if ( !result ) {
|
||||
const char *pmech = NULL;
|
||||
sasl_conn_t *oldctx;
|
||||
ber_socket_t sd;
|
||||
void *ssl;
|
||||
|
||||
if ( sd == AC_SOCKET_INVALID ) {
|
||||
/* not connected yet */
|
||||
rc = 0;
|
||||
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
|
||||
ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd );
|
||||
|
||||
rc = ldap_open_defconn( ld );
|
||||
if ( sd == AC_SOCKET_INVALID ) {
|
||||
/* not connected yet */
|
||||
|
||||
if ( rc == 0 ) {
|
||||
ber_sockbuf_ctrl( ld->ld_defconn->lconn_sb,
|
||||
LBER_SB_OPT_GET_FD, &sd );
|
||||
rc = ldap_open_defconn( ld );
|
||||
|
||||
if( sd == AC_SOCKET_INVALID ) {
|
||||
ld->ld_errno = LDAP_LOCAL_ERROR;
|
||||
rc = ld->ld_errno;
|
||||
if ( rc == 0 ) {
|
||||
ber_sockbuf_ctrl( ld->ld_defconn->lconn_sb,
|
||||
LBER_SB_OPT_GET_FD, &sd );
|
||||
|
||||
if( sd == AC_SOCKET_INVALID ) {
|
||||
ld->ld_errno = LDAP_LOCAL_ERROR;
|
||||
rc = ld->ld_errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
if( rc != 0 ) return ld->ld_errno;
|
||||
|
||||
oldctx = ld->ld_defconn->lconn_sasl_authctx;
|
||||
|
||||
/* If we already have an authentication context, clear it out */
|
||||
if( oldctx ) {
|
||||
if ( oldctx != ld->ld_defconn->lconn_sasl_sockctx ) {
|
||||
sasl_dispose( &oldctx );
|
||||
}
|
||||
ld->ld_defconn->lconn_sasl_authctx = NULL;
|
||||
}
|
||||
}
|
||||
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
|
||||
if( rc != 0 ) return ld->ld_errno;
|
||||
|
||||
oldctx = ld->ld_defconn->lconn_sasl_authctx;
|
||||
{
|
||||
char *saslhost;
|
||||
int nocanon = (int)LDAP_BOOL_GET( &ld->ld_options,
|
||||
LDAP_BOOL_SASL_NOCANON );
|
||||
|
||||
/* If we already have an authentication context, clear it out */
|
||||
if( oldctx ) {
|
||||
if ( oldctx != ld->ld_defconn->lconn_sasl_sockctx ) {
|
||||
sasl_dispose( &oldctx );
|
||||
/* If we don't need to canonicalize just use the host
|
||||
* from the LDAP URI.
|
||||
*/
|
||||
if ( nocanon )
|
||||
saslhost = ld->ld_defconn->lconn_server->lud_host;
|
||||
else
|
||||
saslhost = ldap_host_connected_to( ld->ld_defconn->lconn_sb,
|
||||
"localhost" );
|
||||
rc = ldap_int_sasl_open( ld, ld->ld_defconn, saslhost );
|
||||
if ( !nocanon )
|
||||
LDAP_FREE( saslhost );
|
||||
}
|
||||
ld->ld_defconn->lconn_sasl_authctx = NULL;
|
||||
}
|
||||
|
||||
{
|
||||
char *saslhost;
|
||||
int nocanon = (int)LDAP_BOOL_GET( &ld->ld_options,
|
||||
LDAP_BOOL_SASL_NOCANON );
|
||||
if ( rc != LDAP_SUCCESS ) return rc;
|
||||
|
||||
/* If we don't need to canonicalize just use the host
|
||||
* from the LDAP URI.
|
||||
*/
|
||||
if ( nocanon )
|
||||
saslhost = ld->ld_defconn->lconn_server->lud_host;
|
||||
else
|
||||
saslhost = ldap_host_connected_to( ld->ld_defconn->lconn_sb,
|
||||
"localhost" );
|
||||
rc = ldap_int_sasl_open( ld, ld->ld_defconn, saslhost );
|
||||
if ( !nocanon )
|
||||
LDAP_FREE( saslhost );
|
||||
}
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) return rc;
|
||||
|
||||
ctx = ld->ld_defconn->lconn_sasl_authctx;
|
||||
ctx = ld->ld_defconn->lconn_sasl_authctx;
|
||||
|
||||
#ifdef HAVE_TLS
|
||||
/* Check for TLS */
|
||||
ssl = ldap_pvt_tls_sb_ctx( ld->ld_defconn->lconn_sb );
|
||||
if ( ssl ) {
|
||||
struct berval authid = BER_BVNULL;
|
||||
ber_len_t fac;
|
||||
/* Check for TLS */
|
||||
ssl = ldap_pvt_tls_sb_ctx( ld->ld_defconn->lconn_sb );
|
||||
if ( ssl ) {
|
||||
struct berval authid = BER_BVNULL;
|
||||
ber_len_t fac;
|
||||
|
||||
fac = ldap_pvt_tls_get_strength( ssl );
|
||||
/* failure is OK, we just can't use SASL EXTERNAL */
|
||||
(void) ldap_pvt_tls_get_my_dn( ssl, &authid, NULL, 0 );
|
||||
fac = ldap_pvt_tls_get_strength( ssl );
|
||||
/* failure is OK, we just can't use SASL EXTERNAL */
|
||||
(void) ldap_pvt_tls_get_my_dn( ssl, &authid, NULL, 0 );
|
||||
|
||||
(void) ldap_int_sasl_external( ld, ld->ld_defconn, authid.bv_val, fac );
|
||||
LDAP_FREE( authid.bv_val );
|
||||
}
|
||||
(void) ldap_int_sasl_external( ld, ld->ld_defconn, authid.bv_val, fac );
|
||||
LDAP_FREE( authid.bv_val );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
/* Check for local */
|
||||
if ( ldap_pvt_url_scheme2proto(
|
||||
ld->ld_defconn->lconn_server->lud_scheme ) == LDAP_PROTO_IPC )
|
||||
{
|
||||
char authid[sizeof("gidNumber=4294967295+uidNumber=4294967295,"
|
||||
"cn=peercred,cn=external,cn=auth")];
|
||||
sprintf( authid, "gidNumber=%u+uidNumber=%u,"
|
||||
"cn=peercred,cn=external,cn=auth",
|
||||
getegid(), geteuid() );
|
||||
(void) ldap_int_sasl_external( ld, ld->ld_defconn, authid,
|
||||
LDAP_PVT_SASL_LOCAL_SSF );
|
||||
}
|
||||
/* Check for local */
|
||||
if ( ldap_pvt_url_scheme2proto(
|
||||
ld->ld_defconn->lconn_server->lud_scheme ) == LDAP_PROTO_IPC )
|
||||
{
|
||||
char authid[sizeof("gidNumber=4294967295+uidNumber=4294967295,"
|
||||
"cn=peercred,cn=external,cn=auth")];
|
||||
sprintf( authid, "gidNumber=%u+uidNumber=%u,"
|
||||
"cn=peercred,cn=external,cn=auth",
|
||||
getegid(), geteuid() );
|
||||
(void) ldap_int_sasl_external( ld, ld->ld_defconn, authid,
|
||||
LDAP_PVT_SASL_LOCAL_SSF );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* (re)set security properties */
|
||||
sasl_setprop( ctx, SASL_SEC_PROPS,
|
||||
&ld->ld_options.ldo_sasl_secprops );
|
||||
/* (re)set security properties */
|
||||
sasl_setprop( ctx, SASL_SEC_PROPS,
|
||||
&ld->ld_options.ldo_sasl_secprops );
|
||||
|
||||
ccred.bv_val = NULL;
|
||||
ccred.bv_len = 0;
|
||||
ccred.bv_val = NULL;
|
||||
ccred.bv_len = 0;
|
||||
mech = NULL;
|
||||
|
||||
do {
|
||||
saslrc = sasl_client_start( ctx,
|
||||
mechs,
|
||||
do {
|
||||
saslrc = sasl_client_start( ctx,
|
||||
mechs,
|
||||
#if SASL_VERSION_MAJOR < 2
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
&prompts,
|
||||
(SASL_CONST char **)&ccred.bv_val,
|
||||
&credlen,
|
||||
&mech );
|
||||
&prompts,
|
||||
(SASL_CONST char **)&ccred.bv_val,
|
||||
&credlen,
|
||||
&mech );
|
||||
|
||||
if( pmech == NULL && mech != NULL ) {
|
||||
pmech = mech;
|
||||
if( pmech == NULL && mech != NULL ) {
|
||||
pmech = mech;
|
||||
|
||||
if( flags != LDAP_SASL_QUIET ) {
|
||||
fprintf(stderr,
|
||||
"SASL/%s authentication started\n",
|
||||
pmech );
|
||||
if( flags != LDAP_SASL_QUIET ) {
|
||||
fprintf(stderr,
|
||||
"SASL/%s authentication started\n",
|
||||
pmech );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( saslrc == SASL_INTERACT ) {
|
||||
int res;
|
||||
if( !interact ) break;
|
||||
res = (interact)( ld, flags, defaults, prompts );
|
||||
if( saslrc == SASL_INTERACT ) {
|
||||
int res;
|
||||
if( !interact ) break;
|
||||
res = (interact)( ld, flags, defaults, prompts );
|
||||
|
||||
if( res != LDAP_SUCCESS ) break;
|
||||
}
|
||||
} while ( saslrc == SASL_INTERACT );
|
||||
if( res != LDAP_SUCCESS ) break;
|
||||
}
|
||||
*rmech = mech;
|
||||
} while ( saslrc == SASL_INTERACT );
|
||||
|
||||
ccred.bv_len = credlen;
|
||||
|
||||
if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
|
||||
rc = ld->ld_errno = sasl_err2ldap( saslrc );
|
||||
#if SASL_VERSION_MAJOR >= 2
|
||||
if ( ld->ld_error ) {
|
||||
LDAP_FREE( ld->ld_error );
|
||||
}
|
||||
ld->ld_error = LDAP_STRDUP( sasl_errdetail( ctx ) );
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
do {
|
||||
struct berval *scred;
|
||||
unsigned credlen;
|
||||
} else {
|
||||
/* continuing an in-progress Bind */
|
||||
struct berval *scred = NULL;
|
||||
|
||||
scred = NULL;
|
||||
rc = ldap_parse_sasl_bind_result( ld, result, &scred, 0 );
|
||||
if ( rc != LDAP_SUCCESS )
|
||||
goto done;
|
||||
|
||||
rc = ldap_sasl_bind_s( ld, dn, mech, &ccred, sctrls, cctrls,
|
||||
&scred );
|
||||
|
||||
if ( ccred.bv_val != NULL ) {
|
||||
#if SASL_VERSION_MAJOR < 2
|
||||
LDAP_FREE( ccred.bv_val );
|
||||
#endif
|
||||
ccred.bv_val = NULL;
|
||||
}
|
||||
|
||||
rc = ldap_result2error( ld, result, 0 );
|
||||
if ( rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS ) {
|
||||
if( scred ) {
|
||||
/* and server provided us with data? */
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
|
||||
rc, saslrc, scred ? (long) scred->bv_len : -1L );
|
||||
"ldap_int_sasl_bind: rc=%d len=%ld\n",
|
||||
rc, scred ? (long) scred->bv_len : -1L, 0 );
|
||||
ber_bvfree( scred );
|
||||
scred = NULL;
|
||||
}
|
||||
rc = ld->ld_errno;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if( rc == LDAP_SUCCESS && saslrc == SASL_OK ) {
|
||||
/* we're done, no need to step */
|
||||
if( scred ) {
|
||||
/* but we got additional data? */
|
||||
#define KLUDGE_FOR_MSAD
|
||||
#ifdef KLUDGE_FOR_MSAD
|
||||
/*
|
||||
* MSAD provides empty additional data in violation of LDAP
|
||||
* technical specifications. As no existing SASL mechanism
|
||||
* allows empty data with an outcome message, just ignore it
|
||||
* for now. Hopefully MS will fix their bug before someone
|
||||
* defines a mechanism with possibly empty additional data.
|
||||
*/
|
||||
if( scred->bv_len == 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"ldap_int_sasl_bind: ignoring "
|
||||
" bogus empty data provided with SASL outcome message.\n",
|
||||
rc, saslrc, scred->bv_len );
|
||||
ber_bvfree( scred );
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldap_int_sasl_bind: rc=%d sasl=%d len=%ld\n",
|
||||
rc, saslrc, scred->bv_len );
|
||||
rc = ld->ld_errno = LDAP_LOCAL_ERROR;
|
||||
ber_bvfree( scred );
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ctx = ld->ld_defconn->lconn_sasl_authctx;
|
||||
mech = *rmech;
|
||||
do {
|
||||
if( ! scred ) {
|
||||
/* no data! */
|
||||
@ -632,36 +589,42 @@ ldap_int_sasl_bind(
|
||||
}
|
||||
} while ( saslrc == SASL_INTERACT );
|
||||
|
||||
ccred.bv_len = credlen;
|
||||
ber_bvfree( scred );
|
||||
}
|
||||
|
||||
if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
|
||||
ld->ld_errno = sasl_err2ldap( saslrc );
|
||||
#if SASL_VERSION_MAJOR >= 2
|
||||
if ( ld->ld_error ) {
|
||||
LDAP_FREE( ld->ld_error );
|
||||
}
|
||||
ld->ld_error = LDAP_STRDUP( sasl_errdetail( ctx ) );
|
||||
#endif
|
||||
rc = ld->ld_errno;
|
||||
goto done;
|
||||
}
|
||||
} while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) goto done;
|
||||
|
||||
if ( saslrc != SASL_OK ) {
|
||||
if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
|
||||
rc = ld->ld_errno = sasl_err2ldap( saslrc );
|
||||
#if SASL_VERSION_MAJOR >= 2
|
||||
if ( ld->ld_error ) {
|
||||
LDAP_FREE( ld->ld_error );
|
||||
}
|
||||
ld->ld_error = LDAP_STRDUP( sasl_errdetail( ctx ) );
|
||||
#endif
|
||||
rc = ld->ld_errno = sasl_err2ldap( saslrc );
|
||||
goto done;
|
||||
}
|
||||
|
||||
ccred.bv_len = credlen;
|
||||
|
||||
/* Always send a request on first Bind; only send subsequent if
|
||||
* saslrc == SASL_CONTINUE
|
||||
*/
|
||||
if ( !result || saslrc == SASL_CONTINUE ) {
|
||||
rc = ldap_sasl_bind( ld, dn, mech, &ccred, sctrls, cctrls, msgid );
|
||||
|
||||
if ( ccred.bv_val != NULL ) {
|
||||
#if SASL_VERSION_MAJOR < 2
|
||||
LDAP_FREE( ccred.bv_val );
|
||||
#endif
|
||||
ccred.bv_val = NULL;
|
||||
}
|
||||
if ( rc == LDAP_SUCCESS )
|
||||
rc = LDAP_SASL_BIND_IN_PROGRESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Conversation was completed successfully by now */
|
||||
if( flags != LDAP_SASL_QUIET ) {
|
||||
char *data;
|
||||
saslrc = sasl_getprop( ctx, SASL_USERNAME,
|
||||
(SASL_CONST void **)(char *) &data );
|
||||
if( saslrc == SASL_OK && data && *data ) {
|
||||
@ -677,6 +640,7 @@ ldap_int_sasl_bind(
|
||||
#endif
|
||||
}
|
||||
|
||||
ssf = NULL;
|
||||
saslrc = sasl_getprop( ctx, SASL_SSF, (SASL_CONST void **)(char *) &ssf );
|
||||
if( saslrc == SASL_OK ) {
|
||||
if( flags != LDAP_SASL_QUIET ) {
|
||||
@ -686,7 +650,7 @@ ldap_int_sasl_bind(
|
||||
|
||||
if( ssf && *ssf ) {
|
||||
if ( ld->ld_defconn->lconn_sasl_sockctx ) {
|
||||
oldctx = ld->ld_defconn->lconn_sasl_sockctx;
|
||||
sasl_conn_t *oldctx = ld->ld_defconn->lconn_sasl_sockctx;
|
||||
sasl_dispose( &oldctx );
|
||||
ldap_pvt_sasl_remove( ld->ld_defconn->lconn_sb );
|
||||
}
|
||||
|
@ -685,7 +685,10 @@ LDAP_F (int) ldap_int_sasl_bind LDAP_P((
|
||||
/* should be passed in client controls */
|
||||
unsigned flags,
|
||||
LDAP_SASL_INTERACT_PROC *interact,
|
||||
void *defaults ));
|
||||
void *defaults,
|
||||
LDAPMessage *result,
|
||||
const char **rmech,
|
||||
int *msgid ));
|
||||
|
||||
/* in schema.c */
|
||||
LDAP_F (char *) ldap_int_parse_numericoid LDAP_P((
|
||||
|
@ -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,10 +418,13 @@ 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( HAVE_CYRUS_SASL )
|
||||
LDAP_MUTEX_LOCK( &ldap_int_sasl_mutex );
|
||||
@ -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,10 +467,10 @@ 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( HAVE_CYRUS_SASL )
|
||||
@ -474,6 +481,51 @@ done:
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user