+ Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%d BIND dn=\"%s\" method=%ld\n",
+ op->o_connid, op->o_opid, ndn, (unsigned long) method, 0 );
+
+ if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
+ "do_bind: conn %d unknown version = %ld\n",
+ conn->c_connid, (unsigned long)version ));
+#else
+ Debug( LDAP_DEBUG_ANY, "do_bind: unknown version=%ld\n",
+ (unsigned long) version, 0, 0 );
+#endif
+ send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
+ NULL, "requested protocol version not supported", NULL, NULL );
+ goto cleanup;
+
+ } else if (( global_disallows & SLAP_DISALLOW_BIND_V2 ) &&
+ version < LDAP_VERSION3 )
+ {
+ send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
+ NULL, "requested protocol version not allowed", NULL, NULL );
+ goto cleanup;
+ }
+
+ /* we set connection version regardless of whether bind succeeds
+ * or not.
+ */
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+ conn->c_protocol = version;
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+ if ( method == LDAP_AUTH_SASL ) {
+ char *edn;
+ slap_ssf_t ssf = 0;
+
+ if ( version < LDAP_VERSION3 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
+ "do_bind: conn %d sasl with LDAPv%ld\n",
+ conn->c_connid, (unsigned long)version ));
+#else
+ Debug( LDAP_DEBUG_ANY, "do_bind: sasl with LDAPv%ld\n",
+ (unsigned long) version, 0, 0 );
+#endif
+ send_ldap_disconnect( conn, op,
+ LDAP_PROTOCOL_ERROR, "SASL bind requires LDAPv3" );
+ rc = SLAPD_DISCONNECT;
+ goto cleanup;
+ }
+
+ if( mech == NULL || *mech == '\0' ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
+ "do_bind: conn %d no SASL mechanism provided\n",
+ conn->c_connid ));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "do_bind: no sasl mechanism provided\n",
+ 0, 0, 0 );
+#endif
+ send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, "no SASL mechanism provided", NULL, NULL );
+ goto cleanup;
+ }
+
+ /* check restrictions */
+ rc = backend_check_restrictions( NULL, conn, op, mech, &text );
+ if( rc != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, rc,
+ NULL, text, NULL, NULL );
+ goto cleanup;
+ }
+
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+ if ( conn->c_sasl_bind_in_progress ) {
+ if((strcmp(conn->c_sasl_bind_mech, mech) != 0)) {
+ /* mechanism changed between bind steps */
+ slap_sasl_reset(conn);
+ }
+ } else {
+ conn->c_sasl_bind_mech = mech;
+ mech = NULL;
+ }
+ ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+ edn = NULL;
+ rc = slap_sasl_bind( conn, op, dn, ndn, &cred, &edn, &ssf );
+
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+ if( rc == LDAP_SUCCESS ) {
+ conn->c_dn = edn;
+ conn->c_authmech = conn->c_sasl_bind_mech;
+ conn->c_sasl_bind_mech = NULL;
+ conn->c_sasl_bind_in_progress = 0;
+
+ conn->c_sasl_ssf = ssf;
+ if( ssf > conn->c_ssf ) {
+ conn->c_ssf = ssf;
+ }
+
+ if( conn->c_dn != NULL ) {
+ ber_len_t max = sockbuf_max_incoming;
+ ber_sockbuf_ctrl( conn->c_sb,
+ LBER_SB_OPT_SET_MAX_INCOMING, &max );
+ }
+
+ } else if ( rc == LDAP_SASL_BIND_IN_PROGRESS ) {
+ conn->c_sasl_bind_in_progress = 1;