]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-ldap/config.c
fix NOOP return code (ITS#4563; I'll check and confirm it later; NOOP support might...
[openldap] / servers / slapd / back-ldap / config.c
index f1c76916cd48fe26a09fcbeae8fe7dada1e81fd1..02b475ca76fdaf1236c02cdfc6183fe4d4d19b12 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2003-2005 The OpenLDAP Foundation.
+ * Copyright 2003-2006 The OpenLDAP Foundation.
  * Portions Copyright 1999-2003 Howard Chu.
  * Portions Copyright 2000-2003 Pierangelo Masarati.
  * All rights reserved.
@@ -60,6 +60,12 @@ enum {
        LDAP_BACK_CFG_T_F,
        LDAP_BACK_CFG_WHOAMI,
        LDAP_BACK_CFG_TIMEOUT,
+       LDAP_BACK_CFG_IDLE_TIMEOUT,
+       LDAP_BACK_CFG_CONN_TTL,
+       LDAP_BACK_CFG_NETWORK_TIMEOUT,
+       LDAP_BACK_CFG_VERSION,
+       LDAP_BACK_CFG_SINGLECONN,
+       LDAP_BACK_CFG_CANCEL,
        LDAP_BACK_CFG_REWRITE,
 
        LDAP_BACK_CFG_LAST
@@ -214,6 +220,54 @@ static ConfigTable ldapcfg[] = {
                        "SYNTAX OMsDirectoryString "
                        "SINGLE-VALUE )",
                NULL, NULL },
+       { "idle-timeout", "timeout", 2, 0, 0,
+               ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT,
+               ldap_back_cf_gen, "( OLcfgDbAt:3.15 "
+                       "NAME 'olcDbIdleTimeout' "
+                       "DESC 'connection idle timeout' "
+                       "SYNTAX OMsDirectoryString "
+                       "SINGLE-VALUE )",
+               NULL, NULL },
+       { "conn-ttl", "ttl", 2, 0, 0,
+               ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL,
+               ldap_back_cf_gen, "( OLcfgDbAt:3.16 "
+                       "NAME 'olcDbConnTtl' "
+                       "DESC 'connection ttl' "
+                       "SYNTAX OMsDirectoryString "
+                       "SINGLE-VALUE )",
+               NULL, NULL },
+       { "network-timeout", "timeout", 2, 0, 0,
+               ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT,
+               ldap_back_cf_gen, "( OLcfgDbAt:3.17 "
+                       "NAME 'olcDbNetworkTimeout' "
+                       "DESC 'connection network timeout' "
+                       "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 },
+       { "single-conn", "TRUE/FALSE", 2, 0, 0,
+               ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN,
+               ldap_back_cf_gen, "( OLcfgDbAt:3.19 "
+                       "NAME 'olcDbSingleConn' "
+                       "DESC 'cache a single connection per identity' "
+                       "SYNTAX OMsBoolean "
+                       "SINGLE-VALUE )",
+               NULL, NULL },
+       { "cancel", "ABANDON|ignore|exop", 2, 0, 0,
+               ARG_MAGIC|LDAP_BACK_CFG_CANCEL,
+               ldap_back_cf_gen, "( OLcfgDbAt:3.20 "
+                       "NAME 'olcDbCancel' "
+                       "DESC 'abandon/ignore/exop operations when appropriate' "
+                       "SYNTAX OMsDirectoryString "
+                       "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 },
@@ -247,6 +301,9 @@ static ConfigOCs ldapocs[] = {
                        "$ olcDbTFSupport "
                        "$ olcDbProxyWhoAmI "
                        "$ olcDbTimeout "
+                       "$ olcDbIdleTimeout "
+                       "$ olcDbSingleConn "
+                       "$ olcDbCancel "
                ") )",
                        Cft_Database, ldapcfg},
        { NULL, 0, NULL }
@@ -270,12 +327,20 @@ static slap_verbmasks tls_mode[] = {
 };
 
 static slap_verbmasks t_f_mode[] = {
-       { BER_BVC( "yes" ),             LDAP_BACK_F_SUPPORT_T_F },
-       { BER_BVC( "discover" ),        LDAP_BACK_F_SUPPORT_T_F_DISCOVER },
+       { BER_BVC( "yes" ),             LDAP_BACK_F_T_F },
+       { BER_BVC( "discover" ),        LDAP_BACK_F_T_F_DISCOVER },
        { BER_BVC( "no" ),              LDAP_BACK_F_NONE },
        { BER_BVNULL,                   0 }
 };
 
+static slap_verbmasks cancel_mode[] = {
+       { BER_BVC( "ignore" ),          LDAP_BACK_F_CANCEL_IGNORE },
+       { BER_BVC( "exop" ),            LDAP_BACK_F_CANCEL_EXOP },
+       { BER_BVC( "exop-discover" ),   LDAP_BACK_F_CANCEL_EXOP_DISCOVER },
+       { BER_BVC( "abandon" ),         LDAP_BACK_F_CANCEL_ABANDON },
+       { BER_BVNULL,                   0 }
+};
+
 static slap_cf_aux_table timeout_table[] = {
        { BER_BVC("add="), 0 * sizeof( time_t ), 'u', 0, NULL },
        { BER_BVC("delete="), 1 * sizeof( time_t ), 'u', 0, NULL },
@@ -295,6 +360,10 @@ ldap_back_cf_gen( ConfigArgs *c )
                struct berval   bv = BER_BVNULL;
                rc = 0;
 
+               if ( li == NULL ) {
+                       return 1;
+               }
+
                switch( c->type ) {
                case LDAP_BACK_CFG_URI:
                        if ( li->li_uri != NULL ) {
@@ -310,14 +379,8 @@ ldap_back_cf_gen( ConfigArgs *c )
 
                case LDAP_BACK_CFG_TLS:
                        enum_to_verb( tls_mode, ( li->li_flags & LDAP_BACK_F_TLS_MASK ), &bv );
-                       if ( BER_BVISNULL( &bv ) ) {
-                               /* there's something wrong... */
-                               assert( 0 );
-                               rc = 1;
-
-                       } else {
-                               value_add_one( &c->rvalue_vals, &bv );
-                       }
+                       assert( !BER_BVISNULL( &bv ) );
+                       value_add_one( &c->rvalue_vals, &bv );
                        break;
 
                case LDAP_BACK_CFG_ACL_AUTHCDN:
@@ -330,9 +393,13 @@ ldap_back_cf_gen( ConfigArgs *c )
                case LDAP_BACK_CFG_ACL_BIND: {
                        int     i;
 
+                       if ( li->li_acl_authmethod == LDAP_AUTH_NONE ) {
+                               return 1;
+                       }
+
                        bindconf_unparse( &li->li_acl, &bv );
 
-                       for ( i = 0; isspace( bv.bv_val[ i ] ); i++ )
+                       for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ )
                                /* count spaces */ ;
 
                        if ( i ) {
@@ -373,6 +440,10 @@ ldap_back_cf_gen( ConfigArgs *c )
                        struct berval   bc = BER_BVNULL;
                        char            *ptr;
 
+                       if ( li->li_idassert_authmethod == LDAP_AUTH_NONE ) {
+                               return 1;
+                       }
+
                        if ( li->li_idassert_authmethod != LDAP_AUTH_NONE ) {
                                ber_len_t       len;
 
@@ -419,7 +490,7 @@ ldap_back_cf_gen( ConfigArgs *c )
                                        (void)lutil_strcopy( ptr, "authz=native" );
                                }
 
-                               len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override" );
+                               len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround" );
                                /* flags */
                                if ( !BER_BVISEMPTY( &bv ) ) {
                                        len += STRLENOF( " " );
@@ -445,6 +516,13 @@ ldap_back_cf_gen( ConfigArgs *c )
                                        ptr = lutil_strcopy( ptr, ",override" );
                                }
 
+                               if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
+                                       ptr = lutil_strcopy( ptr, ",obsolete-proxy-authz" );
+
+                               } else if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
+                                       ptr = lutil_strcopy( ptr, ",obsolete-encoding-workaround" );
+                               }
+
                                bv.bv_len = ( ptr - bv.bv_val );
                                /* end-of-flags */
                        }
@@ -463,7 +541,7 @@ ldap_back_cf_gen( ConfigArgs *c )
                                bv.bv_len = ptr - bv.bv_val;
 
                        } else {
-                               for ( i = 0; isspace( bc.bv_val[ i ] ); i++ )
+                               for ( i = 0; isspace( (unsigned char) bc.bv_val[ i ] ); i++ )
                                        /* count spaces */ ;
 
                                if ( i ) {
@@ -488,7 +566,7 @@ ldap_back_cf_gen( ConfigArgs *c )
                        break;
 
                case LDAP_BACK_CFG_T_F:
-                       enum_to_verb( t_f_mode, (li->li_flags & LDAP_BACK_F_SUPPORT_T_F_MASK), &bv );
+                       enum_to_verb( t_f_mode, (li->li_flags & LDAP_BACK_F_T_F_MASK2), &bv );
                        if ( BER_BVISNULL( &bv ) ) {
                                /* there's something wrong... */
                                assert( 0 );
@@ -506,22 +584,100 @@ ldap_back_cf_gen( ConfigArgs *c )
                case LDAP_BACK_CFG_TIMEOUT:
                        BER_BVZERO( &bv );
 
+                       for ( i = 0; i < LDAP_BACK_OP_LAST; i++ ) {
+                               if ( li->li_timeout[ i ] != 0 ) {
+                                       break;
+                               }
+                       }
+
+                       if ( i == LDAP_BACK_OP_LAST ) {
+                               return 1;
+                       }
+
                        slap_cf_aux_table_unparse( li->li_timeout, &bv, timeout_table );
 
-                       if ( !BER_BVISNULL( &bv ) ) {   
-                               for ( i = 0; isspace( bv.bv_val[ i ] ); i++ )
-                                       /* count spaces */ ;
+                       if ( BER_BVISNULL( &bv ) ) {
+                               return 1;
+                       }
 
-                               if ( i ) {
-                                       bv.bv_len -= i;
-                                       AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
-                                               bv.bv_len + 1 );
-                               }
+                       for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ )
+                               /* count spaces */ ;
 
-                               ber_bvarray_add( &c->rvalue_vals, &bv );
+                       if ( i ) {
+                               bv.bv_len -= i;
+                               AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
+                                       bv.bv_len + 1 );
                        }
+
+                       ber_bvarray_add( &c->rvalue_vals, &bv );
                        break;
 
+               case LDAP_BACK_CFG_IDLE_TIMEOUT: {
+                       char    buf[ SLAP_TEXT_BUFLEN ];
+
+                       if ( li->li_idle_timeout == 0 ) {
+                               return 1;
+                       }
+
+                       lutil_unparse_time( buf, sizeof( buf ), li->li_idle_timeout );
+                       ber_str2bv( buf, 0, 0, &bv );
+                       value_add_one( &c->rvalue_vals, &bv );
+                       } break;
+
+               case LDAP_BACK_CFG_CONN_TTL: {
+                       char    buf[ SLAP_TEXT_BUFLEN ];
+
+                       if ( li->li_conn_ttl == 0 ) {
+                               return 1;
+                       }
+
+                       lutil_unparse_time( buf, sizeof( buf ), li->li_conn_ttl );
+                       ber_str2bv( buf, 0, 0, &bv );
+                       value_add_one( &c->rvalue_vals, &bv );
+                       } break;
+
+               case LDAP_BACK_CFG_NETWORK_TIMEOUT: {
+                       char    buf[ SLAP_TEXT_BUFLEN ];
+
+                       if ( li->li_network_timeout == 0 ) {
+                               return 1;
+                       }
+
+                       snprintf( buf, sizeof( buf ), "%ld",
+                               (long)li->li_network_timeout );
+                       ber_str2bv( buf, 0, 0, &bv );
+                       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;
+
+               case LDAP_BACK_CFG_SINGLECONN:
+                       c->value_int = LDAP_BACK_SINGLECONN( li );
+                       break;
+
+               case LDAP_BACK_CFG_CANCEL: {
+                       slap_mask_t     mask = LDAP_BACK_F_CANCEL_MASK2;
+
+                       if ( LDAP_BACK_CANCEL_DISCOVER( li ) ) {
+                               mask &= ~LDAP_BACK_F_CANCEL_EXOP;
+                       }
+                       enum_to_verb( cancel_mode, (li->li_flags & mask), &bv );
+                       if ( BER_BVISNULL( &bv ) ) {
+                               /* there's something wrong... */
+                               assert( 0 );
+                               rc = 1;
+
+                       } else {
+                               value_add_one( &c->rvalue_vals, &bv );
+                       }
+                       } break;
+
                default:
                        /* FIXME: we need to handle all... */
                        assert( 0 );
@@ -590,6 +746,7 @@ ldap_back_cf_gen( ConfigArgs *c )
                case LDAP_BACK_CFG_CHASE:
                case LDAP_BACK_CFG_T_F:
                case LDAP_BACK_CFG_WHOAMI:
+               case LDAP_BACK_CFG_CANCEL:
                        rc = 1;
                        break;
 
@@ -599,6 +756,26 @@ ldap_back_cf_gen( ConfigArgs *c )
                        }
                        break;
 
+               case LDAP_BACK_CFG_IDLE_TIMEOUT:
+                       li->li_idle_timeout = 0;
+                       break;
+
+               case LDAP_BACK_CFG_CONN_TTL:
+                       li->li_conn_ttl = 0;
+                       break;
+
+               case LDAP_BACK_CFG_NETWORK_TIMEOUT:
+                       li->li_network_timeout = 0;
+                       break;
+
+               case LDAP_BACK_CFG_VERSION:
+                       li->li_version = 0;
+                       break;
+
+               case LDAP_BACK_CFG_SINGLECONN:
+                       li->li_flags &= ~LDAP_BACK_F_SINGLECONN;
+                       break;
+
                default:
                        /* FIXME: we need to handle all... */
                        assert( 0 );
@@ -614,14 +791,6 @@ ldap_back_cf_gen( ConfigArgs *c )
                char            **urllist = NULL;
                int             urlrc = LDAP_URL_SUCCESS, i;
 
-               if ( c->argc != 2 ) {
-                       fprintf( stderr, "%s: line %d: "
-                                       "missing uri "
-                                       "in \"uri <uri>\" line\n",
-                                       c->fname, c->lineno );
-                       return 1;
-               }
-
                if ( li->li_uri != NULL ) {
                        ch_free( li->li_uri );
                        li->li_uri = NULL;
@@ -632,7 +801,7 @@ ldap_back_cf_gen( ConfigArgs *c )
                }
 
                /* PARANOID: DN and more are not required nor allowed */
-               urlrc = ldap_url_parselist_ext( &lud, c->argv[ 1 ], ", \t" );
+               urlrc = ldap_url_parselist_ext( &lud, c->argv[ 1 ], ", \t", LDAP_PVT_URL_PARSE_NONE );
                if ( urlrc != LDAP_URL_SUCCESS ) {
                        char    *why;
 
@@ -671,10 +840,11 @@ ldap_back_cf_gen( ConfigArgs *c )
                                why = "unknown reason";
                                break;
                        }
-                       fprintf( stderr, "%s: line %d: "
+                       snprintf( c->msg, sizeof( c->msg),
                                        "unable to parse uri \"%s\" "
-                                       "in \"uri <uri>\" line: %s\n",
-                                       c->fname, c->lineno, c->value_string, why );
+                                       "in \"uri <uri>\" line: %s",
+                                       c->value_string, why );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                        urlrc = 1;
                        goto done_url;
                }
@@ -690,12 +860,13 @@ ldap_back_cf_gen( ConfigArgs *c )
                                        || tmpludp->lud_filter != NULL
                                        || tmpludp->lud_exts != NULL )
                        {
-                               fprintf( stderr, "%s: line %d: "
+                               snprintf( c->msg, sizeof( c->msg ),
                                                "warning, only protocol, "
                                                "host and port allowed "
                                                "in \"uri <uri>\" statement "
-                                               "for uri #%d of \"%s\"\n",
-                                               c->fname, c->lineno, i, c->value_string );
+                                               "for uri #%d of \"%s\"",
+                                               i, c->argv[ 1 ] );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                        }
                }
 
@@ -724,11 +895,12 @@ ldap_back_cf_gen( ConfigArgs *c )
                        urllist[ i ]  = ldap_url_desc2str( &tmplud );
 
                        if ( urllist[ i ] == NULL ) {
-                               fprintf( stderr, "%s: line %d: "
+                               snprintf( c->msg, sizeof( c->msg),
                                        "unable to rebuild uri "
                                        "in \"uri <uri>\" statement "
-                                       "for \"%s\"\n",
-                                       c->fname, c->lineno, c->argv[ 1 ] );
+                                       "for \"%s\"",
+                                       c->argv[ 1 ] );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                                urlrc = 1;
                                goto done_url;
                        }
@@ -777,10 +949,11 @@ done_url:;
                        break;
 
                default:
-                       fprintf( stderr, "%s: line %d: "
+                       snprintf( c->msg, sizeof( c->msg),
                                "\"acl-authcDN <DN>\" incompatible "
-                               "with auth method %d.",
-                               c->fname, c->lineno, li->li_acl_authmethod );
+                               "with auth method %d",
+                               li->li_acl_authmethod );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                        return 1;
                }
                if ( !BER_BVISNULL( &li->li_acl_authcDN ) ) {
@@ -802,10 +975,11 @@ done_url:;
                        break;
 
                default:
-                       fprintf( stderr, "%s: line %d: "
+                       snprintf( c->msg, sizeof( c->msg ),
                                "\"acl-passwd <cred>\" incompatible "
-                               "with auth method %d.",
-                               c->fname, c->lineno, li->li_acl_authmethod );
+                               "with auth method %d",
+                               li->li_acl_authmethod );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                        return 1;
                }
                if ( !BER_BVISNULL( &li->li_acl_passwd ) ) {
@@ -875,6 +1049,28 @@ done_url:;
                                } else if ( strcasecmp( c->argv[ i ], "non-prescriptive" ) == 0 ) {
                                        li->li_idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
 
+                               } else if ( strcasecmp( c->argv[ i ], "obsolete-proxy-authz" ) == 0 ) {
+                                       if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
+                                               Debug( LDAP_DEBUG_ANY,
+                                                               "%s: line %d: \"obsolete-proxy-authz\" flag "
+                                                       "in \"idassert-mode <args>\" "
+                                                       "incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n",
+                                                       c->fname, c->lineno, 0 );
+                                               return 1;
+                                       }
+                                       li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ;
+
+                               } else if ( strcasecmp( c->argv[ i ], "obsolete-encoding-workaround" ) == 0 ) {
+                                       if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
+                                               Debug( LDAP_DEBUG_ANY,
+                                                               "%s: line %d: \"obsolete-encoding-workaround\" flag "
+                                                       "in \"idassert-mode <args>\" "
+                                                       "incompatible with previously issued \"obsolete-proxy-authz\" flag.\n",
+                                                       c->fname, c->lineno, 0 );
+                                               return 1;
+                                       }
+                                       li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND;
+
                                } else {
                                        Debug( LDAP_DEBUG_ANY,
                                                "%s: line %d: unknown flag #%d "
@@ -897,10 +1093,11 @@ done_url:;
                        break;
 
                default:
-                       fprintf( stderr, "%s: line %d: "
+                       snprintf( c->msg, sizeof( c->msg ),
                                "\"idassert-authcDN <DN>\" incompatible "
-                               "with auth method %d.",
-                               c->fname, c->lineno, li->li_idassert_authmethod );
+                               "with auth method %d",
+                               li->li_idassert_authmethod );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                        return 1;
                }
                if ( !BER_BVISNULL( &li->li_idassert_authcDN ) ) {
@@ -922,10 +1119,11 @@ done_url:;
                        break;
 
                default:
-                       fprintf( stderr, "%s: line %d: "
+                       snprintf( c->msg, sizeof( c->msg ),
                                "\"idassert-passwd <cred>\" incompatible "
-                               "with auth method %d.",
-                               c->fname, c->lineno, li->li_idassert_authmethod );
+                               "with auth method %d",
+                               li->li_idassert_authmethod );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                        return 1;
                }
                if ( !BER_BVISNULL( &li->li_idassert_passwd ) ) {
@@ -936,31 +1134,27 @@ done_url:;
 
        case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
                struct berval   bv;
-#ifdef SLAP_AUTHZ_SYNTAX
                struct berval   in;
                int             rc;
 
                ber_str2bv( c->argv[ 1 ], 0, 0, &in );
                rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
                if ( rc != LDAP_SUCCESS ) {
-                       fprintf( stderr, "%s: %d: "
+                       snprintf( c->msg, sizeof( c->msg ),
                                "\"idassert-authzFrom <authz>\": "
-                               "invalid syntax.\n",
-                               c->fname, c->lineno );
+                               "invalid syntax" );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                        return 1;
                }
-#else /* !SLAP_AUTHZ_SYNTAX */
-               ber_str2bv( c->argv[ 1 ], 0, 1, &bv );
-#endif /* !SLAP_AUTHZ_SYNTAX */
                ber_bvarray_add( &li->li_idassert_authz, &bv );
                } break;
 
        case LDAP_BACK_CFG_IDASSERT_METHOD:
                /* no longer supported */
-               fprintf( stderr, "%s: %d: "
+               snprintf( c->msg, sizeof( c->msg ),
                        "\"idassert-method <args>\": "
-                       "no longer supported; use \"idassert-bind\".\n",
-                       c->fname, c->lineno );
+                       "no longer supported; use \"idassert-bind\"" );
+               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                return 1;
 
        case LDAP_BACK_CFG_IDASSERT_BIND:
@@ -971,10 +1165,11 @@ done_url:;
 
                                j = verb_to_mask( argvi, idassert_mode );
                                if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) {
-                                       fprintf( stderr, "%s: %d: "
+                                       snprintf( c->msg, sizeof( c->msg ),
                                                "\"idassert-bind <args>\": "
-                                               "unknown mode \"%s\".\n",
-                                               c->fname, c->lineno, argvi );
+                                               "unknown mode \"%s\"",
+                                               argvi );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                                        return 1;
                                }
 
