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 {
#define SLAP_C_BINDING 0x03 /* binding */
#define SLAP_C_CLOSING 0x04 /* closing */
+char* connection_state2str( int state ) {
+ switch( state ) {
+ case SLAP_C_INVALID: return "!";
+ case SLAP_C_INACTIVE: return "|";
+ case SLAP_C_ACTIVE: return "";
+ case SLAP_C_BINDING: return "B";
+ case SLAP_C_CLOSING: return "C";
+ }
+
+ return "?";
+}
+
static Connection* connection_get( ber_socket_t s );
static int connection_input( Connection *c );
c->c_client_addr = NULL;
c->c_ops = NULL;
c->c_pending_ops = NULL;
+ c->c_authmech = NULL;
+ c->c_authstate = NULL;
c->c_sb = ber_sockbuf_alloc( );
assert( c->c_client_addr == NULL );
assert( c->c_ops == NULL );
assert( c->c_pending_ops == NULL );
+ assert( c->c_authmech == NULL );
+ assert( c->c_authstate == NULL );
c->c_client_name = ch_strdup( name == NULL ? "" : name );
c->c_client_addr = ch_strdup( addr );
free(c->c_client_addr);
c->c_client_addr = NULL;
}
+ if(c->c_authmech != NULL ) {
+ free(c->c_authmech);
+ c->c_authmech = NULL;
+ }
+ if(c->c_authstate != NULL ) {
+ free(c->c_authstate);
+ c->c_authstate = NULL;
+ }
if ( ber_pvt_sb_in_use(c->c_sb) ) {
int sd = ber_pvt_sb_get_desc(c->c_sb);
arg->co_op->o_protocol = conn->c_protocol;
+ arg->co_op->o_authtype = conn->c_authtype;
arg->co_op->o_authmech = conn->c_authmech != NULL
? ch_strdup( conn->c_authmech ) : NULL;
- arg->co_op->o_authtype = conn->c_authtype;
-
+
slap_op_add( &conn->c_ops, arg->co_op );
if(tag == LDAP_REQ_BIND) {