}
 
                if ( protocol < LDAP_VERSION3 ) {
-                       protocol = LDAP_VERSION3;
-                       /* Set LDAP version */
-                       ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
-                                       (const void *)&protocol );
+                       /* we should rather bail out... */
+                       rc = LDAP_UNWILLING_TO_PERFORM;
+                       *text = "invalid protocol version";
+               }
+
+               if ( rc == LDAP_SUCCESS ) {
+                       rc = ldap_start_tls( ld, NULL, NULL, &msgid );
                }
 
-               rc = ldap_start_tls( ld, NULL, NULL, &msgid );
                if ( rc == LDAP_SUCCESS ) {
                        LDAPMessage     *res = NULL;
                        struct timeval  tv;
 ldap_back_prepare_conn( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
 {
        ldapinfo_t      *li = (ldapinfo_t *)op->o_bd->be_private;
-       int             vers = op->o_protocol;
+       int             version;
        LDAP            *ld = NULL;
 #ifdef HAVE_TLS
        int             is_tls = op->o_conn->c_is_tls;
        /* Set LDAP version. This will always succeed: If the client
         * bound with a particular version, then so can we.
         */
-       if ( vers == 0 ) {
+       if ( li->li_version != 0 ) {
+               version = li->li_version;
+
+       } else if ( op->o_protocol != 0 ) {
+               version = op->o_protocol;
+
+       } else {
                /* assume it's an internal op; set to LDAPv3 */
-               vers = LDAP_VERSION3;
+               version = LDAP_VERSION3;
        }
-       ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&vers );
+       ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&version );
 
        /* automatically chase referrals ("chase-referrals [{yes|no}]" statement) */
        ldap_set_option( ld, LDAP_OPT_REFERRALS,
        int             msgid;
        int             rc;
 
+       /* don't proxyAuthz if protocol is not LDAPv3 */
+       switch ( li->li_version ) {
+       case LDAP_VERSION3:
+               break;
+
+       case 0:
+               if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
+                       break;
+               }
+               /* fall thru */
+
+       default:
+               goto done;
+       }
+
        if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
                ndn = op->o_conn->c_ndn;
 
 
        rs->sr_err = LDAP_SUCCESS;
 
+       /* don't proxyAuthz if protocol is not LDAPv3 */
+       switch ( li->li_version ) {
+       case LDAP_VERSION3:
+               break;
+
+       case 0:
+               if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
+                       break;
+               }
+               /* fall thru */
+
+       default:
+               goto done;
+       }
+
        /* FIXME: SASL/EXTERNAL over ldapi:// doesn't honor the authcID,
         * but if it is not set this test fails.  We need a different
         * means to detect if idassert is enabled */
 
        LDAP_BACK_CFG_IDLE_TIMEOUT,
        LDAP_BACK_CFG_CONN_TTL,
        LDAP_BACK_CFG_NETWORK_TIMEOUT,
+       LDAP_BACK_CFG_VERSION,
        LDAP_BACK_CFG_REWRITE,
 
        LDAP_BACK_CFG_LAST
                        "SYNTAX OMsDirectoryString "
                        "SINGLE-VALUE )",
                NULL, NULL },
+       { "protocol-version", "version", 2, 0, 0,
+               ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION,
+               ldap_back_cf_gen, "( OLcfgDbAt:3.18 "
+                       "NAME 'olcDbProtocolVersion' "
+                       "DESC 'protocol version' "
+                       "SYNTAX OMsInteger "
+                       "SINGLE-VALUE )",
+               NULL, NULL },
        { "suffixmassage", "[virtual]> <real", 2, 3, 0,
                ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
                ldap_back_cf_gen, NULL, NULL, NULL },
                        value_add_one( &c->rvalue_vals, &bv );
                        } break;
 
+               case LDAP_BACK_CFG_VERSION:
+                       if ( li->li_version == 0 ) {
+                               return 1;
+                       }
+
+                       c->value_int = li->li_version;
+                       break;
+
                default:
                        /* FIXME: we need to handle all... */
                        assert( 0 );
                        li->li_network_timeout = 0;
                        break;
 
+               case LDAP_BACK_CFG_VERSION:
+                       li->li_version = 0;
+                       break;
+
                default:
                        /* FIXME: we need to handle all... */
                        assert( 0 );
                li->li_network_timeout = (time_t)t;
                } break;
 
