char *mech;
char *cdn, *ndn;
ber_tag_t tag;
- int rc;
+ int rc = LDAP_SUCCESS;
struct berval cred;
Backend *be;
mech = NULL;
cred.bv_val = NULL;
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+ /* Force to connection to "anonymous" until bind succeeds.
+ * This may need to be relocated or done on a case by case basis
+ * to handle certain SASL mechanisms.
+ */
+
+ if ( conn->c_cdn != NULL ) {
+ free( conn->c_cdn );
+ conn->c_cdn = NULL;
+ }
+
+ if ( conn->c_dn != NULL ) {
+ free( conn->c_dn );
+ conn->c_dn = NULL;
+ }
+
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
/*
* Parse the bind request. It looks like this:
*
* authentication CHOICE {
* simple [0] OCTET STRING -- passwd
* krbv42ldap [1] OCTET STRING
- * krbv42dsa [1] OCTET STRING
+ * krbv42dsa [2] OCTET STRING
+ * SASL [3] SaslCredentials
* }
+ * }
+ *
+ * SaslCredentials ::= SEQUENCE {
+ * mechanism LDAPString,
+ * credentials OCTET STRING OPTIONAL
* }
*/
NULL, "sasl mechanism not supported" );
goto cleanup;
}
- }
- /* accept null binds */
- if ( ndn == NULL || *ndn == '\0' ) {
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
- conn->c_protocol = version;
+ if ( conn->c_authmech != NULL ) {
+ assert( conn->c_bind_in_progress );
+
+ if((strcmp(conn->c_authmech, mech) != 0)) {
+ /* mechanism changed, cancel in progress bind */
+ conn->c_bind_in_progress = 0;
+ if( conn->c_authstate != NULL ) {
+ free(conn->c_authstate);
+ conn->c_authstate = NULL;
+ }
+ free(conn->c_authmech);
+ conn->c_authmech = NULL;
+ }
- if ( conn->c_cdn != NULL ) {
- free( conn->c_cdn );
- conn->c_cdn = NULL;
+#ifdef LDAP_DEBUG
+ } else {
+ assert( !conn->c_bind_in_progress );
+ assert( conn->c_authmech == NULL );
+ assert( conn->c_authstate == NULL );
+#endif
}
- if ( conn->c_dn != NULL ) {
- free( conn->c_dn );
- conn->c_dn = NULL;
+ } else {
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+ if ( conn->c_authmech != NULL ) {
+ assert( conn->c_bind_in_progress );
+
+ /* cancel in progress bind */
+ conn->c_bind_in_progress = 0;
+
+ if( conn->c_authstate != NULL ) {
+ free(conn->c_authstate);
+ conn->c_authstate = NULL;
+ }
+ free(conn->c_authmech);
+ conn->c_authmech = NULL;
}
+ }
- ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+ conn->c_protocol = version;
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+ /* accept null binds */
+ if ( ndn == NULL || *ndn == '\0' ) {
+ /*
+ * we already forced connection to "anonymous", we just
+ * need to send success
+ */
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
goto cleanup;
}
if ( (be = select_backend( ndn )) == NULL ) {
if ( cred.bv_len == 0 ) {
- ldap_pvt_thread_mutex_lock( &conn->c_mutex );
-
- conn->c_protocol = version;
-
- if ( conn->c_cdn != NULL ) {
- free( conn->c_cdn );
- conn->c_cdn = NULL;
- }
-
- if ( conn->c_dn != NULL ) {
- free( conn->c_dn );
- conn->c_dn = NULL;
- }
-
- ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-
send_ldap_result( conn, op, LDAP_SUCCESS,
NULL, NULL );
+
} else if ( default_referral && *default_referral ) {
send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS,
NULL, default_referral );
+
} else {
send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
NULL, default_referral );
if ( (*be->be_bind)( be, conn, op, ndn, method, mech, &cred, &edn ) == 0 ) {
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
- conn->c_protocol = version;
-
- if ( conn->c_cdn != NULL ) {
- free( conn->c_cdn );
- }
-
conn->c_cdn = cdn;
cdn = NULL;
- if ( conn->c_dn != NULL ) {
- free( conn->c_dn );
- }
-
if(edn != NULL) {
conn->c_dn = edn;
} else {