@@ -985,11 +1180,11 @@ done_url:;
 
                                if ( strcasecmp( argvi, "native" ) == 0 ) {
                                        if ( li->li_idassert_authmethod != LDAP_AUTH_SASL ) {
-                                               fprintf( stderr, "%s: %d: "
+                                               snprintf( c->msg, sizeof( c->msg ),
                                                        "\"idassert-bind <args>\": "
                                                        "authz=\"native\" incompatible "
-                                                       "with auth method.\n",
-                                                       c->fname, c->lineno );
+                                                       "with auth method" );
+                                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                                                return 1;
                                        }
                                        li->li_idassert_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
@@ -998,27 +1193,30 @@ done_url:;
                                        li->li_idassert_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
 
                                } else {
-                                       fprintf( stderr, "%s: %d: "
+                                       snprintf( c->msg, sizeof( c->msg ),
                                                "\"idassert-bind <args>\": "
-                                               "unknown authz \"%s\".\n",
-                                               c->fname, c->lineno, argvi );
+                                               "unknown authz \"%s\"",
+                                               argvi );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                                        return 1;
                                }
 
                        } else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) {
                                char    *argvi = c->argv[ i ] + STRLENOF( "flags=" );
                                char    **flags = ldap_str2charray( argvi, "," );
-                               int     j;
+                               int     j, err = 0;
 
                                if ( flags == NULL ) {
-                                       fprintf( stderr, "%s: %d: "
+                                       snprintf( c->msg, sizeof( c->msg ),
                                                "\"idassert-bind <args>\": "
-                                               "unable to parse flags \"%s\".\n",
-                                               c->fname, c->lineno, argvi );
+                                               "unable to parse flags \"%s\"",
+                                               argvi );
+                                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                                        return 1;
                                }
 
                                for ( j = 0; flags[ j ] != NULL; j++ ) {
+
                                        if ( strcasecmp( flags[ j ], "override" ) == 0 ) {
                                                li->li_idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
 
@@ -1028,16 +1226,49 @@ done_url:;
                                        } else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) {
                                                li->li_idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
 
+                                       } else if ( strcasecmp( flags[ j ], "obsolete-proxy-authz" ) == 0 ) {
+                                               if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
+                                                       Debug( LDAP_DEBUG_ANY,
+                                                                       "%s: line %d: \"obsolete-proxy-authz\" flag "
+                                                                       "in \"idassert-mode <args>\" "
+                                                                       "incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n",
+                                                                       c->fname, c->lineno, 0 );
+                                                       err = 1;
+                                                       break;
+
+                                               } else {
+                                                       li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ;
+                                               }
+
+                                       } else if ( strcasecmp( flags[ j ], "obsolete-encoding-workaround" ) == 0 ) {
+                                               if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
+                                                       Debug( LDAP_DEBUG_ANY,
+                                                                       "%s: line %d: \"obsolete-encoding-workaround\" flag "
+                                                               "in \"idassert-mode <args>\" "
+                                                               "incompatible with previously issued \"obsolete-proxy-authz\" flag.\n",
+                                                               c->fname, c->lineno, 0 );
+                                                       err = 1;
+                                                       break;
+
+                                               } else {
+                                                       li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND;
+                                               }
+
                                        } else {
-                                               fprintf( stderr, "%s: %d: "
+                                               snprintf( c->msg, sizeof( c->msg ),
                                                        "\"idassert-bind <args>\": "
-                                                       "unknown flag \"%s\".\n",
-                                                       c->fname, c->lineno, flags[ j ] );
-                                               return 1;
+                                                       "unknown flag \"%s\"",
+                                                       flags[ j ] );
+                                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                                               err = 1;
+                                               break;
                                        }
                                }
 
                                ldap_charray_free( flags );
