From a050bdee682f484970ec2e6943fc1b3041c9a33a Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Mon, 14 Mar 2005 23:24:58 +0000 Subject: [PATCH] Sync with HEAD --- servers/slapd/back-ldap/back-ldap.h | 12 +- servers/slapd/back-ldap/bind.c | 96 ++- servers/slapd/back-ldap/chain.c | 319 +++++++- servers/slapd/back-ldap/config.c | 62 +- servers/slapd/back-ldap/search.c | 23 +- servers/slapd/back-ldbm/modrdn.c | 2 + servers/slapd/back-ldbm/search.c | 2 +- servers/slapd/back-ldif/Makefile.in | 41 + servers/slapd/back-ldif/ldif.c | 993 +++++++++++++++++++++++ servers/slapd/back-meta/add.c | 8 +- servers/slapd/back-meta/back-meta.h | 15 +- servers/slapd/back-meta/bind.c | 8 +- servers/slapd/back-meta/compare.c | 13 +- servers/slapd/back-meta/config.c | 68 +- servers/slapd/back-meta/conn.c | 148 +++- servers/slapd/back-meta/delete.c | 17 +- servers/slapd/back-meta/modify.c | 19 +- servers/slapd/back-meta/modrdn.c | 21 +- servers/slapd/back-meta/search.c | 15 +- servers/slapd/back-monitor/database.c | 7 +- servers/slapd/back-passwd/search.c | 2 +- servers/slapd/back-sql/back-sql.h | 1 - servers/slapd/back-sql/search.c | 43 +- servers/slapd/bconfig.c | 7 +- servers/slapd/overlays/Makefile.in | 5 + servers/slapd/overlays/glue.c | 4 +- servers/slapd/overlays/overlays.c | 6 + servers/slapd/overlays/rwm.c | 46 +- servers/slapd/overlays/rwmmap.c | 3 +- servers/slapd/overlays/syncprov.c | 31 + servers/slapd/overlays/translucent.c | 734 +++++++++++++++++ servers/slapd/overlays/unique.c | 14 +- servers/slapd/slap.h | 3 - servers/slapd/slapi/plugin.c | 68 +- servers/slapd/slapi/proto-slapi.h | 1 + servers/slapd/slapi/slapi.h | 17 +- servers/slapd/slapi/slapi_pblock.c | 222 ++--- tests/data/modify.out.master | 3 +- tests/data/relay.out | 8 + tests/data/slapd-ldapgluegroups.conf | 2 - tests/data/slapd-ldapgluepeople.conf | 2 - tests/data/slapd-pw.conf | 2 - tests/data/slapd-translucent-local.conf | 52 ++ tests/data/slapd-translucent-remote.conf | 41 + tests/data/slapd-whoami.conf | 2 - tests/data/slapd.conf | 1 + tests/data/test-translucent-add.ldif | 10 + tests/data/test-translucent-config.ldif | 26 + tests/data/test-translucent-data.ldif | 42 + tests/data/test-translucent-merged.ldif | 40 + tests/data/test.schema | 40 +- tests/run.in | 3 +- tests/scripts/conf.sh | 1 + tests/scripts/defines.sh | 12 + tests/scripts/relay | 17 +- tests/scripts/test004-modify | 3 +- tests/scripts/test010-passwd | 9 + tests/scripts/test031-component-filter | 4 +- tests/scripts/test034-translucent | 717 ++++++++++++++++ 59 files changed, 3779 insertions(+), 354 deletions(-) create mode 100644 servers/slapd/back-ldif/Makefile.in create mode 100644 servers/slapd/back-ldif/ldif.c create mode 100644 servers/slapd/overlays/translucent.c create mode 100644 tests/data/slapd-translucent-local.conf create mode 100644 tests/data/slapd-translucent-remote.conf create mode 100644 tests/data/test-translucent-add.ldif create mode 100644 tests/data/test-translucent-config.ldif create mode 100644 tests/data/test-translucent-data.ldif create mode 100644 tests/data/test-translucent-merged.ldif create mode 100755 tests/scripts/test034-translucent diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index f881c38749..48b2e949ad 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -94,8 +94,16 @@ struct ldapinfo { #define LDAP_BACK_F_NONE 0x00U #define LDAP_BACK_F_SAVECRED 0x01U #define LDAP_BACK_F_USE_TLS 0x02U -#define LDAP_BACK_F_TLS_CRITICAL ( 0x04U | LDAP_BACK_F_USE_TLS ) -#define LDAP_BACK_F_CHASE_REFERRALS 0x8U +#define LDAP_BACK_F_PROPAGATE_TLS 0x04U +#define LDAP_BACK_F_TLS_CRITICAL 0x08U +#define LDAP_BACK_F_CHASE_REFERRALS 0x10U + +#define LDAP_BACK_SAVECRED(li) ( (li)->flags & LDAP_BACK_F_SAVECRED ) +#define LDAP_BACK_USE_TLS(li) ( (li)->flags & LDAP_BACK_F_USE_TLS ) +#define LDAP_BACK_PROPAGATE_TLS(li) ( (li)->flags & LDAP_BACK_F_PROPAGATE_TLS ) +#define LDAP_BACK_TLS_CRITICAL(li) ( (li)->flags & LDAP_BACK_F_TLS_CRITICAL ) +#define LDAP_BACK_CHASE_REFERRALS(li) ( (li)->flags & LDAP_BACK_F_CHASE_REFERRALS ) + Avlnode *conntree; int rwm_started; diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index 817235ee3a..446ce1c458 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -87,7 +87,7 @@ ldap_back_bind( Operation *op, SlapReply *rs ) lc->lc_bound = 1; ber_dupbv( &lc->lc_bound_ndn, &op->o_req_ndn ); - if ( li->flags & LDAP_BACK_F_SAVECRED ) { + if ( LDAP_BACK_SAVECRED( li ) ) { if ( !BER_BVISNULL( &lc->lc_cred ) ) { memset( lc->lc_cred.bv_val, 0, lc->lc_cred.bv_len ); @@ -241,27 +241,99 @@ ldap_back_prepare_conn( struct ldapconn **lcp, Operation *op, SlapReply *rs, lda */ ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&vers ); - /* automatically chase referrals ("chase-referrals"/"dont-chase-referrals" statement) */ - if ( li->flags & LDAP_BACK_F_CHASE_REFERRALS ) { + /* automatically chase referrals ("[dont-]chase-referrals" statement) */ + if ( LDAP_BACK_CHASE_REFERRALS( li ) ) { ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON ); } - /* start TLS ("start-tls"/"try-start-tls" statements) */ - if ( ( li->flags & LDAP_BACK_F_USE_TLS ) - && !ldap_is_ldaps_url( li->url ) - && ( rs->sr_err = ldap_start_tls_s( ld, NULL, NULL ) ) != LDAP_SUCCESS ) +#ifdef HAVE_TLS + /* start TLS ("tls-[try-]{start,propagate}" statements) */ + if ( ( LDAP_BACK_USE_TLS( li ) || ( op->o_conn->c_is_tls && LDAP_BACK_PROPAGATE_TLS( li ) ) ) + && !ldap_is_ldaps_url( li->url ) ) { +#if 1 + /* + * use asynchronous StartTLS + * in case, chase referral (not implemented yet) + */ + int msgid; + + rs->sr_err = ldap_start_tls( ld, NULL, NULL, &msgid ); + if ( rs->sr_err == LDAP_SUCCESS ) { + LDAPMessage *res = NULL; + int rc, retries = 1; + struct timeval tv = { 0, 0 }; + +retry:; + rc = ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res ); + if ( rc < 0 ) { + rs->sr_err = LDAP_OTHER; + + } else if ( rc == 0 ) { + if ( retries ) { + retries--; + tv.tv_sec = 0; + tv.tv_usec = 100000; + goto retry; + } + rs->sr_err = LDAP_OTHER; + + } else if ( rc == LDAP_RES_EXTENDED ) { + struct berval *data = NULL; + + rs->sr_err = ldap_parse_extended_result( ld, res, + NULL, &data, 0 ); + if ( rs->sr_err == LDAP_SUCCESS ) { + rs->sr_err = ldap_result2error( ld, res, 1 ); + res = NULL; + + /* FIXME: in case a referral + * is returned, should we try + * using it instead of the + * configured URI? */ + if ( rs->sr_err == LDAP_SUCCESS ) { + ldap_install_tls( ld ); + + } else if ( rs->sr_err == LDAP_REFERRAL ) { + rs->sr_err = LDAP_OTHER; + rs->sr_text = "unwilling to chase referral returned by Start TLS exop"; + } + + if ( data ) { + if ( data->bv_val ) { + ber_memfree( data->bv_val ); + } + ber_memfree( data ); + } + } + + } else { + rs->sr_err = LDAP_OTHER; + } + + if ( res != NULL ) { + ldap_msgfree( res ); + } + } +#else + /* + * use synchronous StartTLS + */ + rs->sr_err = ldap_start_tls_s( ld, NULL, NULL ); +#endif + /* if StartTLS is requested, only attempt it if the URL * is not "ldaps://"; this may occur not only in case * of misconfiguration, but also when used in the chain * overlay, where the "uri" can be parsed out of a referral */ if ( rs->sr_err == LDAP_SERVER_DOWN - || ( li->flags & LDAP_BACK_F_TLS_CRITICAL ) ) + || ( rs->sr_err != LDAP_SUCCESS && LDAP_BACK_TLS_CRITICAL( li ) ) ) { ldap_unbind_ext_s( ld, NULL, NULL ); goto error_return; } } +#endif /* HAVE_TLS */ if ( *lcp == NULL ) { *lcp = (struct ldapconn *)ch_malloc( sizeof( struct ldapconn ) ); @@ -797,8 +869,12 @@ done:; * If no server-side controls are defined for the operation, * simply add the proxyAuthz control; otherwise, if the * proxyAuthz control is not already set, add it as - * the first one (FIXME: is controls order significant - * for security?). + * the first one + * + * FIXME: is controls order significant for security? + * ANSWER: controls ordering and interoperability + * must be indicated by the specs of each control; if none + * is specified, the order is irrelevant. */ int ldap_back_proxy_authz_ctrl( diff --git a/servers/slapd/back-ldap/chain.c b/servers/slapd/back-ldap/chain.c index 7dcb95f29f..543960f228 100644 --- a/servers/slapd/back-ldap/chain.c +++ b/servers/slapd/back-ldap/chain.c @@ -30,35 +30,121 @@ #include "back-ldap.h" #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR +#define SLAP_CHAINING_DEFAULT LDAP_CHAINING_PREFERRED #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_RESOLVE_DEFAULT (SLAP_CHAINING_DEFAULT << SLAP_CH_RESOLVE_SHIFT) #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 SLAP_CH_CONTINUATION_DEFAULT (SLAP_CHAINING_DEFAULT << SLAP_CH_CONTINUATION_SHIFT) #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) + +static int sc_chainingBehavior; #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; +typedef struct ldap_chain_t { + struct ldapinfo *lc_li; + unsigned lc_flags; +#define LDAP_CHAIN_F_NONE 0x00U +#define LDAP_CHAIN_F_CHAINING 0x01U + +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR + LDAPControl lc_chaining_ctrl; + char lc_chaining_ctrlflag; +#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ +} ldap_chain_t; + +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR +static int +chaining_control_add( + ldap_chain_t *lc, + Operation *op, + LDAPControl ***oldctrlsp ) +{ + LDAPControl **ctrls = NULL; + int c = 0; + + *oldctrlsp = op->o_ctrls; + + /* default chaining control not defined */ + if ( !( lc->lc_flags & LDAP_CHAIN_F_CHAINING ) ) { + return 0; + } + + /* already present */ + if ( get_chaining( op ) > SLAP_CONTROL_IGNORED ) { + return 0; + } + + /* FIXME: check other incompatibilities */ + + /* add to other controls */ + if ( op->o_ctrls ) { + for ( c = 0; op->o_ctrls[ c ]; c++ ) + /* count them */ ; + } + + ctrls = ch_calloc( sizeof( LDAPControl *), c + 2 ); + ctrls[ 0 ] = &lc->lc_chaining_ctrl; + if ( op->o_ctrls ) { + for ( c = 0; op->o_ctrls[ c ]; c++ ) { + ctrls[ c + 1 ] = op->o_ctrls[ c ]; + } + } + ctrls[ c + 1 ] = NULL; + + op->o_ctrls = ctrls; + + op->o_chaining = lc->lc_chaining_ctrlflag; + + return 0; +} + +static int +chaining_control_remove( + Operation *op, + LDAPControl ***oldctrlsp ) +{ + LDAPControl **oldctrls = *oldctrlsp; + + /* we assume that the first control is the chaining control + * added by the chain overlay, so it's the only one we explicitly + * free */ + if ( op->o_ctrls != oldctrls ) { + assert( op->o_ctrls ); + assert( op->o_ctrls[ 0 ] ); + + free( op->o_ctrls ); + + op->o_chaining = 0; + op->o_ctrls = oldctrls; + } + + *oldctrlsp = NULL; + + return 0; +} +#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ + static int ldap_chain_operational( Operation *op, SlapReply *rs ) { @@ -170,14 +256,22 @@ ldap_chain_op( BerVarray ref ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; - struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private; + ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; + struct ldapinfo li, *lip = lc->lc_li; /* NOTE: returned if ref is empty... */ int rc = LDAP_OTHER; +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR + LDAPControl **ctrls = NULL; + + (void)chaining_control_add( lc, op, &ctrls ); +#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ + if ( lip->url != NULL ) { - op->o_bd->be_private = on->on_bi.bi_private; - return ( *op_f )( op, rs ); + op->o_bd->be_private = lip; + rc = ( *op_f )( op, rs ); + goto done; } li = *lip; @@ -245,6 +339,11 @@ Document: draft-ietf-ldapbis-protocol-27.txt } } +done:; +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR + (void)chaining_control_remove( op, &ctrls ); +#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ + return rc; } @@ -260,7 +359,8 @@ ldap_chain_response( Operation *op, SlapReply *rs ) BerVarray ref; struct berval ndn = op->o_ndn; - struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private; + ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; + struct ldapinfo li, *lip = lc->lc_li; #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR int sr_err = rs->sr_err; @@ -394,6 +494,12 @@ ldap_chain_response( Operation *op, SlapReply *rs ) odn = op->o_req_dn, ondn = op->o_req_ndn; +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR + LDAPControl **ctrls = NULL; + + (void)chaining_control_add( lc, op, &ctrls ); +#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ + rs->sr_type = REP_SEARCH; sc2.sc_response = ldap_chain_cb_search_response; @@ -466,6 +572,10 @@ ldap_chain_response( Operation *op, SlapReply *rs ) rc = rs->sr_err; } +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR + (void)chaining_control_remove( op, &ctrls ); +#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ + op->o_req_dn = odn; op->o_req_ndn = ondn; rs->sr_type = REP_SEARCHREF; @@ -536,6 +646,33 @@ dont_chain:; return rc; } +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR +static int +ldap_chain_parse_ctrl( + Operation *op, + SlapReply *rs, + LDAPControl *ctrl ); + +static int +str2chain( const char *s ) +{ + if ( strcasecmp( s, "chainingPreferred" ) == 0 ) { + return LDAP_CHAINING_PREFERRED; + + } else if ( strcasecmp( s, "chainingRequired" ) == 0 ) { + return LDAP_CHAINING_REQUIRED; + + } else if ( strcasecmp( s, "referralsPreferred" ) == 0 ) { + return LDAP_REFERRALS_PREFERRED; + + } else if ( strcasecmp( s, "referralsRequired" ) == 0 ) { + return LDAP_REFERRALS_REQUIRED; + } + + return -1; +} +#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ + static int ldap_chain_db_config( BackendDB *be, @@ -546,21 +683,140 @@ ldap_chain_db_config( ) { slap_overinst *on = (slap_overinst *) be->bd_info; + ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; void *private = be->be_private; char *argv0 = NULL; int rc; - be->be_private = on->on_bi.bi_private; if ( strncasecmp( argv[ 0 ], "chain-", STRLENOF( "chain-" ) ) == 0 ) { argv0 = argv[ 0 ]; argv[ 0 ] = &argv[ 0 ][ STRLENOF( "chain-" ) ]; + +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR + if ( strcasecmp( argv[ 0 ], "chaining" ) == 0 ) { + char **tmpargv = argv; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *)&berbuf; + int resolve = -1, + continuation = -1, + iscritical = 0; + Operation op = { 0 }; + SlapReply rs = { 0 }; + + lc->lc_chaining_ctrlflag = 0; + + for ( argc--, tmpargv++; argc > 0; argc--, tmpargv++ ) { + if ( strncasecmp( tmpargv[ 0 ], "resolve=", STRLENOF( "resolve=" ) ) == 0 ) { + resolve = str2chain( tmpargv[ 0 ] + STRLENOF( "resolve=" ) ); + if ( resolve == -1 ) { + fprintf( stderr, "%s line %d: " + "illegal value %s " + "in \"chain-chaining>\"\n", + fname, lineno, tmpargv[ 0 ] ); + return 1; + } + + } else if ( strncasecmp( tmpargv[ 0 ], "continuation=", STRLENOF( "continuation=" ) ) == 0 ) { + continuation = str2chain( tmpargv[ 0 ] + STRLENOF( "continuation=" ) ); + if ( continuation == -1 ) { + fprintf( stderr, "%s line %d: " + "illegal value %s " + "in \"chain-chaining\"\n", + fname, lineno, tmpargv[ 0 ] ); + return 1; + } + + } else if ( strcasecmp( tmpargv[ 0 ], "critical" ) == 0 ) { + iscritical = 1; + + } else { + fprintf( stderr, "%s line %d: " + "unknown option in \"chain-chaining\"\n", + fname, lineno ); + return 1; + } + } + + if ( resolve != -1 || continuation != -1 ) { + int err; + + if ( resolve == -1 ) { + /* default */ + resolve = SLAP_CHAINING_DEFAULT; + } + + ber_init2( ber, NULL, LBER_USE_DER ); + + err = ber_printf( ber, "{e" /* } */, resolve ); + if ( err == -1 ) { + ber_free( ber, 1 ); + fprintf( stderr, "%s line %d: " + "chaining behavior control encoding error!\n", + fname, lineno ); + return 1; + } + + if ( continuation > -1 ) { + err = ber_printf( ber, "e", continuation ); + if ( err == -1 ) { + ber_free( ber, 1 ); + fprintf( stderr, "%s line %d: " + "chaining behavior control encoding error!\n", + fname, lineno ); + return 1; + } + } + + err = ber_printf( ber, /* { */ "N}" ); + if ( err == -1 ) { + ber_free( ber, 1 ); + fprintf( stderr, "%s line %d: " + "chaining behavior control encoding error!\n", + fname, lineno ); + return 1; + } + + if ( ber_flatten2( ber, &lc->lc_chaining_ctrl.ldctl_value, 0 ) == -1 ) { + exit( EXIT_FAILURE ); + } + + } else { + BER_BVZERO( &lc->lc_chaining_ctrl.ldctl_value ); + } + + lc->lc_chaining_ctrl.ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR; + lc->lc_chaining_ctrl.ldctl_iscritical = iscritical; + + if ( ldap_chain_parse_ctrl( &op, &rs, &lc->lc_chaining_ctrl ) != LDAP_SUCCESS ) + { + fprintf( stderr, "%s line %d: " + "unable to parse chaining control%s%s\n", + fname, lineno, + rs.sr_text ? ": " : "", + rs.sr_text ? rs.sr_text : "" ); + return 1; + } + + lc->lc_chaining_ctrlflag = op.o_chaining; + + lc->lc_flags |= LDAP_CHAIN_F_CHAINING; + + rc = 0; + goto done; + } +#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ } + + + be->be_private = lc->lc_li; rc = lback->bi_db_config( be, fname, lineno, argc, argv ); + be->be_private = private; + +done:; if ( argv0 ) { argv[ 0 ] = argv0; } - - be->be_private = private; + return rc; } @@ -570,6 +826,7 @@ ldap_chain_db_init( ) { slap_overinst *on = (slap_overinst *)be->bd_info; + ldap_chain_t *lc = NULL; int rc; BackendDB bd = *be; @@ -581,35 +838,46 @@ ldap_chain_db_init( } } + lc = ch_malloc( sizeof( ldap_chain_t ) ); + memset( lc, 0, sizeof( ldap_chain_t ) ); + bd.be_private = NULL; rc = lback->bi_db_init( &bd ); - on->on_bi.bi_private = bd.be_private; + lc->lc_li = (struct ldapinfo *)bd.be_private; + on->on_bi.bi_private = (void *)lc; 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 ); -} + int rc = 0; + +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR + rc = overlay_register_control( be, LDAP_CONTROL_X_CHAINING_BEHAVIOR ); #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ + return rc; +} + static int ldap_chain_db_destroy( BackendDB *be ) { - slap_overinst *on = (slap_overinst *) be->bd_info; - void *private = be->be_private; - int rc; + slap_overinst *on = (slap_overinst *) be->bd_info; + ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; + void *private = be->be_private; + int rc; - be->be_private = on->on_bi.bi_private; + be->be_private = (void *)lc->lc_li; rc = lback->bi_db_destroy( be ); - on->on_bi.bi_private = be->be_private; + lc->lc_li = be->be_private; + ch_free( lc ); + on->on_bi.bi_private = NULL; be->be_private = private; return rc; } @@ -620,14 +888,15 @@ ldap_chain_connection_destroy( Connection *conn ) { - slap_overinst *on = (slap_overinst *) be->bd_info; - void *private = be->be_private; - int rc; + slap_overinst *on = (slap_overinst *) be->bd_info; + ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; + void *private = be->be_private; + int rc; - be->be_private = on->on_bi.bi_private; + be->be_private = (void *)lc->lc_li; rc = lback->bi_connection_destroy( be, conn ); - on->on_bi.bi_private = be->be_private; be->be_private = private; + return rc; } @@ -778,9 +1047,7 @@ chain_init( void ) 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; diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index afd8f71204..436c713c57 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -213,26 +213,50 @@ ldap_back_db_config( li->url = ch_strdup( argv[ 1 ] ); #endif - /* start tls */ - } else if ( strcasecmp( argv[0], "start-tls" ) == 0 ) { - if ( argc != 1 ) { - fprintf( stderr, - "%s: line %d: start-tls takes no arguments\n", - fname, lineno ); - return( 1 ); - } - li->flags |= LDAP_BACK_F_TLS_CRITICAL; + } else if ( strncasecmp( argv[0], "tls-", STRLENOF( "tls-" ) ) == 0 ) { + + /* start tls */ + if ( strcasecmp( argv[0], "tls-start" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: tls-start takes no arguments\n", + fname, lineno ); + return( 1 ); + } + li->flags |= ( LDAP_BACK_F_USE_TLS | LDAP_BACK_F_TLS_CRITICAL ); - /* try start tls */ - } else if ( strcasecmp( argv[0], "try-start-tls" ) == 0 ) { - if ( argc != 1 ) { - fprintf( stderr, - "%s: line %d: try-start-tls takes no arguments\n", - fname, lineno ); - return( 1 ); + /* try start tls */ + } else if ( strcasecmp( argv[0], "tls-try-start" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: tls-try-start takes no arguments\n", + fname, lineno ); + return( 1 ); + } + li->flags &= ~LDAP_BACK_F_TLS_CRITICAL; + li->flags |= LDAP_BACK_F_USE_TLS; + + /* propagate start tls */ + } else if ( strcasecmp( argv[0], "tls-propagate" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: tls-propagate takes no arguments\n", + fname, lineno ); + return( 1 ); + } + li->flags |= ( LDAP_BACK_F_PROPAGATE_TLS | LDAP_BACK_F_TLS_CRITICAL ); + + /* try start tls */ + } else if ( strcasecmp( argv[0], "tls-try-propagate" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: tls-try-propagate takes no arguments\n", + fname, lineno ); + return( 1 ); + } + li->flags &= ~LDAP_BACK_F_TLS_CRITICAL; + li->flags |= LDAP_BACK_F_PROPAGATE_TLS; } - li->flags &= ~LDAP_BACK_F_TLS_CRITICAL; - li->flags |= LDAP_BACK_F_USE_TLS; /* name to use for ldap_back_group */ } else if ( strcasecmp( argv[0], "acl-authcdn" ) == 0 @@ -723,7 +747,7 @@ parse_idassert( li->idassert_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ; } else { - fprintf( stderr, "%s: line %s: " + fprintf( stderr, "%s: line %d: " "unknown authz mode \"%s\"\n", fname, lineno, val ); return 1; diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 8c610a5798..edd5bba22d 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -56,7 +56,6 @@ ldap_back_search( int i; char **attrs = NULL; int dontfreetext = 0; - int freeconn = 0; int do_retry = 1; LDAPControl **ctrls = NULL; @@ -120,12 +119,18 @@ retry: if ( rs->sr_err != LDAP_SUCCESS ) { fail:; - rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR ); - if ( freeconn ) { + if ( rs->sr_err == LDAP_SERVER_DOWN ) { + if ( do_retry ) { + do_retry = 0; + if ( ldap_back_retry( lc, op, rs, LDAP_BACK_DONTSEND ) ) { + goto retry; + } + } + rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_DONTSEND ); ldap_back_freeconn( op, lc ); lc = NULL; + goto finish; } - goto finish; } /* We pull apart the ber result, stuff it into a slapd entry, and @@ -138,7 +143,7 @@ fail:; /* check for abandon */ if ( op->o_abandon ) { ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL ); - rc = 0; + rc = SLAPD_ABANDON; goto finish; } @@ -253,7 +258,7 @@ fail:; 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 ] ); + ber_str2bv( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ] ); } /* cleanup */ @@ -274,9 +279,7 @@ fail:; goto retry; } } - /* FIXME: invalidate the connection? */ rs->sr_err = LDAP_SERVER_DOWN; - freeconn = 1; goto fail; } @@ -291,7 +294,9 @@ fail:; } finish:; - send_ldap_result( op, rs ); + if ( rc != SLAPD_ABANDON ) { + send_ldap_result( op, rs ); + } (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); diff --git a/servers/slapd/back-ldbm/modrdn.c b/servers/slapd/back-ldbm/modrdn.c index e9fd151fcc..4df7478e0c 100644 --- a/servers/slapd/back-ldbm/modrdn.c +++ b/servers/slapd/back-ldbm/modrdn.c @@ -361,6 +361,7 @@ ldbm_back_modrdn( /* check for abandon */ if ( op->o_abandon ) { + rs->sr_err = SLAPD_ABANDON; goto return_results; } @@ -420,6 +421,7 @@ ldbm_back_modrdn( /* check for abandon */ if ( op->o_abandon ) { + rs->sr_err = SLAPD_ABANDON; goto return_results; } diff --git a/servers/slapd/back-ldbm/search.c b/servers/slapd/back-ldbm/search.c index 3c09594ff1..1e414f6609 100644 --- a/servers/slapd/back-ldbm/search.c +++ b/servers/slapd/back-ldbm/search.c @@ -232,7 +232,7 @@ searchit: /* check for abandon */ if ( op->o_abandon ) { - rc = LDAP_SUCCESS; + rc = SLAPD_ABANDON; goto done; } diff --git a/servers/slapd/back-ldif/Makefile.in b/servers/slapd/back-ldif/Makefile.in new file mode 100644 index 0000000000..aa521681fb --- /dev/null +++ b/servers/slapd/back-ldif/Makefile.in @@ -0,0 +1,41 @@ +# Makefile.in for back-ldif +# $OpenLDAP$ +## This work is part of OpenLDAP Software . +## +## Copyright 2005 The OpenLDAP Foundation. +## All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted only as authorized by the OpenLDAP +## Public License. +## +## A copy of this license is available in the file LICENSE in the +## top-level directory of the distribution or, alternatively, at +## . + +SRCS = ldif.c +OBJS = ldif.lo + +LDAP_INCDIR= ../../../include +LDAP_LIBDIR= ../../../libraries + +BUILD_OPT = "--enable-ldif" +BUILD_MOD = yes + +mod_DEFS = -DSLAPD_IMPORT +MOD_DEFS = $(yes_DEFS) + +shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA) +NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS) +UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS) + +LIBBASE = back_ldif + +XINCPATH = -I.. -I$(srcdir)/.. +XDEFS = $(MODULES_CPPFLAGS) + +all-local-lib: ../.backend + +../.backend: lib$(LIBBASE).a + @touch $@ + diff --git a/servers/slapd/back-ldif/ldif.c b/servers/slapd/back-ldif/ldif.c new file mode 100644 index 0000000000..56f147489d --- /dev/null +++ b/servers/slapd/back-ldif/ldif.c @@ -0,0 +1,993 @@ +/* ldif.c - the ldif backend */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2005 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* ACKNOWLEDGEMENTS: + * This work was originally developed by Eric Stokes for inclusion + * in OpenLDAP Software. + */ + +#include "portable.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "slap.h" +#include "lutil.h" + +struct ldif_info { + struct berval li_base_path; + ID tool_current; + Entry ** tool_entries; + int tool_put_entry_flag; + int tool_numentries; + ldap_pvt_thread_mutex_t li_mutex; +}; + +#define LDIF ".ldif" + +#define ENTRY_BUFF_INCREMENT 500 + +static char * +dn2path(struct berval * dn, struct berval * rootdn, struct berval * base_path) +{ + char *result = ch_malloc( dn->bv_len + base_path->bv_len + 2 + + STRLENOF( LDIF )); + char *ptr, *sep, *end; + + ptr = lutil_strcopy( result, base_path->bv_val ); + *ptr++ = LDAP_DIRSEP[0]; + ptr = lutil_strcopy( ptr, rootdn->bv_val ); + end = dn->bv_val + dn->bv_len - rootdn->bv_len - 1; + while ( end > dn->bv_val ) { + for (sep = end-1; sep >=dn->bv_val && !DN_SEPARATOR( *sep ); sep--); + *ptr++ = LDAP_DIRSEP[0]; + ptr = lutil_strncopy( ptr, sep+1, end-sep-1 ); + end = sep; + } + strcpy(ptr, LDIF); + return result; +} + +static char * slurp_file(int fd) { + int entry_buf_size = 40 * ENTRY_BUFF_INCREMENT; + int read_chars_total = 0; + int read_chars = 0; + int entry_size = 40 * ENTRY_BUFF_INCREMENT; + char * entry = (char *) malloc(sizeof(char) * 40 * ENTRY_BUFF_INCREMENT); + char * entry_pos = entry; + + while(1) { + if(entry_size - read_chars_total == 0) { + entry = (char *) realloc(entry, sizeof(char) * 2 * entry_size); + entry_size = 2 * entry_size; + } + read_chars = read(fd, (void *) entry_pos, entry_size - read_chars_total); + if(read_chars == -1) { + SLAP_FREE(entry); + return NULL; + } + entry_pos += read_chars; + if(read_chars == 0) { + if(entry_size - read_chars_total > 0) + entry[read_chars_total] = '\0'; + else { + entry = (char *) realloc(entry, sizeof(char) * entry_size + 1); + entry_size = entry_size + 1; + entry[read_chars_total] = '\0'; + } + break; + } + else { + read_chars_total += read_chars; + } + } + return entry; +} + +static int spew_file(int fd, char * spew) { + int written = 0; + int writeres; + int len = strlen(spew); + char * spewptr = spew; + + while(written < len) { + writeres = write(fd, spewptr, len - written); + if(writeres == -1) { + perror("could not spew write"); + return -1; + } + else { + spewptr += writeres; + written += writeres; + } + } + return writeres; +} + +static int spew_entry(Entry * e, char * path) { + int rs; + int openres; + int spew_res; + int entry_length; + char * entry_as_string; + + openres = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + if(openres == -1) { + if(errno == ENOENT) + rs = LDAP_NO_SUCH_OBJECT; + else + rs = LDAP_UNWILLING_TO_PERFORM; + } + else { + entry_as_string = entry2str(e, &entry_length); + if(entry_as_string == NULL) { + rs = LDAP_UNWILLING_TO_PERFORM; + close(openres); + } + else { + spew_res = spew_file(openres, entry_as_string); + close(openres); + if(spew_res == -1) + rs = LDAP_UNWILLING_TO_PERFORM; + else + rs = LDAP_SUCCESS; + } + } + return rs; +} + +static Entry * get_entry_for_fd(int fd) { + char * entry = (char *) slurp_file(fd); + Entry * ldentry = NULL; + + /* error reading file */ + if(entry == NULL) { + goto return_value; + } + + ldentry = str2entry(entry); + + return_value: + if(fd != -1) { + if(close(fd) != 0) { + /* log error */ + } + } + if(entry != NULL) + SLAP_FREE(entry); + return ldentry; +} + +static Entry * get_entry(struct berval * dn, struct berval * rootdn, struct berval * base_path) { + char * path = (char *) dn2path(dn, rootdn, base_path); + int fd = open(path, O_RDONLY); + + /* error opening file (mebbe should log error) */ + if(fd == -1) { + perror("failed to open file"); + goto return_value; + } + goto return_value; + + return_value: + if(path != NULL) + SLAP_FREE(path); + return get_entry_for_fd(fd); +} + +/* takes a base path and a filename and opens that file */ +static int fd_for_path_components(char * base, char * name) { + char * absolutepath; + int fd; + absolutepath = (char *) SLAP_MALLOC(sizeof(char) * + (strlen(base) + + strlen(name) + 2)); + absolutepath[0] = '\0'; + strcat(absolutepath, base); + strcat(absolutepath, LDAP_DIRSEP); + strcat(absolutepath, name); + fd = open(absolutepath, O_RDONLY); + SLAP_FREE(absolutepath); + return fd; +} + +static Entry ** r_enum_tree(Entry ** entries, int *elen, int *eind, char * path) { + DIR * dir_of_path = opendir(path); + int fd; + struct dirent * dir; + char * newpath; + Entry * e; + + if(entries == NULL) { + entries = (Entry **) SLAP_MALLOC(sizeof(Entry *) * ENTRY_BUFF_INCREMENT); + *elen = ENTRY_BUFF_INCREMENT; + } + if(dir_of_path == NULL) {/* can't open directory */ + perror("failed to open directory"); + return entries; + } + + while(1) { + dir = readdir(dir_of_path); + if(dir == NULL) break; /* end of the directory */ + if(dir->d_type == DT_REG) { /* regular file, read the entry into memory */ + if(! (*eind < *elen)) { /* grow entries if necessary */ + entries = (Entry **) SLAP_REALLOC(entries, sizeof(Entry *) * (*elen) * 2); + *elen = *elen * 2; + } + fd = fd_for_path_components(path, dir->d_name); + if(fd != -1) { + e = get_entry_for_fd(fd); + if(e != NULL) { + entries[*eind] = e; + *eind = *eind + 1; + } + else + perror("failed to read entry"); + } + else + perror("failed to open fd"); + } + else if(dir->d_type == DT_DIR) { + if(! (strcasecmp(dir->d_name, ".") == 0 || strcasecmp(dir->d_name, "..") == 0)) { + newpath = (char *) SLAP_MALLOC(sizeof(char) * + (strlen(path) + strlen(dir->d_name) + 2)); + newpath[0] = '\0'; + strcat(newpath, path); + strcat(newpath, LDAP_DIRSEP); + strcat(newpath, dir->d_name); + entries = r_enum_tree(entries, elen, eind, newpath); + SLAP_FREE(newpath); + } + } + } + closedir(dir_of_path); + return entries; +} + +static Entry ** enum_tree(struct berval * path, int * length) { + int index = 0; + return r_enum_tree(NULL, &index, length, path->bv_val); +} + +static char * get_parent_path(char * dnpath) { + int dnpathlen = strlen(dnpath); + char * result; + int i; + + for(i = dnpathlen;i>0;i--) /* find the first path seperator */ + if(dnpath[i] == LDAP_DIRSEP[0]) + break; + result = ch_malloc( i + 1 ); + strncpy(result, dnpath, i); + result[i] = '\0'; + return result; +} + +static int apply_modify_to_entry(Entry * entry, + Modifications * modlist, + Operation * op, + SlapReply * rs) +{ + char textbuf[SLAP_TEXT_BUFLEN]; + size_t textlen = sizeof textbuf; + int rc; + int tempdebug; + Modification *mods = NULL; + Attribute *save_attrs; + + if (!acl_check_modlist(op, entry, modlist)) { + return LDAP_INSUFFICIENT_ACCESS; + } + + /* save_attrs = entry->e_attrs; Why? + entry->e_attrs = attrs_dup(entry->e_attrs); */ + + for (; modlist != NULL; modlist = modlist->sml_next) { + mods = &modlist->sml_mod; + + switch (mods->sm_op) { + case LDAP_MOD_ADD: + rc = modify_add_values(entry, mods, + get_permissiveModify(op), + &rs->sr_text, textbuf, + textlen); + break; + + case LDAP_MOD_DELETE: + rc = modify_delete_values(entry, mods, + get_permissiveModify(op), + &rs->sr_text, textbuf, + textlen); + + break; + + case LDAP_MOD_REPLACE: + rc = modify_replace_values(entry, mods, + get_permissiveModify(op), + &rs->sr_text, textbuf, + textlen); + + break; + case LDAP_MOD_INCREMENT: + break; + case SLAP_MOD_SOFTADD: + mods->sm_op = LDAP_MOD_ADD; + rc = modify_add_values(entry, mods, + get_permissiveModify(op), + &rs->sr_text, textbuf, + textlen); + mods->sm_op = SLAP_MOD_SOFTADD; + if (rc == LDAP_TYPE_OR_VALUE_EXISTS) { + rc = LDAP_SUCCESS; + } + break; + default: + break; + } + if(rc != LDAP_SUCCESS) break; + } + + if(rc == LDAP_SUCCESS) { + if ( mods->sm_desc == slap_schema.si_ad_objectClass ) { + entry->e_ocflags = 0; + } + /* check that the entry still obeys the schema */ + rc = entry_schema_check(op->o_bd, entry, + save_attrs, &rs->sr_text, + textbuf, textlen); + } + return rc; +} + +static int +ldif_back_bind( Operation *op, SlapReply *rs ) +{ + struct ldif_info *ni = NULL; + Attribute * a = NULL; + AttributeDescription *password = slap_schema.si_ad_userPassword; + int return_val = 0; + Entry * entry = NULL; + + ni = (struct ldif_info *) op->o_bd->be_private; + ldap_pvt_thread_mutex_lock(&ni->li_mutex); + entry = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path); + + /* no object is found for them */ + if(entry == NULL) { + if(be_isroot_pw(op)) { + return_val = LDAP_SUCCESS; + goto return_result; + } + else if(be_root_dn(op->o_bd)) { + return_val = LDAP_INVALID_CREDENTIALS; + rs->sr_err = LDAP_INVALID_CREDENTIALS; + goto return_result; + } + else { + rs->sr_err = LDAP_NO_SUCH_OBJECT; + return_val = 1; + goto return_result; + } + } + + /* they don't have userpassword */ + if((a = attr_find(entry->e_attrs, password)) == NULL) { + rs->sr_err = LDAP_INAPPROPRIATE_AUTH; + return_val = 1; + goto return_result; + } + + /* authentication actually failed */ + if(slap_passwd_check(op, entry, a, &op->oq_bind.rb_cred, + &rs->sr_text) != 0) { + rs->sr_err = LDAP_INVALID_CREDENTIALS; + return_val = 1; + goto return_result; + } + + /* let the front-end send success */ + return_val = 0; + goto return_result; + + return_result: + ldap_pvt_thread_mutex_unlock(&ni->li_mutex); + if(return_val != 0) + send_ldap_result( op, rs ); + if(entry != NULL) + entry_free(entry); + return return_val; +} + +static int ldif_back_search(Operation *op, SlapReply *rs) +{ + struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private; + int numentries = 0; + int i = 0; + Entry ** entries = NULL; + + ldap_pvt_thread_mutex_lock(&ni->li_mutex); + entries = (Entry **) enum_tree(&ni->li_base_path, &numentries); + + if(entries != NULL) { + for(i=0;iors_filter) == LDAP_COMPARE_TRUE) { + rs->sr_entry = entries[i]; + rs->sr_attrs = op->ors_attrs; + rs->sr_flags = REP_ENTRY_MODIFIABLE; + send_search_entry(op, rs); + } + entry_free(entries[i]); + } + SLAP_FREE(entries); + rs->sr_err = LDAP_SUCCESS; + ldap_pvt_thread_mutex_unlock(&ni->li_mutex); + send_ldap_result(op, rs); + } + else { + rs->sr_err = LDAP_BUSY; + ldap_pvt_thread_mutex_unlock(&ni->li_mutex); + send_ldap_result(op, rs); + } + + return 0; +} + +static int ldif_back_add(Operation *op, SlapReply *rs) { + struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private; + Entry * e = op->ora_e; + Attribute *save_attrs; + struct berval dn = e->e_nname; + char * leaf_path = NULL; + char * base = NULL; + char * base_ldif = NULL; + struct stat stats; + int statres; + char textbuf[SLAP_TEXT_BUFLEN]; + size_t textlen = sizeof textbuf; + + ldap_pvt_thread_mutex_lock(&ni->li_mutex); + ldap_pvt_thread_mutex_lock(&entry2str_mutex); + + leaf_path = (char *) dn2path(&dn, &op->o_bd->be_nsuffix[0], &ni->li_base_path); + + /* save_attrs = e->e_attrs; why? + e->e_attrs = attrs_dup(e->e_attrs);*/ + + if(leaf_path != NULL) { + char * tmp; + /* build path to container, and path to ldif of container */ + base = (char *) get_parent_path(leaf_path); + base_ldif = (char *) SLAP_MALLOC(sizeof(char) * (strlen(base) + 6)); + tmp = (char *) lutil_strcopy(base_ldif, base); + lutil_strcopy(tmp, LDIF); + + rs->sr_err = entry_schema_check(op->o_bd, e, + save_attrs, + &rs->sr_text, + textbuf, textlen); + if(rs->sr_err == LDAP_SUCCESS) { + statres = stat(base, &stats); /* check if container exists */ + if(statres == -1 && errno == ENOENT) { /* container missing */ + statres = stat(base_ldif, &stats); /* check for leaf node */ + if(statres == -1 && errno == ENOENT) { + rs->sr_err = LDAP_NO_SUCH_OBJECT; /* parent doesn't exist */ + } + else if(statres != -1) { /* create parent */ + int mkdirres = mkdir(base, 0750); + if(mkdirres == -1) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + } + } + else + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + }/* container was possibly created, move on to add the entry */ + if(rs->sr_err == LDAP_SUCCESS) { + statres = stat(leaf_path, &stats); + if(statres == -1 && errno == ENOENT) { + rs->sr_err = (int) spew_entry(e, leaf_path); + } + else /* it already exists */ + rs->sr_err = LDAP_ALREADY_EXISTS; + } + } + } + + ldap_pvt_thread_mutex_unlock(&ni->li_mutex); + ldap_pvt_thread_mutex_unlock(&entry2str_mutex); + + send_ldap_result(op, rs); + if(leaf_path != NULL) + SLAP_FREE(leaf_path); + if(base != NULL) + SLAP_FREE(base); + if(base_ldif != NULL) + SLAP_FREE(base_ldif); + return 0; +} + +static int ldif_back_modify(Operation *op, SlapReply *rs) { + struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private; + Modifications * modlst = op->orm_modlist; + char * path = NULL; + Entry * entry = NULL; + int spew_res; + + ldap_pvt_thread_mutex_lock(&ni->li_mutex); + ldap_pvt_thread_mutex_lock(&entry2str_mutex); + path = (char *) dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path); + entry = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path); + + if(entry != NULL) { + rs->sr_err = apply_modify_to_entry(entry, modlst, op, rs); + if(rs->sr_err == LDAP_SUCCESS) { + spew_res = spew_entry(entry, path); + if(spew_res == -1) { + perror("could not output entry"); + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + } + } + } + else { + rs->sr_err = LDAP_NO_SUCH_OBJECT; + } + + if(path != NULL) + SLAP_FREE(path); + if(entry != NULL) + entry_free(entry); + rs->sr_text = ""; + ldap_pvt_thread_mutex_unlock(&ni->li_mutex); + ldap_pvt_thread_mutex_unlock(&entry2str_mutex); + send_ldap_result(op, rs); + return 0; +} + +static int ldif_back_delete(Operation *op, SlapReply *rs) { + struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private; + char * path = NULL; + int res = 0; + + ldap_pvt_thread_mutex_lock(&ni->li_mutex); + path = (char *) dn2path(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path); + res = unlink(path); + + if(res == -1) { + if(errno == ENOENT) + rs->sr_err = LDAP_NO_SUCH_OBJECT; + else + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + } + else + rs->sr_err = LDAP_SUCCESS; + + SLAP_FREE(path); + ldap_pvt_thread_mutex_unlock(&ni->li_mutex); + send_ldap_result(op, rs); + return 0; +} + +static int is_leaf_node(char * path) { + DIR * nonleafnode; + int path_len = strlen(path); + char * nonleafpath = (char *) SLAP_MALLOC(sizeof(char) * path_len + 1); + int res; + + strncpy(nonleafpath, path, path_len); + nonleafpath[path_len - 5] = '\0'; + nonleafnode = opendir(nonleafpath); + if(nonleafnode == NULL) { + res = 1; + } + else { + closedir(nonleafnode); + res = 0; + } + SLAP_FREE(nonleafpath); + return res; +} + +static int move_entry(Entry * entry, struct berval * ndn, + struct berval * newndn, struct berval * rootdn, + struct berval * base_path) { + int res; + int exists_res; + char * path = (char *) dn2path(ndn, rootdn, base_path); + char * newpath = (char *) dn2path(newndn, rootdn, base_path); + int path_len = strlen(path); + + if((entry == NULL || path == NULL) || newpath == NULL) { /* some object doesn't exist */ + res = LDAP_NO_SUCH_OBJECT; + } + else if(! is_leaf_node(path)) { /* entry is not a leaf node */ + res = LDAP_NOT_ALLOWED_ON_NONLEAF; + } + else { /* do the modrdn */ + exists_res = open(newpath, O_RDONLY); + if(exists_res == -1 && errno == ENOENT) { + res = spew_entry(entry, newpath); + if(res != -1) { + /* if this fails we should log something bad */ + res = unlink(path); + res = LDAP_SUCCESS; + } + else { + if(errno == ENOENT) + res = LDAP_NO_SUCH_OBJECT; + else + res = LDAP_UNWILLING_TO_PERFORM; + unlink(newpath); /* in case file was created */ + } + } + else if(exists_res) { + res = LDAP_ALREADY_EXISTS; + int close_res = close(exists_res); + if(close_res == -1) { + /* log heinous error */ + } + } + else { + res = LDAP_UNWILLING_TO_PERFORM; + } + } + + if(path != NULL) + SLAP_FREE(path); + if(newpath != NULL) + SLAP_FREE(newpath); + return res; +} + +static int ldif_back_modrdn(Operation *op, SlapReply *rs) { + struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private; + struct berval new_dn = {0, NULL}, new_ndn = {0, NULL}; + struct berval * new_parent_dn = NULL; + struct berval p_dn; + Entry * entry = NULL; + LDAPRDN new_rdn = NULL; + LDAPRDN old_rdn = NULL; + Modifications * mods = NULL; + int res; + + ldap_pvt_thread_mutex_lock(&ni->li_mutex); + ldap_pvt_thread_mutex_lock(&entry2str_mutex); + entry = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path); + + /* build the mods to the entry */ + if(entry != NULL) { + if(ldap_bv2rdn(&op->oq_modrdn.rs_newrdn, &new_rdn, (char **)&rs->sr_text, + LDAP_DN_FORMAT_LDAP)) { + rs->sr_err = LDAP_INVALID_DN_SYNTAX; + } + else if(op->oq_modrdn.rs_deleteoldrdn && + ldap_bv2rdn(&op->o_req_dn, &old_rdn, (char **)&rs->sr_text, + LDAP_DN_FORMAT_LDAP)) { + rs->sr_err = LDAP_OTHER; + } + else { /* got both rdns successfully, ready to build mods */ + if(slap_modrdn2mods(op, rs, entry, old_rdn, new_rdn, &mods) != LDAP_SUCCESS) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + } + else { /* built mods successfully */ + + /* build new dn, and new ndn for the entry */ + if(op->oq_modrdn.rs_newSup != NULL) /* new superior */ + p_dn = *op->oq_modrdn.rs_newSup; + else + p_dn = slap_empty_bv; + dnParent(&entry->e_name, &p_dn); + build_new_dn(&new_dn, &p_dn, &op->oq_modrdn.rs_newrdn, NULL); + struct berval bv = {0, NULL}; + dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx ); + ber_dupbv( &new_ndn, &bv ); + entry->e_name = new_dn; + entry->e_nname = new_ndn; + + /* perform the modifications */ + res = apply_modify_to_entry(entry, mods, op, rs); + if(res == LDAP_SUCCESS) { + rs->sr_err = move_entry(entry, &op->o_req_ndn, + &new_ndn, + &op->o_bd->be_nsuffix[0], + &ni->li_base_path); + } + else + rs->sr_err = res; + } + } + } + else /* entry was null */ + rs->sr_err = LDAP_NO_SUCH_OBJECT; + + if(entry != NULL) + entry_free(entry); + rs->sr_text = ""; + ldap_pvt_thread_mutex_unlock(&ni->li_mutex); + ldap_pvt_thread_mutex_unlock(&entry2str_mutex); + send_ldap_result(op, rs); + return 0; +} + +static int ldif_back_compare(Operation *op, SlapReply *rs) { + struct ldif_info *ni = (struct ldif_info *) op->o_bd->be_private; + Entry * e = NULL; + Attribute *a; + + ldap_pvt_thread_mutex_lock(&ni->li_mutex); + + e = (Entry *) get_entry(&op->o_req_ndn, &op->o_bd->be_nsuffix[0], &ni->li_base_path); + if(e != NULL) { + for(a = attrs_find( e->e_attrs, op->oq_compare.rs_ava->aa_desc ); + a != NULL; + a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc )) + { + rs->sr_err = LDAP_COMPARE_FALSE; + + if (value_find_ex(op->oq_compare.rs_ava->aa_desc, + SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | + SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, + a->a_nvals, &op->oq_compare.rs_ava->aa_value, + op->o_tmpmemctx ) == 0) + { + rs->sr_err = LDAP_COMPARE_TRUE; + break; + } + } + } + else { + rs->sr_err = LDAP_NO_SUCH_OBJECT; + } + + if(e != NULL) + entry_free(e); + ldap_pvt_thread_mutex_unlock(&ni->li_mutex); + send_ldap_result(op, rs); + return 0; +} + +static int ldif_tool_entry_open(BackendDB * be, int mode) { + struct ldif_info *ni = (struct ldif_info *) be->be_private; + ni->tool_entries = NULL; + ni->tool_numentries = 0; + ni->tool_current = 0; + ni->tool_put_entry_flag = 0; + return 0; +} + +static int ldif_tool_entry_close(BackendDB * be) { + struct ldif_info *ni = (struct ldif_info *) be->be_private; + int i; + /*if(ni->tool_entries != NULL) { + for(i=0;itool_numentries;i++) { + SLAP_FREE(ni->tool_entries[i]); + }*/ + SLAP_FREE(ni->tool_entries); + return 0; +} + +static ID ldif_tool_entry_first(BackendDB *be) { + struct ldif_info *ni = (struct ldif_info *) be->be_private; + ID id = 1; /* first entry in the array of entries shifted by one */ + ni->tool_current = 1; + if(ni->tool_entries == NULL || ni->tool_put_entry_flag) { + ni->tool_entries = (Entry **) enum_tree(&ni->li_base_path, &ni->tool_numentries); + ni->tool_put_entry_flag = 0; + } + return id; +} + +static ID ldif_tool_entry_next(BackendDB *be) { + struct ldif_info *ni = (struct ldif_info *) be->be_private; + ni->tool_current += 1; + if(ni->tool_put_entry_flag) { + ni->tool_entries = (Entry **) enum_tree(&ni->li_base_path, &ni->tool_numentries); + ni->tool_put_entry_flag = 0; + } + if(ni->tool_current > ni->tool_numentries) + return NOID; + else + return ni->tool_current; +} + +static Entry * ldif_tool_entry_get(BackendDB * be, ID id) { + struct ldif_info *ni = (struct ldif_info *) be->be_private; + Entry * e; + + if(id > ni->tool_numentries || id < 1) + return NULL; + else { + e = ni->tool_entries[id - 1]; + ni->tool_entries[id - 1] = NULL; + return e; + } +} + +static ID ldif_tool_entry_put(BackendDB * be, Entry * e, struct berval *text) { + struct ldif_info *ni = (struct ldif_info *) be->be_private; + Attribute *save_attrs; + struct berval dn = e->e_nname; + char * leaf_path = NULL; + char * base = NULL; + char * base_ldif = NULL; + struct stat stats; + int statres; + char textbuf[SLAP_TEXT_BUFLEN]; + size_t textlen = sizeof textbuf; + int res = LDAP_SUCCESS; + + leaf_path = (char *) dn2path(&dn, &be->be_nsuffix[0], &ni->li_base_path); + + /* save_attrs = e->e_attrs; why? + e->e_attrs = attrs_dup(e->e_attrs);*/ + + if(leaf_path != NULL) { + char * tmp; + /* build path to container, and path to ldif of container */ + base = (char *) get_parent_path(leaf_path); + base_ldif = (char *) SLAP_MALLOC(sizeof(char) * (strlen(base) + 6)); + tmp = (char *) lutil_strcopy(base_ldif, base); + lutil_strcopy(tmp, LDIF); + + statres = stat(base, &stats); /* check if container exists */ + if(statres == -1 && errno == ENOENT) { /* container missing */ + statres = stat(base_ldif, &stats); /* check for leaf node */ + if(statres == -1 && errno == ENOENT) { + res = LDAP_NO_SUCH_OBJECT; /* parent doesn't exist */ + } + else if(statres != -1) { /* create parent */ + int mkdirres = mkdir(base, 0750); + if(mkdirres == -1) { + res = LDAP_UNWILLING_TO_PERFORM; + } + } + else + res = LDAP_UNWILLING_TO_PERFORM; + }/* container was possibly created, move on to add the entry */ + if(res == LDAP_SUCCESS) { + statres = stat(leaf_path, &stats); + if(statres == -1 && errno == ENOENT) { + res = (int) spew_entry(e, leaf_path); + } + else /* it already exists */ + res = LDAP_ALREADY_EXISTS; + } + } + + if(leaf_path != NULL) + SLAP_FREE(leaf_path); + if(base != NULL) + SLAP_FREE(base); + if(base_ldif != NULL) + SLAP_FREE(base_ldif); + if(res == LDAP_SUCCESS) { + ni->tool_put_entry_flag = 1; + return 1; + } + else + return NOID; +} + +static int +ldif_back_db_config( + BackendDB *be, + const char *fname, + int lineno, + int argc, + char **argv ) +{ + struct ldif_info *ni = (struct ldif_info *) be->be_private; + + if ( strcasecmp( argv[0], "directory" ) == 0 ) { + if ( argc < 2 ) { + fprintf( stderr, + "%s: line %d: missing in \"directory \" line\n", + fname, lineno ); + return 1; + } + ber_str2bv(argv[1], 0, 1, &ni->li_base_path); + } else { + return SLAP_CONF_UNKNOWN; + } + return 0; +} + + +static int +ldif_back_db_init( BackendDB *be ) +{ + struct ldif_info *ni; + + ni = ch_calloc( 1, sizeof(struct ldif_info) ); + be->be_private = ni; + ldap_pvt_thread_mutex_init(&ni->li_mutex); + return 0; +} + +static int +ldif_back_db_destroy( + Backend *be + ) +{ + struct ldif_info *ni = be->be_private; + ldap_pvt_thread_mutex_destroy(&ni->li_mutex); + free( be->be_private ); + return 0; +} + +static int +ldif_back_db_open( + Backend *be + ) +{ + struct ldif_info *ni = (struct ldif_info *) be->be_private; + if( BER_BVISEMPTY(&ni->li_base_path)) {/* missing base path */ + fprintf(stderr, "missing base path for back-ldif\n"); + return 1; + } + return 0; +} + +int +ldif_back_initialize( + BackendInfo *bi + ) +{ + bi->bi_open = 0; + bi->bi_close = 0; + bi->bi_config = 0; + bi->bi_destroy = 0; + + bi->bi_db_init = ldif_back_db_init; + bi->bi_db_config = ldif_back_db_config; + bi->bi_db_open = ldif_back_db_open; + bi->bi_db_close = 0; + bi->bi_db_destroy = ldif_back_db_destroy; + + bi->bi_op_bind = ldif_back_bind; + bi->bi_op_unbind = 0; + bi->bi_op_search = ldif_back_search; + bi->bi_op_compare = ldif_back_compare; + bi->bi_op_modify = ldif_back_modify; + bi->bi_op_modrdn = ldif_back_modrdn; + bi->bi_op_add = ldif_back_add; + bi->bi_op_delete = ldif_back_delete; + bi->bi_op_abandon = 0; + + bi->bi_extended = 0; + + bi->bi_chk_referrals = 0; + + bi->bi_connection_init = 0; + bi->bi_connection_destroy = 0; + + bi->bi_tool_entry_open = ldif_tool_entry_open; + bi->bi_tool_entry_close = ldif_tool_entry_close; + bi->bi_tool_entry_first = ldif_tool_entry_first; + bi->bi_tool_entry_next = ldif_tool_entry_next; + bi->bi_tool_entry_get = ldif_tool_entry_get; + bi->bi_tool_entry_put = ldif_tool_entry_put; + bi->bi_tool_entry_reindex = 0; + bi->bi_tool_sync = 0; + + bi->bi_tool_dn2id_get = 0; + bi->bi_tool_id2entry_get = 0; + bi->bi_tool_entry_modify = 0; + + return 0; +} diff --git a/servers/slapd/back-meta/add.c b/servers/slapd/back-meta/add.c index fe9af550d4..857ce7ec5f 100644 --- a/servers/slapd/back-meta/add.c +++ b/servers/slapd/back-meta/add.c @@ -51,14 +51,12 @@ meta_back_add( Operation *op, SlapReply *rs ) * get the current connection */ lc = meta_back_getconn( op, rs, META_OP_REQUIRE_SINGLE, - &op->o_req_ndn, &candidate ); - if ( !lc ) { - send_ldap_result( op, rs ); + &op->o_req_ndn, &candidate, LDAP_BACK_SENDERR ); + if ( !lc || !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) { return rs->sr_err; } - if ( !meta_back_dobind( lc, op ) - || !meta_back_is_valid( lc, candidate ) ) { + if ( !meta_back_is_valid( lc, candidate ) ) { rs->sr_err = LDAP_UNAVAILABLE; send_ldap_result( op, rs ); return rs->sr_err; diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index 3ead454bb4..6df5a58e5c 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -215,7 +215,14 @@ struct metainfo { ldap_pvt_thread_mutex_t conn_mutex; Avlnode *conntree; - int savecred; + unsigned flags; +/* defined in +#define LDAP_BACK_F_NONE 0x00U +#define LDAP_BACK_F_SAVECRED 0x01U +#define LDAP_BACK_F_USE_TLS 0x02U +#define LDAP_BACK_F_TLS_CRITICAL ( 0x04U | LDAP_BACK_F_USE_TLS ) +#define LDAP_BACK_F_CHASE_REFERRALS 0x8U +*/ }; #define META_OP_ALLOW_MULTIPLE 0x00 @@ -227,13 +234,15 @@ meta_back_getconn( SlapReply *rs, int op_type, struct berval *dn, - int *candidate + int *candidate, + ldap_back_send_t sendok ); extern int meta_back_dobind( struct metaconn *lc, - Operation *op + Operation *op, + ldap_back_send_t sendok ); extern int diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c index 0dde00f584..69fe2ea995 100644 --- a/servers/slapd/back-meta/bind.c +++ b/servers/slapd/back-meta/bind.c @@ -63,7 +63,7 @@ meta_back_bind( Operation *op, SlapReply *rs ) op_type = META_OP_REQUIRE_ALL; } lc = meta_back_getconn( op, rs, op_type, - &op->o_req_ndn, NULL ); + &op->o_req_ndn, NULL, LDAP_BACK_SENDERR ); if ( !lc ) { Debug( LDAP_DEBUG_ANY, "meta_back_bind: no target for dn %s.\n%s%s", @@ -248,7 +248,7 @@ retry:; lsc->msc_bound = META_BOUND; lc->mc_bound_target = candidate; - if ( li->savecred ) { + if ( LDAP_BACK_SAVECRED( li ) ) { if ( !BER_BVISNULL( &lsc->msc_cred ) ) { /* destroy sensitive data */ memset( lsc->msc_cred.bv_val, 0, lsc->msc_cred.bv_len ); @@ -277,7 +277,7 @@ return_results:; * meta_back_dobind */ int -meta_back_dobind( struct metaconn *lc, Operation *op ) +meta_back_dobind( struct metaconn *lc, Operation *op, ldap_back_send_t sendok ) { struct metasingleconn *lsc; int bound = 0, i; @@ -328,7 +328,7 @@ 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 + /* FIXME: should we 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, NULL, NULL, &msgid ); diff --git a/servers/slapd/back-meta/compare.c b/servers/slapd/back-meta/compare.c index 3418717f7e..ee15d1495d 100644 --- a/servers/slapd/back-meta/compare.c +++ b/servers/slapd/back-meta/compare.c @@ -51,18 +51,11 @@ meta_back_compare( Operation *op, SlapReply *rs ) dncookie dc; lc = meta_back_getconn( op, rs, META_OP_ALLOW_MULTIPLE, - &op->o_req_ndn, NULL ); - if ( !lc ) { - send_ldap_result( op, rs ); - return -1; + &op->o_req_ndn, NULL, LDAP_BACK_SENDERR ); + if ( !lc || !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) { + return rs->sr_err; } - if ( !meta_back_dobind( lc, op ) ) { - rs->sr_err = LDAP_UNAVAILABLE; - send_ldap_result( op, rs ); - return -1; - } - msgid = ch_calloc( sizeof( int ), li->ntargets ); if ( msgid == NULL ) { return -1; diff --git a/servers/slapd/back-meta/config.c b/servers/slapd/back-meta/config.c index 28b057ed01..a7a6fa1805 100644 --- a/servers/slapd/back-meta/config.c +++ b/servers/slapd/back-meta/config.c @@ -384,7 +384,73 @@ meta_back_db_config( fname, lineno ); return( 1 ); } - li->savecred = 1; + + li->flags |= LDAP_BACK_F_SAVECRED; + + } else if ( strcasecmp( argv[0], "chase-referrals" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: \"chase-referrals\" takes no arguments\n", + fname, lineno ); + return( 1 ); + } + + li->flags |= LDAP_BACK_F_CHASE_REFERRALS; + + } else if ( strcasecmp( argv[0], "dont-chase-referrals" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: \"dont-chase-referrals\" takes no arguments\n", + fname, lineno ); + return( 1 ); + } + + li->flags &= ~LDAP_BACK_F_CHASE_REFERRALS; + + } else if ( strncasecmp( argv[0], "tls-", STRLENOF( "tls-" ) ) == 0 ) { + + /* start tls */ + if ( strcasecmp( argv[0], "tls-start" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: tls-start takes no arguments\n", + fname, lineno ); + return( 1 ); + } + li->flags |= ( LDAP_BACK_F_USE_TLS | LDAP_BACK_F_TLS_CRITICAL ); + + /* try start tls */ + } else if ( strcasecmp( argv[0], "tls-try-start" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: tls-try-start takes no arguments\n", + fname, lineno ); + return( 1 ); + } + li->flags &= ~LDAP_BACK_F_TLS_CRITICAL; + li->flags |= LDAP_BACK_F_USE_TLS; + + /* propagate start tls */ + } else if ( strcasecmp( argv[0], "tls-propagate" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: tls-propagate takes no arguments\n", + fname, lineno ); + return( 1 ); + } + li->flags |= ( LDAP_BACK_F_PROPAGATE_TLS | LDAP_BACK_F_TLS_CRITICAL ); + + /* try start tls */ + } else if ( strcasecmp( argv[0], "tls-try-propagate" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: tls-try-propagate takes no arguments\n", + fname, lineno ); + return( 1 ); + } + li->flags &= ~LDAP_BACK_F_TLS_CRITICAL; + li->flags |= LDAP_BACK_F_PROPAGATE_TLS; + } /* name to use as pseudo-root dn */ } else if ( strcasecmp( argv[ 0 ], "pseudorootdn" ) == 0 ) { diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c index 78fe9b4ccf..3b31118c3f 100644 --- a/servers/slapd/back-meta/conn.c +++ b/servers/slapd/back-meta/conn.c @@ -186,8 +186,8 @@ init_one_conn( Operation *op, SlapReply *rs, struct metatarget *lt, - struct metasingleconn *lsc - ) + struct metasingleconn *lsc, + ldap_back_send_t sendok ) { struct metainfo *li = ( struct metainfo * )op->o_bd->be_private; int vers; @@ -205,7 +205,7 @@ init_one_conn( */ rs->sr_err = ldap_initialize( &lsc->msc_ld, lt->mt_uri ); if ( rs->sr_err != LDAP_SUCCESS ) { - return slap_map_api2result( rs ); + goto error_return; } /* @@ -214,8 +214,100 @@ init_one_conn( */ vers = op->o_conn->c_protocol; ldap_set_option( lsc->msc_ld, LDAP_OPT_PROTOCOL_VERSION, &vers ); - /* FIXME: configurable? */ - ldap_set_option( lsc->msc_ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON ); + + /* automatically chase referrals ("chase-referrals"/"dont-chase-referrals" statement) */ + if ( LDAP_BACK_CHASE_REFERRALS( li ) ) { + ldap_set_option( lsc->msc_ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON ); + } + +#ifdef HAVE_TLS + /* start TLS ("start-tls"/"try-start-tls" statements) */ + if ( ( LDAP_BACK_USE_TLS( li ) || ( op->o_conn->c_is_tls && LDAP_BACK_PROPAGATE_TLS( li ) ) ) + && !ldap_is_ldaps_url( lt->mt_uri ) ) + { +#if 1 + /* + * use asynchronous StartTLS + * in case, chase referral (not implemented yet) + */ + int msgid; + + rs->sr_err = ldap_start_tls( lsc->msc_ld, NULL, NULL, &msgid ); + if ( rs->sr_err == LDAP_SUCCESS ) { + LDAPMessage *res = NULL; + int rc, retries = 1; + struct timeval tv = { 0, 0 }; + +retry:; + rc = ldap_result( lsc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res ); + if ( rc < 0 ) { + rs->sr_err = LDAP_OTHER; + + } else if ( rc == 0 ) { + if ( retries ) { + retries--; + tv.tv_sec = 0; + tv.tv_usec = 100000; + goto retry; + } + rs->sr_err = LDAP_OTHER; + + } else if ( rc == LDAP_RES_EXTENDED ) { + struct berval *data = NULL; + + rs->sr_err = ldap_parse_extended_result( lsc->msc_ld, res, + NULL, &data, 0 ); + if ( rs->sr_err == LDAP_SUCCESS ) { + rs->sr_err = ldap_result2error( lsc->msc_ld, res, 1 ); + res = NULL; + + /* FIXME: in case a referral + * is returned, should we try + * using it instead of the + * configured URI? */ + if ( rs->sr_err == LDAP_SUCCESS ) { + ldap_install_tls( lsc->msc_ld ); + + } else if ( rs->sr_err == LDAP_REFERRAL ) { + rs->sr_err = LDAP_OTHER; + rs->sr_text = "unwilling to chase referral returned by Start TLS exop"; + } + + if ( data ) { + if ( data->bv_val ) { + ber_memfree( data->bv_val ); + } + ber_memfree( data ); + } + } + + } else { + rs->sr_err = LDAP_OTHER; + } + + if ( res != NULL ) { + ldap_msgfree( res ); + } + } +#else + /* + * use synchronous StartTLS + */ + rs->sr_err = ldap_start_tls_s( lsc->msc_ld, NULL, NULL ); +#endif + + /* if StartTLS is requested, only attempt it if the URL + * is not "ldaps://"; this may occur not only in case + * of misconfiguration, but also when used in the chain + * overlay, where the "uri" can be parsed out of a referral */ + if ( rs->sr_err == LDAP_SERVER_DOWN + || ( rs->sr_err != LDAP_SUCCESS && LDAP_BACK_TLS_CRITICAL( li ) ) ) + { + ldap_unbind_ext_s( lsc->msc_ld, NULL, NULL ); + goto error_return; + } + } +#endif /* HAVE_TLS */ /* * Set the network timeout if set @@ -238,7 +330,7 @@ init_one_conn( /* * If the connection DN is not null, an attempt to rewrite it is made */ - if ( op->o_conn->c_dn.bv_len != 0 ) { + if ( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) { dc.rwmap = <->mt_rwmap; dc.conn = op->o_conn; dc.rs = rs; @@ -250,8 +342,7 @@ init_one_conn( if ( ldap_back_dn_massage( &dc, &op->o_conn->c_dn, &lsc->msc_bound_ndn ) ) { - send_ldap_result( op, rs ); - return rs->sr_err; + goto error_return; } /* copy the DN idf needed */ @@ -259,7 +350,7 @@ init_one_conn( ber_dupbv( &lsc->msc_bound_ndn, &op->o_conn->c_dn ); } - assert( lsc->msc_bound_ndn.bv_val ); + assert( !BER_BVISNULL( &lsc->msc_bound_ndn ) ); } else { ber_str2bv( "", 0, 1, &lsc->msc_bound_ndn ); @@ -267,11 +358,23 @@ init_one_conn( lsc->msc_bound = META_UNBOUND; - /* - * The candidate is activated - */ - lsc->msc_candidate = META_CANDIDATE; - return LDAP_SUCCESS; +error_return:; + if ( rs->sr_err != LDAP_SUCCESS ) { + rs->sr_err = slap_map_api2result( rs ); + if ( sendok & LDAP_BACK_SENDERR ) { + send_ldap_result( op, rs ); + rs->sr_text = NULL; + } + + } else { + + /* + * The candidate is activated + */ + lsc->msc_candidate = META_CANDIDATE; + } + + return rs->sr_err; } /* @@ -288,11 +391,12 @@ init_one_conn( */ struct metaconn * meta_back_getconn( - Operation *op, - SlapReply *rs, - int op_type, - struct berval *ndn, - int *candidate ) + Operation *op, + SlapReply *rs, + int op_type, + struct berval *ndn, + int *candidate, + ldap_back_send_t sendok ) { struct metainfo *li = ( struct metainfo * )op->o_bd->be_private; struct metaconn *lc, lc_curr; @@ -326,7 +430,7 @@ meta_back_getconn( * also init'd */ int lerr = init_one_conn( op, rs, li->targets[ i ], - &lc->mc_conns[ i ] ); + &lc->mc_conns[ i ], sendok ); if ( lerr != LDAP_SUCCESS ) { /* @@ -386,7 +490,7 @@ meta_back_getconn( * sends the appropriate result. */ err = init_one_conn( op, rs, li->targets[ i ], - &lc->mc_conns[ i ] ); + &lc->mc_conns[ i ], sendok ); if ( err != LDAP_SUCCESS ) { /* @@ -420,7 +524,7 @@ meta_back_getconn( */ int lerr = init_one_conn( op, rs, li->targets[ i ], - &lc->mc_conns[ i ] ); + &lc->mc_conns[ i ], sendok ); if ( lerr != LDAP_SUCCESS ) { /* diff --git a/servers/slapd/back-meta/delete.c b/servers/slapd/back-meta/delete.c index cd719c08d5..646cbe8de6 100644 --- a/servers/slapd/back-meta/delete.c +++ b/servers/slapd/back-meta/delete.c @@ -41,22 +41,15 @@ meta_back_delete( Operation *op, SlapReply *rs ) dncookie dc; lc = meta_back_getconn( op, rs, META_OP_REQUIRE_SINGLE, - &op->o_req_ndn, &candidate ); - if ( !lc ) { - send_ldap_result( op, rs ); - return -1; + &op->o_req_ndn, &candidate, LDAP_BACK_SENDERR ); + if ( !lc || !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) { + return rs->sr_err; } - - if ( !meta_back_dobind( lc, op ) ) { - rs->sr_err = LDAP_UNAVAILABLE; - } else if ( !meta_back_is_valid( lc, candidate ) ) { + if ( !meta_back_is_valid( lc, candidate ) ) { rs->sr_err = LDAP_OTHER; - } - - if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); - return -1; + return rs->sr_err; } /* diff --git a/servers/slapd/back-meta/modify.c b/servers/slapd/back-meta/modify.c index cd0a3ec00e..e09b9c3566 100644 --- a/servers/slapd/back-meta/modify.c +++ b/servers/slapd/back-meta/modify.c @@ -47,22 +47,15 @@ meta_back_modify( Operation *op, SlapReply *rs ) dncookie dc; lc = meta_back_getconn( op, rs, META_OP_REQUIRE_SINGLE, - &op->o_req_ndn, &candidate ); - if ( !lc ) { - rc = -1; - goto cleanup; + &op->o_req_ndn, &candidate, LDAP_BACK_SENDERR ); + if ( !lc || !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) { + return rs->sr_err; } - if ( !meta_back_dobind( lc, op ) ) { - rs->sr_err = LDAP_UNAVAILABLE; - - } else if ( !meta_back_is_valid( lc, candidate ) ) { + if ( !meta_back_is_valid( lc, candidate ) ) { rs->sr_err = LDAP_OTHER; - } - - if ( rs->sr_err != LDAP_SUCCESS ) { - rc = -1; - goto cleanup; + send_ldap_result( op, rs ); + return rs->sr_err; } /* diff --git a/servers/slapd/back-meta/modrdn.c b/servers/slapd/back-meta/modrdn.c index 756ae36d38..a0d7e408cc 100644 --- a/servers/slapd/back-meta/modrdn.c +++ b/servers/slapd/back-meta/modrdn.c @@ -43,24 +43,21 @@ meta_back_modrdn( Operation *op, SlapReply *rs ) dncookie dc; lc = meta_back_getconn( op, rs, META_OP_REQUIRE_SINGLE, - &op->o_req_ndn, &candidate ); + &op->o_req_ndn, &candidate, LDAP_BACK_SENDERR ); if ( !lc ) { - rc = -1; - goto cleanup; + return rs->sr_err; } assert( candidate != META_TARGET_NONE ); - if ( !meta_back_dobind( lc, op ) ) { - rs->sr_err = LDAP_UNAVAILABLE; - - } else if ( !meta_back_is_valid( lc, candidate ) ) { - rs->sr_err = LDAP_OTHER; + if ( !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) { + return rs->sr_err; } - - if ( rs->sr_err != LDAP_SUCCESS ) { - rc = -1; - goto cleanup; + + if ( !meta_back_is_valid( lc, candidate ) ) { + rs->sr_err = LDAP_OTHER; + send_ldap_result( op, rs ); + return rs->sr_err; } dc.conn = op->o_conn; diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index 6bc693b64b..3dbd522a8b 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -71,16 +71,9 @@ meta_back_search( Operation *op, SlapReply *rs ) * to map attrs and maybe rewrite value */ lc = meta_back_getconn( op, rs, META_OP_ALLOW_MULTIPLE, - &op->o_req_ndn, NULL ); - if ( !lc ) { - send_ldap_result( op, rs ); - return -1; - } - - if ( !meta_back_dobind( lc, op ) ) { - rs->sr_err = LDAP_UNAVAILABLE; - send_ldap_result( op, rs ); - return -1; + &op->o_req_ndn, NULL, LDAP_BACK_SENDERR ); + if ( !lc || !meta_back_dobind( lc, op, LDAP_BACK_SENDERR ) ) { + return rs->sr_err; } /* @@ -310,7 +303,7 @@ new_candidate:; if ( ab ) { ldap_abandon_ext( lsc->msc_ld, msgid[ i ], NULL, NULL ); - rc = 0; + rc = SLAPD_ABANDON; break; } diff --git a/servers/slapd/back-monitor/database.c b/servers/slapd/back-monitor/database.c index 1312d891a5..5acedec8ca 100644 --- a/servers/slapd/back-monitor/database.c +++ b/servers/slapd/back-monitor/database.c @@ -30,7 +30,7 @@ #if defined(LDAP_SLAPI) #include "slapi.h" -static int monitor_back_add_plugin( Backend *be, Entry *e ); +static int monitor_back_add_plugin( monitor_info_t *mi, Backend *be, Entry *e ); #endif /* defined(LDAP_SLAPI) */ #if defined(SLAPD_BDB) @@ -391,7 +391,7 @@ monitor_subsys_database_init( } #if defined(LDAP_SLAPI) - monitor_back_add_plugin( be, e ); + monitor_back_add_plugin( mi, be, e ); #endif /* defined(LDAP_SLAPI) */ if ( oi != NULL ) { @@ -829,11 +829,10 @@ done:; #if defined(LDAP_SLAPI) static int -monitor_back_add_plugin( Backend *be, Entry *e_database ) +monitor_back_add_plugin( monitor_info_t *mi, Backend *be, Entry *e_database ) { Slapi_PBlock *pCurrentPB; int i, rc = LDAP_SUCCESS; - monitor_info_t *mi = ( monitor_info_t * )be->be_private; if ( slapi_int_pblock_get_first( be, &pCurrentPB ) != LDAP_SUCCESS ) { /* diff --git a/servers/slapd/back-passwd/search.c b/servers/slapd/back-passwd/search.c index cfb55531e5..ab2c7c1a22 100644 --- a/servers/slapd/back-passwd/search.c +++ b/servers/slapd/back-passwd/search.c @@ -143,7 +143,7 @@ passwd_back_search( if ( op->o_abandon ) { endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); - return( -1 ); + return( SLAPD_ABANDON ); } /* check time limit */ diff --git a/servers/slapd/back-sql/back-sql.h b/servers/slapd/back-sql/back-sql.h index 49af9ed694..d905d2bf23 100644 --- a/servers/slapd/back-sql/back-sql.h +++ b/servers/slapd/back-sql/back-sql.h @@ -444,7 +444,6 @@ typedef struct backsql_srch_info { **bsi_id_listtail, *bsi_c_eid; int bsi_n_candidates; - int bsi_abandon; int bsi_status; backsql_oc_map_rec *bsi_oc; diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c index 0381f6974f..da3cea0d21 100644 --- a/servers/slapd/back-sql/search.c +++ b/servers/slapd/back-sql/search.c @@ -253,7 +253,6 @@ backsql_init_search( } } - bsi->bsi_abandon = 0; bsi->bsi_id_list = NULL; bsi->bsi_id_listtail = &bsi->bsi_id_list; bsi->bsi_n_candidates = 0; @@ -1464,6 +1463,12 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) Debug( LDAP_DEBUG_TRACE, "==>backsql_oc_get_candidates(): oc=\"%s\"\n", BACKSQL_OC_NAME( oc ), 0, 0 ); + /* check for abandon */ + if ( op->o_abandon ) { + bsi->bsi_status = SLAPD_ABANDON; + return BACKSQL_AVL_STOP; + } + if ( bsi->bsi_n_candidates == -1 ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "unchecked limit has been overcome\n", 0, 0, 0 ); @@ -1943,6 +1948,12 @@ backsql_search( Operation *op, SlapReply *rs ) */ avl_apply( bi->sql_oc_by_oc, backsql_oc_get_candidates, &bsi, BACKSQL_AVL_STOP, AVL_INORDER ); + + /* check for abandon */ + if ( op->o_abandon ) { + rs->sr_err = SLAPD_ABANDON; + goto send_results; + } } if ( op->ors_limit != NULL /* isroot == FALSE */ @@ -1973,7 +1984,8 @@ backsql_search( Operation *op, SlapReply *rs ) /* check for abandon */ if ( op->o_abandon ) { - break; + rs->sr_err = SLAPD_ABANDON; + goto send_results; } /* check time limit */ @@ -1983,10 +1995,7 @@ backsql_search( Operation *op, SlapReply *rs ) rs->sr_err = LDAP_TIMELIMIT_EXCEEDED; rs->sr_ctrls = NULL; rs->sr_ref = rs->sr_v2ref; - rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS - : LDAP_REFERRAL; - send_ldap_result( op, rs ); - goto end_of_search; + goto send_results; } #ifdef BACKSQL_ARBITRARY_KEY @@ -2217,17 +2226,11 @@ next_entry2:; && rs->sr_nentries >= op->ors_slimit ) { rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; - send_ldap_result( op, rs ); - goto end_of_search; + goto send_results; } } end_of_search:; - entry_clean( &base_entry ); - - /* in case we got here accidentally */ - entry_clean( &user_entry ); - if ( rs->sr_nentries > 0 ) { rs->sr_ref = rs->sr_v2ref; rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS @@ -2236,7 +2239,16 @@ end_of_search:; } else { rs->sr_err = bsi.bsi_status; } - send_ldap_result( op, rs ); + +send_results:; + if ( rs->sr_err != SLAPD_ABANDON ) { + send_ldap_result( op, rs ); + } + + entry_clean( &base_entry ); + + /* in case we got here accidentally */ + entry_clean( &user_entry ); if ( rs->sr_v2ref ) { ber_bvarray_free( rs->sr_v2ref ); @@ -2284,7 +2296,8 @@ done:; } Debug( LDAP_DEBUG_TRACE, "<==backsql_search()\n", 0, 0, 0 ); - return 0; + + return rs->sr_err; } /* return LDAP_SUCCESS IFF we can retrieve the specified entry. diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index 577b330953..171b688354 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -578,7 +578,7 @@ static ConfigOCs cf_ocs[] = { "NAME 'olcDatabaseConfig' " "DESC 'OpenLDAP Database-specific options' " "SUP olcConfig STRUCTURAL " - "MAY ( olcDatabase $ olcAccess $ olcLastMod $ olcLimits $ " + "MAY ( olcDatabase $ olcLastMod $ olcLimits $ " "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ " "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ " "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSuffix $ olcSyncrepl $ " @@ -2862,7 +2862,6 @@ config_back_db_open( BackendDB *be ) oprev = ce; } } -#if 0 /* Set up ACLs */ if ( bptr->be_acl ) { Entry *ae; @@ -2881,7 +2880,6 @@ config_back_db_open( BackendDB *be ) } opar->ce_kids = ce; } -#endif } return 0; @@ -2911,9 +2909,6 @@ config_back_db_init( Backend *be ) ber_dupbv( &dn, &be->be_rootdn ); ber_bvarray_add( &be->be_nsuffix, &dn ); - /* Hide from namingContexts */ - SLAP_BFLAGS(be) |= SLAP_BFLAG_CONFIG; - return 0; } diff --git a/servers/slapd/overlays/Makefile.in b/servers/slapd/overlays/Makefile.in index 9f95972edc..7abf065c22 100644 --- a/servers/slapd/overlays/Makefile.in +++ b/servers/slapd/overlays/Makefile.in @@ -23,6 +23,7 @@ SRCS = overlays.c \ refint.c \ rwm.c rwmconf.c rwmdn.c rwmmap.c \ syncprov.c \ + translucent.c \ unique.c OBJS = overlays.lo \ denyop.lo \ @@ -34,6 +35,7 @@ OBJS = overlays.lo \ refint.lo \ rwm.lo rwmconf.lo rwmdn.lo rwmmap.lo \ syncprov.lo \ + translucent.lo \ unique.lo LDAP_INCDIR= ../../../include @@ -78,6 +80,9 @@ rwm.la : rwm.lo $(@PLAT@_LINK_LIBS) syncprov.la : syncprov.lo $(@PLAT@_LINK_LIBS) $(LTLINK_MOD) -module -o $@ syncprov.lo version.lo $(LINK_LIBS) +translucent.la : translucent.lo $(@PLAT@_LINK_LIBS) + $(LTLINK_MOD) -module -o $@ translucent.lo version.lo $(LINK_LIBS) + unique.la : unique.lo $(@PLAT@_LINK_LIBS) $(LTLINK_MOD) -module -o $@ unique.lo version.lo $(LINK_LIBS) diff --git a/servers/slapd/overlays/glue.c b/servers/slapd/overlays/glue.c index a09176e5c7..b5e53f13c8 100644 --- a/servers/slapd/overlays/glue.c +++ b/servers/slapd/overlays/glue.c @@ -396,7 +396,9 @@ end_of_loop:; break; } - if ( !op->o_abandon ) { + if ( op->o_abandon ) { + rs->sr_err = SLAPD_ABANDON; + } else { op->o_callback = cb.sc_next; rs->sr_err = gs.err; rs->sr_matched = gs.matched; diff --git a/servers/slapd/overlays/overlays.c b/servers/slapd/overlays/overlays.c index 3e73167b20..8b1a19ec98 100644 --- a/servers/slapd/overlays/overlays.c +++ b/servers/slapd/overlays/overlays.c @@ -50,6 +50,9 @@ extern int rwm_init(); #if SLAPD_OVER_SYNCPROV == SLAPD_MOD_STATIC extern int syncprov_init(); #endif +#if SLAPD_OVER_TRANSLUCENT == SLAPD_MOD_STATIC +extern int translucent_init(); +#endif #if SLAPD_OVER_UNIQUE == SLAPD_MOD_STATIC extern int unique_init(); #endif @@ -85,6 +88,9 @@ static struct { #if SLAPD_OVER_SYNCPROV == SLAPD_MOD_STATIC { "Syncrepl Provider", syncprov_init }, #endif +#if SLAPD_OVER_TRANSLUCENT == SLAPD_MOD_STATIC + { "Translucent Proxy", translucent_init }, +#endif #if SLAPD_OVER_UNIQUE == SLAPD_MOD_STATIC { "Attribute Uniqueness", unique_init }, #endif diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c index 00227172c6..b696e37942 100644 --- a/servers/slapd/overlays/rwm.c +++ b/servers/slapd/overlays/rwm.c @@ -171,8 +171,8 @@ rwm_op_add( Operation *op, SlapReply *rs ) } } - if ( (*ap)->a_desc->ad_type->sat_syntax - == slap_schema.si_syn_distinguishedName ) + if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName + || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) ) { /* * FIXME: rewrite could fail; in this case @@ -327,7 +327,8 @@ rwm_op_compare( Operation *op, SlapReply *rs ) ad = mapping->m_dst_ad; } - if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) + if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName + || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) ) { struct berval *mapped_valsp[2]; @@ -436,11 +437,11 @@ rwm_op_modify( Operation *op, SlapReply *rs ) last--; for ( j = 0; !BER_BVISNULL( &(*mlp)->sml_values[ j ] ); j++ ) { - struct ldapmapping *mapping = NULL; - + struct ldapmapping *oc_mapping = NULL; + ( void )rwm_mapping( &rwmap->rwm_oc, &(*mlp)->sml_values[ j ], - &mapping, RWM_MAP ); - if ( mapping == NULL ) { + &oc_mapping, RWM_MAP ); + if ( oc_mapping == NULL ) { if ( rwmap->rwm_at.drop_missing ) { /* FIXME: we allow to remove objectClasses as well; * if the resulting entry is inconsistent, that's @@ -457,13 +458,13 @@ rwm_op_modify( Operation *op, SlapReply *rs ) } else { ch_free( (*mlp)->sml_values[ j ].bv_val ); - ber_dupbv( &(*mlp)->sml_values[ j ], &mapping->m_dst ); + ber_dupbv( &(*mlp)->sml_values[ j ], &oc_mapping->m_dst ); } } } else { - if ( (*mlp)->sml_desc->ad_type->sat_syntax == - slap_schema.si_syn_distinguishedName ) + if ( (*mlp)->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName + || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) ) { #ifdef ENABLE_REWRITE rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN", @@ -516,7 +517,6 @@ cleanup_mod:; free( ml ); } - /* TODO: rewrite attribute types, values of DN-valued attributes ... */ return SLAP_CB_CONTINUE; } @@ -822,7 +822,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN ) * about duplicate values?) */ isupdate = be_shadow_update( op ); for ( ap = a_first; *ap; ) { - struct ldapmapping *mapping; + struct ldapmapping *mapping = NULL; int drop_missing; int last; Attribute *a; @@ -832,6 +832,13 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN ) /* go on */ ; } else { + if ( op->ors_attrs != NULL && + !SLAP_USERATTRS( rs->sr_attr_flags ) && + !ad_inlist( (*ap)->a_desc, op->ors_attrs ) ) + { + goto cleanup_attr; + } + drop_missing = rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP ); if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) ) @@ -842,13 +849,6 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN ) if ( mapping != NULL ) { (*ap)->a_desc = mapping->m_dst_ad; } - - if ( op->ors_attrs != NULL && - !SLAP_USERATTRS( rs->sr_attr_flags ) && - !ad_inlist( (*ap)->a_desc, op->ors_attrs ) ) - { - goto cleanup_attr; - } } if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) { @@ -915,8 +915,8 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN ) * everything pass thru the ldap backend. */ /* FIXME: handle distinguishedName-like syntaxes, like * nameAndOptionalUID */ - } else if ( (*ap)->a_desc->ad_type->sat_syntax == - slap_schema.si_syn_distinguishedName ) + } else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName + || ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) ) { #ifdef ENABLE_REWRITE dc.ctx = "searchAttrDN"; @@ -1253,7 +1253,9 @@ rwm_response( Operation *op, SlapReply *rs ) switch( op->o_tag ) { case LDAP_REQ_SEARCH: /* Note: the operation attrs are remapped */ - if ( op->ors_attrs != NULL && op->ors_attrs != rs->sr_attrs ) + if ( rs->sr_type == REP_RESULT + && op->ors_attrs != NULL + && op->ors_attrs != rs->sr_attrs ) { ch_free( op->ors_attrs ); op->ors_attrs = rs->sr_attrs; diff --git a/servers/slapd/overlays/rwmmap.c b/servers/slapd/overlays/rwmmap.c index e551f3568a..e8a630cce6 100644 --- a/servers/slapd/overlays/rwmmap.c +++ b/servers/slapd/overlays/rwmmap.c @@ -386,7 +386,8 @@ map_attr_value( if ( value != NULL ) { assert( mapped_value != NULL ); - if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) + if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName + || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) ) { dncookie fdc = *dc; int rc; diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c index aa51bcd07e..c406f5b1fa 100644 --- a/servers/slapd/overlays/syncprov.c +++ b/servers/slapd/overlays/syncprov.c @@ -860,6 +860,16 @@ syncprov_drop_psearch( syncops *so, int lock ) return 0; } +static int +syncprov_ab_cleanup( Operation *op, SlapReply *rs ) +{ + slap_callback *sc = op->o_callback; + op->o_callback = sc->sc_next; + syncprov_drop_psearch( op->o_callback->sc_private, 0 ); + op->o_tmpfree( sc, op->o_tmpmemctx ); + return 0; +} + static int syncprov_op_abandon( Operation *op, SlapReply *rs ) { @@ -881,8 +891,17 @@ syncprov_op_abandon( Operation *op, SlapReply *rs ) if ( so ) { /* Is this really a Cancel exop? */ if ( op->o_tag != LDAP_REQ_ABANDON ) { + so->s_op->o_cancel = SLAP_CANCEL_ACK; rs->sr_err = LDAP_CANCELLED; send_ldap_result( so->s_op, rs ); + if ( so->s_flags & PS_IS_DETACHED ) { + slap_callback *cb; + cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx ); + cb->sc_cleanup = syncprov_ab_cleanup; + cb->sc_next = op->o_callback; + cb->sc_private = so; + return SLAP_CB_CONTINUE; + } } syncprov_drop_psearch( so, 0 ); } @@ -1468,6 +1487,18 @@ syncprov_op_mod( Operation *op, SlapReply *rs ) ldap_pvt_thread_mutex_unlock( &mt->mt_mutex ); ldap_pvt_thread_yield(); ldap_pvt_thread_mutex_lock( &mt->mt_mutex ); + + /* clean up if the caller is giving up */ + if ( op->o_abandon ) { + modinst *m2; + for ( m2 = mt->mt_mods; m2->mi_next != mi; + m2 = m2->mi_next ); + m2->mi_next = mi->mi_next; + if ( mt->mt_tail == mi ) mt->mt_tail = m2; + op->o_tmpfree( cb, op->o_tmpmemctx ); + ldap_pvt_thread_mutex_unlock( &mt->mt_mutex ); + return SLAPD_ABANDON; + } } ldap_pvt_thread_mutex_unlock( &mt->mt_mutex ); } else { diff --git a/servers/slapd/overlays/translucent.c b/servers/slapd/overlays/translucent.c new file mode 100644 index 0000000000..38ff0039f6 --- /dev/null +++ b/servers/slapd/overlays/translucent.c @@ -0,0 +1,734 @@ +/* Copyright 2004, Symas Corporation. + * All Rights Reserved. + */ + +#include "portable.h" + +#ifdef SLAPD_OVER_TRANSLUCENT + +#include + +#include +#include + +#include "slap.h" + +/* config block */ + +typedef struct translucent_configuration { + int debug; + int strict; + int no_add; + int glue; +} translucent_configuration; + +/* stack of captive backends */ + +typedef struct overlay_stack { + BackendInfo *info; /* captive backend */ + void *private; /* local backend_private */ + translucent_configuration *config; /* our_private: configuration */ +} overlay_stack; + +/* for translucent_init() */ + +static slap_overinst translucent; + +/* +** glue_parent() +** call syncrepl_add_glue() with the parent suffix; +** +*/ + +static struct berval glue[] = { BER_BVC("top"), BER_BVC("glue"), BER_BVNULL }; + +void glue_parent(Operation *op) { + Operation nop = *op; + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + struct berval dn = { 0, NULL }; + char *odn = op->o_req_ndn.bv_val; + Attribute *a; + Entry *e; + int idn, ldn; + + /* tis more work to use strchr() for a berval... */ + for(idn = 0; odn[idn] && odn[idn] != ','; idn++); + if(!idn || !odn[idn]) return; /* because you never know */ + idn++; + ldn = dn.bv_len = op->o_req_ndn.bv_len - idn; + dn.bv_val = ch_malloc(ldn + 1); + strcpy(dn.bv_val, odn + idn); + + Debug(LDAP_DEBUG_TRACE, "=> glue_parent: fabricating glue for <%s>\n", dn.bv_val, 0, 0); + + e = ch_calloc(1, sizeof(Entry)); + e->e_id = NOID; + ber_dupbv(&e->e_name, &dn); + ber_dupbv(&e->e_nname, &dn); + + a = ch_calloc(1, sizeof(Attribute)); + a->a_desc = slap_schema.si_ad_objectClass; + a->a_vals = ch_malloc(sizeof(struct berval) * 3); + ber_dupbv(&a->a_vals[0], &glue[0]); + ber_dupbv(&a->a_vals[1], &glue[1]); + ber_dupbv(&a->a_vals[2], &glue[2]); + a->a_nvals = a->a_vals; + a->a_next = e->e_attrs; + e->e_attrs = a; + + a = ch_calloc(1, sizeof(Attribute)); + a->a_desc = slap_schema.si_ad_structuralObjectClass; + a->a_vals = ch_malloc(sizeof(struct berval) * 2); + ber_dupbv(&a->a_vals[0], &glue[1]); + ber_dupbv(&a->a_vals[1], &glue[2]); + a->a_nvals = a->a_vals; + a->a_next = e->e_attrs; + e->e_attrs = a; + + nop.o_req_dn = dn; + nop.o_req_ndn = dn; + nop.ora_e = e; + nop.o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig; + + syncrepl_add_glue(&nop, e); + return; +} + +/* +** dup_bervarray() +** copy a BerVarray; +*/ + +BerVarray dup_bervarray(BerVarray b) { + int i, len; + BerVarray nb; + for(len = 0; b[len].bv_val; len++); + nb = ch_malloc((len+1) * sizeof(BerValue)); + for(i = 0; i < len; i++) ber_dupbv(&nb[i], &b[i]); + nb[len].bv_val = NULL; + nb[len].bv_len = 0; + return(nb); +} + +/* +** free_attr_chain() +** free only the Attribute*, not the contents; +** +*/ +void free_attr_chain(Attribute *a) { + Attribute *ax; + for(ax = NULL; a; a = a->a_next) { + if(ax) ch_free(ax); + ax = a; + } + return; +} + +/* +** translucent_add() +** if not bound as root, send ACCESS error; +** if config.glue, glue_parent(); +** return CONTINUE; +** +*/ + +static int translucent_add(Operation *op, SlapReply *rs) { + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + overlay_stack *ov = on->on_bi.bi_private; + Debug(LDAP_DEBUG_TRACE, "==> translucent_add: %s\n", + op->o_req_dn.bv_val, 0, 0); + if(!be_isroot(op)) { + op->o_bd->bd_info = (BackendInfo *) on->on_info; + send_ldap_error(op, rs, LDAP_INSUFFICIENT_ACCESS, + "user modification of overlay database not permitted"); + return(rs->sr_err); + } + if(!ov->config->glue) glue_parent(op); + return(SLAP_CB_CONTINUE); +} + +/* +** translucent_modrdn() +** if not bound as root, send ACCESS error; +** if !config.glue, glue_parent(); +** else return CONTINUE; +** +*/ + +static int translucent_modrdn(Operation *op, SlapReply *rs) { + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + overlay_stack *ov = on->on_bi.bi_private; + Debug(LDAP_DEBUG_TRACE, "==> translucent_modrdn: %s -> %s\n", + op->o_req_dn.bv_val, op->orr_newrdn.bv_val, 0); + if(!be_isroot(op)) { + op->o_bd->bd_info = (BackendInfo *) on->on_info; + send_ldap_error(op, rs, LDAP_INSUFFICIENT_ACCESS, + "user modification of overlay database not permitted"); + return(rs->sr_err); + } + if(!ov->config->glue) glue_parent(op); + return(SLAP_CB_CONTINUE); +} + +/* +** translucent_delete() +** if not bound as root, send ACCESS error; +** else return CONTINUE; +** +*/ + +static int translucent_delete(Operation *op, SlapReply *rs) { + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + Debug(LDAP_DEBUG_TRACE, "==> translucent_delete: %s\n", + op->o_req_dn.bv_val, 0, 0); + if(!be_isroot(op)) { + op->o_bd->bd_info = (BackendInfo *) on->on_info; + send_ldap_error(op, rs, LDAP_INSUFFICIENT_ACCESS, + "user modification of overlay database not permitted"); + return(rs->sr_err); + } + return(SLAP_CB_CONTINUE); +} + +/* +** translucent_modify() +** modify in local backend if exists in both; +** otherwise, add to local backend; +** fail if not defined in captive backend; +** +*/ + +static int translucent_modify(Operation *op, SlapReply *rs) { + SlapReply nrs = { REP_RESULT }; + Operation nop = *op; + + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + overlay_stack *ov = on->on_bi.bi_private; + translucent_configuration *cf = ov->config; + void *private = op->o_bd->be_private; + Entry ne, *e, *re = NULL; + Attribute *a, *ax; + Modifications *m, *mm; + int del, rc, erc = 0; + + Debug(LDAP_DEBUG_TRACE, "==> translucent_modify: %s\n", + op->o_req_dn.bv_val, 0, 0); + +/* +** fetch entry from the captive backend; +** if it did not exist, fail; +** release it, if captive backend supports this; +** +*/ + + op->o_bd->bd_info = (BackendInfo *) on->on_info; + op->o_bd->be_private = ov->private; + rc = ov->info->bi_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &re); + op->o_bd->be_private = private; + + /* if(ov->config->no_add && (!re || rc != LDAP_SUCCESS)) */ + if(!re || rc != LDAP_SUCCESS) { + send_ldap_error(op, rs, LDAP_NO_SUCH_OBJECT, + "attempt to modify nonexistent local record"); + return(rs->sr_err); + } + +/* +** fetch entry from local backend; +** if it exists: +** foreach Modification: +** if attr not present in local: +** if Mod == LDAP_MOD_DELETE: +** if remote attr not present, return NO_SUCH; +** if remote attr present, drop this Mod; +** else force this Mod to LDAP_MOD_ADD; +** return CONTINUE; +** +*/ + + rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &e); + + if(e && rc == LDAP_SUCCESS) { + Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: found local entry\n", 0, 0, 0); + for(m = op->orm_modlist; m; m = m->sml_next) { + for(a = e->e_attrs; a; a = a->a_next) + if(a->a_desc == m->sml_desc) break; + if(a) continue; /* found local attr */ + if(m->sml_op == LDAP_MOD_DELETE) { + for(a = re->e_attrs; a; a = a->a_next) + if(a->a_desc == m->sml_desc) break; + /* not found remote attr */ + if(!a) { + erc = LDAP_NO_SUCH_ATTRIBUTE; + goto release; + } + if(ov->config->strict) { + erc = LDAP_CONSTRAINT_VIOLATION; + goto release; + } + Debug(LDAP_DEBUG_TRACE, + "=> translucent_modify: silently dropping delete: %s\n", + m->sml_desc->ad_cname.bv_val, 0, 0); + for(mm = op->orm_modlist; mm->sml_next != m; mm = mm->sml_next); + mm->sml_next = m->sml_next; + mm = m; + m = m->sml_next; + mm->sml_next = NULL; /* hack */ + slap_mods_free(mm); + if(m) continue; + } + m->sml_op = LDAP_MOD_ADD; + } + erc = SLAP_CB_CONTINUE; +release: + if(re) { + op->o_bd->be_private = ov->private; + if(ov->info->bi_entry_release_rw) + ov->info->bi_entry_release_rw(op, re, 0); + else + entry_free(re); + op->o_bd->be_private = private; + } + be_entry_release_r(op, e); + if(erc == SLAP_CB_CONTINUE) { + op->o_bd->bd_info = (BackendInfo *) on; + return(erc); + } else if(erc) { + send_ldap_error(op, rs, erc, + "attempt to delete nonexistent attribute"); + return(erc); + } + } + +/* +** foreach Modification: +** if MOD_ADD or MOD_REPLACE, add Attribute; +** if no Modifications were suitable: +** if config.strict, throw CONSTRAINT_VIOLATION; +** else, return early SUCCESS; +** fabricate Entry with new Attribute chain; +** glue_parent() for this Entry; +** call bi_op_add() in local backend; +** +*/ + + Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: fabricating local add\n", 0, 0, 0); + a = NULL; + for(del = 0, ax = NULL, m = op->orm_modlist; m; m = m->sml_next) { + if(((m->sml_op & LDAP_MOD_OP) != LDAP_MOD_ADD) && + ((m->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE)) { + Debug(LDAP_DEBUG_ANY, + "=> translucent_modify: silently dropped modification(%d): %s\n", + m->sml_op, m->sml_desc->ad_cname.bv_val, 0); + if((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) del++; + continue; + } + a = ch_calloc(1, sizeof(Attribute)); + a->a_desc = m->sml_desc; + a->a_vals = m->sml_values; + a->a_nvals = m->sml_nvalues; + a->a_next = ax; + ax = a; + } + + if(del && ov->config->strict) { + free_attr_chain(a); + send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, + "attempt to delete attributes from local database"); + return(rs->sr_err); + } + + if(!ax) { + if(ov->config->strict) { + send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, + "modification contained other than ADD or REPLACE"); + return(rs->sr_err); + } + op->o_bd->bd_info = (BackendInfo *) on; + /* rs->sr_text = "no valid modification found"; */ + rs->sr_err = LDAP_SUCCESS; + send_ldap_result(op, rs); + return(rs->sr_err); + } + + ne.e_id = NOID; + ne.e_name = op->o_req_dn; + ne.e_nname = op->o_req_ndn; + ne.e_attrs = a; + ne.e_ocflags = 0; + ne.e_bv.bv_len = 0; + ne.e_bv.bv_val = NULL; + ne.e_private = NULL; + + nop.o_tag = LDAP_REQ_ADD; + nop.oq_add.rs_e = ≠ + + op->o_bd->bd_info = (BackendInfo *) on; + glue_parent(&nop); + + rc = on->on_info->oi_orig->bi_op_add(&nop, &nrs); + free_attr_chain(a); + + return(rc); +} + +static int translucent_compare(Operation *op, SlapReply *rs) { + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + overlay_stack *ov = on->on_bi.bi_private; + void *private = op->o_bd->be_private; + translucent_configuration *cf = ov->config; + + AttributeAssertion *ava = op->orc_ava; + Attribute *a, *an, *ra, *as = NULL; + Entry *e, *ee, *re; + int rc; + + Debug(LDAP_DEBUG_TRACE, "==> translucent_compare: <%s> %s:%s\n", + op->o_req_dn.bv_val, ava->aa_desc->ad_cname.bv_val, ava->aa_value.bv_val); + +/* +** if the local backend has an entry for this attribute: +** CONTINUE and let it do the compare; +** +*/ + + op->o_bd->bd_info = (BackendInfo *) on->on_info; + rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, ava->aa_desc, 0, &e); + if(e && rc == LDAP_SUCCESS) { + be_entry_release_r(op, e); + op->o_bd->bd_info = (BackendInfo *) on; + return(SLAP_CB_CONTINUE); + } + +/* +** call compare() in the captive backend; +** return the result; +** +*/ + + op->o_bd->be_private = ov->private; + rc = ov->info->bi_op_compare(op, rs); + op->o_bd->be_private = private; + op->o_bd->bd_info = (BackendInfo *) on; + return(rc); +} + +/* +** translucent_search_cb() +** merge local data with the search result +** +*/ + +static int translucent_search_cb(Operation *op, SlapReply *rs) { + slap_overinst *on; + Entry *e, *re = NULL; + Attribute *a, *ax, *an, *as = NULL; + BerVarray b, bx; + void *private; + int i, rc, size; + + if(!op || !rs || rs->sr_type != REP_SEARCH || !rs->sr_entry) + return(SLAP_CB_CONTINUE); + + Debug(LDAP_DEBUG_TRACE, "==> tranclucent_search_cb: %s\n", + rs->sr_entry->e_name.bv_val, 0, 0); + + on = (slap_overinst *) op->o_bd->bd_info; + op->o_bd->bd_info = (BackendInfo *) on->on_info; + + private = op->o_bd->be_private; + op->o_bd->be_private = op->o_callback->sc_private; + + rc = be_entry_get_rw(op, &rs->sr_entry->e_nname, NULL, NULL, 0, &e); + +/* +** if we got an entry from local backend: +** make a copy of this search result; +** foreach local attr: +** foreach search result attr: +** if match, result attr with local attr; +** if new local, add to list; +** append new local attrs to search result; +** +*/ + + if(e && rc == LDAP_SUCCESS) { + re = entry_dup(rs->sr_entry); + for(ax = e->e_attrs; ax; ax = ax->a_next) { +#if 0 + if(is_at_operational(ax->a_desc->ad_type)) continue; +#endif + for(a = re->e_attrs; a; a = a->a_next) { + if(a->a_desc == ax->a_desc) { + if(a->a_vals != a->a_nvals) + ber_bvarray_free(a->a_nvals); + ber_bvarray_free(a->a_vals); + a->a_vals = dup_bervarray(ax->a_vals); + a->a_nvals = (ax->a_vals == ax->a_nvals) ? + a->a_vals : dup_bervarray(ax->a_nvals); + break; + } + } + if(a) continue; + an = attr_dup(ax); + an->a_next = as; + as = an; + } + be_entry_release_r(op, e); + + /* literally append, so locals are always last */ + if(as) { + if(re->e_attrs) { + for(ax = re->e_attrs; ax->a_next; ax = ax->a_next); + ax->a_next = as; + } else { + re->e_attrs = as; + } + } + rs->sr_entry = re; + rs->sr_flags |= REP_ENTRY_MUSTBEFREED; + } + + op->o_bd->be_private = private; + op->o_bd->bd_info = (BackendInfo *) on; + + return(SLAP_CB_CONTINUE); +} + +/* +** translucent_search() +** search via captive backend; +** override results with any local data; +** +*/ + +static int translucent_search(Operation *op, SlapReply *rs) { + Operation nop = *op; + + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + slap_callback cb = { NULL, NULL, NULL, NULL }; + overlay_stack *ov = on->on_bi.bi_private; + translucent_configuration *cf = ov->config; + void *private = op->o_bd->be_private; + int rc; + + Debug(LDAP_DEBUG_TRACE, "==> translucent_search: <%s> %s\n", + op->o_req_dn.bv_val, op->ors_filterstr.bv_val, 0); + cb.sc_response = (slap_response *) translucent_search_cb; + cb.sc_private = private; + + cb.sc_next = nop.o_callback; + nop.o_callback = &cb; + + op->o_bd->be_private = ov->private; + rc = ov->info->bi_op_search(&nop, rs); + op->o_bd->be_private = private; + + return(rs->sr_err); +} + + +/* +** translucent_bind() +** pass bind request to captive backend; +** +*/ + +static int translucent_bind(Operation *op, SlapReply *rs) { + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + overlay_stack *ov = on->on_bi.bi_private; + void *private = op->o_bd->be_private; + int rc = 0; + + Debug(LDAP_DEBUG_TRACE, "translucent_bind: <%s> method %d\n", + op->o_req_dn.bv_val, op->orb_method, 0); + + op->o_bd->be_private = ov->private; + rc = ov->info->bi_op_bind(op, rs); + op->o_bd->be_private = private; + + return(rc); +} + +/* +** translucent_config() +** pass config directives to captive backend; +** parse unrecognized directives ourselves; +** +*/ + +static int translucent_config( + BackendDB *be, + const char *fname, + int lineno, + int argc, + char **argv +) +{ + slap_overinst *on = (slap_overinst *) be->bd_info; + overlay_stack *ov = on->on_bi.bi_private; + void *private = be->be_private; + int rc; + + /* "this should never happen" */ + if(!ov->info) { + fprintf(stderr, "fatal: captive backend not initialized"); + return(1); + } + + be->be_private = ov->private; + rc = ov->info->bi_db_config ? ov->info->bi_db_config(be, fname, lineno, argc, argv) : 0; + be->be_private = private; + + /* pass okay or error up, SLAP_CONF_UNKNOWN might be ours */ + if(rc == 0 || rc == 1) return(rc); + + rc = 0; + if(!strcasecmp(*argv, "translucent_strict")) { + ov->config->strict++; + } else if(!strcasecmp(*argv, "translucent_no_add")) { + ov->config->no_add++; + } else if(!strcasecmp(*argv, "translucent_no_glue")) { + ov->config->glue++; + } else if(!strcasecmp(*argv, "translucent_debug")) { + if(argc == 1) { + ov->config->debug = 0xFFFF; + rc = 0; + } else if(argc == 2) { + ov->config->debug = atoi(argv[1]); + rc = 0; + } else { + fprintf(stderr, "%s: line %d: too many arguments (%d) to debug\n", + fname, lineno, argc); + rc = 1; + } + } else { + fprintf(stderr, "%s: line %d: unknown keyword %s\n", + fname, lineno, *argv); + rc = SLAP_CONF_UNKNOWN; + } + return(rc); +} + +/* +** translucent_db_init() +** initialize the captive backend; +** +*/ + +static int translucent_db_init(BackendDB *be) { + slap_overinst *on = (slap_overinst *) be->bd_info; + void *private = be->be_private; + overlay_stack *ov; + int rc; + + Debug(LDAP_DEBUG_TRACE, "==> translucent_init\n", 0, 0, 0); + + ov = ch_calloc(1, sizeof(overlay_stack)); + ov->config = ch_calloc(1, sizeof(translucent_configuration)); + ov->info = backend_info("ldap"); + + if(!ov->info) { + Debug(LDAP_DEBUG_ANY, "translucent: backend_info failed!\n", 0, 0, 0); + return(1); + } + + /* forcibly disable schema checking on the local backend */ + SLAP_DBFLAGS(be) |= SLAP_DBFLAG_NO_SCHEMA_CHECK; + + be->be_private = NULL; + rc = ov->info->bi_db_init ? ov->info->bi_db_init(be) : 0; + + if(rc) Debug(LDAP_DEBUG_TRACE, + "translucent: bi_db_init() returned error %d\n", rc, 0, 0); + + ov->private = be->be_private; + be->be_private = private; + on->on_bi.bi_private = ov; + return(rc); +} + +/* +** translucent_open() +** if the captive backend has an open() method, call it; +** +*/ + +static int translucent_open(BackendDB *be) { + slap_overinst *on = (slap_overinst *) be->bd_info; + overlay_stack *ov = on->on_bi.bi_private; + void *private = be->be_private; + int rc; + + /* "should never happen" */ + if(!ov->info) { + Debug(LDAP_DEBUG_ANY, "translucent_open() called with bad ov->info\n", 0, 0, 0); + return(LDAP_OTHER); + } + + Debug(LDAP_DEBUG_TRACE, "translucent_open\n", 0, 0, 0); + + be->be_private = ov->private; + rc = ov->info->bi_db_open ? ov->info->bi_db_open(be) : 0; + be->be_private = private; + + if(rc) Debug(LDAP_DEBUG_TRACE, + "translucent: bi_db_open() returned error %d\n", rc, 0, 0); + + return(rc); +} + +/* +** translucent_close() +** if the captive backend has a close() method, call it; +** free any config data; +** +*/ + +static int translucent_close(BackendDB *be) { + slap_overinst *on = (slap_overinst *) be->bd_info; + overlay_stack *ov = on->on_bi.bi_private; + translucent_configuration *cf = ov->config; + void *private = be->be_private; + int rc; + + be->be_private = ov->private; + rc = (ov->info && ov->info->bi_db_close) ? ov->info->bi_db_close(be) : 0; + be->be_private = private; + if(ov->config) ch_free(ov->config); + ch_free(ov); + return(rc); +} + +/* +** translucent_init() +** initialize the slap_overinst with our entry points; +** +*/ + +int translucent_init() { + + translucent.on_bi.bi_type = "translucent"; + translucent.on_bi.bi_db_init = translucent_db_init; + translucent.on_bi.bi_db_config = translucent_config; + translucent.on_bi.bi_db_open = translucent_open; + translucent.on_bi.bi_db_close = translucent_close; + translucent.on_bi.bi_op_bind = translucent_bind; + translucent.on_bi.bi_op_add = translucent_add; + translucent.on_bi.bi_op_modify = translucent_modify; + translucent.on_bi.bi_op_modrdn = translucent_modrdn; + translucent.on_bi.bi_op_delete = translucent_delete; + translucent.on_bi.bi_op_search = translucent_search; + translucent.on_bi.bi_op_compare = translucent_compare; + + return(overlay_register(&translucent)); +} + +#if SLAPD_OVER_TRANSLUCENT == SLAPD_MOD_DYNAMIC && defined(PIC) +int init_module(int argc, char *argv[]) { + return translucent_init(); +} +#endif + +#endif /* SLAPD_OVER_TRANSLUCENT */ + diff --git a/servers/slapd/overlays/unique.c b/servers/slapd/overlays/unique.c index d44e205fdf..79e7db9403 100644 --- a/servers/slapd/overlays/unique.c +++ b/servers/slapd/overlays/unique.c @@ -46,6 +46,7 @@ typedef struct unique_data_s { } unique_data; typedef struct unique_counter_s { + struct berval *ndn; int count; } unique_counter; @@ -231,16 +232,23 @@ static int count_attr_cb( SlapReply *rs ) { + unique_counter *uc; + /* because you never know */ if(!op || !rs) return(0); /* Only search entries are interesting */ if(rs->sr_type != REP_SEARCH) return(0); + uc = op->o_callback->sc_private; + + /* Ignore the current entry */ + if ( dn_match( uc->ndn, &rs->sr_entry->e_nname )) return(0); + Debug(LDAP_DEBUG_TRACE, "==> count_attr_cb <%s>\n", rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0); - ((unique_counter*)op->o_callback->sc_private)->count++; + uc->count++; return(0); } @@ -316,7 +324,7 @@ static int unique_search( unique_data *ud = on->on_bi.bi_private; SlapReply nrs = { REP_RESULT }; slap_callback cb = { NULL, NULL, NULL, NULL }; /* XXX */ - unique_counter uq = { 0 }; + unique_counter uq = { NULL, 0 }; int rc; nop->ors_filter = str2filter_x(nop, key); @@ -334,6 +342,8 @@ static int unique_search( nop->ors_attrs = slap_anlist_no_attrs; nop->ors_attrsonly = 1; + uq.ndn = &op->o_req_ndn; + nop->o_req_ndn = ud->dn; nop->o_ndn = op->o_bd->be_rootndn; diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 127ac5a45b..2214f0cb8e 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -822,7 +822,6 @@ struct slap_internal_schema { AttributeDescription *si_ad_monitorContext; AttributeDescription *si_ad_vendorName; AttributeDescription *si_ad_vendorVersion; - AttributeDescription *si_ad_configContext; /* subentry attribute descriptions */ AttributeDescription *si_ad_administrativeRole; @@ -2030,7 +2029,6 @@ struct slap_backend_info { slap_mask_t bi_flags; /* backend flags */ #define SLAP_BFLAG_MONITOR 0x0001U /* a monitor backend */ -#define SLAP_BFLAG_CONFIG 0x0002U /* a config backend */ #define SLAP_BFLAG_NOLASTMODCMD 0x0010U #define SLAP_BFLAG_INCREMENT 0x0100U #define SLAP_BFLAG_ALIASES 0x1000U @@ -2040,7 +2038,6 @@ struct slap_backend_info { #define SLAP_BFLAGS(be) ((be)->bd_info->bi_flags) #define SLAP_MONITOR(be) (SLAP_BFLAGS(be) & SLAP_BFLAG_MONITOR) -#define SLAP_CONFIG(be) (SLAP_BFLAGS(be) & SLAP_BFLAG_CONFIG) #define SLAP_INCREMENT(be) (SLAP_BFLAGS(be) & SLAP_BFLAG_INCREMENT) #define SLAP_ALIASES(be) (SLAP_BFLAGS(be) & SLAP_BFLAG_ALIASES) #define SLAP_REFERRALS(be) (SLAP_BFLAGS(be) & SLAP_BFLAG_REFERRALS) diff --git a/servers/slapd/slapi/plugin.c b/servers/slapd/slapi/plugin.c index 428d1cf2fa..6ebe041408 100644 --- a/servers/slapd/slapi/plugin.c +++ b/servers/slapd/slapi/plugin.c @@ -24,6 +24,7 @@ #include #include #include +#include /* * Note: if ltdl.h is not available, slapi should not be compiled @@ -64,8 +65,6 @@ static Slapi_PBlock *pGPlugins = NULL; static Slapi_PBlock * plugin_pblock_new( int type, - const char *path, - const char *initfunc, int argc, char *argv[] ) { @@ -73,6 +72,9 @@ plugin_pblock_new( Slapi_PluginDesc *pPluginDesc = NULL; lt_dlhandle hdLoadHandle; int rc; + char **av2 = NULL, **ppPluginArgv; + char *path = argv[2]; + char *initfunc = argv[3]; pPlugin = slapi_pblock_new(); if ( pPlugin == NULL ) { @@ -90,7 +92,23 @@ plugin_pblock_new( goto done; } - rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)argv ); + av2 = ldap_charray_dup( argv ); + if ( !av2 ) { + rc = LDAP_NO_MEMORY; + goto done; + } + + if ( argc > 0 ) { + ppPluginArgv = &av2[4]; + } else { + ppPluginArgv = NULL; + } + rc = slapi_pblock_set( pPlugin, SLAPI_PLUGIN_ARGV, (void *)ppPluginArgv ); + if ( rc != 0 ) { + goto done; + } + + rc = slapi_pblock_set( pPlugin, SLAPI_X_CONFIG_ARGV, (void *)av2 ); if ( rc != 0 ) { goto done; } @@ -114,6 +132,9 @@ done: if ( rc != 0 && pPlugin != NULL ) { slapi_pblock_destroy( pPlugin ); pPlugin = NULL; + if ( av2 ) { + ldap_charray_free( av2 ); + } } return pPlugin; @@ -681,7 +702,6 @@ slapi_int_read_config( { int iType = -1; int numPluginArgc = 0; - char **ppPluginArgv = NULL; if ( argc < 4 ) { fprintf( stderr, @@ -707,11 +727,6 @@ slapi_int_read_config( } numPluginArgc = argc - 4; - if ( numPluginArgc > 0 ) { - ppPluginArgv = &argv[4]; - } else { - ppPluginArgv = NULL; - } if ( iType == SLAPI_PLUGIN_PREOPERATION || iType == SLAPI_PLUGIN_EXTENDEDOP || @@ -720,8 +735,7 @@ slapi_int_read_config( int rc; Slapi_PBlock *pPlugin; - pPlugin = plugin_pblock_new( iType, argv[2], argv[3], - numPluginArgc, ppPluginArgv ); + pPlugin = plugin_pblock_new( iType, numPluginArgc, argv ); if (pPlugin == NULL) { return 1; } @@ -747,6 +761,38 @@ slapi_int_read_config( return 0; } +void +slapi_int_plugin_unparse( + Backend *be, + BerVarray *out +) +{ + Slapi_PBlock *pp; + int i, j, rc; + char **argv, ibuf[32], *ptr; + struct berval idx, bv; + + *out = NULL; + idx.bv_val = ibuf; + i = 0; + for ( pp=be->be_pb; pp; slapi_pblock_get( pp, SLAPI_IBM_PBLOCK, &pp ) ) { + slapi_pblock_get( pp, SLAPI_X_CONFIG_ARGV, &argv ); + idx.bv_len = sprintf( idx.bv_val, "{%d}", i ); + bv.bv_len = idx.bv_len; + for (j=1; argv[j]; j++) { + bv.bv_len += strlen(argv[j]); + if ( j ) bv.bv_len++; + } + bv.bv_val = ch_malloc( bv.bv_len + 1 ); + ptr = lutil_strcopy( bv.bv_val, ibuf ); + for (j=1; argv[j]; j++) { + if ( j ) *ptr++ = ' '; + ptr = lutil_strcopy( ptr, argv[j] ); + } + ber_bvarray_add( out, &bv ); + } +} + int slapi_int_initialize(void) { diff --git a/servers/slapd/slapi/proto-slapi.h b/servers/slapd/slapi/proto-slapi.h index 1470e34518..96dc7991c0 100644 --- a/servers/slapd/slapi/proto-slapi.h +++ b/servers/slapd/slapi/proto-slapi.h @@ -285,6 +285,7 @@ extern int slapi_int_register_extop(Backend *pBE, ExtendedOp **opList, Slapi_PBl extern int slapi_int_get_extop_plugin(struct berval *reqoid, SLAPI_FUNC *pFuncAddr ); extern int slapi_int_read_config(Backend *be, const char *fname, int lineno, int argc, char **argv ); +extern void slapi_int_plugin_unparse(Backend *be, BerVarray *out ); extern int slapi_int_initialize(void); diff --git a/servers/slapd/slapi/slapi.h b/servers/slapd/slapi/slapi.h index fea688d1ea..45c8aea68f 100644 --- a/servers/slapd/slapi/slapi.h +++ b/servers/slapd/slapi/slapi.h @@ -131,13 +131,16 @@ typedef enum slapi_extension_e { #ifndef NO_PBLOCK_CLASS /* where's this test from? */ -#if 0 /* unused (yet?) */ -#define CMP_EQUAL 0 -#define CMP_GREATER 1 -#define CMP_LOWER (-1) -#endif +typedef enum slapi_pblock_class_e { + PBLOCK_CLASS_INVALID = 0, + PBLOCK_CLASS_INTEGER, + PBLOCK_CLASS_LONG_INTEGER, + PBLOCK_CLASS_POINTER, + PBLOCK_CLASS_FUNCTION_POINTER +} slapi_pblock_class_t; + +#define PBLOCK_SUCCESS (0) #define PBLOCK_ERROR (-1) -#define INVALID_PARAM PBLOCK_ERROR #define PBLOCK_MAX_PARAMS 100 struct slapi_pblock { @@ -283,6 +286,8 @@ extern Backend * slapi_cl_get_be(char *dn); #define SLAPI_X_CONN_SSF 1303 #define SLAPI_X_CONN_SASL_CONTEXT 1304 +#define SLAPI_X_CONFIG_ARGV 1400 + #define SLAPD_AUTH_NONE "none" #define SLAPD_AUTH_SIMPLE "simple" #define SLAPD_AUTH_SSL "SSL" diff --git a/servers/slapd/slapi/slapi_pblock.c b/servers/slapd/slapi/slapi_pblock.c index 79efa4124e..6dcbe7b536 100644 --- a/servers/slapd/slapi/slapi_pblock.c +++ b/servers/slapd/slapi/slapi_pblock.c @@ -24,53 +24,57 @@ #include #include -static int -isOkNetscapeParam( int param ) +static slapi_pblock_class_t +getPBlockClass( int param ) { switch ( param ) { - case SLAPI_BACKEND: - case SLAPI_CONNECTION: - case SLAPI_OPERATION: - case SLAPI_OPERATION_PARAMETERS: - case SLAPI_OPERATION_TYPE: - case SLAPI_OPERATION_ID: - case SLAPI_OPERATION_AUTHTYPE: + case SLAPI_PLUGIN_TYPE: + case SLAPI_PLUGIN_ARGC: + case SLAPI_PLUGIN_VERSION: + case SLAPI_PLUGIN_OPRETURN: + case SLAPI_PLUGIN_INTOP_RESULT: + case SLAPI_CONFIG_LINENO: + case SLAPI_CONFIG_ARGC: + case SLAPI_BIND_METHOD: + case SLAPI_MODRDN_DELOLDRDN: + case SLAPI_SEARCH_SCOPE: + case SLAPI_SEARCH_DEREF: + case SLAPI_SEARCH_SIZELIMIT: + case SLAPI_SEARCH_TIMELIMIT: + case SLAPI_SEARCH_ATTRSONLY: + case SLAPI_NENTRIES: + case SLAPI_CHANGENUMBER: + case SLAPI_DBSIZE: case SLAPI_REQUESTOR_ISROOT: - case SLAPI_BE_MONITORDN: - case SLAPI_BE_TYPE: case SLAPI_BE_READONLY: case SLAPI_BE_LASTMOD: - case SLAPI_CONN_ID: - case SLAPI_OPINITIATED_TIME: - case SLAPI_REQUESTOR_DN: + case SLAPI_DB2LDIF_PRINTKEY: + case SLAPI_LDIF2DB_REMOVEDUPVALS: + case SLAPI_MANAGEDSAIT: + case SLAPI_IBM_BROADCAST_BE: + case SLAPI_IBM_REPLICATE: + case SLAPI_IBM_CL_MAX_ENTRIES: + case SLAPI_IBM_CL_FIRST_ENTRY: + case SLAPI_IBM_CL_LAST_ENTRY: + case SLAPI_IBM_EVENT_ENABLED: + case SLAPI_IBM_EVENT_MAXREG: + case SLAPI_IBM_EVENT_REGPERCONN: case SLAPI_REQUESTOR_ISUPDATEDN: - case SLAPI_CONN_DN: - case SLAPI_CONN_CLIENTIP: - case SLAPI_CONN_SERVERIP: - case SLAPI_CONN_AUTHTYPE: - case SLAPI_CONN_AUTHMETHOD: - case SLAPI_CONN_CERT: case SLAPI_X_CONN_IS_UDP: - case SLAPI_X_CONN_CLIENTPATH: - case SLAPI_X_CONN_SERVERPATH: case SLAPI_X_CONN_SSF: - case SLAPI_X_CONN_SASL_CONTEXT: - case SLAPI_IBM_CONN_DN_ALT: - case SLAPI_IBM_CONN_DN_ORIG: - case SLAPI_IBM_GSSAPI_CONTEXT: - case SLAPI_PLUGIN: - case SLAPI_PLUGIN_PRIVATE: - case SLAPI_PLUGIN_TYPE: - case SLAPI_PLUGIN_ARGV: - case SLAPI_PLUGIN_ARGC: - case SLAPI_PLUGIN_VERSION: - case SLAPI_PLUGIN_OPRETURN: - case SLAPI_PLUGIN_OBJECT: + case SLAPI_RESULT_CODE: + return PBLOCK_CLASS_INTEGER; + break; + + case SLAPI_CONN_ID: + case SLAPI_OPERATION_ID: + case SLAPI_OPINITIATED_TIME: + case SLAPI_ABANDON_MSGID: + return PBLOCK_CLASS_LONG_INTEGER; + break; + + case SLAPI_PLUGIN_DB_INIT_FN: case SLAPI_PLUGIN_DESTROY_FN: - case SLAPI_PLUGIN_DESCRIPTION: - case SLAPI_PLUGIN_INTOP_RESULT: - case SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES: - case SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS: case SLAPI_PLUGIN_DB_BIND_FN: case SLAPI_PLUGIN_DB_UNBIND_FN: case SLAPI_PLUGIN_DB_SEARCH_FN: @@ -132,11 +136,49 @@ isOkNetscapeParam( int param ) case SLAPI_PLUGIN_MR_FILTER_INDEX_FN: case SLAPI_PLUGIN_MR_FILTER_RESET_FN: case SLAPI_PLUGIN_MR_INDEX_FN: + case SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN: + case SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN: + case SLAPI_PLUGIN_ACL_ALLOW_ACCESS: + case SLAPI_X_PLUGIN_PRE_GROUP_FN: + case SLAPI_X_PLUGIN_POST_GROUP_FN: + case SLAPI_PLUGIN_AUDIT_FN: + return PBLOCK_CLASS_FUNCTION_POINTER; + break; + + case SLAPI_BACKEND: + case SLAPI_CONNECTION: + case SLAPI_OPERATION: + case SLAPI_OPERATION_PARAMETERS: + case SLAPI_OPERATION_TYPE: + case SLAPI_OPERATION_AUTHTYPE: + case SLAPI_BE_MONITORDN: + case SLAPI_BE_TYPE: + case SLAPI_REQUESTOR_DN: + case SLAPI_CONN_DN: + case SLAPI_CONN_CLIENTIP: + case SLAPI_CONN_SERVERIP: + case SLAPI_CONN_AUTHTYPE: + case SLAPI_CONN_AUTHMETHOD: + case SLAPI_CONN_CERT: + case SLAPI_X_CONN_CLIENTPATH: + case SLAPI_X_CONN_SERVERPATH: + case SLAPI_X_CONN_SASL_CONTEXT: + case SLAPI_X_CONFIG_ARGV: + case SLAPI_IBM_CONN_DN_ALT: + case SLAPI_IBM_CONN_DN_ORIG: + case SLAPI_IBM_GSSAPI_CONTEXT: case SLAPI_PLUGIN_MR_OID: case SLAPI_PLUGIN_MR_TYPE: case SLAPI_PLUGIN_MR_VALUE: case SLAPI_PLUGIN_MR_VALUES: case SLAPI_PLUGIN_MR_KEYS: + case SLAPI_PLUGIN: + case SLAPI_PLUGIN_PRIVATE: + case SLAPI_PLUGIN_ARGV: + case SLAPI_PLUGIN_OBJECT: + case SLAPI_PLUGIN_DESCRIPTION: + case SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES: + case SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS: case SLAPI_PLUGIN_MR_FILTER_REUSABLE: case SLAPI_PLUGIN_MR_QUERY_OPERATOR: case SLAPI_PLUGIN_MR_USAGE: @@ -152,10 +194,7 @@ isOkNetscapeParam( int param ) case SLAPI_PLUGIN_SYNTAX_OID: case SLAPI_PLUGIN_SYNTAX_FLAGS: case SLAPI_PLUGIN_SYNTAX_COMPARE: - case SLAPI_MANAGEDSAIT: case SLAPI_CONFIG_FILENAME: - case SLAPI_CONFIG_LINENO: - case SLAPI_CONFIG_ARGC: case SLAPI_CONFIG_ARGV: case SLAPI_TARGET_DN: case SLAPI_REQCONTROLS: @@ -164,7 +203,6 @@ isOkNetscapeParam( int param ) case SLAPI_RESCONTROLS: case SLAPI_ADD_RESCONTROL: case SLAPI_ADD_ENTRY: - case SLAPI_BIND_METHOD: case SLAPI_BIND_CREDENTIALS: case SLAPI_BIND_SASLMECHANISM: case SLAPI_BIND_RET_SASLCREDS: @@ -172,17 +210,10 @@ isOkNetscapeParam( int param ) case SLAPI_COMPARE_VALUE: case SLAPI_MODIFY_MODS: case SLAPI_MODRDN_NEWRDN: - case SLAPI_MODRDN_DELOLDRDN: case SLAPI_MODRDN_NEWSUPERIOR: - case SLAPI_SEARCH_SCOPE: - case SLAPI_SEARCH_DEREF: - case SLAPI_SEARCH_SIZELIMIT: - case SLAPI_SEARCH_TIMELIMIT: case SLAPI_SEARCH_FILTER: case SLAPI_SEARCH_STRFILTER: case SLAPI_SEARCH_ATTRS: - case SLAPI_SEARCH_ATTRSONLY: - case SLAPI_ABANDON_MSGID: case SLAPI_SEQ_TYPE: case SLAPI_SEQ_ATTRNAME: case SLAPI_SEQ_VAL: @@ -196,57 +227,27 @@ isOkNetscapeParam( int param ) case SLAPI_MR_FILTER_OID: case SLAPI_MR_FILTER_DNATTRS: case SLAPI_LDIF2DB_FILE: - case SLAPI_LDIF2DB_REMOVEDUPVALS: - case SLAPI_DB2LDIF_PRINTKEY: case SLAPI_PARENT_TXN: case SLAPI_TXN: case SLAPI_SEARCH_RESULT_SET: case SLAPI_SEARCH_RESULT_ENTRY: - case SLAPI_NENTRIES: case SLAPI_SEARCH_REFERRALS: - case SLAPI_CHANGENUMBER: case SLAPI_LOG_OPERATION: - case SLAPI_DBSIZE: - case SLAPI_RESULT_CODE: case SLAPI_RESULT_TEXT: case SLAPI_RESULT_MATCHED: - case SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN: - case SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN: - case SLAPI_PLUGIN_ACL_ALLOW_ACCESS: - case SLAPI_X_PLUGIN_PRE_GROUP_FN: - case SLAPI_X_PLUGIN_POST_GROUP_FN: case SLAPI_X_GROUP_ENTRY: case SLAPI_X_GROUP_ATTRIBUTE: case SLAPI_X_GROUP_OPERATION_DN: case SLAPI_X_GROUP_TARGET_ENTRY: - return LDAP_SUCCESS; + case SLAPI_PLUGIN_AUDIT_DATA: + case SLAPI_IBM_PBLOCK: + return PBLOCK_CLASS_POINTER; + break; default: - return INVALID_PARAM; + break; } -} -static int -isValidParam( Slapi_PBlock *pb, int param ) -{ - if ( !pb ) { - return INVALID_PARAM; - } - - if ( pb->ckParams == TRUE ) { - if ( IBM_RESERVED( param ) ) return LDAP_SUCCESS; - if (param == SLAPI_PLUGIN_AUDIT_FN || - param == SLAPI_PLUGIN_AUDIT_DATA ) - return LDAP_SUCCESS; - if ( param < LAST_IBM_PARAM ) { - return INVALID_PARAM; - } else if ( NETSCAPE_RESERVED( param ) ) { - return INVALID_PARAM; - } else { - return isOkNetscapeParam(param); - } - } else { - return LDAP_SUCCESS; - } + return PBLOCK_CLASS_INVALID; } static void @@ -265,22 +266,49 @@ static int get( Slapi_PBlock *pb, int param, void **val ) { int i; + slapi_pblock_class_t pbClass; - if ( isValidParam( pb, param ) == INVALID_PARAM ) { + pbClass = getPBlockClass( param ); + if ( pbClass == PBLOCK_CLASS_INVALID ) { return PBLOCK_ERROR; } Lock( pb ); - - *val = NULL; + + switch ( pbClass ) { + case PBLOCK_CLASS_INTEGER: + *((int *)val) = 0; + break; + case PBLOCK_CLASS_LONG_INTEGER: + *((long *)val) = 0L; + break; + case PBLOCK_CLASS_POINTER: + case PBLOCK_CLASS_FUNCTION_POINTER: + *val = NULL; + break; + } + for ( i = 0; i < pb->numParams; i++ ) { if ( pb->curParams[i] == param ) { - *val = pb->curVals[i]; + switch ( pbClass ) { + case PBLOCK_CLASS_INTEGER: + *((int *)val) = (int)pb->curVals[i]; + break; + case PBLOCK_CLASS_LONG_INTEGER: + *((long *)val) = (long)pb->curVals[i]; + break; + case PBLOCK_CLASS_POINTER: + case PBLOCK_CLASS_FUNCTION_POINTER: + *val = pb->curVals[i]; + break; + default: + break; + } break; } } unLock( pb ); - return LDAP_SUCCESS; + return PBLOCK_SUCCESS; } static int @@ -289,8 +317,10 @@ set( Slapi_PBlock *pb, int param, void *val ) #if defined(LDAP_SLAPI) int i, freeit; int addcon = 0; + slapi_pblock_class_t pbClass; - if ( isValidParam( pb, param ) == INVALID_PARAM ) { + pbClass = getPBlockClass( param ); + if ( pbClass == PBLOCK_CLASS_INVALID ) { return PBLOCK_ERROR; } @@ -313,9 +343,11 @@ set( Slapi_PBlock *pb, int param, void *val ) case SLAPI_IBM_CONN_DN_ORIG: case SLAPI_RESULT_TEXT: case SLAPI_RESULT_MATCHED: - freeit = 1; break; + freeit = 1; + break; default: - freeit = 0; break; + freeit = 0; + break; } for( i = 0; i < pb->numParams; i++ ) { if ( pb->curParams[i] == param ) { @@ -347,7 +379,7 @@ set( Slapi_PBlock *pb, int param, void *val ) } unLock( pb ); - return LDAP_SUCCESS; + return PBLOCK_SUCCESS; #endif /* LDAP_SLAPI */ return PBLOCK_ERROR; } @@ -386,7 +418,7 @@ deleteParam( Slapi_PBlock *p, int param ) } p->numParams--; unLock( p ); - return LDAP_SUCCESS; + return PBLOCK_SUCCESS; } Slapi_PBlock * diff --git a/tests/data/modify.out.master b/tests/data/modify.out.master index 1adb7a2bed..aed6b39df3 100644 --- a/tests/data/modify.out.master +++ b/tests/data/modify.out.master @@ -98,7 +98,7 @@ associatedDomain: example.com dn: cn=Gern Jensen,ou=Information Technology Division,ou=People,dc=example,dc= com -objectClass: OpenLDAPperson +objectClass: testPerson cn: Gern Jensen sn: Jensen uid: gjensen @@ -112,6 +112,7 @@ facsimileTelephoneNumber: +1 313 555 7557 telephoneNumber: +1 313 555 8343 mail: gjensen@mailgw.example.com homePhone: +1 313 555 8844 +testTime: 20050304001801.234Z dn: ou=Groups,dc=example,dc=com objectClass: organizationalUnit diff --git a/tests/data/relay.out b/tests/data/relay.out index 9588fd7db7..c88d78591d 100644 --- a/tests/data/relay.out +++ b/tests/data/relay.out @@ -2566,6 +2566,14 @@ seeAlso: cn=All Staff,ou=Groups,o=Example,c=US # refldap://localhost:9010/ou=Referrals,o=Beispiel,c=DE??sub +# searching filter="(uid=example)" +# attrs="uid" +# base="o=Example,c=US"... +dn: o=Example,c=US +uid: example + +# refldap://localhost:9010/ou=Referrals,o=Beispiel,c=DE??sub + # searching filter="(member=cn=Another Added Group,ou=Groups,o=Example,c=US)" # attrs="member" # base="o=Example,c=US"... diff --git a/tests/data/slapd-ldapgluegroups.conf b/tests/data/slapd-ldapgluegroups.conf index 51513efb29..ca0682ea89 100644 --- a/tests/data/slapd-ldapgluegroups.conf +++ b/tests/data/slapd-ldapgluegroups.conf @@ -23,8 +23,6 @@ include ./schema/nis.schema pidfile ./testrun/slapd.3.pid argsfile ./testrun/slapd.3.args -# password-hash {md5} - #mod#modulepath ../servers/slapd/back-@BACKEND@/ #mod#moduleload back_@BACKEND@.la #monitormod#modulepath ../servers/slapd/back-monitor/ diff --git a/tests/data/slapd-ldapgluepeople.conf b/tests/data/slapd-ldapgluepeople.conf index 5c9155e1c9..0f3f4fa6ad 100644 --- a/tests/data/slapd-ldapgluepeople.conf +++ b/tests/data/slapd-ldapgluepeople.conf @@ -23,8 +23,6 @@ include ./schema/nis.schema pidfile ./testrun/slapd.2.pid argsfile ./testrun/slapd.2.args -# password-hash {md5} - #mod#modulepath ../servers/slapd/back-@BACKEND@/ #mod#moduleload back_@BACKEND@.la #monitormod#modulepath ../servers/slapd/back-monitor/ diff --git a/tests/data/slapd-pw.conf b/tests/data/slapd-pw.conf index cd3b42ded8..4d7d3c85d5 100644 --- a/tests/data/slapd-pw.conf +++ b/tests/data/slapd-pw.conf @@ -22,8 +22,6 @@ include ./schema/nis.schema pidfile ./testrun/slapd.1.pid argsfile ./testrun/slapd.1.args -# password-hash {md5} - #mod#modulepath ../servers/slapd/back-@BACKEND@/ #mod#moduleload back_@BACKEND@.la #monitormod#modulepath ../servers/slapd/back-monitor/ diff --git a/tests/data/slapd-translucent-local.conf b/tests/data/slapd-translucent-local.conf new file mode 100644 index 0000000000..8f9db68801 --- /dev/null +++ b/tests/data/slapd-translucent-local.conf @@ -0,0 +1,52 @@ +# stand-alone slapd config -- for testing (with translucent overlay) +# $OpenLDAP$ +## This work is part of OpenLDAP Software . +## +## Copyright 2004 The OpenLDAP Foundation. +## All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted only as authorized by the OpenLDAP +## Public License. +## +## A copy of this license is available in the file LICENSE in the +## top-level directory of the distribution or, alternatively, at +## . + +ucdata-path ./ucdata +include ./schema/core.schema +include ./schema/cosine.schema +include ./schema/inetorgperson.schema +include ./schema/openldap.schema +include ./schema/nis.schema + +# +pidfile ./testrun/slapd.2.pid +argsfile ./testrun/slapd.2.args + +#mod#modulepath ../servers/slapd/back-@BACKEND@/:../servers/slapd/back-ldap/:../servers/slapd/overlays +#mod#moduleload back_@BACKEND@.la +#mod#moduleload back_ldap.la +#translucentmod#modulepath ../servers/slapd/overlays +#translucentmod#moduleload translucent.la + +####################################################################### +# database definitions +####################################################################### + +database @BACKEND@ +suffix "o=translucent" +directory ./testrun/db.2.a +rootdn "o=translucent" +rootpw secret +index objectClass eq +index cn,sn,uid pres,eq,sub + +overlay translucent +translucent_no_glue + +# XXX this uri really shouldn't be hardcoded +uri @URI1@ +lastmod off +acl-authcDN uid=binder,o=translucent +acl-passwd bindtest diff --git a/tests/data/slapd-translucent-remote.conf b/tests/data/slapd-translucent-remote.conf new file mode 100644 index 0000000000..b51b3c5b52 --- /dev/null +++ b/tests/data/slapd-translucent-remote.conf @@ -0,0 +1,41 @@ +# stand-alone slapd config -- for testing (with translucent overlay) +# $OpenLDAP$ +## This work is part of OpenLDAP Software . +## +## Copyright 2004 The OpenLDAP Foundation. +## All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted only as authorized by the OpenLDAP +## Public License. +## +## A copy of this license is available in the file LICENSE in the +## top-level directory of the distribution or, alternatively, at +## . + +ucdata-path ./ucdata +include ./schema/core.schema +include ./schema/cosine.schema +include ./schema/inetorgperson.schema +include ./schema/openldap.schema +include ./schema/nis.schema + +# +pidfile ./testrun/slapd.1.pid +argsfile ./testrun/slapd.1.args + +#mod#modulepath ../servers/slapd/back-@BACKEND@/:../servers/slapd/overlays +#mod#moduleload back_@BACKEND@.la + +####################################################################### +# database definitions +####################################################################### + +database @BACKEND@ +suffix "o=translucent" +directory ./testrun/db.1.a +rootdn "o=translucent" +rootpw secret +index objectClass eq +index cn,sn,uid pres,eq,sub + diff --git a/tests/data/slapd-whoami.conf b/tests/data/slapd-whoami.conf index 20d4ad379c..cc82bbcafb 100644 --- a/tests/data/slapd-whoami.conf +++ b/tests/data/slapd-whoami.conf @@ -22,8 +22,6 @@ include ./schema/nis.schema pidfile ./testrun/slapd.1.pid argsfile ./testrun/slapd.1.args -# password-hash {md5} - #mod#modulepath ../servers/slapd/back-@BACKEND@/ #mod#moduleload back_@BACKEND@.la #monitormod#modulepath ../servers/slapd/back-monitor/ diff --git a/tests/data/slapd.conf b/tests/data/slapd.conf index abc0e2046c..45283e55e2 100644 --- a/tests/data/slapd.conf +++ b/tests/data/slapd.conf @@ -18,6 +18,7 @@ include ./schema/cosine.schema include ./schema/inetorgperson.schema include ./schema/openldap.schema include ./schema/nis.schema +include ./testdata/test.schema # pidfile ./testrun/slapd.1.pid diff --git a/tests/data/test-translucent-add.ldif b/tests/data/test-translucent-add.ldif new file mode 100644 index 0000000000..fd6acc72fb --- /dev/null +++ b/tests/data/test-translucent-add.ldif @@ -0,0 +1,10 @@ +dn: uid=danger,ou=users,o=translucent +objectClass: inetOrgPerson +uid: danger +sn: danger +cn: henry +businessCategory: frontend-override +carLicense: LIVID +employeeType: special +departmentNumber: 9999999 +roomNumber: 41L-535 diff --git a/tests/data/test-translucent-config.ldif b/tests/data/test-translucent-config.ldif new file mode 100644 index 0000000000..9285176fbd --- /dev/null +++ b/tests/data/test-translucent-config.ldif @@ -0,0 +1,26 @@ +# toplevel + +dn: o=translucent +objectClass: top +objectClass: organization +o: translucent +description: backend database root + +# backend OU + +dn: ou=users,o=translucent +objectClass: top +objectClass: organizationalUnit +ou: users +description: backend user container root + +# bind user for frontend connection + +dn: uid=binder,o=translucent +objectClass: inetOrgPerson +uid: binder +sn: test +cn: binder +businessCategory: binder-test-user +displayName: Binder Test User +userPassword: bindtest diff --git a/tests/data/test-translucent-data.ldif b/tests/data/test-translucent-data.ldif new file mode 100644 index 0000000000..ee32cbbc74 --- /dev/null +++ b/tests/data/test-translucent-data.ldif @@ -0,0 +1,42 @@ +# typical user +dn: uid=danger,ou=users,o=translucent +objectClass: inetOrgPerson +uid: danger +sn: warning +cn: danger +businessCategory: backend-opaque +carLicense: BACK +departmentNumber: 7341 +displayName: Warning +employeeNumber: 5150 +employeeType: contractor +givenName: Danger Warning + +# another example +dn: uid=example,ou=users,o=translucent +objectClass: inetOrgPerson +uid: example +sn: user +cn: example +businessCategory: backend-opaque +carLicense: SAMPLE +departmentNumber: 7341 +displayName: Example +employeeNumber: 5150 +employeeType: fulltime +givenName: Example User + +# +dn: uid=fred,ou=users,o=translucent +objectClass: inetOrgPerson +uid: fred +sn: said +cn: said +businessCategory: backend-opaque +carLicense: RIGHT +departmentNumber: 9919 +displayName: Right Said Fred +employeeNumber: 44199 +employeeType: fulltime +givenName: Right Said + diff --git a/tests/data/test-translucent-merged.ldif b/tests/data/test-translucent-merged.ldif new file mode 100644 index 0000000000..5bb54ec31a --- /dev/null +++ b/tests/data/test-translucent-merged.ldif @@ -0,0 +1,40 @@ +dn: uid=danger,ou=users,o=translucent +objectClass: inetOrgPerson +uid: danger +sn: danger +cn: henry +businessCategory: frontend-override +carLicense: LIVID +departmentNumber: 9999999 +displayName: Warning +employeeNumber: 5150 +employeeType: special +givenName: Danger Warning +roomNumber: 41L-535 + +dn: uid=example,ou=users,o=translucent +objectClass: inetOrgPerson +uid: example +sn: user +cn: example +businessCategory: backend-opaque +carLicense: SAMPLE +departmentNumber: 7341 +displayName: Example +employeeNumber: 5150 +employeeType: fulltime +givenName: Example User + +dn: uid=fred,ou=users,o=translucent +objectClass: inetOrgPerson +uid: fred +sn: said +cn: said +businessCategory: backend-opaque +carLicense: RIGHT +departmentNumber: 9919 +displayName: Right Said Fred +employeeNumber: 44199 +employeeType: fulltime +givenName: Right Said + diff --git a/tests/data/test.schema b/tests/data/test.schema index 766ba1089b..373d8ca10f 100644 --- a/tests/data/test.schema +++ b/tests/data/test.schema @@ -17,17 +17,33 @@ # For testing purposes only. # For Attribute Aliasing. -attributetype ( 1.3.6.1.4.1.4203.666.1.34 NAME 'x509CertificateIssuer' - EQUALITY distinguishedNameMatch - DESC 'Aliasing attribute: Issuer, use' - SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +attributetype ( 1.3.6.1.4.1.4203.666.1.34 + NAME 'x509CertificateIssuer' + EQUALITY distinguishedNameMatch + DESC 'Aliasing attribute: Issuer, use' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) -attributetype ( 1.3.6.1.4.1.4203.666.1.35 NAME 'x509CertificateSerial' - DESC 'Aliasing attribute: Serial, use' - EQUALITY integerMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) +attributetype ( 1.3.6.1.4.1.4203.666.1.35 + NAME 'x509CertificateSerial' + DESC 'Aliasing attribute: Serial, use' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) -attributetype ( 1.3.6.1.4.1.4203.666.1.36 NAME 'x509CertificateSerialAndIssuer' - DESC 'Aliasing attribute: Serial and Issuer together, use' - EQUALITY certificateExactMatch - SYNTAX 1.2.826.0.1.3344810.7.1 ) +attributetype ( 1.3.6.1.4.1.4203.666.1.36 + NAME 'x509CertificateSerialAndIssuer' + DESC 'Aliasing attribute: Serial and Issuer together, use' + EQUALITY certificateExactMatch + SYNTAX 1.2.826.0.1.3344810.7.1 ) + +# generalized time testing + +attributetype ( 1.3.6.1.4.1.4203.666.1.37 + name 'testTime' + equality generalizedTimeMatch + ordering generalizedTimeOrderingMatch + syntax 1.3.6.1.4.1.1466.115.121.1.24 + single-value ) + +objectClass ( 1.3.6.1.4.1.4203.666.1.38 + name 'testPerson' sup OpenLDAPperson + may testTime ) diff --git a/tests/run.in b/tests/run.in index 5b212f2386..0754ba59d7 100644 --- a/tests/run.in +++ b/tests/run.in @@ -37,6 +37,7 @@ AC_glue=glue@BUILD_GLUE@ AC_pcache=pcache@BUILD_PROXYCACHE@ AC_ppolicy=ppolicy@BUILD_PPOLICY@ AC_refint=refint@BUILD_REFINT@ +AC_translucent=translucent@BUILD_TRANSLUCENT@ AC_unique=unique@BUILD_UNIQUE@ AC_rwm=rwm@BUILD_RWM@ AC_syncprov=syncprov@BUILD_SYNCPROV@ @@ -48,7 +49,7 @@ AC_WITH_MODULES_ENABLED=@WITH_MODULES_ENABLED@ export AC_bdb AC_hdb AC_ldap AC_ldbm AC_meta AC_monitor AC_relay AC_sql export AC_glue AC_pcache AC_ppolicy AC_refint AC_unique AC_rwm AC_syncprov -export AC_WITH_SASL AC_WITH_TLS AC_WITH_MODULES_ENABLED +export AC_translucent AC_WITH_SASL AC_WITH_TLS AC_WITH_MODULES_ENABLED if test ! -x ../servers/slapd/slapd ; then echo "Could not locate slapd(8)" diff --git a/tests/scripts/conf.sh b/tests/scripts/conf.sh index 139267d748..4e471a6da7 100755 --- a/tests/scripts/conf.sh +++ b/tests/scripts/conf.sh @@ -47,6 +47,7 @@ sed -e "s/@BACKEND@/${BACKEND}/" \ -e "s/^#${AC_ppolicy}#//" \ -e "s/^#${AC_refint}#//" \ -e "s/^#${AC_syncprov}#//" \ + -e "s/^#${AC_translucent}#//" \ -e "s/^#${AC_unique}#//" \ -e "s/^#${AC_rwm}#//" \ -e "s/^#${MON}#//" \ diff --git a/tests/scripts/defines.sh b/tests/scripts/defines.sh index 1bf43a34d1..e2a44ba9f1 100755 --- a/tests/scripts/defines.sh +++ b/tests/scripts/defines.sh @@ -25,6 +25,7 @@ PROXYCACHE=${AC_pcache-pcacheno} PPOLICY=${AC_ppolicy-ppolicyno} REFINT=${AC_refint-refintno} RWM=${AC_rwm-rwmno} +TRANSLUCENT=${AC_translucent-translucentno} UNIQUE=${AC_unique-uniqueno} SYNCPROV=${AC_syncprov-syncprovno} WITH_SASL=${AC_WITH_SASL-no} @@ -85,6 +86,8 @@ CHAINCONF2=$DATADIR/slapd-chain2.conf GLUESYNCCONF1=$DATADIR/slapd-glue-syncrepl1.conf GLUESYNCCONF2=$DATADIR/slapd-glue-syncrepl2.conf SQLCONF=$DATADIR/slapd-sql.conf +TRANSLUCENTLOCALCONF=$DATADIR/slapd-translucent-local.conf +TRANSLUCENTREMOTECONF=$DATADIR/slapd-translucent-remote.conf CONF1=$TESTDIR/slapd.1.conf CONF2=$TESTDIR/slapd.2.conf @@ -169,6 +172,10 @@ LDIFLDAPGLUE3=$DATADIR/test-ldapgluegroups.ldif LDIFCOMPMATCH=$DATADIR/test-compmatch.ldif LDIFCHAIN1=$DATADIR/test-chain1.ldif LDIFCHAIN2=$DATADIR/test-chain2.ldif +LDIFTRANSLUCENTDATA=$DATADIR/test-translucent-data.ldif +LDIFTRANSLUCENTCONFIG=$DATADIR/test-translucent-config.ldif +LDIFTRANSLUCENTADD=$DATADIR/test-translucent-add.ldif +LDIFTRANSLUCENTMERGED=$DATADIR/test-translucent-merged.ldif SQLADD=$DATADIR/sql-add.ldif MONITOR="" REFDN="c=US" @@ -182,6 +189,10 @@ JAJDN="cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com" REFINTDN="cn=Manager,o=refint" UNIQUEDN="cn=Manager,o=unique" EMPTYDNDN="cn=Manager,c=US" +TRANSLUCENTROOT="o=translucent" +TRANSLUCENTUSER="ou=users,o=translucent" +TRANSLUCENTDN="uid=binder,o=translucent" +TRANSLUCENTPASSWD="bindtest" LOG1=$TESTDIR/slapd.1.log LOG2=$TESTDIR/slapd.2.log @@ -245,6 +256,7 @@ CHAINMODOUT=$DATADIR/chainmod.out GLUESYNCOUT=$DATADIR/gluesync.out SQLREAD=$DATADIR/sql-read.out SQLWRITE=$DATADIR/sql-write.out +TRANSLUCENTOUT=$DATADIR/translucent.search.out # Just in case we linked the binaries dynamically LD_LIBRARY_PATH=`pwd`/../libraries:${LD_LIBRARY_PATH} export LD_LIBRARY_PATH diff --git a/tests/scripts/relay b/tests/scripts/relay index befaee6cff..f6cfcef7c1 100755 --- a/tests/scripts/relay +++ b/tests/scripts/relay @@ -308,7 +308,22 @@ if test $RC != 0 ; then exit $RC fi -BASEDN="o=Example,c=US" +FILTER="(uid=example)" +echo "Searching filter=\"$FILTER\"" +echo " attrs=\"uid\"" +echo " base=\"$BASEDN\"..." +echo "# searching filter=\"$FILTER\"" >> $SEARCHOUT +echo "# attrs=\"uid\"" >> $SEARCHOUT +echo "# base=\"$BASEDN\"..." >> $SEARCHOUT +$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" "$FILTER" uid \ + >> $SEARCHOUT 2>&1 +RC=$? +if test $RC != 0 ; then + echo "Search failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + FILTER="(member=cn=Another Added Group,ou=Groups,$BASEDN)" echo "Searching filter=\"$FILTER\"" echo " attrs=\"member\"" diff --git a/tests/scripts/test004-modify b/tests/scripts/test004-modify index a82a7bde78..53b237003e 100755 --- a/tests/scripts/test004-modify +++ b/tests/scripts/test004-modify @@ -135,7 +135,7 @@ objectClass: userSecurityInformation dn: cn=Gern Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com changetype: add -objectclass: OpenLDAPperson +objectclass: testPerson cn: Gern Jensen sn: Jensen uid: gjensen @@ -149,6 +149,7 @@ facsimiletelephonenumber: +1 313 555 7557 telephonenumber: +1 313 555 8343 mail: gjensen@mailgw.example.com homephone: +1 313 555 8844 +testTime: 20050304001801.234Z dn: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=example,dc=com changetype: delete diff --git a/tests/scripts/test010-passwd b/tests/scripts/test010-passwd index f79c5aca0a..636d0cece4 100755 --- a/tests/scripts/test010-passwd +++ b/tests/scripts/test010-passwd @@ -139,6 +139,15 @@ if test $RC != 0 ; then exit $RC fi +echo "Logging end state with ldapsearch..." +echo "" >> $TESTOUT +echo "++ Initial search" >> $TESTOUT +$LDAPSEARCH -h $LOCALHOST -p $PORT1 \ + -D "$MANAGERDN" -w $PASSWD \ + -b "$BASEDN" \ + 'objectclass=*' >> $TESTOUT 2>&1 + + test $KILLSERVERS != no && kill -HUP $KILLPIDS echo ">>>>> Test succeeded" diff --git a/tests/scripts/test031-component-filter b/tests/scripts/test031-component-filter index 0edf704842..437f152193 100755 --- a/tests/scripts/test031-component-filter +++ b/tests/scripts/test031-component-filter @@ -252,7 +252,7 @@ if test $RC != 0 ; then exit $RC fi -FILTER="(x509CertificateIssuer:distinguishedNameMatch:=c=US)" +FILTER="(x509CertificateIssuer=c=US)" echo " f=$FILTER ..." echo "# f=$FILTER ..." >> $SEARCHOUT $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \ @@ -265,7 +265,7 @@ if test $RC != 0 ; then exit $RC fi -FILTER="(x509CertificateSerial:integerMatch:=0)" +FILTER="(x509CertificateSerial=0)" echo " f=$FILTER ..." echo "# f=$FILTER ..." >> $SEARCHOUT $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \ diff --git a/tests/scripts/test034-translucent b/tests/scripts/test034-translucent new file mode 100755 index 0000000000..7728d676ef --- /dev/null +++ b/tests/scripts/test034-translucent @@ -0,0 +1,717 @@ +#! /bin/sh +# $OpenLDAP$ +## This work is part of OpenLDAP Software . +## +## Copyright 2004 The OpenLDAP Foundation. +## All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted only as authorized by the OpenLDAP +## Public License. +## +## A copy of this license is available in the file LICENSE in the +## top-level directory of the distribution or, alternatively, at +## . + +echo "running defines.sh" +. $SRCDIR/scripts/defines.sh + +PERSONAL="(objectClass=inetOrgPerson)" +NOWHERE="/dev/null" +FAILURE="additional info:" + +if test $TRANSLUCENT = translucentno ; then + echo "Translucent Proxy overlay not available, test skipped" + exit 0 +fi + +if test $BACKEND = ldbm ; then + echo "Translucent Proxy overlay not qualified for use with LDBM, skipping" + exit 0 +fi + +if test $AC_ldap = ldapno ; then + echo "Translucent Proxy overlay requires back-ldap backend, test skipped" + exit 0 +fi + +# configure backside +mkdir -p $TESTDIR $DBDIR1 + +. $CONFFILTER $BACKEND $MONITORDB < $TRANSLUCENTREMOTECONF > $CONF1 +echo "Running slapadd to build remote slapd database..." +$SLAPADD -f $CONF1 -l $LDIFTRANSLUCENTCONFIG +RC=$? +if test $RC != 0 ; then + echo "slapadd failed ($RC)!" + exit $RC +fi + +echo "Starting remote slapd on TCP/IP port $PORT1..." +$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 & +PID=$! +if test $WAIT != 0 ; then + echo PID $PID + read foo +fi +REMOTEPID="$PID" +KILLPIDS="$PID" + +for i in 0 1 2 3 4 5; do + $LDAPSEARCH -s base -b "$MONITOR" -H $URI1 \ + 'objectclass=*' > /dev/null 2>&1 + RC=$? + if test $RC = 0 ; then + break + fi + echo "Waiting 5 seconds for remote slapd to start..." + sleep 5 +done + +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +# configure frontside +mkdir -p $DBDIR2 + +. $CONFFILTER $BACKEND $MONITORDB < $TRANSLUCENTLOCALCONF > $CONF2 + +echo "Starting local slapd on TCP/IP port $PORT2..." +$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING > $LOG2 2>&1 & +PID=$! +if test $WAIT != 0 ; then + echo PID $PID + read foo +fi +LOCALPID="$PID" +KILLPIDS="$LOCALPID $REMOTEPID" + +for i in 0 1 2 3 4 5; do + $LDAPSEARCH -s base -b "$MONITOR" -H $URI2 \ + 'objectclass=*' > /dev/null 2>&1 + RC=$? + if test $RC = 0 ; then + break + fi + echo "Waiting 5 seconds for local slapd to start..." + sleep 5 +done + +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing slapd Translucent Proxy operations..." + +echo "Testing search: no remote data defined..." + +$LDAPSEARCH -H $URI2 -b "$TRANSLUCENTUSER" "$PERSONAL" >$SEARCHOUT 2>&1 + +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +if test -s $SEARCHOUT; then + echo "ldapsearch should have returned no records!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit 1 +fi + +echo "Populating remote database..." + +$LDAPADD -D "$TRANSLUCENTROOT" -H $URI1 \ + -w $PASSWD < $LDIFTRANSLUCENTDATA > $NOWHERE 2>&1 + +RC=$? +if test $RC != 0 ; then + echo "ldapadd failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing search: remote database via local slapd..." + +$LDAPSEARCH -H $URI2 -b "$TRANSLUCENTUSER" "$PERSONAL" > $SEARCHOUT 2>&1 + +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +. $LDIFFILTER < $SEARCHOUT > $SEARCHFLT +. $LDIFFILTER < $LDIFTRANSLUCENTDATA > $LDIFFLT +$CMP $SEARCHFLT $LDIFFLT > $CMPOUT + +if test $? != 0 ; then + echo "Comparison failed -- corruption from remote to local!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit 1 +fi + +echo "Testing add: prohibited local record..." + +$LDAPADD -D "$TRANSLUCENTDN" -H $URI2 \ + -w $TRANSLUCENTPASSWD < $LDIFTRANSLUCENTADD > $TESTOUT 2>&1 + +RC=$? +if test $RC != 50 ; then + echo "ldapadd failed ($RC), expected INSUFFICIENT ACCESS!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing add: valid local record, no_glue..." + +$LDAPADD -v -v -v -D "$TRANSLUCENTROOT" -H $URI2 \ + -w $PASSWD < $LDIFTRANSLUCENTADD > $TESTOUT 2>&1 + +RC=$? +if test $RC != 32 ; then + echo "ldapadd failed ($RC), expected NO SUCH OBJECT!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing modrdn: valid local record, no_glue..." + +$LDAPMODRDN -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 'uid=fred,ou=users,o=translucent' 'uid=someguy' + +RC=$? +if test $RC != 32 ; then + echo "ldapmodrdn failed ($RC), expected NO SUCH OBJECT!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Shutting down local slapd..." +kill -HUP $LOCALPID +sleep 5 + +echo "Configuring local slapd without translucent_no_glue..." +. $CONFFILTER $BACKEND $MONITORDB < $TRANSLUCENTLOCALCONF | \ + grep -v translucent_no_glue > $CONF2 + +echo "Restarting local slapd on TCP/IP port $PORT2..." +$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING >> $LOG2 2>&1 & +PID=$! +if test $WAIT != 0 ; then + echo PID $PID + read foo +fi +LOCALPID="$PID" +KILLPIDS="$REMOTEPID $PID" + +for i in 0 1 2 3 4 5; do + $LDAPSEARCH -s base -b "$MONITOR" -H $URI2 \ + 'objectclass=*' > /dev/null 2>&1 + RC=$? + if test $RC = 0 ; then + break + fi + echo "Waiting 5 seconds for local slapd to start..." + sleep 5 +done + +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing add: valid local record..." + +$LDAPADD -D "$TRANSLUCENTROOT" -H $URI2 \ + -w $PASSWD < $LDIFTRANSLUCENTADD > $TESTOUT 2>&1 + +RC=$? +if test $RC != 0 ; then + echo "ldapadd failed ($RC)!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing search: data merging..." + +$LDAPSEARCH -H $URI2 -b "$TRANSLUCENTUSER" "$PERSONAL" > $SEARCHOUT 2>&1 + +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +$CMP $SEARCHOUT $LDIFTRANSLUCENTMERGED > $CMPOUT + +if test $? != 0 ; then + echo "Comparison failed -- local data failed to merge with remote!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit 1 +fi + +echo "Testing compare: valid local..." + +$LDAPCOMPARE -z -H $URI2 -w $TRANSLUCENTPASSWD -D $TRANSLUCENTDN \ + "uid=danger,ou=users,o=translucent" "carLicense:LIVID" + +RC=$? +if test $RC != 6 ; then + echo "ldapcompare failed ($RC), expected TRUE!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing compare: valid remote..." + +$LDAPCOMPARE -z -x -H $URI2 -w $TRANSLUCENTPASSWD -D $TRANSLUCENTDN \ + "uid=binder,o=translucent" "businessCategory:binder-test-user" + +RC=$? +if test $RC != 6 ; then + echo "ldapcompare failed ($RC), expected TRUE!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing compare: bogus local..." + +$LDAPCOMPARE -z -x -H $URI2 -w $TRANSLUCENTPASSWD -D $TRANSLUCENTDN \ + "uid=danger,ou=users,o=translucent" "businessCategory:invalid-test-value" + +RC=$? +if test $RC != 5 ; then + echo "ldapcompare failed ($RC), expected FALSE!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing compare: bogus remote..." + +$LDAPCOMPARE -z -x -H $URI2 -w $TRANSLUCENTPASSWD -D $TRANSLUCENTDN \ + "uid=binder,o=translucent" "businessCategory:invalid-test-value" + +RC=$? +if test $RC != 5 ; then + echo "ldapcompare failed ($RC), expected FALSE!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing modify: nonexistent record..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_MOD +version: 1 +dn: uid=bogus,ou=users,o=translucent +changetype: modify +replace: roomNumber +roomNumber: 31J-2112 +EOF_MOD + +RC=$? +if test $RC != 32 ; then + echo "ldapmodify failed ($RC), expected NO SUCH OBJECT!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing modify: valid local record, nonexistent attribute..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_MOD1 +version: 1 +dn: uid=danger,ou=users,o=translucent +changetype: modify +replace: roomNumber +roomNumber: 9N-21 +EOF_MOD1 + +RC=$? +if test $RC != 0 ; then + echo "ldapmodify failed ($RC)!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +$LDAPSEARCH -H $URI2 -b "uid=danger,ou=users,o=translucent" > $SEARCHOUT 2>&1 + +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +ATTR=`grep roomNumber $SEARCHOUT` > $NOWHERE 2>&1 +if test "$ATTR" != "roomNumber: 9N-21" ; then + echo "modification failed!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit 1 +fi + +echo "Testing search: specific nonexistent remote attribute..." + +$LDAPSEARCH -H $URI2 -b "uid=danger,ou=users,o=translucent" roomNumber > $SEARCHOUT 2>&1 + +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing modify: nonexistent local record, nonexistent attribute..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_MOD2 +version: 1 +dn: uid=fred,ou=users,o=translucent +changetype: modify +replace: roomNumber +roomNumber: 31J-2112 +EOF_MOD2 + +RC=$? +if test $RC != 0 ; then + echo "ldapmodify failed ($RC)!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +$LDAPSEARCH -H $URI2 -b "uid=fred,ou=users,o=translucent" > $SEARCHOUT 2>&1 + +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +ATTR=`grep roomNumber $SEARCHOUT` > $NOWHERE 2>&1 +if test "$ATTR" != "roomNumber: 31J-2112" ; then + echo "modification failed!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit 1 +fi + +echo "Testing modify: valid remote record, nonexistent attribute..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_MOD9 +version: 1 +dn: uid=fred,ou=users,o=translucent +changetype: modify +delete: preferredLanguage +EOF_MOD9 + +RC=$? +if test $RC != 16 ; then + echo "ldapmodify failed ($RC), expected NO SUCH ATTRIBUTE!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing delete: valid local record, nonexistent attribute..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_MOD4 +version: 1 +dn: uid=fred,ou=users,o=translucent +changetype: modify +delete: roomNumber +EOF_MOD4 + +RC=$? +if test $RC != 0 ; then + echo "ldapmodify failed ($RC)!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing modrdn: prohibited local record..." + +$LDAPMODRDN -D "$TRANSLUCENTDN" -H $URI2 -w $TRANSLUCENTPASSWD > \ + $TESTOUT 2>&1 'uid=fred,ou=users,o=translucent' 'uid=someguy' + +RC=$? +if test $RC != 50 ; then + echo "ldapmodrdn failed ($RC), expected INSUFFICIENT ACCESS!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing modrdn: valid local record..." + +$LDAPMODRDN -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 'uid=fred,ou=users,o=translucent' 'uid=someguy' + +RC=$? +if test $RC != 0 ; then + echo "ldapmodrdn failed ($RC)!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing delete: prohibited local record..." + +$LDAPMODIFY -v -D "$TRANSLUCENTDN" -H $URI2 -w $TRANSLUCENTPASSWD > \ + $TESTOUT 2>&1 << EOF_DEL2 +version: 1 +dn: uid=someguy,ou=users,o=translucent +changetype: delete +EOF_DEL2 + +RC=$? +if test $RC != 50 ; then + echo "ldapadd failed ($RC), expected INSUFFICIENT ACCESS!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing delete: valid local record..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_DEL3 +version: 1 +dn: uid=someguy,ou=users,o=translucent +changetype: delete +EOF_DEL3 + +RC=$? +if test $RC != 0 ; then + echo "ldapmodify failed ($RC)!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing delete: valid remote record..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_DEL8 +version: 1 +dn: uid=fred,ou=users,o=translucent +changetype: delete +EOF_DEL8 + +RC=$? +if test $RC != 32 ; then + echo "ldapmodify failed ($RC), expected NO SUCH OBJECT!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing delete: nonexistent local record, nonexistent attribute..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_DEL1 +version: 1 +dn: uid=fred,ou=users,o=translucent +changetype: modify +delete: roomNumber +EOF_DEL1 + +RC=$? +if test $RC != 0 ; then + echo "ldapmodify failed ($RC)!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +$LDAPSEARCH -H $URI2 -b "uid=fred,ou=users,o=translucent" > $SEARCHOUT 2>&1 + +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing delete: valid local record, nonexistent attribute..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_MOD8 +version: 1 +dn: uid=danger,ou=users,o=translucent +changetype: modify +delete: preferredLanguage +EOF_MOD8 + +RC=$? +if test $RC != 16 ; then + echo "ldapmodify failed ($RC), expected NO SUCH ATTRIBUTE!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing modify: valid remote record, combination add-modify-delete..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_MOD6 +version: 1 +dn: uid=fred,ou=users,o=translucent +changetype: modify +delete: carLicense +- +add: preferredLanguage +preferredLanguage: ISO8859-1 +- +replace: employeeType +employeeType: consultant +EOF_MOD6 + +RC=$? +if test $RC != 0 ; then + echo "ldapmodify failed ($RC)!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +$LDAPSEARCH -H $URI2 -b "uid=fred,ou=users,o=translucent" > $SEARCHOUT 2>&1 + +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +ATTR=`grep employeeType $SEARCHOUT` > $NOWHERE 2>&1 +if test "$ATTR" != "employeeType: consultant" ; then + echo "modification failed!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit 1 +fi + +ATTR=`grep preferredLanguage $SEARCHOUT` > $NOWHERE 2>&1 +if test "$ATTR" != "preferredLanguage: ISO8859-1" ; then + echo "modification failed!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit 1 +fi + +echo "Shutting down local slapd..." +kill -HUP $LOCALPID +sleep 5 + +echo "Configuring local slapd with translucent_strict..." +echo translucent_strict >> $CONF2 + +echo "Restarting slapd on TCP/IP port $PORT2..." +$SLAPD -f $CONF2 -h $URI2 -d $LVL $TIMING >> $LOG2 2>&1 & +PID=$! +if test $WAIT != 0 ; then + echo PID $PID + read foo +fi +LOCALPID="$PID" +KILLPIDS="$REMOTEPID $PID" + +for i in 0 1 2 3 4 5; do + $LDAPSEARCH -s base -b "$MONITOR" -H $URI2 \ + 'objectclass=*' > /dev/null 2>&1 + RC=$? + if test $RC = 0 ; then + break + fi + echo "Waiting 5 seconds for local slapd to start..." + sleep 5 +done + +if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing strict mode delete: nonexistent local attribute..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_MOD5 +version: 1 +dn: uid=example,ou=users,o=translucent +changetype: modify +delete: preferredLanguage +EOF_MOD5 + +RC=$? +if test $RC != 19 ; then + echo "ldapmodify failed ($RC), expected CONSTRAINT VIOLATION!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing strict mode delete: nonexistent remote attribute..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_MOD3 +version: 1 +dn: uid=danger,ou=users,o=translucent +changetype: modify +delete: displayName +EOF_MOD3 + +RC=$? +if test $RC != 19 ; then + echo "ldapmodify failed ($RC), expected CONSTRAINT VIOLATION!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +echo "Testing strict mode modify: combination add-modify-delete..." + +$LDAPMODIFY -v -D "$TRANSLUCENTROOT" -H $URI2 -w $PASSWD > \ + $TESTOUT 2>&1 << EOF_MOD6 +version: 1 +dn: uid=example,ou=users,o=translucent +changetype: modify +delete: carLicense +- +add: preferredLanguage +preferredLanguage: ISO8859-1 +- +replace: employeeType +employeeType: consultant +EOF_MOD6 + +RC=$? +if test $RC != 19 ; then + echo "ldapmodify failed ($RC), expected CONSTRAINT VIOLATION!" + grep "$FAILURE" $TESTOUT + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +test $KILLSERVERS != no && kill -HUP $KILLPIDS + +echo ">>>>> Test succeeded" +exit 0 -- 2.39.5