-int
-ldap_pvt_sasl_bind(
- LDAP *ld,
- LDAP_CONST char *dn,
- LDAP_CONST char *mechanism,
- LDAP_CONST sasl_callback_t *callbacks,
- LDAPControl **sctrls,
- LDAPControl **cctrls )
-{
- int saslrc, rc, msgid, ssf = 0;
- struct berval ccred, *scred;
- char *mechlist = NULL;
- char *host;
- sasl_interact_t *client_interact = NULL;
-
- Debug( LDAP_DEBUG_TRACE, "ldap_pvt_sasl_bind\n", 0, 0, 0 );
-
- /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */
- if (ld->ld_version < LDAP_VERSION3) {
- ld->ld_errno = LDAP_NOT_SUPPORTED;
- return ld->ld_errno;
- }
-
- /*
- * This connects to the host, side effect being that
- * ldap_host_connected_to() works.
- */
- rc = ldap_pvt_sasl_getmechs( ld, mechanism, &mechlist );
- if ( rc != LDAP_SUCCESS ) {
- return ld->ld_errno;
- }
-
- /* XXX this doesn't work with PF_LOCAL hosts */
- host = ldap_host_connected_to( &ld->ld_sb );
-
- if ( host == NULL ) {
- LDAP_FREE( mechlist );
- ld->ld_errno = LDAP_UNAVAILABLE;
- return ld->ld_errno;
- }
-
- if ( ld->ld_sasl_context != NULL ) {
- LDAP_FREE( mechlist );
- sasl_dispose( &ld->ld_sasl_context );
- }
-
- saslrc = sasl_client_new( "ldap", host, callbacks, 0, &ld->ld_sasl_context );
-
- LDAP_FREE( host );
-
- if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
- LDAP_FREE( mechlist );
- ld->ld_errno = ldap_pvt_sasl_err2ldap( rc );
- sasl_dispose( &ld->ld_sasl_context );
- return ld->ld_errno;
- }
-
- ccred.bv_val = NULL;
- ccred.bv_len = 0;
-
- saslrc = sasl_client_start( ld->ld_sasl_context,
- mechlist,
- NULL,
- &client_interact,
- &ccred.bv_val,
- (unsigned int *)&ccred.bv_len,
- &mechanism );
-
- LDAP_FREE( mechlist );
-
- if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
- ld->ld_errno = ldap_pvt_sasl_err2ldap( saslrc );
- sasl_dispose( &ld->ld_sasl_context );
- return ld->ld_errno;
- }
-
- scred = NULL;
-
- do {
- sasl_interact_t *client_interact = NULL;
-
- rc = ldap_sasl_bind_s( ld, dn, mechanism, &ccred, sctrls, cctrls, &scred );
- if ( rc == LDAP_SUCCESS ) {
- break;
- } else if ( rc != LDAP_SASL_BIND_IN_PROGRESS ) {
- if ( ccred.bv_val != NULL ) {
- LDAP_FREE( ccred.bv_val );
- }
- sasl_dispose( &ld->ld_sasl_context );
- return ld->ld_errno;
- }
-
- if ( ccred.bv_val != NULL ) {
- LDAP_FREE( ccred.bv_val );
- ccred.bv_val = NULL;
- }
-
- saslrc = sasl_client_step( ld->ld_sasl_context,
- (scred == NULL) ? NULL : scred->bv_val,
- (scred == NULL) ? 0 : scred->bv_len,
- &client_interact,
- &ccred.bv_val,
- (unsigned int *)&ccred.bv_len );
-
- ber_bvfree( scred );
-
- if ( (saslrc != SASL_OK) && (saslrc != SASL_CONTINUE) ) {
- ld->ld_errno = ldap_pvt_sasl_err2ldap( saslrc );
- sasl_dispose( &ld->ld_sasl_context );
- return ld->ld_errno;
- }
- } while ( rc == LDAP_SASL_BIND_IN_PROGRESS );
-
- assert ( rc == LDAP_SUCCESS );
-
- if ( sasl_getprop( ld->ld_sasl_context, SASL_SSF, (void **)&ssf )
- == SASL_OK && ssf ) {
- ldap_pvt_sasl_install( &ld->ld_sb, ld->ld_sasl_context );
- }
-
- return rc;
-}
-
-/* based on sample/sample-client.c */
-static int
-ldap_pvt_sasl_getsecret(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret)
-{
- struct berval *passphrase = (struct berval *)context;
- size_t len;
-
- if ( conn == NULL || psecret == NULL || id != SASL_CB_PASS ) {
- return SASL_BADPARAM;
- }
-
- len = (passphrase != NULL) ? (size_t)passphrase->bv_len: 0;
-
- *psecret = (sasl_secret_t *) LDAP_MALLOC( sizeof( sasl_secret_t ) + len );
- if ( *psecret == NULL ) {
- return SASL_NOMEM;
- }
-
- (*psecret)->len = passphrase->bv_len;
-
- if ( passphrase != NULL ) {
- memcpy((*psecret)->data, passphrase->bv_val, len);
- }
-
- return SASL_OK;
-}
-
-static int
-ldap_pvt_sasl_getsimple(void *context, int id, const char **result, int *len)
-{
- const char *value = (const char *)context;
-
- if ( result == NULL ) {
- return SASL_BADPARAM;
- }
-
- switch ( id ) {
- case SASL_CB_USER:
- case SASL_CB_AUTHNAME:
- *result = value;
- if ( len )
- *len = value ? strlen( value ) : 0;
- break;
- case SASL_CB_LANGUAGE:
- *result = NULL;
- if ( len )
- *len = 0;
- break;
- default:
- return SASL_BADPARAM;
- }
-
- return SASL_OK;
-}
-