]> git.sur5r.net Git - openldap/commitdiff
Sync with HEAD
authorKurt Zeilenga <kurt@openldap.org>
Fri, 28 Jan 2005 18:29:47 +0000 (18:29 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Fri, 28 Jan 2005 18:29:47 +0000 (18:29 +0000)
36 files changed:
clients/tools/common.c
clients/tools/common.h
clients/tools/ldapsearch.c
doc/man/man5/slapd-bdb.5
include/ldap.h
include/slapi-plugin.h
libraries/libldap/request.c
libraries/libldap/url.c
servers/slapd/back-bdb/config.c
servers/slapd/back-bdb/init.c
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/chain.c
servers/slapd/back-ldap/search.c
servers/slapd/back-meta/add.c
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/compare.c
servers/slapd/back-meta/config.c
servers/slapd/back-meta/delete.c
servers/slapd/back-meta/modify.c
servers/slapd/back-meta/modrdn.c
servers/slapd/back-meta/search.c
servers/slapd/back-relay/init.c
servers/slapd/backend.c
servers/slapd/backover.c
servers/slapd/compare.c
servers/slapd/controls.c
servers/slapd/filterentry.c
servers/slapd/frontend.c
servers/slapd/main.c
servers/slapd/matchedValues.c
servers/slapd/mr.c
servers/slapd/overlays/ppolicy.c
servers/slapd/overlays/syncprov.c
servers/slapd/proto-slap.h
servers/slapd/slap.h
servers/slapd/slapcommon.c

index 415be46b9dc7bcfd6b1180a90a5d8e1d9cf6445c..39c6586d30e6d352124c66f775f11e17173c0162 100644 (file)
@@ -80,6 +80,12 @@ int   protocol = -1;
 int   verbose = 0;
 int   version = 0;
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+int chaining = 0;
+static int chainingResolve = -1;
+static int chainingContinuation = -1;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 /* Set in main() */
 char *prog = NULL;
 
@@ -107,6 +113,11 @@ N_("             [!]noop\n")
 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
 N_("             ppolicy\n")
 #endif
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+N_("             [!]chaining[=<resolveBehavior>[/<continuationBehavior>]]\n")
+N_("                     one of \"chainingPreferred\", \"chainingRequired\",\n")
+N_("                     \"referralsPreferred\", \"referralsRequired\"\n")
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 N_("             [!]postread[=<attrs>]  (a comma-separated attribute list)\n")
 N_("             [!]preread[=<attrs>]   (a comma-separated attribute list)\n"),
 N_("  -f file    read operations from `file'\n"),
@@ -286,6 +297,52 @@ tool_args( int argc, char **argv )
                                postread = 1 + crit;
                                postread_attrs = cvalue;
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+                       } else if ( strcasecmp( control, "chaining" ) == 0 ) {
+                               chaining = 1 + crit;
+
+                               if ( cvalue != NULL ) {
+                                       char    *continuation;
+
+                                       continuation = strchr( cvalue, '/' );
+                                       if ( continuation ) {
+                                               /* FIXME: this makes sense only in searches */
+                                               *continuation++ = '\0';
+                                               if ( strcasecmp( continuation, "chainingPreferred" ) == 0 ) {
+                                                       chainingContinuation = LDAP_CHAINING_PREFERRED;
+                                               } else if ( strcasecmp( continuation, "chainingRequired" ) == 0 ) {
+                                                       chainingContinuation = LDAP_CHAINING_REQUIRED;
+                                               } else if ( strcasecmp( continuation, "referralsPreferred" ) == 0 ) {
+                                                       chainingContinuation = LDAP_REFERRALS_PREFERRED;
+                                               } else if ( strcasecmp( continuation, "referralsRequired" ) == 0 ) {
+                                                       chainingContinuation = LDAP_REFERRALS_REQUIRED;
+                                               } else {
+                                                       fprintf( stderr,
+                                                               "chaining behavior control "
+                                                               "continuation value \"%s\" invalid\n",
+                                                               continuation );
+                                                       exit( EXIT_FAILURE );
+                                               }
+                                       }
+       
+                                       if ( strcasecmp( cvalue, "chainingPreferred" ) == 0 ) {
+                                               chainingResolve = LDAP_CHAINING_PREFERRED;
+                                       } else if ( strcasecmp( cvalue, "chainingRequired" ) == 0 ) {
+                                               chainingResolve = LDAP_CHAINING_REQUIRED;
+                                       } else if ( strcasecmp( cvalue, "referralsPreferred" ) == 0 ) {
+                                               chainingResolve = LDAP_REFERRALS_PREFERRED;
+                                       } else if ( strcasecmp( cvalue, "referralsRequired" ) == 0 ) {
+                                               chainingResolve = LDAP_REFERRALS_REQUIRED;
+                                       } else {
+                                               fprintf( stderr,
+                                                       "chaining behavior control "
+                                                       "resolve value \"%s\" invalid\n",
+                                                       cvalue);
+                                               exit( EXIT_FAILURE );
+                                       }
+                               }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
                        } else {
                                fprintf( stderr, "Invalid general control name: %s\n",
                                        control );
@@ -867,7 +924,7 @@ void
 tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
 {
        int i = 0, j, crit = 0, err;
-       LDAPControl c[8], **ctrls;
+       LDAPControl c[9], **ctrls;
 
        ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
        if ( ctrls == NULL ) {
@@ -915,8 +972,7 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
 
        if ( manageDSAit ) {
                c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-               c[i].ldctl_value.bv_val = NULL;
-               c[i].ldctl_value.bv_len = 0;
+               BER_BVZERO( &c[i].ldctl_value );
                c[i].ldctl_iscritical = manageDSAit > 1;
                ctrls[i] = &c[i];
                i++;
@@ -924,8 +980,7 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
 
        if ( noop ) {
                c[i].ldctl_oid = LDAP_CONTROL_NOOP;
-               c[i].ldctl_value.bv_val = NULL;
-               c[i].ldctl_value.bv_len = 0;
+               BER_BVZERO( &c[i].ldctl_value );
                c[i].ldctl_iscritical = noop > 1;
                ctrls[i] = &c[i];
                i++;
@@ -991,6 +1046,52 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
                if( attrs ) ldap_charray_free( attrs );
        }
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+       if ( chaining ) {
+               if ( chainingResolve > -1 ) {
+                       BerElementBuffer berbuf;
+                       BerElement *ber = (BerElement *)&berbuf;
+
+                       ber_init2( ber, NULL, LBER_USE_DER );
+
+                       err = ber_printf( ber, "{e" /* } */, chainingResolve );
+                       if ( err == -1 ) {
+                               ber_free( ber, 1 );
+                               fprintf( stderr, _("Chaining behavior control encoding error!\n") );
+                               exit( EXIT_FAILURE );
+                       }
+
+                       if ( chainingContinuation > -1 ) {
+                               err = ber_printf( ber, "e", chainingContinuation );
+                               if ( err == -1 ) {
+                                       ber_free( ber, 1 );
+                                       fprintf( stderr, _("Chaining behavior control encoding error!\n") );
+                                       exit( EXIT_FAILURE );
+                               }
+                       }
+
+                       err = ber_printf( ber, /* { */ "N}" );
+                       if ( err == -1 ) {
+                               ber_free( ber, 1 );
+                               fprintf( stderr, _("Chaining behavior control encoding error!\n") );
+                               exit( EXIT_FAILURE );
+                       }
+
+                       if ( ber_flatten2( ber, &c[i].ldctl_value, 0 ) == -1 ) {
+                               exit( EXIT_FAILURE );
+                       }
+
+               } else {
+                       BER_BVZERO( &c[i].ldctl_value );
+               }
+
+               c[i].ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR;
+               c[i].ldctl_iscritical = chaining > 1;
+               ctrls[i] = &c[i];
+               i++;
+       }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
        while ( count-- ) {
                ctrls[i++] = extra_c++;
        }
index 3022721d5bc99518b54ebc76ab2f7e0935324d07..d6903ac9f9a6dd6cfa64dec0533a54ff3b7bfccc 100644 (file)
@@ -49,6 +49,9 @@ extern int   manageDSAit;
 extern int   noop;
 extern int   ppolicy;
 extern int     preread, postread;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+extern int     chaining;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
 
 extern int   not;
 extern int   want_bindpw;
index e2f99449591a1261bba2f79a951a703758e750cc..c603281d970e5f7209f065ee701c03dbfa67a36a 100644 (file)
@@ -379,7 +379,7 @@ handle_private_option( int i )
                        if( crit ) subentries *= -1;
 #endif
 
-       } else if ( strcasecmp( control, "sync" ) == 0 ) {
+               } else if ( strcasecmp( control, "sync" ) == 0 ) {
                        char *cookiep;
                        char *slimitp;
                        if ( ldapsync ) {
@@ -664,31 +664,34 @@ getNextPage:
 #ifdef LDAP_CONTROL_PAGEDRESULTS
                || pagedResults
 #endif
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+               || chaining
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
                || ldapsync
                || subentries || valuesReturnFilter )
        {
                int err;
                int i=0;
-               LDAPControl c[6];
+               LDAPControl c[10];
 
 #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
-       if ( domainScope ) {
-               c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
-               c[i].ldctl_value.bv_val = NULL;
-               c[i].ldctl_value.bv_len = 0;
-               c[i].ldctl_iscritical = domainScope > 1;
-               i++;
-       }
+               if ( domainScope ) {
+                       c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
+                       c[i].ldctl_value.bv_val = NULL;
+                       c[i].ldctl_value.bv_len = 0;
+                       c[i].ldctl_iscritical = domainScope > 1;
+                       i++;
+               }
 #endif
 
 #ifdef LDAP_CONTROL_SUBENTRIES
                if ( subentries ) {
-               if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+                       if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
                                return EXIT_FAILURE;
                        }
 
                        err = ber_printf( seber, "b", abs(subentries) == 1 ? 0 : 1 );
-               if ( err == -1 ) {
+                       if ( err == -1 ) {
                                ber_free( seber, 1 );
                                fprintf( stderr, _("Subentries control encoding error!\n") );
                                return EXIT_FAILURE;
index 50716b7c7e0f65b888753cb80a1957e965acb76b..d43be03ea5a22a99add04f49c55ba23bfc0b96f7 100644 (file)
@@ -73,12 +73,6 @@ results if the data comes from a transaction that is later aborted.
 In this case, the modified data is discarded and a subsequent search
 will return a different result.
 .TP
-.B fasttool
-Disables transaction logging when using the slapadd/slapindex tools,
-using the DB_TXN_NOT_DURABLE flag. Does not affect normal slapd operation,
-but will improve the performance of slapadd/slapindex.
-See the Berkeley DB reference guide for more details.
-.TP
 .B idlcachesize <integer>
 Specify the size of the in-memory index cache, in index slots. The
 default is zero. A larger value will speed up frequent searches of
index b06dd612c3fda8a3e04e1f79772e64d80cec4d68..dda9db93df3b3faae62549d1c85dd836eea8b978 100644 (file)
@@ -277,6 +277,18 @@ typedef struct ldapcontrol {
 #define LDAP_SEARCH_FLAG_DOMAIN_SCOPE          1 /* do not generate referrals */
 #define LDAP_SEARCH_FLAG_PHANTOM_ROOT          2 /* search all NCs subordinate to base */
 
+/* LDAP Chaining Behavior Control *//* work in progress */
+/* <draft-sermersheim-ldap-chaining>;
+ * see also LDAP_REQUIRES_CHAINING, LDAP_CANNOT_CHAIN */
+#ifdef LDAP_DEVEL
+#define LDAP_CONTROL_X_CHAINING_BEHAVIOR       "1.3.6.1.4.1.4203.666.11.3"
+
+#define        LDAP_CHAINING_PREFERRED                         0
+#define        LDAP_CHAINING_REQUIRED                          1
+#define LDAP_REFERRALS_PREFERRED                       2
+#define LDAP_REFERRALS_REQUIRED                                3
+#endif
+
 /* LDAP Unsolicited Notifications */
 #define        LDAP_NOTICE_OF_DISCONNECTION    "1.3.6.1.4.1.1466.20036" /* RFC 2251 */
 #define LDAP_NOTICE_DISCONNECT LDAP_NOTICE_OF_DISCONNECTION
@@ -550,6 +562,13 @@ typedef struct ldapcontrol {
 /* for the Assertion control */
 #define LDAP_ASSERTION_FAILED                  0x410f
 
+/* for the Chaining Behavior control (consecutive result codes requested;
+ * see <draft-sermersheim-ldap-chaining> ) */
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+#define        LDAP_REQUIRES_CHAINING                  0x4110
+#define LDAP_CANNOT_CHAIN                      0x4111
+#endif
+
 /* API Error Codes
  *
  * Based on draft-ietf-ldap-c-api-xx
index f8cc9f2150eaacc926bdda77d3acf5d1f269cf05..dcb3a95a630087ebb3622203f90455132695190d 100644 (file)
@@ -317,6 +317,8 @@ void *slapi_get_object_extension(int objecttype, void *object,
 void slapi_set_object_extension(int objecttype, void *object,
        int extensionhandle, void *extension);
 
+int slapi_x_backend_get_flags( const Slapi_Backend *be, unsigned long *flags );
+
 /* parameters currently supported */
 
 /*
@@ -330,6 +332,20 @@ void slapi_set_object_extension(int objecttype, void *object,
 #define SLAPI_ATTR_FLAG_COLLECTIVE     0x0080
 #define SLAPI_ATTR_FLAG_NOUSERMOD      0x0100
 
+/*
+ * Backend flags returned by slapi_x_backend_get_flags()
+ */
+#define SLAPI_BACKEND_FLAG_NOLASTMOD           0x0001U
+#define SLAPI_BACKEND_FLAG_NO_SCHEMA_CHECK     0x0002U
+#define SLAPI_BACKEND_FLAG_GLUE_INSTANCE       0x0010U /* a glue backend */
+#define SLAPI_BACKEND_FLAG_GLUE_SUBORDINATE    0x0020U /* child of a glue hierarchy */
+#define SLAPI_BACKEND_FLAG_GLUE_LINKED         0x0040U /* child is connected to parent */
+#define SLAPI_BACKEND_FLAG_OVERLAY             0x0080U /* this db struct is an overlay */
+#define SLAPI_BACKEND_FLAG_GLOBAL_OVERLAY      0x0100U /* this db struct is a global overlay */
+#define SLAPI_BACKEND_FLAG_SHADOW              0x8000U /* a shadow */
+#define SLAPI_BACKEND_FLAG_SYNC_SHADOW         0x1000U /* a sync shadow */
+#define SLAPI_BACKEND_FLAG_SLURP_SHADOW                0x2000U /* a slurp shadow */
+
 /*
  * ACL levels
  */
index ed9c6f3e22fdafbe4bb01bb4f6adc7a5c6cd9526..41caa7f7b5372caf5ec7ddc61b23bf4b4cee3db3 100644 (file)
@@ -1125,7 +1125,7 @@ re_encode_request( LDAP *ld,
                                scope = LDAP_SCOPE_BASE;
                                break;
                        case LDAP_SCOPE_SUBTREE:
-#ifdef LDAP_FEATURE_SUBORDINATE_SCOPE
+#ifdef LDAP_SCOPE_SUBORDINATE
                        case LDAP_SCOPE_SUBORDINATE:
 #endif
                                scope = LDAP_SCOPE_SUBTREE;
index 0f6379f443ebe538b22ce05f352af0594cc3aec0..b6a669fce90d32464f12d67575848f0c0620a92f 100644 (file)
@@ -509,7 +509,7 @@ desc2str_len( LDAPURLDesc *u )
        case LDAP_SCOPE_BASE:
        case LDAP_SCOPE_ONELEVEL:
        case LDAP_SCOPE_SUBTREE:
-#ifdef LDAP_FEATURE_SUBORDINATE_SCOPE
+#ifdef LDAP_SCOPE_SUBORDINATE
        case LDAP_SCOPE_SUBORDINATE:
 #endif
                switch ( u->lud_scope ) {
@@ -525,7 +525,7 @@ desc2str_len( LDAPURLDesc *u )
                        len += STRLENOF( "sub" );
                        break;
 
-#ifdef LDAP_FEATURE_SUBORDINATE_SCOPE
+#ifdef LDAP_SCOPE_SUBORDINATE
                case LDAP_SCOPE_SUBORDINATE:
                        len += STRLENOF( "subordinate" );
                        break;
@@ -597,7 +597,7 @@ desc2str( LDAPURLDesc *u, char *s, int len )
        case LDAP_SCOPE_BASE:
        case LDAP_SCOPE_ONELEVEL:
        case LDAP_SCOPE_SUBTREE:
-#ifdef LDAP_FEATURE_SUBORDINATE_SCOPE
+#ifdef LDAP_SCOPE_SUBORDINATE
        case LDAP_SCOPE_SUBORDINATE:
 #endif
                gotscope = 1;
@@ -690,7 +690,7 @@ desc2str( LDAPURLDesc *u, char *s, int len )
                len -= STRLENOF("sub");
                break;
 
-#ifdef LDAP_FEATURE_SUBORDINATE_SCOPE
+#ifdef LDAP_SCOPE_SUBORDINATE
        case LDAP_SCOPE_SUBORDINATE:
                strcpy( &s[sofar], "children" );
                sofar += STRLENOF("children");
index ec70bf0095b73b2f95812578dfed5a65fa9112d2..76d1c63adc2b3668940e2f8b7d971001439621b4 100644 (file)
@@ -63,15 +63,6 @@ bdb_db_config(
        } else if ( strcasecmp( argv[0], "dbnosync" ) == 0 ) {
                bdb->bi_dbenv_xflags |= DB_TXN_NOSYNC;
 
-       /* slapadd/slapindex logging configuration */
-       } else if ( strcasecmp( argv[0], "fasttool" ) == 0 ) {
-               if ( slapMode & SLAP_TOOL_MODE )
-#if DB_VERSION_FULL >= 0x04030015
-               bdb->bi_dbenv_xflags |= DB_LOG_INMEMORY;
-#else
-               bdb->bi_dbenv_xflags |= DB_TXN_NOT_DURABLE;
-#endif
-
        /* slapindex algorithm tuning */
        } else if ( strcasecmp( argv[0], "linearindex" ) == 0 ) {
                bdb->bi_linear_index = 1;
index 53e036a6de1303cfa6d6a0e74fb43530d76d3413..32892d6014fb71e05e1f4c02ae3a4f78ea8db674 100644 (file)
@@ -41,27 +41,6 @@ struct berval bdb_uuid = BER_BVNULL;
 typedef void * db_malloc(size_t);
 typedef void * db_realloc(void *, size_t);
 
-#if 0
-static int
-bdb_open( BackendInfo *bi )
-{
-       return 0;
-}
-
-static int
-bdb_destroy( BackendInfo *bi )
-{
-       return 0;
-}
-
-static int
-bdb_close( BackendInfo *bi )
-{
-       /* terminate the underlying database system */
-       return 0;
-}
-#endif
-
 static int
 bdb_db_init( BackendDB *be )
 {
@@ -140,7 +119,7 @@ bdb_db_open( BackendDB *be )
 
        flags = DB_INIT_MPOOL | DB_THREAD | DB_CREATE;
 
-if ( !( slapMode & SLAP_TOOL_QUICK ))
+       if ( !( slapMode & SLAP_TOOL_QUICK ))
                flags |= DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN;
        
 #if 0
@@ -386,7 +365,6 @@ if ( !( slapMode & SLAP_TOOL_QUICK ))
                ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
        }
 
-       /* <insert> open (and create) index databases */
        return 0;
 }
 
@@ -583,11 +561,6 @@ bdb_back_initialize(
 
        bi->bi_op_unbind = 0;
 
-#if 0  /* DELETE ME */
-       bi->bi_op_abandon = bdb_abandon;
-       bi->bi_op_cancel = bdb_cancel;
-#endif
-
        bi->bi_extended = bdb_extended;
 
        bi->bi_chk_referrals = bdb_referrals;
index 998ce2453789f33bb4b960e32f5a94c81dd56d24..bdf8078e2f25b9665ce0ae4062ccd498e207bef8 100644 (file)
@@ -404,6 +404,8 @@ ldap_back_dobind_int(
 
        ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
        if ( !lc->lc_bound ) {
+               struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+
                /*
                 * FIXME: we need to let clients use proxyAuthz
                 * otherwise we cannot do symmetric pools of servers;
@@ -419,11 +421,17 @@ ldap_back_dobind_int(
                /*
                 * if no bind took place yet, but the connection is bound
                 * and the "idassert-authcDN" (or other ID) is set, 
-                * then bind as the asserting ideintity and explicitly 
+                * then bind as the asserting identity and explicitly 
                 * add the proxyAuthz control to every operation with the
                 * dn bound to the connection as control value.
+                * This is done also if this is the authrizing backend,
+                * but the "override" flag is given to idassert.
+                * It allows to use SASL bind and yet proxyAuthz users
                 */
-               if ( op->o_conn != NULL && BER_BVISNULL( &lc->lc_bound_ndn ) ) {
+               if ( op->o_conn != NULL &&
+                               ( BER_BVISNULL( &lc->lc_bound_ndn ) ||
+                                 ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
+               {
                        (void)ldap_back_proxy_authz_bind( lc, op, rs );
                        goto done;
                }
index 67927c40d767c0c98eb6d788c79ee3af13abe3bf..d481abb7a486707060f8b820c0896d517adeec95 100644 (file)
 #include "slap.h"
 #include "back-ldap.h"
 
-static BackendInfo *lback;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+#define SLAP_CH_RESOLVE_SHIFT                          SLAP_CONTROL_SHIFT
+#define SLAP_CH_RESOLVE_MASK                           (0x3 << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_CHAINING_PREFERRED             (LDAP_CHAINING_PREFERRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_CHAINING_REQUIRED              (LDAP_CHAINING_REQUIRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_REFERRALS_PREFERRED            (LDAP_REFERRALS_PREFERRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_REFERRALS_REQUIRED             (LDAP_REFERRALS_REQUIRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_DEFAULT                                SLAP_CH_RESOLVE_CHAINING_PREFERRED
+#define        SLAP_CH_CONTINUATION_SHIFT                      (SLAP_CH_RESOLVE_SHIFT + 2)
+#define SLAP_CH_CONTINUATION_MASK                      (0x3 << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_CHAINING_PREFERRED                (LDAP_CHAINING_PREFERRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_CHAINING_REQUIRED         (LDAP_CHAINING_REQUIRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_REFERRALS_PREFERRED       (LDAP_REFERRALS_PREFERRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_REFERRALS_REQUIRED                (LDAP_REFERRALS_REQUIRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_DEFAULT                   SLAP_CH_CONTINUATION_CHAINING_PREFERRED
+
+#define o_chaining                     o_ctrlflag[sc_chainingBehavior]
+#define get_chaining(op)               ((op)->o_chaining & SLAP_CONTROL_MASK)
+#define get_chainingBehavior(op)       ((op)->o_chaining & (SLAP_CH_RESOLVE_MASK|SLAP_CH_CONTINUATION_MASK))
+#define get_resolveBehavior(op)                ((op)->o_chaining & SLAP_CH_RESOLVE_MASK)
+#define get_continuationBehavior(op)   ((op)->o_chaining & SLAP_CH_CONTINUATION_MASK)
+#endif /*  LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
+#define        LDAP_CH_NONE                    ((void *)(0))
+#define        LDAP_CH_RES                     ((void *)(1))
+#define LDAP_CH_ERR                    ((void *)(2))
+
+static int             sc_chainingBehavior;
+static BackendInfo     *lback;
 
 static int
 ldap_chain_operational( Operation *op, SlapReply *rs )
@@ -58,6 +86,11 @@ ldap_chain_cb_search_response( Operation *op, SlapReply *rs )
 {
        assert( op->o_tag == LDAP_REQ_SEARCH );
 
+       /* if in error, don't proceed any further */
+       if ( op->o_callback->sc_private == LDAP_CH_ERR ) {
+               return 0;
+       }
+
        if ( rs->sr_type == REP_SEARCH ) {
                Attribute       **ap = &rs->sr_entry->e_attrs;
 
@@ -79,9 +112,27 @@ ldap_chain_cb_search_response( Operation *op, SlapReply *rs )
                
                return SLAP_CB_CONTINUE;
 
+       } else if ( rs->sr_type == REP_SEARCHREF ) {
+               /* if we get it here, it means the library was unable
+                * to chase the referral... */
+
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+               if ( get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
+                       switch ( get_continuationBehavior( op ) ) {
+                       case SLAP_CH_RESOLVE_CHAINING_REQUIRED:
+                               op->o_callback->sc_private = LDAP_CH_ERR;
+                               return -1;
+
+                       default:
+                               break;
+                       }
+               }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+               return SLAP_CB_CONTINUE;
+
        } else if ( rs->sr_type == REP_RESULT ) {
                /* back-ldap tried to send result */
-               op->o_callback->sc_private = (void *)(1);
+               op->o_callback->sc_private = LDAP_CH_RES;
        }
 
        return 0;
@@ -94,8 +145,13 @@ ldap_chain_cb_search_response( Operation *op, SlapReply *rs )
 static int
 ldap_chain_cb_response( Operation *op, SlapReply *rs )
 {
+       /* if in error, don't proceed any further */
+       if ( op->o_callback->sc_private == LDAP_CH_ERR ) {
+               return 0;
+       }
+
        if ( rs->sr_type == REP_RESULT ) {
-               op->o_callback->sc_private = (void *)(1);
+               op->o_callback->sc_private = LDAP_CH_RES;
 
        } else if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH )
        {
@@ -115,7 +171,9 @@ ldap_chain_op(
 {
        slap_overinst   *on = (slap_overinst *) op->o_bd->bd_info;
        struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
-       int             rc;
+
+       /* NOTE: returned if ref is empty... */
+       int             rc = LDAP_OTHER;
 
        if ( lip->url != NULL ) {
                op->o_bd->be_private = on->on_bi.bi_private;
@@ -204,10 +262,44 @@ ldap_chain_response( Operation *op, SlapReply *rs )
 
        struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+       int             sr_err = rs->sr_err;
+       slap_reply_t    sr_type = rs->sr_type;
+       slap_mask_t     chain_mask = 0;
+       ber_len_t       chain_shift = 0;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
        if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF ) {
                return SLAP_CB_CONTINUE;
        }
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+       if ( rs->sr_err == LDAP_REFERRAL && get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
+               switch ( get_resolveBehavior( op ) ) {
+               case SLAP_CH_RESOLVE_REFERRALS_PREFERRED:
+               case SLAP_CH_RESOLVE_REFERRALS_REQUIRED:
+                       return SLAP_CB_CONTINUE;
+
+               default:
+                       chain_mask = SLAP_CH_RESOLVE_MASK;
+                       chain_shift = SLAP_CH_RESOLVE_SHIFT;
+                       break;
+               }
+
+       } else if ( rs->sr_type == REP_SEARCHREF && get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
+               switch ( get_continuationBehavior( op ) ) {
+               case SLAP_CH_CONTINUATION_REFERRALS_PREFERRED:
+               case SLAP_CH_CONTINUATION_REFERRALS_REQUIRED:
+                       return SLAP_CB_CONTINUE;
+
+               default:
+                       chain_mask = SLAP_CH_CONTINUATION_MASK;
+                       chain_shift = SLAP_CH_CONTINUATION_SHIFT;
+                       break;
+               }
+       }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
        /*
         * TODO: add checks on who/when chain operations; e.g.:
         *   a) what identities are authorized
@@ -254,6 +346,14 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                        char            textbuf[ SLAP_TEXT_BUFLEN ];
                        size_t          textlen = sizeof( textbuf );
 
+#if 0
+                       /* FIXME: op->o_bd is still set to the BackendDB 
+                        * structure of the database that tried to handle
+                        * the operation and actually returned a referral
+                        * ... */
+                       assert( SLAP_DBFLAGS( op->o_bd ) & SLAP_DBFLAG_GLOBAL_OVERLAY );
+#endif
+
                        /* global overlay: create entry */
                        /* NOTE: this is a hack to use the chain overlay
                         * as global.  I expect to be able to remove this
@@ -362,6 +462,8 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                                if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
                                        break;
                                }
+
+                               rc = rs->sr_err;
                        }
 
                        op->o_req_dn = odn;
@@ -393,12 +495,38 @@ ldap_chain_response( Operation *op, SlapReply *rs )
                break;
        }
 
-       if ( sc2.sc_private == NULL ) {
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+       if ( rc != LDAP_SUCCESS || sc2.sc_private == LDAP_CH_ERR ) {
+               if ( rs->sr_err == LDAP_CANNOT_CHAIN ) {
+                       goto cannot_chain;
+               }
+
+               switch ( ( get_chainingBehavior( op ) & chain_mask ) >> chain_shift ) {
+               case LDAP_CHAINING_REQUIRED:
+cannot_chain:;
+                       op->o_callback = NULL;
+                       send_ldap_error( op, rs, LDAP_CANNOT_CHAIN, "operation cannot be completed without chaining" );
+                       break;
+
+               default:
+                       rc = SLAP_CB_CONTINUE;
+                       rs->sr_err = sr_err;
+                       rs->sr_type = sr_type;
+                       break;
+               }
+               goto dont_chain;
+       }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
+       if ( sc2.sc_private == LDAP_CH_NONE ) {
                op->o_callback = NULL;
                rc = rs->sr_err = slap_map_api2result( rs );
                send_ldap_result( op, rs );
        }
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+dont_chain:;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
        op->o_do_not_cache = cache;
        op->o_bd->be_private = private;
        op->o_callback = sc;
@@ -423,9 +551,9 @@ ldap_chain_db_config(
        int             rc;
 
        be->be_private = on->on_bi.bi_private;
-       if ( strncasecmp( argv[ 0 ], "chain-", sizeof( "chain-" ) - 1 ) == 0 ) {
+       if ( strncasecmp( argv[ 0 ], "chain-", STRLENOF( "chain-" ) ) == 0 ) {
                argv0 = argv[ 0 ];
-               argv[ 0 ] = &argv[ 0 ][ sizeof( "chain-" ) - 1 ];
+               argv[ 0 ] = &argv[ 0 ][ STRLENOF( "chain-" ) ];
        }
        rc = lback->bi_db_config( be, fname, lineno, argc, argv );
        if ( argv0 ) {
@@ -460,6 +588,16 @@ ldap_chain_db_init(
        return rc;
 }
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+static int
+ldap_chain_db_open(
+       BackendDB *be
+)
+{
+       return overlay_register_control( be, LDAP_CONTROL_X_CHAINING_BEHAVIOR );
+}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 static int
 ldap_chain_db_destroy(
        BackendDB *be
@@ -476,13 +614,156 @@ ldap_chain_db_destroy(
        return rc;
 }
 
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+static int
+ldap_chain_parse_ctrl(
+       Operation       *op,
+       SlapReply       *rs,
+       LDAPControl     *ctrl )
+{
+       ber_tag_t       tag;
+       BerElement      *ber;
+       ber_int_t       mode,
+                       behavior;
+
+       if ( get_chaining( op ) != SLAP_CONTROL_NONE ) {
+               rs->sr_text = "Chaining behavior control specified multiple times";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( op->o_pagedresults != SLAP_CONTROL_NONE ) {
+               rs->sr_text = "Chaining behavior control specified with pagedResults control";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
+               mode = (SLAP_CH_RESOLVE_DEFAULT|SLAP_CH_CONTINUATION_DEFAULT);
+
+       } else {
+               ber_len_t       len;
+
+               /* Parse the control value
+                *      ChainingBehavior ::= SEQUENCE { 
+                *           resolveBehavior         Behavior OPTIONAL, 
+                *           continuationBehavior    Behavior OPTIONAL } 
+                *                             
+                *      Behavior :: = ENUMERATED { 
+                *           chainingPreferred       (0), 
+                *           chainingRequired        (1), 
+                *           referralsPreferred      (2), 
+                *           referralsRequired       (3) } 
+                */
+
+               ber = ber_init( &ctrl->ldctl_value );
+               if( ber == NULL ) {
+                       rs->sr_text = "internal error";
+                       return LDAP_OTHER;
+               }
+
+               tag = ber_scanf( ber, "{e" /* } */, &behavior );
+               /* FIXME: since the whole SEQUENCE is optional,
+                * should we accept no enumerations at all? */
+               if ( tag != LBER_ENUMERATED ) {
+                       rs->sr_text = "Chaining behavior control: resolveBehavior decoding error";
+                       return LDAP_PROTOCOL_ERROR;
+               }
+
+               switch ( behavior ) {
+               case LDAP_CHAINING_PREFERRED:
+                       mode = SLAP_CH_RESOLVE_CHAINING_PREFERRED;
+                       break;
+
+               case LDAP_CHAINING_REQUIRED:
+                       mode = SLAP_CH_RESOLVE_CHAINING_REQUIRED;
+                       break;
+
+               case LDAP_REFERRALS_PREFERRED:
+                       mode = SLAP_CH_RESOLVE_REFERRALS_PREFERRED;
+                       break;
+
+               case LDAP_REFERRALS_REQUIRED:
+                       mode = SLAP_CH_RESOLVE_REFERRALS_REQUIRED;
+                       break;
+
+               default:
+                       rs->sr_text = "Chaining behavior control: unknown resolveBehavior";
+                       return LDAP_PROTOCOL_ERROR;
+               }
+
+               tag = ber_peek_tag( ber, &len );
+               if ( tag == LBER_ENUMERATED ) {
+                       tag = ber_scanf( ber, "e", &behavior );
+                       if ( tag == LBER_ERROR ) {
+                               rs->sr_text = "Chaining behavior control: continuationBehavior decoding error";
+                               return LDAP_PROTOCOL_ERROR;
+                       }
+               }
+
+               if ( tag == LBER_DEFAULT ) {
+                       mode |= SLAP_CH_CONTINUATION_DEFAULT;
+
+               } else {
+                       switch ( behavior ) {
+                       case LDAP_CHAINING_PREFERRED:
+                               mode |= SLAP_CH_CONTINUATION_CHAINING_PREFERRED;
+                               break;
+
+                       case LDAP_CHAINING_REQUIRED:
+                               mode |= SLAP_CH_CONTINUATION_CHAINING_REQUIRED;
+                               break;
+
+                       case LDAP_REFERRALS_PREFERRED:
+                               mode |= SLAP_CH_CONTINUATION_REFERRALS_PREFERRED;
+                               break;
+
+                       case LDAP_REFERRALS_REQUIRED:
+                               mode |= SLAP_CH_CONTINUATION_REFERRALS_REQUIRED;
+                               break;
+
+                       default:
+                               rs->sr_text = "Chaining behavior control: unknown continuationBehavior";
+                               return LDAP_PROTOCOL_ERROR;
+                       }
+               }
+
+               if ( ( ber_scanf( ber, /* { */ "}") ) == LBER_ERROR ) {
+                       rs->sr_text = "Chaining behavior control: decoding error";
+                       return LDAP_PROTOCOL_ERROR;
+               }
+
+               (void) ber_free( ber, 1 );
+       }
+
+       op->o_chaining = mode | ( ctrl->ldctl_iscritical
+                       ? SLAP_CONTROL_CRITICAL
+                       : SLAP_CONTROL_NONCRITICAL );
+
+       return LDAP_SUCCESS;
+}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
 static slap_overinst ldapchain;
 
 int
 chain_init( void )
 {
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+       int     rc;
+
+       rc = register_supported_control( LDAP_CONTROL_X_CHAINING_BEHAVIOR,
+                       /* SLAP_CTRL_GLOBAL| */ SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE, NULL,
+                       ldap_chain_parse_ctrl, &sc_chainingBehavior );
+       if ( rc != LDAP_SUCCESS ) {
+               fprintf( stderr, "Failed to register chaining behavior control: %d\n", rc );
+               return rc;
+       }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
        ldapchain.on_bi.bi_type = "chain";
        ldapchain.on_bi.bi_db_init = ldap_chain_db_init;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+       ldapchain.on_bi.bi_db_open = ldap_chain_db_open;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
        ldapchain.on_bi.bi_db_config = ldap_chain_db_config;
        ldapchain.on_bi.bi_db_destroy = ldap_chain_db_destroy;
        
index b42352614f65e09159e8df6bfb80efcedadff3dd..cd84f8dcda2be003f328acfe53f3e26170b9609d 100644 (file)
@@ -234,13 +234,34 @@ fail:;
                        }
 
                } else {
+                       char            **references = NULL;
+
                        rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
                                        &match.bv_val, (char **)&rs->sr_text,
-                                       NULL, &rs->sr_ctrls, 1 );
-                       if (rc != LDAP_SUCCESS ) {
+                                       &references, &rs->sr_ctrls, 1 );
+                       if ( rc != LDAP_SUCCESS ) {
                                rs->sr_err = rc;
                        }
                        rs->sr_err = slap_map_api2result( rs );
+
+                       if ( references ) {
+                               int     cnt;
+
+                               for ( cnt = 0; references[ cnt ]; cnt++ )
+                                       /* NO OP */ ;
+                               
+                               rs->sr_ref = ch_calloc( cnt + 1, sizeof( struct berval ) );
+
+                               for ( cnt = 0; references[ cnt ]; cnt++ ) {
+                                       ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
+                               }
+
+                               /* cleanup */
+                               if ( references ) {
+                                       ldap_value_free( references );
+                               }
+                       }
+
                        rc = 0;
                        break;
                }
@@ -283,12 +304,19 @@ finish:;
                rs->sr_matched = NULL;
                LDAP_FREE( match.bv_val );
        }
+
        if ( rs->sr_text ) {
                if ( !dontfreetext ) {
                        LDAP_FREE( (char *)rs->sr_text );
                }
                rs->sr_text = NULL;
        }
+
+       if ( rs->sr_ref ) {
+               ber_bvarray_free( rs->sr_ref );
+               rs->sr_ref = NULL;
+       }
+
        if ( attrs ) {
                ch_free( attrs );
        }
index 15f13ee892e8bed5c31acd819f476469859f4431..fe9af550d499b8e1bb14232228666680b49a4d6e 100644 (file)
@@ -169,7 +169,7 @@ meta_back_add( Operation *op, SlapReply *rs )
        attrs[ i ] = NULL;
 
        rs->sr_err = ldap_add_ext_s( lc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
-                             attrs, NULL, NULL );
+                             attrs, op->o_ctrls, NULL );
        for ( --i; i >= 0; --i ) {
                free( attrs[ i ]->mod_bvalues );
                free( attrs[ i ] );
index 36dc7af36cc465959eb005b8119ba4009d566f67..0dde00f58452c78d516378613f92e03667eb7bc9 100644 (file)
@@ -192,18 +192,11 @@ meta_back_do_single_bind(
                return -1;
        }
 
-       if ( op->o_ctrls ) {
-               rs->sr_err = ldap_set_option( lsc->msc_ld, 
-                               LDAP_OPT_SERVER_CONTROLS, op->o_ctrls );
-               if ( rs->sr_err != LDAP_SUCCESS ) {
-                       rs->sr_err = slap_map_api2result( rs );
-                       goto return_results;
-               }
-       }
-
        /* FIXME: this fixes the bind problem right now; we need
         * to use the asynchronous version to get the "matched"
         * and more in case of failure ... */
+       /* FIXME: should be check if at least some of the op->o_ctrls
+        * can/should be passed? */
        rs->sr_err = ldap_sasl_bind( lsc->msc_ld, mdn.bv_val,
                        LDAP_SASL_SIMPLE, &op->orb_cred,
                        op->o_ctrls, NULL, &msgid );
@@ -308,17 +301,6 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
                        continue;
                }
 
-               /*
-                * If required, set controls
-                */
-               if ( op->o_ctrls ) {
-                       if ( ldap_set_option( lsc->msc_ld, LDAP_OPT_SERVER_CONTROLS,
-                                       op->o_ctrls ) != LDAP_SUCCESS ) {
-                               ( void )meta_clear_one_candidate( lsc, 1 );
-                               continue;
-                       }
-               }
-
                /*
                 * If the target is already bound it is skipped
                 */
@@ -346,8 +328,10 @@ meta_back_dobind( struct metaconn *lc, Operation *op )
                        BER_BVZERO( &lsc->msc_cred );
                }
 
+               /* FIXME: should be check if at least some of the op->o_ctrls
+                * can/should be passed? */
                rc = ldap_sasl_bind( lsc->msc_ld, "", LDAP_SASL_SIMPLE, &cred,
-                               op->o_ctrls, NULL, &msgid );
+                               NULL, NULL, &msgid );
                if ( rc == LDAP_SUCCESS ) {
                        LDAPMessage     *res;
                        struct timeval  tv = { 0, 0 };
index 9a808a9581cf21fae120b4c5ceb66210e8daed5f..3418717f7e88c61cec5eafc3dbdde94cb9f79a3b 100644 (file)
@@ -144,7 +144,7 @@ meta_back_compare( Operation *op, SlapReply *rs )
                 */
                 rc = ldap_compare_ext( lc->mc_conns[ i ].msc_ld, mdn.bv_val,
                                mapped_attr.bv_val, &mapped_value,
-                               NULL, NULL, &msgid[ i ] );
+                               op->o_ctrls, NULL, &msgid[ i ] );
 
                if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                        free( mdn.bv_val );
index 9682b2d7af54245b1e87516301675f303b9f8874..28b057ed01e14bebfef21581c42609dac8d4dede 100644 (file)
@@ -172,7 +172,8 @@ meta_back_db_config(
 
                ludp->lud_dn[ 0 ] = '\0';
 
-               for ( tmpludp = ludp->lud_next; tmpludp; tmpludp = tmpludp->lud_next ) {
+               /* check all, to apply the scope check on the first one */
+               for ( tmpludp = ludp; tmpludp; tmpludp = tmpludp->lud_next ) {
                        if ( tmpludp->lud_dn != NULL && tmpludp->lud_dn[ 0 ] != '\0' ) {
                                fprintf( stderr, "%s: line %d: "
                                                "multiple URIs must have "
@@ -181,6 +182,10 @@ meta_back_db_config(
                                return( 1 );
 
                        }
+
+                       if ( tmpludp->lud_scope == LDAP_SCOPE_BASE ) {
+                               tmpludp->lud_scope = LDAP_SCOPE_DEFAULT;
+                       }
                }
 
                li->targets[ i ]->mt_uri = ldap_url_list2urls( ludp );
index 13f8f527d982cf26f2365026d785872d4ee9fc1c..cd719c08d5e8102b4891857d2ac76a6e8883c5b0 100644 (file)
@@ -73,7 +73,7 @@ meta_back_delete( Operation *op, SlapReply *rs )
        }
 
        (void)ldap_delete_ext_s( lc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
-                       NULL, NULL );
+                       op->o_ctrls, NULL );
 
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
index 40709354a4dafc2f5c3de380e12d6132f4a6c29e..cd0a3ec00ec6b8ee2d3c2a4af9097d69f98e1c89 100644 (file)
@@ -183,7 +183,7 @@ meta_back_modify( Operation *op, SlapReply *rs )
        modv[ i ] = 0;
 
        rs->sr_err = ldap_modify_ext_s( lc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
-                       modv, NULL, NULL );
+                       modv, op->o_ctrls, NULL );
 
 cleanup:;
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
index d4ea67f895d2c9c950488f354fbfb1666df4cd2c..756ae36d387c71526d402a34d3a94ec58427889e 100644 (file)
@@ -119,7 +119,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
                        op->orr_newrdn.bv_val,
                        mnewSuperior.bv_val,
                        op->orr_deleteoldrdn,
-                       NULL, NULL ) != LDAP_SUCCESS;
+                       op->o_ctrls, NULL ) != LDAP_SUCCESS;
 
 cleanup:;
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
index cd2c3f7bc6f34c00831d4df8b8b35145e32b0d90..6bc693b64b9893542f00576a828d325edd58ccd3 100644 (file)
@@ -259,7 +259,7 @@ meta_back_search( Operation *op, SlapReply *rs )
                rc = ldap_search_ext( lsc->msc_ld,
                                mbase.bv_val, realscope, mfilter.bv_val,
                                mapped_attrs, op->ors_attrsonly,
-                               NULL, NULL,
+                               op->o_ctrls, NULL,
                                NULL, op->ors_slimit, &msgid[ i ] ); 
                if ( mapped_attrs ) {
                        free( mapped_attrs );
index 9cb0a91a756a5cc6016a65c4e0d2fc1db52f019d..d5a3d9ac15a5d4abacad01c05896079954e688ba 100644 (file)
@@ -97,10 +97,20 @@ relay_back_db_open( Backend *be )
 
        if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
                ri->ri_bd = select_backend( &ri->ri_realsuffix, 0, 1 );
+
                /* must be there: it was during config! */
                assert( ri->ri_bd );
 
-               /* FIXME: (somehow) copy supported controls ? */
+               /* inherit controls */
+               if ( ri->ri_bd->be_controls ) {
+                       be->be_controls = ldap_charray_dup( ri->ri_bd->be_controls );
+               }
+
+       } else {
+               /* inherit all? */
+               if ( frontendDB->be_controls ) {
+                       be->be_controls = ldap_charray_dup( frontendDB->be_controls );
+               }
        }
 
        return 0;
index 105dffe4f911dc34db780da903e811664d712d93..084a82568855d6c7b41a0eec3bbe0e25aa20358b 100644 (file)
@@ -74,7 +74,7 @@ int backend_init(void)
        if((nBackendInfo != 0) || (backendInfo != NULL)) {
                /* already initialized */
                Debug( LDAP_DEBUG_ANY,
-                       "backend_init: already initialized.\n", 0, 0, 0 );
+                       "backend_init: already initialized\n", 0, 0, 0 );
                return -1;
        }
 
@@ -164,7 +164,8 @@ int backend_add(BackendInfo *aBackendInfo)
 /* startup a specific backend database */
 int backend_startup_one(Backend *be)
 {
-       int rc = 0;
+       int             rc = 0;
+       BackendInfo     *bi = be->bd_info;
 
        assert(be);
 
@@ -173,6 +174,17 @@ int backend_startup_one(Backend *be)
 
        LDAP_TAILQ_INIT( be->be_pending_csn_list );
 
+       /* back-relay takes care of itself; so may do other */
+       if ( be->be_controls == NULL ) {
+               if ( overlay_is_over( be ) ) {
+                       bi = ((slap_overinfo *)be->bd_info->bi_private)->oi_orig;
+               }
+
+               if ( bi->bi_controls ) {
+                       be->be_controls = ldap_charray_dup( bi->bi_controls );
+               }
+       }
+
        Debug( LDAP_DEBUG_TRACE,
                "backend_startup: starting \"%s\"\n",
                be->be_suffix ? be->be_suffix[0].bv_val : "(unknown)",
@@ -185,6 +197,32 @@ int backend_startup_one(Backend *be)
                                rc, 0, 0 );
                }
        }
+
+       /* back-relay takes care of itself; so may do other */
+       bi = be->bd_info;
+       if ( overlay_is_over( be ) ) {
+               bi = ((slap_overinfo *)be->bd_info->bi_private)->oi_orig;
+       }
+
+       if ( bi->bi_controls ) {
+               if ( be->be_controls == NULL ) {
+                       be->be_controls = ldap_charray_dup( bi->bi_controls );
+
+               } else {
+                       int     i;
+
+                       /* maybe not efficient, but it's startup and few dozens of controls... */
+                       for ( i = 0; bi->bi_controls[ i ]; i++ ) {
+                               if ( !ldap_charray_inlist( be->be_controls, bi->bi_controls[ i ] ) ) {
+                                       rc = ldap_charray_add( &be->be_controls, bi->bi_controls[ i ] );
+                                       if ( rc != 0 ) {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+
        return rc;
 }
 
@@ -410,6 +448,9 @@ int backend_destroy(void)
                        free( bd->be_rootpw.bv_val );
                }
                acl_destroy( bd->be_acl, frontendDB->be_acl );
+               if ( bd->be_controls ) {
+                       ldap_charray_free( bd->be_controls );
+               }
        }
        free( backendDB );
 
@@ -500,6 +541,7 @@ backend_db_init(
        be = &backends[nbackends++];
 
        be->bd_info = bi;
+
        be->be_def_limit = frontendDB->be_def_limit;
        be->be_dfltaccess = frontendDB->be_dfltaccess;
 
@@ -513,11 +555,11 @@ backend_db_init(
        /* assign a default depth limit for alias deref */
        be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH; 
 
-       if(bi->bi_db_init) {
+       if ( bi->bi_db_init ) {
                rc = bi->bi_db_init( be );
        }
 
-       if(rc != 0) {
+       if ( rc != 0 ) {
                fprintf( stderr, "database init failed (%s)\n", type );
                nbackends--;
                return NULL;
@@ -541,6 +583,7 @@ be_db_close( void )
        if ( frontendDB->bd_info->bi_db_close ) {
                (*frontendDB->bd_info->bi_db_close)( frontendDB );
        }
+
 }
 
 Backend *
@@ -803,25 +846,34 @@ backend_check_controls(
 
        if( ctrls ) {
                for( ; *ctrls != NULL ; ctrls++ ) {
-                       if( (*ctrls)->ldctl_iscritical && !ldap_charray_inlist(
-                               op->o_bd->be_controls, (*ctrls)->ldctl_oid ) )
+                       int cid;
+                       if( slap_find_control_id( (*ctrls)->ldctl_oid, &cid ) ==
+                               LDAP_CONTROL_NOT_FOUND )
+                       {
+                               /* unrecognized control */ 
+                               if ( (*ctrls)->ldctl_iscritical ) {
+                                       /* should not be reachable */ 
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "backend_check_controls: unrecognized control: %s\n",
+                                               (*ctrls)->ldctl_oid, 0, 0 );
+                                       assert( 0 );
+                               }
+
+                       } else if ( !slap_global_control( op, (*ctrls)->ldctl_oid ) &&
+                               !ldap_charray_inlist( op->o_bd->be_controls,
+                                       (*ctrls)->ldctl_oid ) )
                        {
-                               /* FIXME: standards compliance issue
-                                *
-                                * Per RFC 2251 (and LDAPBIS discussions), if the control
+                               /* Per RFC 2251 (and LDAPBIS discussions), if the control
                                 * is recognized and appropriate for the operation (which
                                 * we've already verified), then the server should make
-                                * use of the control when performing the operation
-                                * (without regard to criticality).  This code is incorrect
-                                * on two counts.
-                                * 1) a service error (e.g., unwillingToPerform) should be
-                                * returned where a particular backend cannot service the
-                                * operation,
-                                * 2) this error should be returned irregardless of the
-                                * criticality of the control.
+                                * use of the control when performing the operation.
+                                * 
+                                * Here we find that operation extended by the control
+                                * is not unavailable in a particular context, hence the
+                                * return of unwillingToPerform.
                                 */
                                rs->sr_text = "control unavailable in context";
-                               rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
+                               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                                break;
                        }
                }
@@ -1435,13 +1487,21 @@ backend_attribute(
                        BER_BVZERO( &anlist[ 1 ].an_name );
                        rs.sr_attrs = anlist;
                        
-                       rs.sr_attr_flags = slap_attr_flags( rs.sr_attrs );
-
-                       rc = backend_operational( op, &rs );
+                       /* NOTE: backend_operational() is also called
+                        * when returning results, so it's supposed
+                        * to do no harm to entries */
+                       rs.sr_entry = e;
+                       rc = backend_operational( op, &rs );
+                       rs.sr_entry = NULL;
+                       if ( rc == LDAP_SUCCESS ) {
+                               if ( rs.sr_operational_attrs ) {
+                                       freeattr = 1;
+                                       a = rs.sr_operational_attrs;
 
-                       if ( rc == LDAP_SUCCESS && rs.sr_operational_attrs ) {
-                               freeattr = 1;
-                               a = rs.sr_operational_attrs;
+                               } else {
+                                       rc = LDAP_NO_SUCH_ATTRIBUTE;
+                               }
                        }
                }
 
@@ -1523,6 +1583,144 @@ freeit:         if ( e != target ) {
        return rc;
 }
 
+#ifdef LDAP_SLAPI
+static int backend_compute_output_attr_access(computed_attr_context *c, Slapi_Attr *a, Slapi_Entry *e)
+{
+       struct berval   *nval = (struct berval *)c->cac_private;
+       Operation       *op = NULL;
+
+       slapi_pblock_get( c->cac_pb, SLAPI_OPERATION, &op );
+       if ( op == NULL ) {
+               return 1;
+       }
+
+       return access_allowed( op, e, a->a_desc, nval, ACL_AUTH, NULL ) == 0;
+}
+#endif /* LDAP_SLAPI */
+
+int 
+backend_access(
+       Operation               *op,
+       Entry                   *target,
+       struct berval           *edn,
+       AttributeDescription    *entry_at,
+       struct berval           *nval,
+       slap_access_t           access,
+       slap_mask_t             *mask )
+{
+       Entry           *e = NULL;
+       int             rc = LDAP_INSUFFICIENT_ACCESS;
+       Backend         *be = op->o_bd;
+
+       /* pedantic */
+       assert( op );
+       assert( op->o_conn );
+       assert( edn );
+       assert( access > ACL_NONE );
+
+       op->o_bd = select_backend( edn, 0, 0 );
+
+       if ( target && dn_match( &target->e_nname, edn ) ) {
+               e = target;
+
+       } else {
+               rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &e );
+       } 
+
+       if ( e ) {
+               Attribute       *a = NULL;
+               int             freeattr = 0;
+
+               if ( entry_at == NULL ) {
+                       entry_at = slap_schema.si_ad_entry;
+               }
+
+               if ( entry_at == slap_schema.si_ad_entry || entry_at == slap_schema.si_ad_children )
+               {
+                       if ( access_allowed_mask( op, e, entry_at,
+                                       NULL, access, NULL, mask ) == 0 )
+                       {
+                               rc = LDAP_INSUFFICIENT_ACCESS;
+
+                       } else {
+                               rc = LDAP_SUCCESS;
+                       }
+
+               } else {
+                       a = attr_find( e->e_attrs, entry_at );
+                       if ( a == NULL ) {
+                               SlapReply       rs = { 0 };
+                               AttributeName   anlist[ 2 ];
+
+                               anlist[ 0 ].an_name = entry_at->ad_cname;
+                               anlist[ 0 ].an_desc = entry_at;
+                               BER_BVZERO( &anlist[ 1 ].an_name );
+                               rs.sr_attrs = anlist;
+                       
+                               rs.sr_attr_flags = slap_attr_flags( rs.sr_attrs );
+
+                               /* NOTE: backend_operational() is also called
+                                * when returning results, so it's supposed
+                                * to do no harm to entries */
+                               rs.sr_entry = e;
+                               rc = backend_operational( op, &rs );
+                               rs.sr_entry = NULL;
+
+                               if ( rc == LDAP_SUCCESS ) {
+                                       if ( rs.sr_operational_attrs ) {
+                                               freeattr = 1;
+                                               a = rs.sr_operational_attrs;
+
+                                       } else {
+                                               rc = LDAP_NO_SUCH_OBJECT;
+                                       }
+                               }
+                       }
+
+                       if ( a ) {
+                               if ( access_allowed_mask( op, e, entry_at,
+                                               nval, access, NULL, mask ) == 0 )
+                               {
+                                       rc = LDAP_INSUFFICIENT_ACCESS;
+                                       goto freeit;
+                               }
+                               rc = LDAP_SUCCESS;
+                       }
+#ifdef LDAP_SLAPI
+                       else if ( op->o_pb ) {
+                               /* try any computed attributes */
+                               computed_attr_context   ctx;
+
+                               slapi_int_pblock_set_operation( op->o_pb, op );
+
+                               ctx.cac_pb = op->o_pb;
+                               ctx.cac_attrs = NULL;
+                               ctx.cac_userattrs = 0;
+                               ctx.cac_opattrs = 0;
+                               ctx.cac_private = (void *)nval;
+
+                               rc = compute_evaluator( &ctx, entry_at->ad_cname.bv_val, e, backend_compute_output_attr_access );
+                               if ( rc == 1 ) {
+                                       rc = LDAP_INSUFFICIENT_ACCESS;
+
+                               } else {
+                                       rc = LDAP_SUCCESS;
+                               }
+                       }
+#endif /* LDAP_SLAPI */
+               }
+freeit:                if ( e != target ) {
+                       be_entry_release_r( op, e );
+               }
+               if ( freeattr ) {
+                       attr_free( a );
+               }
+       }
+
+       op->o_bd = be;
+       return rc;
+}
+
 int backend_operational(
        Operation *op,
        SlapReply *rs )
@@ -1539,15 +1737,15 @@ int backend_operational(
         * and the backend supports specific operational attributes, 
         * add them to the attribute list
         */
-       if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( op->ors_attrs &&
-               ad_inlist( slap_schema.si_ad_entryDN, op->ors_attrs )))
+       if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs &&
+               ad_inlist( slap_schema.si_ad_entryDN, rs->sr_attrs )))
        {
                *ap = slap_operational_entryDN( rs->sr_entry );
                ap = &(*ap)->a_next;
        }
 
-       if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( op->ors_attrs &&
-               ad_inlist( slap_schema.si_ad_subschemaSubentry, op->ors_attrs )))
+       if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs &&
+               ad_inlist( slap_schema.si_ad_subschemaSubentry, rs->sr_attrs )))
        {
                *ap = slap_operational_subschemaSubentry( op->o_bd );
                ap = &(*ap)->a_next;
@@ -1558,7 +1756,7 @@ int backend_operational(
        if ( SLAP_ISOVERLAY( be_orig ))
                op->o_bd = select_backend( be_orig->be_nsuffix, 0, 0 );
 
-       if (( SLAP_OPATTRS( rs->sr_attr_flags ) || op->ors_attrs ) &&
+       if (( SLAP_OPATTRS( rs->sr_attr_flags ) || rs->sr_attrs ) &&
                op->o_bd && op->o_bd->be_operational != NULL )
        {
                Attribute       *a;
index 6e396a59043930ec36ed447179b5784aab22851e..4f0082b0d6cebf23ccdbfa8b06d782977cf44375 100644 (file)
@@ -467,6 +467,45 @@ overlay_is_inst( BackendDB *be, const char *over_type )
        return 0;
 }
 
+int
+overlay_register_control( BackendDB *be, const char *oid )
+{
+       int             rc = 0;
+       int             gotit = 0;
+
+       if ( SLAP_DBFLAGS( be ) & SLAP_DBFLAG_GLOBAL_OVERLAY ) {
+               int     i;
+               
+               /* add to all backends... */
+               for ( i = 0; i < nBackendDB; i++ ) {
+                       BackendDB       *bd = &backendDB[i];
+                       
+                       if ( be == bd ) {
+                               gotit = 1;
+                       }
+
+                       if ( bd->be_controls == NULL ||
+                               !ldap_charray_inlist( bd->be_controls, oid ) )
+                       {
+                               rc = ldap_charray_add( &bd->be_controls, oid );
+                               if ( rc ) {
+                                       break;
+                               }
+                       }
+               }
+
+       }
+       
+       if ( rc == 0 && !gotit && !ldap_charray_inlist( be->be_controls, oid ) ) {
+               rc = ldap_charray_add( &be->be_controls, oid );
+               if ( rc ) {
+                       return rc;
+               }
+       }
+
+       return rc;
+}
+
 /* add an overlay to a particular backend. */
 int
 overlay_config( BackendDB *be, const char *ov )
@@ -489,6 +528,13 @@ overlay_config( BackendDB *be, const char *ov )
                oi->oi_orig = be->bd_info;
                oi->oi_bi = *be->bd_info;
 
+               /* NOTE: the first time a global overlay is configured,
+                * frontendDB gets this flag; it is used later by overlays
+                * to determine if they're stacked on top of the frontendDB */
+               if ( oi->oi_orig == frontendDB->bd_info ) {
+                       SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLOBAL_OVERLAY;
+               }
+
                /* Save a pointer to ourself in bi_private.
                 */
                oi->oi_bi.bi_private = oi;
index d6596c248791d9102f28b092118375cd3566e4fb..9c41d57d411f96c30c813d1946e1be621c464dd7 100644 (file)
@@ -274,6 +274,7 @@ fe_op_compare( Operation *op, SlapReply *rs )
                send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
                        "subschemaSubentry compare not supported" );
 
+#ifndef SLAP_COMPARE_IN_FRONTEND
        } else if ( ava.aa_desc == slap_schema.si_ad_hasSubordinates
                && op->o_bd->be_has_subordinates )
        {
@@ -281,9 +282,16 @@ fe_op_compare( Operation *op, SlapReply *rs )
 
                rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &entry );
                if ( rc == 0 && entry ) {
-                       rc = op->o_bd->be_has_subordinates( op, entry,
-                               &hasSubordinates );
-                       be_entry_release_r( op, entry );
+                       if ( ! access_allowed( op, entry,
+                               ava.aa_desc, &ava.aa_value, ACL_COMPARE, NULL ) )
+                       {       
+                               rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                               
+                       } else {
+                               rc = rs->sr_err = op->o_bd->be_has_subordinates( op,
+                                               entry, &hasSubordinates );
+                               be_entry_release_r( op, entry );
+                       }
                }
 
                if ( rc == 0 ) {
@@ -293,20 +301,90 @@ fe_op_compare( Operation *op, SlapReply *rs )
                                ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
                        if ( hasSubordinates == asserted ) {
                                rs->sr_err = LDAP_COMPARE_TRUE;
+
                        } else {
                                rs->sr_err = LDAP_COMPARE_FALSE;
                        }
+
+               } else {
+#ifdef SLAP_ACL_HONOR_DISCLOSE
+                       /* return error only if "disclose"
+                        * is granted on the object */
+                       if ( backend_access( op, NULL, &op->o_req_ndn,
+                                       slap_schema.si_ad_entry,
+                                       NULL, ACL_DISCLOSE, NULL ) == LDAP_INSUFFICIENT_ACCESS )
+                       {
+                               rs->sr_err = LDAP_NO_SUCH_OBJECT;
+                       }
+#endif /* SLAP_ACL_HONOR_DISCLOSE */
                }
+
                send_ldap_result( op, rs );
 
-               if( rc == 0 ) rs->sr_err = LDAP_SUCCESS;
+               if ( rc == 0 ) {
+                       rs->sr_err = LDAP_SUCCESS;
+               }
 
        } else if ( op->o_bd->be_compare ) {
                op->o_bd->be_compare( op, rs );
 
+#endif /* ! SLAP_COMPARE_IN_FRONTEND */
        } else {
-               send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
-                       "operation not supported within namingContext" );
+               /* do our best to compare that AVA
+                * 
+                * NOTE: this code is used only
+                * if SLAP_COMPARE_IN_FRONTEND 
+                * is #define'd (it's not by default)
+                * or if op->o_bd->be_compare is NULL.
+                * 
+                * FIXME: one potential issue is that
+                * if SLAP_COMPARE_IN_FRONTEND overlays
+                * are not executed for compare. */
+               BerVarray       vals = NULL;
+               int             rc = LDAP_OTHER;
+
+               rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn,
+                               ava.aa_desc, &vals, ACL_COMPARE );
+               switch ( rs->sr_err ) {
+               default:
+#ifdef SLAP_ACL_HONOR_DISCLOSE
+                       /* return error only if "disclose"
+                        * is granted on the object */
+                       if ( backend_access( op, NULL, &op->o_req_ndn,
+                                       slap_schema.si_ad_entry,
+                                       NULL, ACL_DISCLOSE, NULL )
+                                       == LDAP_INSUFFICIENT_ACCESS )
+                       {
+                               rs->sr_err = LDAP_NO_SUCH_OBJECT;
+                       }
+#endif /* SLAP_ACL_HONOR_DISCLOSE */
+                       break;
+
+               case LDAP_SUCCESS:
+                       if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
+                               SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
+                                       SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
+                               vals, &ava.aa_value, op->o_tmpmemctx ) == 0 )
+                       {
+                               rs->sr_err = LDAP_COMPARE_TRUE;
+                               break;
+
+                       } else {
+                               rs->sr_err = LDAP_COMPARE_FALSE;
+                       }
+                       rc = LDAP_SUCCESS;
+                       break;
+               }
+
+               send_ldap_result( op, rs );
+
+               if ( rc == 0 ) {
+                       rs->sr_err = LDAP_SUCCESS;
+               }
+               
+               if ( vals ) {
+                       ber_bvarray_free_x( vals, op->o_tmpmemctx );
+               }
        }
 
 #if defined( LDAP_SLAPI )
index 8d0114917245a9cce44f0e43a217d687f8d4ee76..c201273eb579f44430bcba861f4e04fab2ad8d58 100644 (file)
@@ -115,7 +115,7 @@ static struct slap_control control_defs[] = {
 #ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
        { LDAP_CONTROL_X_DOMAIN_SCOPE,
                (int)offsetof(struct slap_control_ids, sc_domainScope),
-               SLAP_CTRL_FRONTEND|SLAP_CTRL_SEARCH, NULL,
+               SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH, NULL,
                parseDomainScope, LDAP_SLIST_ENTRY_INITIALIZER(next) },
 #endif
 #ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY
@@ -133,7 +133,7 @@ static struct slap_control control_defs[] = {
 #ifdef LDAP_CONTORL_X_SEARCH_OPTIONS
        { LDAP_CONTORL_X_SEARCH_OPTIONS,
                (int)offsetof(struct slap_control_ids, sc_searchOptions),
-               SLAP_CTRL_FRONTEND|SLAP_CTRL_SEARCH, NULL,
+               SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH, NULL,
                parseSearchOptions, LDAP_SLIST_ENTRY_INITIALIZER(next) },
 #endif
 #ifdef LDAP_CONTROL_SUBENTRIES
@@ -158,7 +158,7 @@ static struct slap_control control_defs[] = {
                parseManageDSAit, LDAP_SLIST_ENTRY_INITIALIZER(next) },
        { LDAP_CONTROL_PROXY_AUTHZ,
                (int)offsetof(struct slap_control_ids, sc_proxyAuthz),
-               SLAP_CTRL_FRONTEND|SLAP_CTRL_ACCESS, proxy_authz_extops,
+               SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS, proxy_authz_extops,
                parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) },
        { NULL, 0, 0, NULL, 0, LDAP_SLIST_ENTRY_INITIALIZER(next) }
 };
@@ -380,6 +380,34 @@ slap_find_control_id(
        return LDAP_CONTROL_NOT_FOUND;
 }
 
+int
+slap_global_control( Operation *op, const char *oid )
+{
+       struct slap_control *ctrl = find_ctrl( oid );
+
+       if ( ctrl == NULL ) {
+               /* should not be reachable */
+               Debug( LDAP_DEBUG_ANY,
+                       "slap_global_control: unrecognized control: %s\n",      
+                       oid, 0, 0 );
+               assert( 0 );
+               return 0;
+       }
+
+       if ( ctrl->sc_mask & SLAP_CTRL_GLOBAL ) return 1;
+
+       if (( op->o_tag & LDAP_REQ_SEARCH ) &&
+               ( ctrl->sc_mask & SLAP_CTRL_GLOBAL_SEARCH ))
+       {
+               return 1;
+       }
+
+       Debug( LDAP_DEBUG_ANY,
+               "slap_global_control: unavailable control: %s\n",      
+               oid, 0, 0 );
+       return 0;
+}
+
 void slap_free_ctrls(
        Operation *op,
        LDAPControl **ctrls )
@@ -612,17 +640,6 @@ int get_ctrls(
                                        goto return_results;
                                }
 
-                               if ( sc->sc_mask & SLAP_CTRL_FRONTEND ) {
-                                       /* kludge to disable backend_control() check */
-                                       c->ldctl_iscritical = 0;
-
-                               } else if ( tagmask == SLAP_CTRL_SEARCH &&
-                                       sc->sc_mask & SLAP_CTRL_FRONTEND_SEARCH )
-                               {
-                                       /* kludge to disable backend_control() check */
-                                       c->ldctl_iscritical = 0;
-                               }
-
                        } else if( c->ldctl_iscritical ) {
                                /* unavailable CRITICAL control */
                                rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
index 5cc91fbb8c9e7603350abbc4b95cc6b50addb1d1..005c6f7aa44ae4553e6e99961893000052118b98 100644 (file)
@@ -172,7 +172,7 @@ static int test_mra_filter(
                 * one attribute, and SEARCH permissions can be checked
                 * directly.
                 */
-               if( !access_allowed( op, e,
+               if ( !access_allowed( op, e,
                        mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
                {
                        return LDAP_INSUFFICIENT_ACCESS;
@@ -191,18 +191,20 @@ static int test_mra_filter(
                        return LDAP_COMPARE_FALSE;
                }
 
-               for(a = attrs_find( e->e_attrs, mra->ma_desc );
+               for ( a = attrs_find( e->e_attrs, mra->ma_desc );
                        a != NULL;
                        a = attrs_find( a->a_next, mra->ma_desc ) )
                {
-                       struct berval *bv;
+                       struct berval   *bv;
+                       int             normalize_attribute = 0;
+
 #ifdef LDAP_COMP_MATCH
                        /* Component Matching */
-                       if( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
+                       if ( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
                                num_attr_vals = 0;
                                if ( !a->a_comp_data ) {
                                        for ( ;
-                                               a->a_vals[num_attr_vals].bv_val != NULL;
+                                               !BER_BVISNULL( &a->a_vals[num_attr_vals] );
                                                num_attr_vals++ )
                                        {
                                                /* empty */;
@@ -231,22 +233,25 @@ static int test_mra_filter(
                        /* If ma_rule is not the same as the attribute's
                         * normal rule, then we can't use the a_nvals.
                         */
-                       if (mra->ma_rule == a->a_desc->ad_type->sat_equality) {
+                       if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
                                bv = a->a_nvals;
+
                        } else {
                                bv = a->a_vals;
+                               normalize_attribute = 1;
                        }
 #ifdef LDAP_COMP_MATCH
                        i = 0;
 #endif
-                       for ( ; bv->bv_val != NULL; bv++ ) {
+                       for ( ; !BER_BVISNULL( bv ); bv++ ) {
                                int ret;
                                int rc;
                                const char *text;
        
 #ifdef LDAP_COMP_MATCH
-                               if( mra->ma_cf &&
-                                       mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
+                               if ( mra->ma_cf &&
+                                       mra->ma_rule->smr_usage & SLAP_MR_COMPONENT )
+                               {
                                        /* Check if decoded component trees are already linked */
                                        if ( num_attr_vals ) {
                                                a->a_comp_data->cd_tree[i] = attr_converter(
@@ -262,11 +267,53 @@ static int test_mra_filter(
                                } else 
 #endif
                                {
+                                       struct berval   nbv = BER_BVNULL;
+
+                                       if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
+                                               /*
+                               
+                               Document: draft-ietf-ldapbis-protocol
+
+                                   4.5.1. Search Request 
+                                       ...
+                                   If the type field is present and the matchingRule is present, 
+                                   the matchValue is compared against entry attributes of the 
+                                   specified type. In this case, the matchingRule MUST be one 
+                                   suitable for use with the specified type (see [Syntaxes]), 
+                                   otherwise the filter item is Undefined.  
+
+
+                               In this case, since the matchingRule requires the assertion
+                               value to be normalized, we normalize the attribute value
+                               according to the syntax of the matchingRule.
+
+                               This should likely be done inside value_match(), by passing
+                               the appropriate flags, but this is not done at present.
+                               See ITS#3406.
+                                                */
+                                               if ( mra->ma_rule->smr_normalize(
+                                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                                               mra->ma_rule->smr_syntax,
+                                                               mra->ma_rule,
+                                                               bv, &nbv, memctx ) != LDAP_SUCCESS )
+                                               {
+                                                       /* FIXME: stop processing? */
+                                                       continue;
+                                               }
+
+                                       } else {
+                                               nbv = *bv;
+                                       }
+
                                        rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
-                                               bv, &mra->ma_value, &text );
+                                               &nbv, &mra->ma_value, &text );
+
+                                       if ( nbv.bv_val != bv->bv_val ) {
+                                               memfree( nbv.bv_val, memctx );
+                                       }
                                }
 
-                               if( rc != LDAP_SUCCESS ) return rc;
+                               if ( rc != LDAP_SUCCESS ) return rc;
                                if ( ret == 0 ) return LDAP_COMPARE_TRUE;
                        }
                }
@@ -279,9 +326,10 @@ static int test_mra_filter(
                        struct berval   *bv, value;
                        const char      *text = NULL;
                        int             rc;
+                       int             normalize_attribute = 0;
 
                        /* check if matching is appropriate */
-                       if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type )) {
+                       if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type ) ) {
                                continue;
                        }
 
@@ -293,20 +341,21 @@ static int test_mra_filter(
 
                        /* check search access */
                        if ( !access_allowed( op, e,
-                               a->a_desc, &value, ACL_SEARCH, NULL ) ) {
+                               a->a_desc, &value, ACL_SEARCH, NULL ) )
+                       {
                                memfree( value.bv_val, memctx );
                                continue;
                        }
 #ifdef LDAP_COMP_MATCH
                        /* Component Matching */
-                       if( mra->ma_cf &&
-                               mra->ma_rule->smr_usage & SLAP_MR_COMPONENT)
+                       if ( mra->ma_cf &&
+                               mra->ma_rule->smr_usage & SLAP_MR_COMPONENT )
                        {
                                int ret;
 
                                rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
                                        (struct berval*)a, (void*)mra, &text );
-                               if( rc != LDAP_SUCCESS ) break;
+                               if ( rc != LDAP_SUCCESS ) break;
        
                                if ( ret == 0 ) {
                                        rc = LDAP_COMPARE_TRUE;
@@ -317,19 +366,42 @@ static int test_mra_filter(
 #endif
 
                        /* check match */
-                       if (mra->ma_rule == a->a_desc->ad_type->sat_equality) {
+                       if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
                                bv = a->a_nvals;
+
                        } else {
                                bv = a->a_vals;
+                               normalize_attribute = 1;
                        }
 
-                       for ( ; bv->bv_val != NULL; bv++ ) {
-                               int ret;
-       
+                       for ( ; !BER_BVISNULL( bv ); bv++ ) {
+                               int             ret;
+                               struct berval   nbv = BER_BVNULL;
+
+                               if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
+                                       /* see comment above */
+                                       if ( mra->ma_rule->smr_normalize(
+                                                       SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                                       mra->ma_rule->smr_syntax,
+                                                       mra->ma_rule,
+                                                       bv, &nbv, memctx ) != LDAP_SUCCESS )
+                                       {
+                                               /* FIXME: stop processing? */
+                                               continue;
+                                       }
+
+                               } else {
+                                       nbv = *bv;
+                               }
+
                                rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
-                                       bv, &value, &text );
+                                       &nbv, &value, &text );
+
+                               if ( nbv.bv_val != bv->bv_val ) {
+                                       memfree( nbv.bv_val, memctx );
+                               }
 
-                               if( rc != LDAP_SUCCESS ) break;
+                               if ( rc != LDAP_SUCCESS ) break;
        
                                if ( ret == 0 ) {
                                        rc = LDAP_COMPARE_TRUE;
@@ -378,7 +450,7 @@ static int test_mra_filter(
                                        const char      *text = NULL;
 
                                        /* check if matching is appropriate */
-                                       if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type )) {
+                                       if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type ) ) {
                                                continue;
                                        }
 
@@ -407,7 +479,7 @@ static int test_mra_filter(
 
                                if ( rc == LDAP_SUCCESS && ret == 0 ) rc = LDAP_COMPARE_TRUE;
 
-                               if( rc != LDAP_SUCCESS ) {
+                               if ( rc != LDAP_SUCCESS ) {
                                        ldap_dnfree_x( dn, memctx );
                                        return rc;
                                }
@@ -532,7 +604,7 @@ test_ava_filter(
                        continue;
                }
 
-               for ( bv = a->a_nvals; bv->bv_val != NULL; bv++ ) {
+               for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
                        int ret, match;
                        const char *text;
 
@@ -721,7 +793,7 @@ test_substrings_filter(
                        continue;
                }
 
-               for ( bv = a->a_nvals; bv->bv_val != NULL; bv++ ) {
+               for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
                        int ret, match;
                        const char *text;
 
index e1fca24d32d4eb01ffc1aea3dca32948316b20ce..bf9635b8755a659ef468f279e7d15a0f71b24d08 100644 (file)
@@ -42,8 +42,8 @@
 #include "slapi/slapi.h"
 #endif
 
-BackendInfo    slap_frontendInfo;
-BackendDB      slap_frontendDB;
+static BackendInfo     slap_frontendInfo;
+static BackendDB       slap_frontendDB;
 BackendDB      *frontendDB;
 
 int
@@ -87,6 +87,7 @@ frontend_init( void )
 
        /* known controls */
        frontendDB->bd_info->bi_controls = slap_known_controls;
+       frontendDB->be_controls = ldap_charray_dup( slap_known_controls );
 
        /* calls */
        frontendDB->bd_info->bi_op_abandon = fe_op_abandon;
index d458acb033e11974ad473f9420b665e098fbffce..c88876e046dcfbc2c281e7f92d2ed4144a9ffab9 100644 (file)
@@ -259,7 +259,6 @@ int main( int argc, char **argv )
        char        *serverName;
        int         serverMode = SLAP_SERVER_MODE;
 
-       struct berval cookie = BER_BVNULL;
        struct sync_cookie *scp = NULL;
        struct sync_cookie *scp_entry = NULL;
 
@@ -356,8 +355,7 @@ int main( int argc, char **argv )
                case 'c':       /* provide sync cookie, override if exist in replica */
                        scp = (struct sync_cookie *) ch_calloc( 1,
                                                                                sizeof( struct sync_cookie ));
-                       ber_str2bv( optarg, strlen( optarg ), 1, &cookie );
-                       ber_bvarray_add( &scp->octet_str, &cookie );
+                       ber_str2bv( optarg, 0, 1, &scp->octet_str );
                        slap_parse_sync_cookie( scp );
 
                        LDAP_STAILQ_FOREACH( scp_entry, &slap_sync_cookie, sc_next ) {
index b95765ef93fa1bd7145916a02073b5731147d5c4..2ef1d934e891e4b867e46a926a171c04ccd318a6 100644 (file)
@@ -171,7 +171,7 @@ test_ava_vrFilter(
                if( mr == NULL ) continue;
 
                bv = a->a_nvals;
-               for ( j=0; bv->bv_val != NULL; bv++, j++ ) {
+               for ( j=0; !BER_BVISNULL( bv ); bv++, j++ ) {
                        int rc, match;
                        const char *text;
 
@@ -218,7 +218,7 @@ test_presence_vrFilter(
 
                if ( !is_ad_subtype( a->a_desc, desc ) ) continue;
 
-               for ( bv = a->a_vals, j=0; bv->bv_val != NULL; bv++, j++ );
+               for ( bv = a->a_vals, j = 0; !BER_BVISNULL( bv ); bv++, j++ );
                memset( (*e_flags)[i], 1, j);
        }
 
@@ -245,7 +245,7 @@ test_substrings_vrFilter(
                if( mr == NULL ) continue;
 
                bv = a->a_nvals;
-               for ( j = 0; bv->bv_val != NULL; bv++, j++ ) {
+               for ( j = 0; !BER_BVISNULL( bv ); bv++, j++ ) {
                        int rc, match;
                        const char *text;
 
@@ -270,10 +270,11 @@ test_mra_vrFilter(
        MatchingRuleAssertion *mra,
        char            ***e_flags )
 {
-       int i, j;
+       int     i, j;
 
-       for ( i=0; a != NULL; a = a->a_next, i++ ) {
-               struct berval *bv, assertedValue;
+       for ( i = 0; a != NULL; a = a->a_next, i++ ) {
+               struct berval   *bv, assertedValue;
+               int             normalize_attribute = 0;
 
                if ( mra->ma_desc ) {
                        if ( !is_ad_subtype( a->a_desc, mra->ma_desc ) ) {
@@ -294,23 +295,47 @@ test_mra_vrFilter(
                                SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
                                &mra->ma_value, &assertedValue, &text, op->o_tmpmemctx );
 
-                       if( rc != LDAP_SUCCESS ) continue;
+                       if ( rc != LDAP_SUCCESS ) continue;
                }
 
                /* check match */
-               if (mra->ma_rule == a->a_desc->ad_type->sat_equality) {
+               if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
                        bv = a->a_nvals;
+
                } else {
                        bv = a->a_vals;
+                       normalize_attribute = 1;
                }
                                        
-               for ( j = 0; bv->bv_val != NULL; bv++, j++ ) {
-                       int rc, match;
-                       const char *text;
+               for ( j = 0; !BER_BVISNULL( bv ); bv++, j++ ) {
+                       int             rc, match;
+                       const char      *text;
+                       struct berval   nbv = BER_BVNULL;
+
+                       if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
+                               /* see comment in filterentry.c */
+                               if ( mra->ma_rule->smr_normalize(
+                                               SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                               mra->ma_rule->smr_syntax,
+                                               mra->ma_rule,
+                                               bv, &nbv, op->o_tmpmemctx ) != LDAP_SUCCESS )
+                               {
+                                       /* FIXME: stop processing? */
+                                       continue;
+                               }
+
+                       } else {
+                               nbv = *bv;
+                       }
 
                        rc = value_match( &match, a->a_desc, mra->ma_rule, 0,
-                               bv, &assertedValue, &text );
-                       if( rc != LDAP_SUCCESS ) return rc;
+                               &nbv, &assertedValue, &text );
+
+                       if ( nbv.bv_val != bv->bv_val ) {
+                               op->o_tmpfree( nbv.bv_val, op->o_tmpmemctx );
+                       }
+
+                       if ( rc != LDAP_SUCCESS ) return rc;
 
                        if ( match == 0 ) {
                                (*e_flags)[i][j] = 1;
index 89381cc38bb0114e6c37a39ed51fe2dc36747999..976721669cbbcc064f6d30200aba80afb3dfbc8f 100644 (file)
@@ -217,9 +217,7 @@ register_matching_rule(
        int             code;
        const char      *err;
 
-       if( def->mrd_usage == SLAP_MR_NONE &&
-               def->mrd_compat_syntaxes == NULL )
-       {
+       if( def->mrd_usage == SLAP_MR_NONE && def->mrd_compat_syntaxes == NULL ) {
                Debug( LDAP_DEBUG_ANY, "register_matching_rule: not usable %s\n",
                    def->mrd_desc, 0, 0 );
 
@@ -228,10 +226,9 @@ register_matching_rule(
 
        if( def->mrd_associated != NULL ) {
                amr = mr_find( def->mrd_associated );
-
                if( amr == NULL ) {
-                       Debug( LDAP_DEBUG_ANY, "register_matching_rule: could not locate "
-                               "associated matching rule %s for %s\n",
+                       Debug( LDAP_DEBUG_ANY, "register_matching_rule: "
+                               "could not locate associated matching rule %s for %s\n",
                                def->mrd_associated, def->mrd_desc, 0 );
 
                        return -1;
@@ -243,17 +240,15 @@ register_matching_rule(
                        if (( def->mrd_usage & SLAP_MR_EQUALITY ) &&
                                (( def->mrd_usage & SLAP_MR_SUBTYPE_MASK ) != SLAP_MR_NONE ))
                        {
-                               Debug( LDAP_DEBUG_ANY,
-                                  "register_matching_rule: inappropriate (approx) association "
-                                               "%s for %s\n",
+                               Debug( LDAP_DEBUG_ANY, "register_matching_rule: "
+                                               "inappropriate (approx) association %s for %s\n",
                                        def->mrd_associated, def->mrd_desc, 0 );
                                return -1;
                        }
 
                } else if (!( amr->smr_usage & SLAP_MR_EQUALITY )) {
-                               Debug( LDAP_DEBUG_ANY,
-                                  "register_matching_rule: inappropriate (equalilty) association "
-                                               "%s for %s\n",
+                               Debug( LDAP_DEBUG_ANY, "register_matching_rule: "
+                                       "inappropriate (equalilty) association %s for %s\n",
                                        def->mrd_associated, def->mrd_desc, 0 );
                                return -1;
                }
index 11bd2ca7eebdf00ca26758296be5a596eafaffb9..f572875fef781615c35a269607984e3babb6149f 100644 (file)
@@ -1706,6 +1706,14 @@ ppolicy_db_init(
        return 0;
 }
 
+static int
+ppolicy_db_open(
+    BackendDB *be
+)
+{
+       return overlay_register_control( be, LDAP_CONTROL_PASSWORDPOLICYREQUEST );
+}
+
 static int
 ppolicy_close(
        BackendDB *be
@@ -1802,7 +1810,7 @@ int ppolicy_init()
        }
 
        code = register_supported_control( LDAP_CONTROL_PASSWORDPOLICYREQUEST,
-               SLAP_CTRL_ADD|SLAP_CTRL_BIND|SLAP_CTRL_MODIFY, extops,
+               SLAP_CTRL_ADD|SLAP_CTRL_BIND|SLAP_CTRL_MODIFY|SLAP_CTRL_HIDE, extops,
                ppolicy_parseCtrl, &ppolicy_cid );
        if ( code != LDAP_SUCCESS ) {
                fprintf( stderr, "Failed to register control %d\n", code );
@@ -1813,6 +1821,7 @@ int ppolicy_init()
 
        ppolicy.on_bi.bi_type = "ppolicy";
        ppolicy.on_bi.bi_db_init = ppolicy_db_init;
+       ppolicy.on_bi.bi_db_open = ppolicy_db_open;
        ppolicy.on_bi.bi_db_config = ppolicy_config;
        ppolicy.on_bi.bi_db_close = ppolicy_close;
 
index 8b5ca2077b01eb9d74fef2787dbddc13a2db0d38..aa51bcd07ec7b094db044e0d1023dba82b368cb3 100644 (file)
@@ -2012,6 +2012,11 @@ syncprov_db_open(
        Attribute *a;
        int rc;
 
+       rc = overlay_register_control( be, LDAP_CONTROL_SYNC );
+       if ( rc ) {
+               return rc;
+       }
+
        connection_fake_init( &conn, op, thrctx );
        op->o_bd = be;
        op->o_dn = be->be_rootdn;
index bacc1b3772468e7a63dd0e8cd1a3068d617eef70..133ecb8d00daf4cd2f744205ac5a79cfc04c9714 100644 (file)
@@ -291,6 +291,15 @@ LDAP_SLAPD_F (int) backend_attribute LDAP_P((
        slap_access_t access
 ));
 
+LDAP_SLAPD_F (int) backend_access LDAP_P((
+       Operation               *op,
+       Entry                   *target,
+       struct berval           *edn,
+       AttributeDescription    *entry_at,
+       struct berval           *nval,
+       slap_access_t           access,
+       slap_mask_t             *mask ));
+
 LDAP_SLAPD_F (int) backend_operational LDAP_P((
        Operation *op,
        SlapReply *rs 
@@ -315,6 +324,9 @@ LDAP_SLAPD_F (slap_overinst *) overlay_next LDAP_P(( slap_overinst *on ));
 LDAP_SLAPD_F (slap_overinst *) overlay_find LDAP_P(( const char *name ));
 LDAP_SLAPD_F (int) overlay_is_over LDAP_P(( BackendDB *be ));
 LDAP_SLAPD_F (int) overlay_is_inst LDAP_P(( BackendDB *be, const char *name ));
+LDAP_SLAPD_F (int) overlay_register_control LDAP_P((
+       BackendDB *be,
+       const char *oid ));
 
 /*
  * ch_malloc.c
@@ -413,8 +425,12 @@ LDAP_SLAPD_F (int) register_supported_control LDAP_P((
 LDAP_SLAPD_F (int) slap_controls_init LDAP_P ((void));
 LDAP_SLAPD_F (void) controls_destroy LDAP_P ((void));
 LDAP_SLAPD_F (int) controls_root_dse_info LDAP_P ((Entry *e));
-LDAP_SLAPD_F (int) get_supported_controls LDAP_P (( char ***ctrloidsp, slap_mask_t **ctrlmasks ));
-LDAP_SLAPD_F (int) slap_find_control_id LDAP_P (( const char *oid, int *cid ));
+LDAP_SLAPD_F (int) get_supported_controls LDAP_P ((
+       char ***ctrloidsp, slap_mask_t **ctrlmasks ));
+LDAP_SLAPD_F (int) slap_find_control_id LDAP_P ((
+       const char *oid, int *cid ));
+LDAP_SLAPD_F (int) slap_global_control LDAP_P ((
+       Operation *op, const char *oid ));
 
 /*
  * config.c
@@ -422,9 +438,7 @@ LDAP_SLAPD_F (int) slap_find_control_id LDAP_P (( const char *oid, int *cid ));
 LDAP_SLAPD_F (int) read_config LDAP_P(( const char *fname, int depth ));
 LDAP_SLAPD_F (void) config_destroy LDAP_P ((void));
 LDAP_SLAPD_F (char **) slap_str2clist LDAP_P((
-                                               char ***,
-                                               char *,
-                                               const char * ));
+       char ***, char *, const char * ));
 #ifdef LDAP_SLAPI
 LDAP_SLAPD_V (int) slapi_plugins_used;
 #endif
index 79d3a38c1302db62b3bfab3b279f4643aac095b4..08566e473071d1903dd03efd7aed33dc286d023f 100644 (file)
@@ -1564,7 +1564,11 @@ struct slap_backend_db {
  */
 #define                be_has_subordinates bd_info->bi_has_subordinates
 
-#define                be_controls     bd_info->bi_controls
+       /* supported controls */
+       /* NOTE: this stores a duplicate of the control OIDs as listed
+        * in bd_info->bi_controls at database startup; later on,
+        * controls may be added run-time, e.g. by overlays */
+       char            **be_controls;
 
 #define                be_connection_init      bd_info->bi_connection_init
 #define                be_connection_destroy   bd_info->bi_connection_destroy
@@ -1589,7 +1593,8 @@ struct slap_backend_db {
 #define        SLAP_DBFLAG_GLUE_INSTANCE       0x0010U /* a glue backend */
 #define        SLAP_DBFLAG_GLUE_SUBORDINATE    0x0020U /* child of a glue hierarchy */
 #define        SLAP_DBFLAG_GLUE_LINKED         0x0040U /* child is connected to parent */
-#define SLAP_DBFLAG_OVERLAY                    0x0080U /* this db struct is an overlay */
+#define SLAP_DBFLAG_OVERLAY            0x0080U /* this db struct is an overlay */
+#define        SLAP_DBFLAG_GLOBAL_OVERLAY      0x0100U /* this db struct is a global overlay */
 #define SLAP_DBFLAG_SHADOW             0x8000U /* a shadow */
 #define SLAP_DBFLAG_SYNC_SHADOW                0x1000U /* a sync shadow */
 #define SLAP_DBFLAG_SLURP_SHADOW       0x2000U /* a slurp shadow */
@@ -2558,8 +2563,8 @@ typedef struct slap_counters_t {
 #define SLAP_CTRL_HIDE                         0x80000000U
 #endif
 
-#define SLAP_CTRL_FRONTEND                     0x00800000U
-#define SLAP_CTRL_FRONTEND_SEARCH      0x00010000U     /* for NOOP */
+#define SLAP_CTRL_GLOBAL                       0x00800000U
+#define SLAP_CTRL_GLOBAL_SEARCH                0x00010000U     /* for NOOP */
 
 #define SLAP_CTRL_OPFLAGS                      0x0000FFFFU
 #define SLAP_CTRL_ABANDON                      0x00000001U
index c768f52f3ec7463c6dc81de01211219a024dbf48..41642c6ceda19e2fcb818eded7d78ce624f89c58 100644 (file)
@@ -60,7 +60,7 @@ usage( int tool, const char *progname )
 
        case SLAPADD:
                options = "\n\t[-n databasenumber | -b suffix]\n"
-                       "\t[-l ldiffile] [-u] [-w]\n";
+                       "\t[-l ldiffile] [-q] [-u] [-w]\n";
                break;
 
        case SLAPAUTH:
@@ -77,7 +77,7 @@ usage( int tool, const char *progname )
                break;
 
        case SLAPINDEX:
-               options = "\n\t[-n databasenumber | -b suffix]\n";
+               options = "\n\t[-n databasenumber | -b suffix] [-q]\n";
                break;
 
        case SLAPTEST:
@@ -151,7 +151,7 @@ slap_tool_init(
                break;
 
        case SLAPINDEX:
-               options = "b:cd:f:n:v";
+               options = "b:cd:f:n:qv";
                mode |= SLAP_TOOL_READMAIN;
                break;