+       case LDAP_BACK_CFG_VERSION:
+               switch ( c->value_int ) {
+               case 0:
+               case LDAP_VERSION2:
+               case LDAP_VERSION3:
+                       li->li_version = c->value_int;
+                       break;
+
+               default:
+                       return 1;
+               }
+               break;
+
        case LDAP_BACK_CFG_REWRITE:
                snprintf( c->msg, sizeof( c->msg ),
                        "rewrite/remap capabilities have been moved "
 
        }
 
        if ( op->orr_newSup ) {
-               int     version = LDAP_VERSION3;
+               /* needs LDAPv3 */
+               switch ( li->li_version ) {
+               case LDAP_VERSION3:
+                       break;
+
+               case 0:
+                       if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
+                               break;
+                       }
+                       /* fall thru */
+
+               default:
+                       /* op->o_protocol cannot be anything but LDAPv3,
+                        * otherwise wouldn't be here */
+                       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                       send_ldap_result( op, rs );
+                       goto cleanup;
+               }
                
-               ldap_set_option( lc->lc_ld, LDAP_OPT_PROTOCOL_VERSION, &version );
                newSup = op->orr_newSup->bv_val;
        }
 
 
                        mi->mi_targets[ i ].mt_nretries = nretries;
                }
 
+       } else if ( strcasecmp( argv[ 0 ], "protocol-version" ) == 0 ) {
+               int     *version = mi->mi_ntargets ?
+                               &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_version
+                               : &mi->mi_version;
+
+               if ( argc != 2 ) {
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: need value in \"protocol-version <version>\"\n",
+                               fname, lineno, 0 );
+                       return 1;
+               }
+
+               if ( lutil_atou( version, argv[ 1 ] ) != 0 ) {
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: unable to parse version \"%s\" in \"protocol-version <version>\"\n",
+                               fname, lineno, argv[ 1 ] );
+                       return 1;
+               }
+
+               switch ( *version ) {
+               case 0:
+               case LDAP_VERSION2:
+               case LDAP_VERSION3:
+                       break;
+
+               default:
+                       Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: unsupported version \"%s\" in \"protocol-version <version>\"\n",
+                               fname, lineno, argv[ 1 ] );
+                       return 1;
+               }
+
        /* anything else */
        } else {
                return SLAP_CONF_UNKNOWN;
 
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
-       int                     vers;
+       int                     version;
        dncookie                dc;
        int                     isauthz = ( candidate == mc->mc_authz_target );
 
         * Set LDAP version. This will always succeed: If the client
         * bound with a particular version, then so can we.
         */
-       vers = op->o_conn->c_protocol;
-       ldap_set_option( msc->msc_ld, LDAP_OPT_PROTOCOL_VERSION, &vers );
+       if ( mt->mt_version != 0 ) {
+               version = mt->mt_version;
+
+       } else if ( op->o_conn->c_protocol != 0 ) {
+               version = op->o_conn->c_protocol;
+
+       } else {
+               version = LDAP_VERSION3;
+       }
+       ldap_set_option( msc->msc_ld, LDAP_OPT_PROTOCOL_VERSION, &version );
 
        /* automatically chase referrals ("chase-referrals [{yes|no}]" statement) */
        ldap_set_option( msc->msc_ld, LDAP_OPT_REFERRALS,
 
        dc.rs = rs;
 
        if ( op->orr_newSup ) {
-               int     version = LDAP_VERSION3;
 
                /*
                 * NOTE: the newParent, if defined, must be on the 
                 * feature from back-ldap
                 */
 
-               /* newSuperior needs LDAPv3; if we got here, we can safely
-                * enforce it */
-               ldap_set_option( mc->mc_conns[ candidate ].msc_ld,
-                               LDAP_OPT_PROTOCOL_VERSION, &version );
+               /* needs LDAPv3 */
+               switch ( mi->mi_targets[ candidate ].mt_version ) {
+               case LDAP_VERSION3:
+                       break;
+
+               case 0:
+                       if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
+                               break;
+                       }
+                       /* fall thru */
 
+               default:
+                       /* op->o_protocol cannot be anything but LDAPv3,
+                        * otherwise wouldn't be here */
+                       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                       maperr = 0;
+                       goto cleanup;
+               }
+               
                /*
                 * Rewrite the new superior, if defined and required
                 */