+                               if ( err ) {
+                                       return 1;
+                               }
 
                        } else if ( bindconf_parse( c->argv[ i ], &li->li_idassert ) ) {
                                return 1;
@@ -1063,14 +1294,41 @@ done_url:;
                }
                break;
 
-       case LDAP_BACK_CFG_T_F:
+       case LDAP_BACK_CFG_T_F: {
+               slap_mask_t             mask;
+
                i = verb_to_mask( c->argv[1], t_f_mode );
                if ( BER_BVISNULL( &t_f_mode[i].word ) ) {
                        return 1;
                }
-               li->li_flags &= ~LDAP_BACK_F_SUPPORT_T_F_MASK;
-               li->li_flags |= t_f_mode[i].mask;
-               break;
+
+               mask = t_f_mode[i].mask;
+
+               if ( LDAP_BACK_ISOPEN( li )
+                       && mask == LDAP_BACK_F_T_F_DISCOVER
+                       && !LDAP_BACK_T_F( li ) )
+               {
+                       int             rc;
+
+                       if ( li->li_uri == NULL ) {
+                               snprintf( c->msg, sizeof( c->msg ),
+                                       "need URI to discover \"cancel\" support "
+                                       "in \"cancel exop-discover\"" );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               return 1;
+                       }
+
+                       rc = slap_discover_feature( li->li_uri, li->li_version,
+                                       slap_schema.si_ad_supportedFeatures->ad_cname.bv_val,
+                                       LDAP_FEATURE_ABSOLUTE_FILTERS );
+                       if ( rc == LDAP_COMPARE_TRUE ) {
+                               mask |= LDAP_BACK_F_T_F;
+                       }
+               }
+
+               li->li_flags &= ~LDAP_BACK_F_T_F_MASK2;
+               li->li_flags |= mask;
+               } break;
 
        case LDAP_BACK_CFG_WHOAMI:
                if ( c->argc == 1 || c->value_int ) {
@@ -1084,12 +1342,8 @@ done_url:;
                break;
 
        case LDAP_BACK_CFG_TIMEOUT:
-               if ( c->argc < 2 ) {
-                       return 1;
-               }
-
                for ( i = 1; i < c->argc; i++ ) {
-                       if ( isdigit( c->argv[ i ][ 0 ] ) ) {
+                       if ( isdigit( (unsigned char) c->argv[ i ][ 0 ] ) ) {
                                int             j;
                                unsigned        u;
 
@@ -1110,13 +1364,110 @@ done_url:;
                }
                break;
 
+       case LDAP_BACK_CFG_IDLE_TIMEOUT: {
+               unsigned long   t;
+
+               if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
+                       snprintf( c->msg, sizeof( c->msg),
+                               "unable to parse idle timeout \"%s\"",
+                               c->argv[ 1 ] );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       return 1;
+               }
+               li->li_idle_timeout = (time_t)t;
+               } break;
+
+       case LDAP_BACK_CFG_CONN_TTL: {
+               unsigned long   t;
+
+               if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
+                       snprintf( c->msg, sizeof( c->msg),
+                               "unable to parse conn ttl\"%s\"",
+                               c->argv[ 1 ] );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       return 1;
+               }
+               li->li_conn_ttl = (time_t)t;
+               } break;
+
+       case LDAP_BACK_CFG_NETWORK_TIMEOUT: {
+               unsigned long   t;
+
+               if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
+                       snprintf( c->msg, sizeof( c->msg),
+                               "unable to parse network timeout \"%s\"",
+                               c->argv[ 1 ] );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       return 1;
+               }
+               li->li_network_timeout = (time_t)t;
+               } break;
+
+       case LDAP_BACK_CFG_VERSION:
+               if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) {
+                       snprintf( c->msg, sizeof( c->msg ),
+                               "unsupported version \"%s\" "
+                               "in \"protocol-version <version>\"",
+                               c->argv[ 1 ] );
+                       Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                       return 1;
+               }
+
+               li->li_version = c->value_int;
+               break;
+
+       case LDAP_BACK_CFG_SINGLECONN:
+               if ( c->value_int ) {
+                       li->li_flags |= LDAP_BACK_F_SINGLECONN;
+
+               } else {
+                       li->li_flags &= ~LDAP_BACK_F_SINGLECONN;
+               }
+               break;
+
+       case LDAP_BACK_CFG_CANCEL: {
+               slap_mask_t             mask;
+
+               i = verb_to_mask( c->argv[1], cancel_mode );
+               if ( BER_BVISNULL( &cancel_mode[i].word ) ) {
+                       return 1;
+               }
+
+               mask = cancel_mode[i].mask;
+
+               if ( LDAP_BACK_ISOPEN( li )
+                       && mask == LDAP_BACK_F_CANCEL_EXOP_DISCOVER
+                       && !LDAP_BACK_CANCEL( li ) )
+               {
+                       int             rc;
+
+                       if ( li->li_uri == NULL ) {
+                               snprintf( c->msg, sizeof( c->msg ),
+                                       "need URI to discover \"cancel\" support "
+                                       "in \"cancel exop-discover\"" );
+                               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
+                               return 1;
+                       }
+
+                       rc = slap_discover_feature( li->li_uri, li->li_version,
+                                       slap_schema.si_ad_supportedExtension->ad_cname.bv_val,
+                                       LDAP_EXOP_CANCEL );
+                       if ( rc == LDAP_COMPARE_TRUE ) {
+                               mask |= LDAP_BACK_F_CANCEL_EXOP;
+                       }
+               }
+
+               li->li_flags &= ~LDAP_BACK_F_CANCEL_MASK2;
+               li->li_flags |= mask;
+               } break;
+
        case LDAP_BACK_CFG_REWRITE:
-               fprintf( stderr, "%s: line %d: "
+               snprintf( c->msg, sizeof( c->msg ),
                        "rewrite/remap capabilities have been moved "
                        "to the \"rwm\" overlay; see slapo-rwm(5) "
                        "for details (hint: add \"overlay rwm\" "
-                       "and prefix all directives with \"rwm-\").\n",
-                       c->fname, c->lineno );
+                       "and prefix all directives with \"rwm-\")" );
+               Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                return 1;
                
        default:
@@ -1228,7 +1579,7 @@ ldap_back_exop_whoami(
 retry:
                rs->sr_err = ldap_whoami( lc->lc_ld, ctrls, NULL, &msgid );
                if ( rs->sr_err == LDAP_SUCCESS ) {
-                       if ( ldap_result( lc->lc_ld, msgid, 1, NULL, &res ) == -1 ) {
+                       if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, NULL, &res ) == -1 ) {
                                ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER,
                                        &rs->sr_err );
                                if ( rs->sr_err == LDAP_SERVER_DOWN && doretry ) {