From 521fa9168d55a02f46b20fa8b9e09ee641812047 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Mon, 24 Jan 2005 22:28:46 +0000 Subject: [PATCH] Sync with HEAD --- configure | 2 +- doc/Makefile.in | 2 + doc/man/Makefile.in | 2 + doc/man/man1/Makefile.in | 2 + doc/man/man3/Makefile.in | 2 + doc/man/man5/Makefile.in | 2 + doc/man/man5/slapd-ldap.5 | 9 +- doc/man/man5/slapd-meta.5 | 21 +- doc/man/man5/slapo-chain.5 | 41 ++-- doc/man/man5/slapo-rwm.5 | 21 +- doc/man/man8/Makefile.in | 2 + include/ldap.h | 3 +- include/ldif.h | 3 + include/rewrite.h | 13 +- libraries/libldap/open.c | 44 ++-- libraries/liblutil/fetch.c | 1 - libraries/liblutil/ldif.c | 15 ++ libraries/librewrite/xmap.c | 2 +- servers/Makefile.in | 2 + servers/slapd/add.c | 4 + servers/slapd/at.c | 13 ++ servers/slapd/attr.c | 8 +- servers/slapd/back-bdb/attr.c | 18 ++ servers/slapd/back-bdb/back-bdb.h | 2 +- servers/slapd/back-bdb/dbcache.c | 10 +- servers/slapd/back-bdb/dn2id.c | 4 +- servers/slapd/back-bdb/idl.c | 63 +++--- servers/slapd/back-bdb/index.c | 23 +- servers/slapd/back-bdb/init.c | 31 ++- servers/slapd/back-bdb/proto-bdb.h | 5 + servers/slapd/back-bdb/tools.c | 30 ++- servers/slapd/back-ldap/add.c | 21 +- servers/slapd/back-ldap/back-ldap.h | 13 +- servers/slapd/back-ldap/bind.c | 206 +++++++++++------ servers/slapd/back-ldap/chain.c | 318 +++++++++++++++------------ servers/slapd/back-ldap/compare.c | 14 +- servers/slapd/back-ldap/config.c | 53 ++++- servers/slapd/back-ldap/delete.c | 8 +- servers/slapd/back-ldap/extended.c | 10 +- servers/slapd/back-ldap/init.c | 6 +- servers/slapd/back-ldap/modify.c | 8 +- servers/slapd/back-ldap/modrdn.c | 8 +- servers/slapd/back-ldap/proto-ldap.h | 8 +- servers/slapd/back-ldap/search.c | 25 +-- servers/slapd/back-ldbm/id2entry.c | 2 +- servers/slapd/back-ldbm/tools.c | 2 +- servers/slapd/back-meta/add.c | 92 ++++++-- servers/slapd/back-meta/back-meta.h | 11 +- servers/slapd/back-meta/config.c | 25 ++- servers/slapd/back-meta/map.c | 28 ++- servers/slapd/back-meta/modify.c | 23 +- servers/slapd/back-null/null.c | 2 +- servers/slapd/back-sql/back-sql.h | 5 +- servers/slapd/back-sql/init.c | 5 +- servers/slapd/back-sql/schema-map.c | 38 +--- servers/slapd/back-sql/search.c | 20 +- servers/slapd/back-sql/sql-wrap.c | 4 +- servers/slapd/back-sql/util.c | 7 +- servers/slapd/backend.c | 3 +- servers/slapd/bind.c | 2 + servers/slapd/compare.c | 2 + servers/slapd/daemon.c | 6 + servers/slapd/delete.c | 4 + servers/slapd/entry.c | 226 ++++++++++++------- servers/slapd/filterentry.c | 2 +- servers/slapd/modify.c | 4 + servers/slapd/modrdn.c | 4 + servers/slapd/oc.c | 9 + servers/slapd/overlays/rwm.c | 229 +++++++++++-------- servers/slapd/overlays/rwmdn.c | 2 +- servers/slapd/overlays/rwmmap.c | 129 ++++++----- servers/slapd/proto-slap.h | 2 + servers/slapd/saslauthz.c | 3 +- servers/slapd/schema/README | 2 +- servers/slapd/search.c | 2 + servers/slapd/slap.h | 1 + servers/slapd/slapadd.c | 120 +++++++++- servers/slapd/slapcommon.c | 7 +- tests/data/chain.out | 4 + tests/data/chainmod.out | 4 + tests/data/chainref.out | 4 + tests/data/relay.out | 197 ++++++++++------- tests/data/slapd-relay.conf | 12 + tests/data/test-chain1.ldif | 8 + tests/data/test-chain2.ldif | 5 + tests/scripts/defines.sh | 1 + tests/scripts/relay | 77 ++++++- tests/scripts/test032-chain | 25 +++ 88 files changed, 1618 insertions(+), 840 deletions(-) create mode 100644 tests/data/chainref.out diff --git a/configure b/configure index 78fcb210e8..ec687c71a5 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # $OpenLDAP$ -# from OpenLDAP: pkg/ldap/configure.in,v 1.560 2004/12/04 18:48:48 hyc Exp +# from OpenLDAP # This work is part of OpenLDAP Software . # diff --git a/doc/Makefile.in b/doc/Makefile.in index cc57b151a7..bdf0973246 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -1,5 +1,7 @@ ## doc Makefile.in for OpenLDAP # $OpenLDAP$ +## This work is part of OpenLDAP Software . +## ## Copyright 1998-2005 The OpenLDAP Foundation. ## All rights reserved. ## diff --git a/doc/man/Makefile.in b/doc/man/Makefile.in index cd8110b728..659c8d8f3a 100644 --- a/doc/man/Makefile.in +++ b/doc/man/Makefile.in @@ -1,5 +1,7 @@ # man Makefile.in for OpenLDAP # $OpenLDAP$ +## This work is part of OpenLDAP Software . +## ## Copyright 1998-2005 The OpenLDAP Foundation. ## All rights reserved. ## diff --git a/doc/man/man1/Makefile.in b/doc/man/man1/Makefile.in index ec72d43eea..e962328e4d 100644 --- a/doc/man/man1/Makefile.in +++ b/doc/man/man1/Makefile.in @@ -1,5 +1,7 @@ # man1 Makefile.in for OpenLDAP # $OpenLDAP$ +## This work is part of OpenLDAP Software . +## ## Copyright 1998-2005 The OpenLDAP Foundation. ## All rights reserved. ## diff --git a/doc/man/man3/Makefile.in b/doc/man/man3/Makefile.in index af516dc0e2..06b739e261 100644 --- a/doc/man/man3/Makefile.in +++ b/doc/man/man3/Makefile.in @@ -1,5 +1,7 @@ # man3 Makefile.in for OpenLDAP # $OpenLDAP$ +## This work is part of OpenLDAP Software . +## ## Copyright 1998-2005 The OpenLDAP Foundation. ## All rights reserved. ## diff --git a/doc/man/man5/Makefile.in b/doc/man/man5/Makefile.in index f51c6a178b..81b2ab6c32 100644 --- a/doc/man/man5/Makefile.in +++ b/doc/man/man5/Makefile.in @@ -1,5 +1,7 @@ # man5 Makefile.in for OpenLDAP # $OpenLDAP$ +## This work is part of OpenLDAP Software . +## ## Copyright 1998-2005 The OpenLDAP Foundation. ## All rights reserved. ## diff --git a/doc/man/man5/slapd-ldap.5 b/doc/man/man5/slapd-ldap.5 index e345281e53..893861c504 100644 --- a/doc/man/man5/slapd-ldap.5 +++ b/doc/man/man5/slapd-ldap.5 @@ -79,8 +79,8 @@ The URI list is space- or comma-separated. .TP .B acl-authcDN "" DN which is used to query the target server for acl checking; it -should have read access on the target server to attributes used on the -proxy for acl checking. +is supposed to have read access on the target server to attributes used +on the proxy for acl checking. There is no risk of giving away such values; they are only used to check permissions. .B The acl-authcDN identity is by no means implicitly used by the proxy @@ -90,7 +90,10 @@ See the feature instead. .TP .B acl-passwd -Password used with the bind DN above. +Password used with the +.B +acl-authcDN +above. .TP .B idassert-authcdn "" DN which is used to propagate the client's identity to the target diff --git a/doc/man/man5/slapd-meta.5 b/doc/man/man5/slapd-meta.5 index c063ab2247..4b796d3760 100644 --- a/doc/man/man5/slapd-meta.5 +++ b/doc/man/man5/slapd-meta.5 @@ -134,17 +134,20 @@ The optional number marks target as the default one, starting from 1. Target must be defined. .TP -.B binddn "" -This directive, as in the LDAP backend, allows to define the DN that is -used to query the target server for acl checking; it should have read -access on the target server to attributes used on the proxy for acl -checking. +.B acl-authcDN "" +DN which is used to query the target server for acl checking, +as in the LDAP backend; it is supposed to have read access +on the target server to attributes used on the proxy for acl checking. There is no risk of giving away such values; they are only used to check permissions. -.TP -.B bindpw -This directive sets the password for acl checking in conjunction -with the above mentioned "binddn" directive. +.B The acl-authcDN identity is by no means implicitly used by the proxy +.B when the client connects anonymously. +.TP +.B acl-passwd +Password used with the +.B +acl-authcDN +above. .TP .B rebind-as-user If this option is given, the client's bind credentials are remembered diff --git a/doc/man/man5/slapo-chain.5 b/doc/man/man5/slapo-chain.5 index 9f53458f51..f3ab4c4718 100644 --- a/doc/man/man5/slapo-chain.5 +++ b/doc/man/man5/slapo-chain.5 @@ -15,11 +15,11 @@ allows automatic referral chasing. Any time a referral is returned (except for bind operations), it is chased by using an instance of the ldap backend. If operations are performed with an identity (i.e. after a bind), -the referrals are chased with the -.B acl-authcDN -(if any; see +that identity can be asserted while chasing the referrals +by means of the \fIidentity assertion\fP feature of back-ldap +(see .BR slapd-ldap (5) -for details), with the original identity asserted by means of the +for details), which is essentially based on the .B proxyAuthz control (see \fIdraft-weltman-ldapv3-proxy\fP for details). @@ -28,36 +28,39 @@ The config directives that are specific to the .B chain overlay can be prefixed by .BR chain\- , -to avoid conflicts with directives specific to the underlying database -or to other stacked overlays. +to avoid potential conflicts with directives specific to the underlying +database or to other stacked overlays. .LP There are no chain overlay specific directives; however, directives -related to the instance of the ldap backend that is implicitly -instantiated by the overlay may assume a special meaning when used -in conjuction with this overlay. +related to the \fIldap\fP database that is implicitly instantiated +by the overlay may assume a special meaning when used in conjuction +with this overlay. They are described in +.BR slapd-ldap (5). .TP .B overlay chain This directive adds the chain overlay to the current backend. -The chain overlay may be used with any backend but is intended -for use with local storage backends that may return referrals. -It is useless in conjunction with the ldap and meta backends -because they exploit the libldap specific referral chase feature. +The chain overlay may be used with any backend, but it is mainly +intended for use with local storage backends that may return referrals. +It is useless in conjunction with the \fIldap\fP and \fImeta\fP backends +because they already exploit the libldap specific referral chase feature. .TP .B chain-uri This directive instructs the underlying ldap database about which -URI to contact to follow referrals. -If not given, the referral itself is parsed, and the protocol/host/port +URI to contact to chase referrals. +If not present, the referral itself is parsed, and the protocol/host/port portions are used to establish a connection. .LP -Directives for configuring the underlying ldap database must also be given, -as shown here: +Directives for configuring the underlying ldap database may also +be required, as shown here: .LP .RS .nf -chain-acl-authcDN cn=Auth,dc=example,dc=com -chain-acl-passwd secret +chain-idassert-method "simple" +chain-idassert-authcDN "cn=Auth,dc=example,dc=com" +chain-idassert-passwd "secret" +chain-idassert-mode "self" .fi .RE .LP diff --git a/doc/man/man5/slapo-rwm.5 b/doc/man/man5/slapo-rwm.5 index 0fe80aaa7a..a2a19fde55 100644 --- a/doc/man/man5/slapo-rwm.5 +++ b/doc/man/man5/slapo-rwm.5 @@ -188,15 +188,15 @@ n as return code if the rule matches; the flag does not alter the recursive behavior of the rule, so, to have it performed only once, it must be used in combination with `:', e.g. -.B `:U{16}' -returns the value `16' after exactly one execution of the rule, if the -pattern matches. +.B `:U{32}' +returns the value `32' (indicating noSuchObject) after exactly +one execution of the rule, if the pattern matches. As a consequence, its behavior is equivalent to `@', with the return code set to .BR n ; or, in other words, `@' is equivalent to `U{0}'. -By convention, the freely available codes are above 16 included; -the others are reserved. +Positive errors are allowed, indicating the related LDAP error codes +as specified in \fIdraft-ietf-ldapbis-protocol\fP. .LP The ordering of the flags can be significant. For instance: `IG{2}' means ignore errors and jump two lines ahead @@ -400,26 +400,29 @@ rwm-rewriteEngine on rwm-rewriteEngine on # all dataflow from client to server referring to DNs rwm-rewriteContext default -rwm-rewriteRule "(.*)$" "$1" ":" +rwm-rewriteRule "(.+,)?$" "$1" ":" # empty filter rule rwm-rewriteContext searchFilter # all dataflow from server to client rwm-rewriteContext searchEntryDN -rwm-rewriteRule "(.*)$" "$1" ":" +rwm-rewriteRule "(.+,)?$" "$1" ":" rwm-rewriteContext searchAttrDN alias searchEntryDN rwm-rewriteContext matchedDN alias searchEntryDN +# misc empty rules +rwm-rewriteContext referralAttrDN +rwm-rewriteContext referralDN # Everything defined here goes into the `default' context. # This rule changes the naming context of anything sent # to `dc=home,dc=net' to `dc=OpenLDAP, dc=org' -rwm-rewriteRule "(.*)dc=home,[ ]?dc=net$" +rwm-rewriteRule "(.+,)?dc=home,[ ]?dc=net$" "$1dc=OpenLDAP, dc=org" ":" # since a pretty/normalized DN does not include spaces # after rdn separators, e.g. `,', this rule suffices: -rwm-rewriteRule "(.*)dc=home,dc=net$" +rwm-rewriteRule "(.+,)?dc=home,dc=net$" "$1dc=OpenLDAP,dc=org" ":" # Start a new context (ends input of the previous one). diff --git a/doc/man/man8/Makefile.in b/doc/man/man8/Makefile.in index 49c7ac0120..70d8e1fd22 100644 --- a/doc/man/man8/Makefile.in +++ b/doc/man/man8/Makefile.in @@ -1,5 +1,7 @@ # man8 Makefile.in for OpenLDAP # $OpenLDAP$ +## This work is part of OpenLDAP Software . +## ## Copyright 1998-2005 The OpenLDAP Foundation. ## All rights reserved. ## diff --git a/include/ldap.h b/include/ldap.h index daccf104ec..b06dd612c3 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -234,10 +234,9 @@ typedef struct ldapcontrol { #define LDAP_CONTROL_VLVRESPONSE "2.16.840.1.113730.3.4.10" /* Password policy Controls *//* work in progress */ -#ifdef LDAP_DEVEL +/* ITS#3458: released, but not to latest draft; disabled by default */ #define LDAP_CONTROL_PASSWORDPOLICYREQUEST "1.3.6.1.4.1.42.2.27.8.5.1" #define LDAP_CONTROL_PASSWORDPOLICYRESPONSE "1.3.6.1.4.1.42.2.27.8.5.1" -#endif /* LDAP Sync -- draft-zeilenga-ldup-sync *//* submitted for publication */ #define LDAP_SYNC_OID "1.3.6.1.4.1.4203.1.9.1" diff --git a/include/ldif.h b/include/ldif.h index 88c062217e..fec4b65ae9 100644 --- a/include/ldif.h +++ b/include/ldif.h @@ -75,6 +75,9 @@ ldif_fetch_url LDAP_P(( LDAP_LDIF_F( char * ) ldif_getline LDAP_P(( char **next )); +LDAP_LDIF_F( int ) +ldif_countlines LDAP_P(( LDAP_CONST char *line )); + LDAP_LDIF_F( int ) ldif_read_record LDAP_P(( FILE *fp, diff --git a/include/rewrite.h b/include/rewrite.h index ccf359c297..155f504452 100644 --- a/include/rewrite.h +++ b/include/rewrite.h @@ -38,8 +38,7 @@ * Rewrite internal status returns */ #define REWRITE_SUCCESS LDAP_SUCCESS -#define REWRITE_ERR LDAP_OPERATIONS_ERROR -#define REWRITE_NO_SUCH_OBJECT LDAP_NO_SUCH_OBJECT +#define REWRITE_ERR LDAP_OTHER /* * Rewrite modes (input values for rewrite_info_init); determine the @@ -66,11 +65,11 @@ * REWRITE_REGEXEC_UNWILLING the server should issue an 'unwilling * to perform' error */ -#define REWRITE_REGEXEC_OK 0x0000 -#define REWRITE_REGEXEC_ERR 0x0001 -#define REWRITE_REGEXEC_STOP 0x0002 -#define REWRITE_REGEXEC_UNWILLING 0x0003 -#define REWRITE_REGEXEC_USER 0x0004 /* and above ... */ +#define REWRITE_REGEXEC_OK (0) +#define REWRITE_REGEXEC_ERR (-1) +#define REWRITE_REGEXEC_STOP (-2) +#define REWRITE_REGEXEC_UNWILLING (-3) +#define REWRITE_REGEXEC_USER (1) /* and above: LDAP errors */ /* * Rewrite variable flags diff --git a/libraries/libldap/open.c b/libraries/libldap/open.c index e5243c869d..407c1a3f99 100644 --- a/libraries/libldap/open.c +++ b/libraries/libldap/open.c @@ -119,6 +119,9 @@ ldap_create( LDAP **ldp ) /* but not pointers to malloc'ed items */ ld->ld_options.ldo_sctrls = NULL; ld->ld_options.ldo_cctrls = NULL; + ld->ld_options.ldo_tm_api = NULL; + ld->ld_options.ldo_tm_net = NULL; + ld->ld_options.ldo_defludp = NULL; #ifdef HAVE_CYRUS_SASL ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech @@ -131,27 +134,26 @@ ldap_create( LDAP **ldp ) ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL; #endif - ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp); + if ( gopts->ldo_tm_api && + ldap_int_timeval_dup( &ld->ld_options.ldo_tm_api, gopts->ldo_tm_api )) + goto nomem; - if ( ld->ld_options.ldo_defludp == NULL ) { - LDAP_FREE( (char*)ld ); - return LDAP_NO_MEMORY; - } + if ( gopts->ldo_tm_net && + ldap_int_timeval_dup( &ld->ld_options.ldo_tm_net, gopts->ldo_tm_net )) + goto nomem; - if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) { - ldap_free_urllist( ld->ld_options.ldo_defludp ); - LDAP_FREE( (char*) ld ); - return LDAP_NO_MEMORY; + if ( gopts->ldo_defludp ) { + ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp); + + if ( ld->ld_options.ldo_defludp == NULL ) goto nomem; } + if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) goto nomem; + ld->ld_lberoptions = LBER_USE_DER; ld->ld_sb = ber_sockbuf_alloc( ); - if ( ld->ld_sb == NULL ) { - ldap_free_urllist( ld->ld_options.ldo_defludp ); - LDAP_FREE( (char*) ld ); - return LDAP_NO_MEMORY; - } + if ( ld->ld_sb == NULL ) goto nomem; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_init( &ld->ld_req_mutex ); @@ -159,6 +161,20 @@ ldap_create( LDAP **ldp ) #endif *ldp = ld; return LDAP_SUCCESS; + +nomem: + ldap_free_select_info( ld->ld_selectinfo ); + ldap_free_urllist( ld->ld_options.ldo_defludp ); + LDAP_FREE( ld->ld_options.ldo_tm_net ); + LDAP_FREE( ld->ld_options.ldo_tm_api ); +#ifdef HAVE_CYRUS_SASL + LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid ); + LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid ); + LDAP_FREE( ld->ld_options.ldo_def_sasl_realm ); + LDAP_FREE( ld->ld_options.ldo_def_sasl_mech ); +#endif + LDAP_FREE( (char *)ld ); + return LDAP_NO_MEMORY; } /* diff --git a/libraries/liblutil/fetch.c b/libraries/liblutil/fetch.c index 0a0ef85249..49a72c6e4c 100644 --- a/libraries/liblutil/fetch.c +++ b/libraries/liblutil/fetch.c @@ -1,6 +1,5 @@ /* fetch.c - routines for fetching data at URLs */ /* $OpenLDAP$ */ -/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1999-2005 The OpenLDAP Foundation. diff --git a/libraries/liblutil/ldif.c b/libraries/liblutil/ldif.c index 79f1140611..e0412b2ae9 100644 --- a/libraries/liblutil/ldif.c +++ b/libraries/liblutil/ldif.c @@ -308,6 +308,21 @@ ldif_parse_line2( * which it updates and must be supplied on subsequent calls. */ +int +ldif_countlines( LDAP_CONST char *buf ) +{ + char *nl; + int ret = 0; + + if ( !buf ) return ret; + + for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) { + nl++; + if ( *nl != ' ' ) ret++; + } + return ret; +} + char * ldif_getline( char **next ) { diff --git a/libraries/librewrite/xmap.c b/libraries/librewrite/xmap.c index 0448c8ee96..ca6e6819be 100644 --- a/libraries/librewrite/xmap.c +++ b/libraries/librewrite/xmap.c @@ -259,7 +259,7 @@ rewrite_xmap_apply( ldap_pvt_thread_mutex_unlock( &xpasswd_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ - rc = REWRITE_NO_SUCH_OBJECT; + rc = LDAP_NO_SUCH_OBJECT; break; } diff --git a/servers/Makefile.in b/servers/Makefile.in index f8616acfb2..fa3071f75e 100644 --- a/servers/Makefile.in +++ b/servers/Makefile.in @@ -1,5 +1,7 @@ # servers Makefile.in for OpenLDAP # $OpenLDAP$ +## This work is part of OpenLDAP Software . +## ## Copyright 1998-2005 The OpenLDAP Foundation. ## All rights reserved. ## diff --git a/servers/slapd/add.c b/servers/slapd/add.c index 204caa0380..92f6759aea 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -220,14 +220,18 @@ fe_op_add( Operation *op, SlapReply *rs ) if ( !rs->sr_ref ) rs->sr_ref = default_referral; if ( rs->sr_ref ) { rs->sr_err = LDAP_REFERRAL; + op->o_bd = frontendDB; send_ldap_result( op, rs ); + op->o_bd = NULL; if ( rs->sr_ref != default_referral ) { ber_bvarray_free( rs->sr_ref ); } } else { + op->o_bd = frontendDB; send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "no global superior knowledge" ); + op->o_bd = NULL; } goto done; } diff --git a/servers/slapd/at.c b/servers/slapd/at.c index 58c40006bd..7958a1ec39 100644 --- a/servers/slapd/at.c +++ b/servers/slapd/at.c @@ -57,9 +57,12 @@ struct aindexrec { }; static Avlnode *attr_index = NULL; +static Avlnode *attr_cache = NULL; static LDAP_SLIST_HEAD(ATList, slap_attribute_type) attr_list = LDAP_SLIST_HEAD_INITIALIZER(&attr_list); +int at_oc_cache; + static int attr_index_cmp( const void *v_air1, @@ -100,8 +103,18 @@ at_bvfind( struct berval *name ) { struct aindexrec *air; + if ( attr_cache ) { + air = avl_find( attr_cache, name, attr_index_name_cmp ); + if ( air ) return air->air_at; + } + air = avl_find( attr_index, name, attr_index_name_cmp ); + if ( air && ( slapMode & SLAP_TOOL_MODE ) && at_oc_cache ) { + avl_insert( &attr_cache, (caddr_t) air, + attr_index_cmp, avl_dup_error ); + } + return air != NULL ? air->air_at : NULL; } diff --git a/servers/slapd/attr.c b/servers/slapd/attr.c index 8908a65da9..ee0f46daab 100644 --- a/servers/slapd/attr.c +++ b/servers/slapd/attr.c @@ -177,7 +177,7 @@ attr_merge( Attribute **a; for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) { - if ( ad_cmp( (*a)->a_desc, desc ) == 0 ) { + if ( (*a)->a_desc == desc ) { break; } } @@ -261,7 +261,7 @@ attr_merge_one( Attribute **a; for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) { - if ( ad_cmp( (*a)->a_desc, desc ) == 0 ) { + if ( (*a)->a_desc == desc ) { break; } } @@ -353,7 +353,7 @@ attr_find( AttributeDescription *desc ) { for ( ; a != NULL; a = a->a_next ) { - if ( ad_cmp( a->a_desc, desc ) == 0 ) { + if ( a->a_desc == desc ) { return( a ); } } @@ -376,7 +376,7 @@ attr_delete( Attribute **a; for ( a = attrs; *a != NULL; a = &(*a)->a_next ) { - if ( ad_cmp( (*a)->a_desc, desc ) == 0 ) { + if ( (*a)->a_desc == desc ) { Attribute *save = *a; *a = (*a)->a_next; attr_free( save ); diff --git a/servers/slapd/back-bdb/attr.c b/servers/slapd/back-bdb/attr.c index 73c35c86c2..70a20ea9c1 100644 --- a/servers/slapd/back-bdb/attr.c +++ b/servers/slapd/back-bdb/attr.c @@ -67,6 +67,24 @@ bdb_attr_comp_ref( *cr = a != NULL ? a->ai_cr : 0 ; } +void +bdb_attr_mask_cr( + struct bdb_info *bdb, + AttributeDescription *desc, + slap_mask_t *indexmask, + ComponentReference** cr ) +{ + AttrInfo *a; + + a = (AttrInfo *) avl_find( bdb->bi_attrs, desc, ainfo_type_cmp ); + if ( a ) { + *indexmask = a->ai_indexmask; + *cr = a->ai_cr; + } else { + *indexmask = NULL; + *cr = NULL; + } +} #endif void diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index d788665c3c..44517010fb 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -241,7 +241,7 @@ struct bdb_op_info { #if DB_VERSION_FULL >= 0x04010011 #undef DB_OPEN #define DB_OPEN(db, file, name, type, flags, mode) \ - (db)->open(db, NULL, file, name, type, (flags)|DB_AUTO_COMMIT, mode) + (db)->open(db, NULL, file, name, type, flags, mode) #endif #endif diff --git a/servers/slapd/back-bdb/dbcache.c b/servers/slapd/back-bdb/dbcache.c index adcdf463a7..3885b4c09a 100644 --- a/servers/slapd/back-bdb/dbcache.c +++ b/servers/slapd/back-bdb/dbcache.c @@ -63,7 +63,7 @@ bdb_db_cache( const char *name, DB **dbout ) { - int i; + int i, flags; int rc; struct bdb_info *bdb = (struct bdb_info *) be->be_private; struct bdb_db_info *db; @@ -118,11 +118,15 @@ bdb_db_cache( #ifdef HAVE_EBCDIC __atoe( file ); +#endif + flags = DB_CREATE | DB_THREAD; +#ifdef DB_AUTO_COMMIT + if ( !( slapMode & SLAP_TOOL_QUICK )) + flags |= DB_AUTO_COMMIT; #endif rc = DB_OPEN( db->bdi_db, file, NULL /* name */, - BDB_INDEXTYPE, bdb->bi_db_opflags | DB_CREATE | DB_THREAD, - bdb->bi_dbenv_mode ); + BDB_INDEXTYPE, bdb->bi_db_opflags | flags, bdb->bi_dbenv_mode ); ch_free( file ); diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c index b157ad23a9..b1eee39761 100644 --- a/servers/slapd/back-bdb/dn2id.c +++ b/servers/slapd/back-bdb/dn2id.c @@ -577,7 +577,7 @@ hdb_dn2id_delete( data.data = d; /* Delete our ID from the parent's list */ - rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE | DB_RMW ); + rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE ); if ( rc == 0 ) { if ( !strcmp( d->nrdn, BEI(e)->bei_nrdn.bv_val )) rc = cursor->c_del( cursor, 0 ); @@ -591,7 +591,7 @@ hdb_dn2id_delete( */ if ( rc == 0 ) { BDB_ID2DISK( e->e_id, &nid ); - rc = cursor->c_get( cursor, &key, &data, DB_SET | DB_RMW ); + rc = cursor->c_get( cursor, &key, &data, DB_SET ); if ( rc == 0 ) rc = cursor->c_del( cursor, 0 ); } diff --git a/servers/slapd/back-bdb/idl.c b/servers/slapd/back-bdb/idl.c index 186ad24b3c..29a337218d 100644 --- a/servers/slapd/back-bdb/idl.c +++ b/servers/slapd/back-bdb/idl.c @@ -482,8 +482,6 @@ bdb_idl_fetch_key( data.ulen = sizeof(buf); data.flags = DB_DBT_USERMEM; - if ( tid ) flags |= DB_RMW; - /* If we're not reusing an existing cursor, get a new one */ if( opflag != DB_NEXT ) { rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags ); @@ -646,7 +644,7 @@ bdb_idl_insert_key( /* Fetch the first data item for this key, to see if it * exists and if it's a range. */ - rc = cursor->c_get( cursor, key, &data, DB_SET | DB_RMW ); + rc = cursor->c_get( cursor, key, &data, DB_SET ); err = "c_get"; if ( rc == 0 ) { if ( nlo != 0 ) { @@ -690,42 +688,30 @@ bdb_idl_insert_key( /* Update hi/lo if needed, then delete all the items * between lo and hi */ - data.data = &nid; - if ( id > hi ) { - rc = cursor->c_del( cursor, 0 ); - if ( rc != 0 ) { - err = "c_del hi"; - goto fail; - } - rc = cursor->c_put( cursor, key, &data, DB_KEYLAST ); - if ( rc != 0 ) { - err = "c_put hi"; - goto fail; - } + if ( id < lo ) { + lo = id; + nlo = nid; + } else if ( id > hi ) { + hi = id; + nhi = nid; } + data.data = &nid; /* Don't fetch anything, just position cursor */ data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; data.dlen = data.ulen = 0; - rc = cursor->c_get( cursor, key, &data, DB_SET | DB_RMW ); + rc = cursor->c_get( cursor, key, &data, DB_SET ); if ( rc != 0 ) { err = "c_get 2"; goto fail; } - if ( id < lo ) { - rc = cursor->c_del( cursor, 0 ); - if ( rc != 0 ) { - err = "c_del lo"; - goto fail; - } - rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST ); - if ( rc != 0 ) { - err = "c_put lo"; - goto fail; - } + rc = cursor->c_del( cursor, 0 ); + if ( rc != 0 ) { + err = "c_del range1"; + goto fail; } - /* Delete all the records between lo and hi */ - for ( i=2; ic_get( cursor, &key2, &data, DB_NEXT_DUP | DB_RMW ); + /* Delete all the records */ + for ( i=1; ic_get( cursor, &key2, &data, DB_NEXT_DUP ); if ( rc != 0 ) { err = "c_get next_dup"; goto fail; @@ -745,6 +731,18 @@ bdb_idl_insert_key( err = "c_put range"; goto fail; } + nid = nlo; + rc = cursor->c_put( cursor, key, &data, DB_KEYLAST ); + if ( rc != 0 ) { + err = "c_put lo"; + goto fail; + } + nid = nhi; + rc = cursor->c_put( cursor, key, &data, DB_KEYLAST ); + if ( rc != 0 ) { + err = "c_put hi"; + goto fail; + } } else { /* There's room, just store it */ goto put1; @@ -854,7 +852,7 @@ bdb_idl_delete_key( /* Fetch the first data item for this key, to see if it * exists and if it's a range. */ - rc = cursor->c_get( cursor, key, &data, DB_SET | DB_RMW ); + rc = cursor->c_get( cursor, key, &data, DB_SET ); err = "c_get"; if ( rc == 0 ) { if ( tmp != 0 ) { @@ -862,8 +860,7 @@ bdb_idl_delete_key( if (tmp != nid) { /* position to correct item */ tmp = nid; - rc = cursor->c_get( cursor, key, &data, - DB_GET_BOTH | DB_RMW ); + rc = cursor->c_get( cursor, key, &data, DB_GET_BOTH ); if ( rc != 0 ) { err = "c_get id"; goto fail; diff --git a/servers/slapd/back-bdb/index.c b/servers/slapd/back-bdb/index.c index 6f101275be..3e725c8800 100644 --- a/servers/slapd/back-bdb/index.c +++ b/servers/slapd/back-bdb/index.c @@ -283,20 +283,21 @@ static int index_at_values( if( rc ) return rc; } -#ifdef LDAP_COMP_MATCH - /* component indexing */ - bdb_attr_comp_ref ( op->o_bd->be_private, type->sat_ad, &cr_list ); - if ( cr_list ) { - for( cr = cr_list ; cr ; cr = cr->cr_next ) { - rc = indexer( op, txn, cr->cr_ad, &type->sat_cname, - cr->cr_nvals, id, opid, - cr->cr_indexmask ); - } - } -#endif /* If this type has no AD, we've never used it before */ if( type->sat_ad ) { +#ifdef LDAP_COMP_MATCH + /* component indexing */ + bdb_attr_mask_cr( op->o_bd->be_private, type->sat_ad, &mask, &cr_list ); + if ( cr_list ) { + for( cr = cr_list ; cr ; cr = cr->cr_next ) { + rc = indexer( op, txn, cr->cr_ad, &type->sat_cname, + cr->cr_nvals, id, opid, + cr->cr_indexmask ); + } + } +#else bdb_attr_mask( op->o_bd->be_private, type->sat_ad, &mask ); +#endif ad = type->sat_ad; } diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index 188464e42a..53e036a6de 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -138,8 +138,10 @@ bdb_db_open( BackendDB *be ) return rc; } - flags = DB_INIT_MPOOL | DB_THREAD | DB_CREATE - | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN; + flags = DB_INIT_MPOOL | DB_THREAD | DB_CREATE; + +if ( !( slapMode & SLAP_TOOL_QUICK )) + flags |= DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN; #if 0 /* Never do automatic recovery, must perform it manually. @@ -273,6 +275,11 @@ bdb_db_open( BackendDB *be ) flags = DB_THREAD | bdb->bi_db_opflags; +#ifdef DB_AUTO_COMMIT + if ( !( slapMode & SLAP_TOOL_QUICK )) + flags |= DB_AUTO_COMMIT; +#endif + bdb->bi_databases = (struct bdb_db_info **) ch_malloc( BDB_INDICES * sizeof(struct bdb_db_info *) ); @@ -364,7 +371,9 @@ bdb_db_open( BackendDB *be ) return rc; } - XLOCK_ID(bdb->bi_dbenv, &bdb->bi_cache.c_locker); + if ( !( slapMode & SLAP_TOOL_QUICK )) { + XLOCK_ID(bdb->bi_dbenv, &bdb->bi_cache.c_locker); + } /* If we're in server mode and time-based checkpointing is enabled, * submit a task to perform periodic checkpoints. @@ -417,7 +426,9 @@ bdb_db_close( BackendDB *be ) ldap_pvt_thread_rdwr_wunlock ( &bdb->bi_idl_tree_rwlock ); } - XLOCK_ID_FREE(bdb->bi_dbenv, bdb->bi_cache.c_locker); + if ( !( slapMode & SLAP_TOOL_QUICK )) { + XLOCK_ID_FREE(bdb->bi_dbenv, bdb->bi_cache.c_locker); + } return 0; } @@ -434,11 +445,13 @@ bdb_db_destroy( BackendDB *be ) /* close db environment */ if( bdb->bi_dbenv ) { /* force a checkpoint */ - rc = TXN_CHECKPOINT( bdb->bi_dbenv, 0, 0, DB_FORCE ); - if( rc != 0 ) { - Debug( LDAP_DEBUG_ANY, - "bdb_db_destroy: txn_checkpoint failed: %s (%d)\n", - db_strerror(rc), rc, 0 ); + if ( !( slapMode & SLAP_TOOL_QUICK )) { + rc = TXN_CHECKPOINT( bdb->bi_dbenv, 0, 0, DB_FORCE ); + if( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, + "bdb_db_destroy: txn_checkpoint failed: %s (%d)\n", + db_strerror(rc), rc, 0 ); + } } rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 ); diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index c770b3fc42..48f41659d1 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -36,9 +36,14 @@ LDAP_BEGIN_DECL #ifdef LDAP_COMP_MATCH #define bdb_attr_comp_ref BDB_SYMBOL(attr_comp_ref) +#define bdb_attr_mask_cr BDB_SYMBOL(attr_mask_cr) void bdb_attr_comp_ref( struct bdb_info *bdb, AttributeDescription *desc, ComponentReference **cr ); +void bdb_attr_mask_cr( struct bdb_info *bdb, + AttributeDescription *desc, + slap_mask_t *indexmask, + ComponentReference **cr ); #endif void bdb_attr_mask( struct bdb_info *bdb, diff --git a/servers/slapd/back-bdb/tools.c b/servers/slapd/back-bdb/tools.c index f65d4b99d4..ec38daa6cd 100644 --- a/servers/slapd/back-bdb/tools.c +++ b/servers/slapd/back-bdb/tools.c @@ -307,6 +307,7 @@ ID bdb_tool_entry_put( Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_tool_entry_put) "( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 ); + if (! (slapMode & SLAP_TOOL_QUICK)) { rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid, bdb->bi_db_opflags ); if( rc != 0 ) { @@ -318,6 +319,7 @@ ID bdb_tool_entry_put( text->bv_val, 0, 0 ); return NOID; } + } op.o_hdr = &ohdr; op.o_bd = be; @@ -356,6 +358,7 @@ ID bdb_tool_entry_put( done: if( rc == 0 ) { + if ( !( slapMode & SLAP_TOOL_QUICK )) { rc = TXN_COMMIT( tid, 0 ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, @@ -366,8 +369,10 @@ done: text->bv_val, 0, 0 ); e->e_id = NOID; } + } } else { + if ( !( slapMode & SLAP_TOOL_QUICK )) { TXN_ABORT( tid ); snprintf( text->bv_val, text->bv_len, "txn_aborted! %s (%d)", @@ -375,6 +380,7 @@ done: Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n", text->bv_val, 0, 0 ); + } e->e_id = NOID; } @@ -420,6 +426,7 @@ int bdb_tool_entry_reindex( return -1; } + if (! (slapMode & SLAP_TOOL_QUICK)) { rc = TXN_BEGIN( bi->bi_dbenv, NULL, &tid, bi->bi_db_opflags ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, @@ -428,6 +435,7 @@ int bdb_tool_entry_reindex( db_strerror(rc), rc, 0 ); goto done; } + } /* * just (re)add them for now @@ -445,22 +453,11 @@ int bdb_tool_entry_reindex( op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; -#if 0 /* ndef BDB_HIER */ - /* add dn2id indices */ - rc = bdb_dn2id_add( &op, tid, NULL, e ); - if( rc != 0 && rc != DB_KEYEXIST ) { - Debug( LDAP_DEBUG_ANY, - "=> " LDAP_XSTRING(bdb_tool_entry_reindex) - ": dn2id_add failed: %s (%d)\n", - db_strerror(rc), rc, 0 ); - goto done; - } -#endif - rc = bdb_index_entry_add( &op, tid, e ); done: if( rc == 0 ) { + if (! (slapMode & SLAP_TOOL_QUICK)) { rc = TXN_COMMIT( tid, 0 ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, @@ -469,13 +466,16 @@ done: db_strerror(rc), rc, 0 ); e->e_id = NOID; } + } } else { + if (! (slapMode & SLAP_TOOL_QUICK)) { TXN_ABORT( tid ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(bdb_tool_entry_reindex) ": txn_aborted! %s (%d)\n", db_strerror(rc), rc, 0 ); + } e->e_id = NOID; } bdb_entry_release( &op, e, 0 ); @@ -508,6 +508,7 @@ ID bdb_tool_entry_modify( "=> " LDAP_XSTRING(bdb_tool_entry_modify) "( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 ); + if (! (slapMode & SLAP_TOOL_QUICK)) { rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid, bdb->bi_db_opflags ); if( rc != 0 ) { @@ -519,6 +520,7 @@ ID bdb_tool_entry_modify( text->bv_val, 0, 0 ); return NOID; } + } op.o_hdr = &ohdr; op.o_bd = be; @@ -561,6 +563,7 @@ ID bdb_tool_entry_modify( done: if( rc == 0 ) { + if (! (slapMode & SLAP_TOOL_QUICK)) { rc = TXN_COMMIT( tid, 0 ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, @@ -571,8 +574,10 @@ done: "%s\n", text->bv_val, 0, 0 ); e->e_id = NOID; } + } } else { + if (! (slapMode & SLAP_TOOL_QUICK)) { TXN_ABORT( tid ); snprintf( text->bv_val, text->bv_len, "txn_aborted! %s (%d)", @@ -580,6 +585,7 @@ done: Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n", text->bv_val, 0, 0 ); + } e->e_id = NOID; } diff --git a/servers/slapd/back-ldap/add.c b/servers/slapd/back-ldap/add.c index 1805a31b3e..eb272c7662 100644 --- a/servers/slapd/back-ldap/add.c +++ b/servers/slapd/back-ldap/add.c @@ -46,14 +46,14 @@ ldap_back_add( int isupdate; int do_retry = 1; LDAPControl **ctrls = NULL; - int rc = LDAP_SUCCESS; + rs->sr_err = LDAP_SUCCESS; + Debug( LDAP_DEBUG_ARGS, "==> ldap_back_add(\"%s\")\n", op->o_req_dn.bv_val, 0, 0 ); - lc = ldap_back_getconn( op, rs ); - if ( !lc || !ldap_back_dobind( lc, op, rs ) ) { - rc = -1; + lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); + if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { goto cleanup; } @@ -89,20 +89,19 @@ ldap_back_add( attrs[ i ] = NULL; ctrls = op->o_ctrls; - rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls ); - if ( rc != LDAP_SUCCESS ) { + rs->sr_err = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls ); + if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); - rc = -1; goto cleanup; } retry: rs->sr_err = ldap_add_ext( lc->lc_ld, op->o_req_dn.bv_val, attrs, ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, 1 ); + rs->sr_err = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; - if ( ldap_back_retry( lc, op, rs ) ) { + if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { goto retry; } } @@ -118,8 +117,8 @@ cleanup: } Debug( LDAP_DEBUG_ARGS, "<== ldap_back_add(\"%s\"): %d\n", - op->o_req_dn.bv_val, rc, 0 ); + op->o_req_dn.bv_val, rs->sr_err, 0 ); - return rc; + return rs->sr_err; } diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index 3f5b109d37..174a7039c5 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -90,12 +90,23 @@ struct ldapinfo { /* end of ID assert stuff */ ldap_pvt_thread_mutex_t conn_mutex; - int savecred; + unsigned flags; +#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 ) Avlnode *conntree; int rwm_started; }; +typedef enum ldap_back_send_t { + LDAP_BACK_DONTSEND = 0x00, + LDAP_BACK_SENDOK = 0x01, + LDAP_BACK_SENDERR = 0x02, + LDAP_BACK_SENDRESULT = (LDAP_BACK_SENDOK|LDAP_BACK_SENDERR) +} ldap_back_send_t; + LDAP_END_DECL #include "proto-ldap.h" diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index f7446f35c9..998ce24537 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -16,7 +16,7 @@ * . */ /* ACKNOWLEDGEMENTS: - * This work was initially developed by the Howard Chu for inclusion + * This work was initially developed by Howard Chu for inclusion * in OpenLDAP Software and subsequently enhanced by Pierangelo * Masarati. */ @@ -41,6 +41,9 @@ static LDAP_REBIND_PROC ldap_back_rebind; static int ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs ); +static int +ldap_back_prepare_conn( struct ldapconn **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok ); + int ldap_back_bind( Operation *op, SlapReply *rs ) { @@ -50,9 +53,9 @@ ldap_back_bind( Operation *op, SlapReply *rs ) int rc = 0; ber_int_t msgid; - lc = ldap_back_getconn( op, rs ); + lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); if ( !lc ) { - return( -1 ); + return rs->sr_err; } if ( !BER_BVISNULL( &lc->lc_bound_ndn ) ) { @@ -65,7 +68,7 @@ ldap_back_bind( Operation *op, SlapReply *rs ) rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val, LDAP_SASL_SIMPLE, &op->orb_cred, op->o_ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, 1 ); + rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); if ( rc == LDAP_SUCCESS ) { /* If defined, proxyAuthz will be used also when @@ -84,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->savecred ) { + if ( li->flags & LDAP_BACK_F_SAVECRED ) { if ( !BER_BVISNULL( &lc->lc_cred ) ) { memset( lc->lc_cred.bv_val, 0, lc->lc_cred.bv_len ); @@ -219,12 +222,76 @@ ldap_back_freeconn( Operation *op, struct ldapconn *lc ) return 0; } +static int +ldap_back_prepare_conn( struct ldapconn **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok ) +{ + struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private; + int vers = op->o_protocol; + LDAP *ld = NULL; + + assert( lcp != NULL ); + + rs->sr_err = ldap_initialize( &ld, li->url ); + if ( rs->sr_err != LDAP_SUCCESS ) { + goto error_return; + } + + /* Set LDAP version. This will always succeed: If the client + * bound with a particular version, then so can we. + */ + ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&vers ); + + /* Set LDAP version. This will always succeed: If the client + * bound with a particular version, then so can we. + */ + ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, + (const void *)&vers ); + + /* FIXME: configurable? */ + ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON ); + + 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 ) + { + /* 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 ) ) + { + ldap_unbind_ext_s( ld, NULL, NULL ); + goto error_return; + } + } + + if ( *lcp == NULL ) { + *lcp = (struct ldapconn *)ch_malloc( sizeof( struct ldapconn ) ); + memset( *lcp, 0, sizeof( struct ldapconn ) ); + } + (*lcp)->lc_ld = ld; + +error_return:; + if ( rs->sr_err != LDAP_SUCCESS ) { + rs->sr_err = slap_map_api2result( rs ); + if ( sendok & LDAP_BACK_SENDERR ) { + if ( rs->sr_text == NULL ) { + rs->sr_text = "ldap_initialize() failed"; + } + send_ldap_result( op, rs ); + rs->sr_text = NULL; + } + } + + return rs->sr_err; +} + struct ldapconn * -ldap_back_getconn( Operation *op, SlapReply *rs ) +ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok ) { struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private; struct ldapconn *lc, lc_curr; - LDAP *ld; int is_priv = 0; /* Searches for a ldapconn in the avl tree */ @@ -258,31 +325,12 @@ ldap_back_getconn( Operation *op, SlapReply *rs ) /* Looks like we didn't get a bind. Open a new session... */ if ( !lc ) { - int vers = op->o_protocol; - rs->sr_err = ldap_initialize( &ld, li->url ); - - if ( rs->sr_err != LDAP_SUCCESS ) { - rs->sr_err = slap_map_api2result( rs ); - if ( rs->sr_text == NULL ) { - rs->sr_text = "ldap_initialize() failed"; - } - if ( op->o_conn ) { - send_ldap_result( op, rs ); - } - rs->sr_text = NULL; - return( NULL ); + /* lc here must be NULL */ + if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) { + return NULL; } - /* Set LDAP version. This will always succeed: If the client - * bound with a particular version, then so can we. - */ - ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, - (const void *)&vers ); - /* FIXME: configurable? */ - ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON ); - lc = (struct ldapconn *)ch_malloc( sizeof( struct ldapconn ) ); lc->lc_conn = lc_curr.lc_conn; - lc->lc_ld = ld; ber_dupbv( &lc->lc_local_ndn, &lc_curr.lc_local_ndn ); ldap_pvt_thread_mutex_init( &lc->lc_mutex ); @@ -320,18 +368,18 @@ ldap_back_getconn( Operation *op, SlapReply *rs ) /* Err could be -1 in case a duplicate ldapconn is inserted */ if ( rs->sr_err != 0 ) { ldap_back_conn_free( lc ); - if ( op->o_conn ) { + if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) { send_ldap_error( op, rs, LDAP_OTHER, "internal server error" ); } - return( NULL ); + return NULL; } } else { Debug( LDAP_DEBUG_TRACE, "=>ldap_back_getconn: conn %p fetched\n", (void *) lc, 0, 0 ); } - return( lc ); + return lc; } /* @@ -341,12 +389,19 @@ ldap_back_getconn( Operation *op, SlapReply *rs ) * it from all the callers, and I made the function return the flag, so * it can be used to simplify the check. */ -int -ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs ) +static int +ldap_back_dobind_int( + struct ldapconn *lc, + Operation *op, + SlapReply *rs, + ldap_back_send_t sendok, + int retries ) { int rc; ber_int_t msgid; + assert( retries >= 0 ); + ldap_pvt_thread_mutex_lock( &lc->lc_mutex ); if ( !lc->lc_bound ) { /* @@ -373,12 +428,33 @@ ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs ) goto done; } +retry:; rs->sr_err = ldap_sasl_bind( lc->lc_ld, lc->lc_bound_ndn.bv_val, LDAP_SASL_SIMPLE, &lc->lc_cred, NULL, NULL, &msgid ); - - rc = ldap_back_op_result( lc, op, rs, msgid, 0 ); + + if ( rs->sr_err == LDAP_SERVER_DOWN ) { + if ( retries > 0 ) { + ldap_unbind_ext_s( lc->lc_ld, NULL, NULL ); + lc->lc_ld = NULL; + + /* lc here must be the regular lc, reset and ready for init */ + if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) { + return 0; + } + + retries--; + goto retry; + } + + ldap_back_freeconn( op, lc ); + rs->sr_err = slap_map_api2result( rs ); + + return 0; + } + + rc = ldap_back_op_result( lc, op, rs, msgid, sendok ); if ( rc == LDAP_SUCCESS ) { lc->lc_bound = 1; } @@ -390,6 +466,12 @@ done:; return rc; } +int +ldap_back_dobind( struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok ) +{ + return ldap_back_dobind_int( lc, op, rs, sendok, 1 ); +} + /* * ldap_back_rebind * @@ -400,7 +482,9 @@ static int ldap_back_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params ) { - struct ldapconn *lc = params; + struct ldapconn *lc = (struct ldapconn *)params; + + /* FIXME: add checks on the URL/identity? */ return ldap_sasl_bind_s( ld, lc->lc_bound_ndn.bv_val, LDAP_SASL_SIMPLE, &lc->lc_cred, NULL, NULL, NULL ); @@ -408,11 +492,11 @@ ldap_back_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request, int ldap_back_op_result( - struct ldapconn *lc, - Operation *op, - SlapReply *rs, - ber_int_t msgid, - int sendok ) + struct ldapconn *lc, + Operation *op, + SlapReply *rs, + ber_int_t msgid, + ldap_back_send_t sendok ) { char *match = NULL; LDAPMessage *res = NULL; @@ -474,7 +558,10 @@ retry:; rs->sr_matched = match; } } - if ( op->o_conn && ( sendok || rs->sr_err != LDAP_SUCCESS ) ) { + if ( op->o_conn && + ( ( sendok & LDAP_BACK_SENDOK ) + || ( ( sendok & LDAP_BACK_SENDERR ) && rs->sr_err != LDAP_SUCCESS ) ) ) + { send_ldap_result( op, rs ); } if ( match ) { @@ -493,37 +580,20 @@ retry:; /* return true if bound, false if failed */ int -ldap_back_retry( struct ldapconn *lc, Operation *op, SlapReply *rs ) +ldap_back_retry( struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok ) { - struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private; - int vers = op->o_protocol; - LDAP *ld; - ldap_pvt_thread_mutex_lock( &lc->lc_mutex ); ldap_unbind_ext_s( lc->lc_ld, NULL, NULL ); + lc->lc_ld = NULL; lc->lc_bound = 0; - rs->sr_err = ldap_initialize( &ld, li->url ); - - if ( rs->sr_err != LDAP_SUCCESS ) { - rs->sr_err = slap_map_api2result( rs ); - if ( rs->sr_text == NULL ) { - rs->sr_text = "ldap_initialize() failed"; - } - if ( op->o_conn ) { - send_ldap_result( op, rs ); - } - rs->sr_text = NULL; + + /* lc here must be the regular lc, reset and ready for init */ + if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) { return 0; } - /* Set LDAP version. This will always succeed: If the client - * bound with a particular version, then so can we. - */ - ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&vers ); - /* FIXME: configurable? */ - ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON ); - lc->lc_ld = ld; + ldap_pvt_thread_mutex_unlock( &lc->lc_mutex ); - return ldap_back_dobind( lc, op, rs ); + return ldap_back_dobind_int( lc, op, rs, sendok, 0 ); } static int @@ -695,7 +765,7 @@ ldap_back_proxy_authz_bind( struct ldapconn *lc, Operation *op, SlapReply *rs ) goto done; } - rc = ldap_back_op_result( lc, op, rs, msgid, 0 ); + rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR ); if ( rc == LDAP_SUCCESS ) { lc->lc_bound = 1; } diff --git a/servers/slapd/back-ldap/chain.c b/servers/slapd/back-ldap/chain.c index 58b6106cf0..67927c40d7 100644 --- a/servers/slapd/back-ldap/chain.c +++ b/servers/slapd/back-ldap/chain.c @@ -31,18 +31,11 @@ static BackendInfo *lback; -#if 0 -static int -ldap_chain_chk_referrals( Operation *op, SlapReply *rs ) -{ - return LDAP_SUCCESS; -} -#endif - static int ldap_chain_operational( Operation *op, SlapReply *rs ) { - /* trap entries generated by back-ldap. + /* Trap entries generated by back-ldap. + * * FIXME: we need a better way to recognize them; a cleaner * solution would be to be able to intercept the response * of be_operational(), so that we can divert only those @@ -57,8 +50,11 @@ ldap_chain_operational( Operation *op, SlapReply *rs ) return SLAP_CB_CONTINUE; } +/* + * Search specific response that strips entryDN from entries + */ static int -ldap_chain_cb_response( Operation *op, SlapReply *rs ) +ldap_chain_cb_search_response( Operation *op, SlapReply *rs ) { assert( op->o_tag == LDAP_REQ_SEARCH ); @@ -82,83 +78,159 @@ ldap_chain_cb_response( Operation *op, SlapReply *rs ) } return SLAP_CB_CONTINUE; + + } else if ( rs->sr_type == REP_RESULT ) { + /* back-ldap tried to send result */ + op->o_callback->sc_private = (void *)(1); } return 0; } +/* + * Dummy response that simply traces if back-ldap tried to send + * anything to the client + */ +static int +ldap_chain_cb_response( Operation *op, SlapReply *rs ) +{ + if ( rs->sr_type == REP_RESULT ) { + op->o_callback->sc_private = (void *)(1); + + } else if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) + { + /* strip the entryDN attribute, but keep returning results */ + (void)ldap_chain_cb_search_response( op, rs ); + } + + return SLAP_CB_CONTINUE; +} + +static int +ldap_chain_op( + Operation *op, + SlapReply *rs, + int ( *op_f )( Operation *op, SlapReply *rs ), + BerVarray ref ) +{ + slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; + struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private; + int rc; + + if ( lip->url != NULL ) { + op->o_bd->be_private = on->on_bi.bi_private; + return ( *op_f )( op, rs ); + } + + li = *lip; + op->o_bd->be_private = &li; + + /* if we parse the URI then by no means + * we can cache stuff or reuse connections, + * because in back-ldap there's no caching + * based on the URI value, which is supposed + * to be set once for all (correct?) */ + op->o_do_not_cache = 1; + + for ( ; !BER_BVISNULL( ref ); ref++ ) { + LDAPURLDesc *srv; + char *save_dn; + + /* We're setting the URI of the first referral; + * what if there are more? + +Document: draft-ietf-ldapbis-protocol-27.txt + +4.1.10. Referral + ... + If the client wishes to progress the operation, it MUST follow the + referral by contacting one of the supported services. If multiple + URIs are present, the client assumes that any supported URI may be + used to progress the operation. + + * so we actually need to follow exactly one, + * and we can assume any is fine. + */ + + /* parse reference and use + * proto://[host][:port]/ only */ + rc = ldap_url_parse_ext( ref->bv_val, &srv ); + if ( rc != LDAP_URL_SUCCESS ) { + /* try next */ + rc = LDAP_OTHER; + continue; + } + + /* remove DN essentially because later on + * ldap_initialize() will parse the URL + * as a comma-separated URL list */ + save_dn = srv->lud_dn; + srv->lud_dn = ""; + srv->lud_scope = LDAP_SCOPE_DEFAULT; + li.url = ldap_url_desc2str( srv ); + srv->lud_dn = save_dn; + ldap_free_urldesc( srv ); + + if ( li.url == NULL ) { + /* try next */ + rc = LDAP_OTHER; + continue; + } + + rc = ( *op_f )( op, rs ); + + ldap_memfree( li.url ); + li.url = NULL; + + if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) { + break; + } + } + + return rc; +} + static int ldap_chain_response( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; void *private = op->o_bd->be_private; - slap_callback *sc = op->o_callback; + slap_callback *sc = op->o_callback, + sc2 = { 0 }; int rc = 0; int cache = op->o_do_not_cache; - char *authzid = NULL; BerVarray ref; struct berval ndn = op->o_ndn; struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private; - if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF ) + if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF ) { return SLAP_CB_CONTINUE; + } + + /* + * TODO: add checks on who/when chain operations; e.g.: + * a) what identities are authorized + * b) what request DN (e.g. only chain requests rooted at ) + * c) what referral URIs + * d) what protocol scheme (e.g. only ldaps://) + * e) what ssf + */ ref = rs->sr_ref; rs->sr_ref = NULL; - op->o_callback = NULL; - - if ( lip->url == NULL ) { - /* if we parse the URI then by no means - * we can cache stuff or reuse connections, - * because in back-ldap there's no caching - * based on the URI value, which is supposed - * to be set once for all (correct?) */ - op->o_do_not_cache = 1; - - /* FIXME: we're setting the URI of the first referral; - * what if there are more? Is this something we should - * worry about? */ - li = *lip; - op->o_bd->be_private = &li; - - if ( rs->sr_type != REP_SEARCHREF ) { - LDAPURLDesc *srv; - char *save_dn; - - /* parse reference and use - * proto://[host][:port]/ only */ - rc = ldap_url_parse_ext( ref[0].bv_val, &srv ); - if ( rc != LDAP_URL_SUCCESS ) { - /* error */ - return 1; - } - - /* remove DN essentially because later on - * ldap_initialize() will parse the URL - * as a comma-separated URL list */ - save_dn = srv->lud_dn; - srv->lud_dn = ""; - srv->lud_scope = LDAP_SCOPE_DEFAULT; - li.url = ldap_url_desc2str( srv ); - srv->lud_dn = save_dn; - ldap_free_urldesc( srv ); - - if ( li.url == NULL ) { - /* error */ - return 1; - } - } - - } else { - op->o_bd->be_private = on->on_bi.bi_private; - } + /* we need this to know if back-ldap returned any result */ + sc2.sc_response = ldap_chain_cb_response; + op->o_callback = &sc2; /* Chaining can be performed by a privileged user on behalf * of normal users, using the ProxyAuthz control, by exploiting * the identity assertion feature of back-ldap; see idassert-* * directives in slapd-ldap(5). + * + * FIXME: the idassert-authcDN is one, will it be fine regardless + * of the URI we obtain from the referral? */ switch ( op->o_tag ) { @@ -166,10 +238,10 @@ ldap_chain_response( Operation *op, SlapReply *rs ) struct berval rndn = op->o_req_ndn; Connection *conn = op->o_conn; + /* FIXME: can we really get a referral for binds? */ op->o_req_ndn = slap_empty_bv; - op->o_conn = NULL; - rc = lback->bi_op_bind( op, rs ); + rc = ldap_chain_op( op, rs, lback->bi_op_bind, ref ); op->o_req_ndn = rndn; op->o_conn = conn; } @@ -182,7 +254,7 @@ ldap_chain_response( Operation *op, SlapReply *rs ) char textbuf[ SLAP_TEXT_BUFLEN ]; size_t textlen = sizeof( textbuf ); - /* global overlay; create entry */ + /* global overlay: create entry */ /* NOTE: this is a hack to use the chain overlay * as global. I expect to be able to remove this * soon by using slap_mods2entry() earlier in @@ -197,7 +269,7 @@ ldap_chain_response( Operation *op, SlapReply *rs ) break; } } - rc = lback->bi_op_add( op, rs ); + rc = ldap_chain_op( op, rs, lback->bi_op_add, ref ); if ( cleanup_attrs ) { attrs_free( op->ora_e->e_attrs ); op->ora_e->e_attrs = NULL; @@ -205,32 +277,38 @@ ldap_chain_response( Operation *op, SlapReply *rs ) break; } case LDAP_REQ_DELETE: - rc = lback->bi_op_delete( op, rs ); + rc = ldap_chain_op( op, rs, lback->bi_op_delete, ref ); break; case LDAP_REQ_MODRDN: - rc = lback->bi_op_modrdn( op, rs ); + rc = ldap_chain_op( op, rs, lback->bi_op_modrdn, ref ); break; case LDAP_REQ_MODIFY: - rc = lback->bi_op_modify( op, rs ); + rc = ldap_chain_op( op, rs, lback->bi_op_modify, ref ); break; case LDAP_REQ_COMPARE: - rc = lback->bi_op_compare( op, rs ); + rc = ldap_chain_op( op, rs, lback->bi_op_compare, ref ); break; case LDAP_REQ_SEARCH: if ( rs->sr_type == REP_SEARCHREF ) { struct berval *curr = ref, odn = op->o_req_dn, ondn = op->o_req_ndn; - slap_callback sc2 = { 0 }; - int tmprc = 0; - ber_len_t refcnt = 0; - BerVarray newref = NULL; - - sc2.sc_response = ldap_chain_cb_response; - op->o_callback = &sc2; rs->sr_type = REP_SEARCH; + sc2.sc_response = ldap_chain_cb_search_response; + + li = *lip; + li.url = NULL; + op->o_bd->be_private = &li; + + /* if we parse the URI then by no means + * we can cache stuff or reuse connections, + * because in back-ldap there's no caching + * based on the URI value, which is supposed + * to be set once for all (correct?) */ + op->o_do_not_cache = 1; + /* copy the private info because we need to modify it */ for ( ; !BER_BVISNULL( &curr[0] ); curr++ ) { LDAPURLDesc *srv; @@ -238,11 +316,11 @@ ldap_chain_response( Operation *op, SlapReply *rs ) /* parse reference and use * proto://[host][:port]/ only */ - tmprc = ldap_url_parse_ext( curr[0].bv_val, &srv ); - if ( tmprc != LDAP_URL_SUCCESS ) { - /* error */ - rc = 1; - goto end_of_searchref; + rc = ldap_url_parse_ext( curr[0].bv_val, &srv ); + if ( rc != LDAP_URL_SUCCESS ) { + /* try next */ + rs->sr_err = LDAP_OTHER; + continue; } /* remove DN essentially because later on @@ -263,15 +341,15 @@ ldap_chain_response( Operation *op, SlapReply *rs ) ldap_free_urldesc( srv ); if ( li.url == NULL ) { - /* error */ - rc = 1; - goto end_of_searchref; + /* try next */ + rs->sr_err = LDAP_OTHER; + continue; } /* FIXME: should we also copy filter and scope? * according to RFC3296, no */ - tmprc = lback->bi_op_search( op, rs ); + rc = lback->bi_op_search( op, rs ); ldap_memfree( li.url ); li.url = NULL; @@ -281,76 +359,51 @@ ldap_chain_response( Operation *op, SlapReply *rs ) op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); - if ( tmprc ) { - /* error */ - rc = 1; - goto end_of_searchref; - } - - if ( rs->sr_err != LDAP_SUCCESS ) { - /* if search was not successful, - * at least return the referral! */ - /* FIXME: assumes referrals - * are always created via - * referral_rewrite() and freed via - * ber_bvarray_free( rs->sr_ref ) */ - newref = ch_realloc( newref, sizeof( struct berval ) * (refcnt + 2) ); - ber_dupbv( &newref[ refcnt ], &curr[ 0 ] ); - refcnt++; - BER_BVZERO( &newref[ refcnt ] ); + if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) { + break; } } -end_of_searchref:; op->o_req_dn = odn; op->o_req_ndn = ondn; rs->sr_type = REP_SEARCHREF; rs->sr_entry = NULL; - /* if the error was bad, it was already returned - * by back-ldap; destroy the referrals left; - * otherwise, let the frontend return them. */ - if ( newref ) { - if ( rc == 0 ) { - rc = SLAP_CB_CONTINUE; - if ( ref != default_referral ) { - ber_bvarray_free( ref ); - } - ref = newref; - - } else { - ber_bvarray_free( newref ); - } + if ( rc != LDAP_SUCCESS ) { + /* couldn't chase any of the referrals */ + rc = SLAP_CB_CONTINUE; } } else { - rc = lback->bi_op_search( op, rs ); + rc = ldap_chain_op( op, rs, lback->bi_op_search, ref ); } break; case LDAP_REQ_EXTENDED: - rc = lback->bi_extended( op, rs ); + rc = ldap_chain_op( op, rs, lback->bi_extended, ref ); /* FIXME: ldap_back_extended() by design * doesn't send result; frontend is expected * to send it... */ if ( rc != SLAPD_ABANDON ) { send_ldap_extended( op, rs ); + rc = LDAP_SUCCESS; } break; default: rc = SLAP_CB_CONTINUE; break; } + + if ( sc2.sc_private == NULL ) { + op->o_callback = NULL; + rc = rs->sr_err = slap_map_api2result( rs ); + send_ldap_result( op, rs ); + } + op->o_do_not_cache = cache; op->o_bd->be_private = private; op->o_callback = sc; op->o_ndn = ndn; - if ( authzid ) { - op->o_tmpfree( authzid, op->o_tmpmemctx ); - } rs->sr_ref = ref; - if ( lip->url == NULL && li.url != NULL ) { - ldap_memfree( li.url ); - } return rc; } @@ -388,9 +441,9 @@ ldap_chain_db_init( 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; + int rc; + BackendDB bd = *be; if ( lback == NULL ) { lback = backend_info( "ldap" ); @@ -400,10 +453,9 @@ ldap_chain_db_init( } } - be->be_private = NULL; - rc = lback->bi_db_init( be ); - on->on_bi.bi_private = be->be_private; - be->be_private = private; + bd.be_private = NULL; + rc = lback->bi_db_init( &bd ); + on->on_bi.bi_private = bd.be_private; return rc; } @@ -447,10 +499,6 @@ chain_init( void ) ldapchain.on_response = ldap_chain_response; -#if 0 - ldapchain.on_bi.bi_chk_referrals = ldap_chain_chk_referrals; -#endif - return overlay_register( &ldapchain ); } diff --git a/servers/slapd/back-ldap/compare.c b/servers/slapd/back-ldap/compare.c index ffa9f6bf77..a538e3d4b2 100644 --- a/servers/slapd/back-ldap/compare.c +++ b/servers/slapd/back-ldap/compare.c @@ -42,9 +42,8 @@ ldap_back_compare( LDAPControl **ctrls = NULL; int rc = LDAP_SUCCESS; - lc = ldap_back_getconn( op, rs ); - if (!lc || !ldap_back_dobind( lc, op, rs ) ) { - rc = -1; + lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); + if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { goto cleanup; } @@ -52,7 +51,6 @@ ldap_back_compare( rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); - rc = -1; goto cleanup; } @@ -61,10 +59,10 @@ retry: op->orc_ava->aa_desc->ad_cname.bv_val, &op->orc_ava->aa_value, ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, 1 ); - if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { + rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); + if ( rc == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; - if ( ldap_back_retry(lc, op, rs ) ) { + if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { goto retry; } } @@ -72,5 +70,5 @@ retry: cleanup: (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls ); - return rc; + return rs->sr_err; } diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index bdbdc698ce..470becaa3c 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -213,26 +213,67 @@ 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; + + /* 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 ); + } + 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 - || strcasecmp( argv[0], "binddn" ) == 0 ) { + || strcasecmp( argv[0], "binddn" ) == 0 ) + { if ( argc != 2 ) { fprintf( stderr, "%s: line %d: missing name in \"%s \" line\n", fname, lineno, argv[0] ); return( 1 ); } + + if ( strcasecmp( argv[0], "binddn" ) == 0 ) { + fprintf( stderr, "%s: line %d: " + "\"binddn\" statement is deprecated; " + "use \"acl-authcDN\" instead\n", + fname, lineno ); + /* FIXME: some day we'll need to throw an error */ + } + ber_str2bv( argv[1], 0, 1, &li->acl_authcDN ); /* password to use for ldap_back_group */ } else if ( strcasecmp( argv[0], "acl-passwd" ) == 0 - || strcasecmp( argv[0], "bindpw" ) == 0 ) { + || strcasecmp( argv[0], "bindpw" ) == 0 ) + { if ( argc != 2 ) { fprintf( stderr, "%s: line %d: missing password in \"%s \" line\n", fname, lineno, argv[0] ); return( 1 ); } + + if ( strcasecmp( argv[0], "bindpw" ) == 0 ) { + fprintf( stderr, "%s: line %d: " + "\"bindpw\" statement is deprecated; " + "use \"acl-passwd\" instead\n", + fname, lineno ); + /* FIXME: some day we'll need to throw an error */ + } + ber_str2bv( argv[1], 0, 1, &li->acl_passwd ); /* identity assertion stuff... */ @@ -252,7 +293,7 @@ ldap_back_db_config( fname, lineno ); return( 1 ); } - li->savecred = 1; + li->flags |= LDAP_BACK_F_SAVECRED; /* intercept exop_who_am_i? */ } else if ( strcasecmp( argv[0], "proxy-whoami" ) == 0 ) { @@ -340,8 +381,8 @@ ldap_back_exop_whoami( ctrls[0] = &c; op2.o_ndn = op->o_conn->c_ndn; - lc = ldap_back_getconn(&op2, rs); - if (!lc || !ldap_back_dobind( lc, op, rs )) { + lc = ldap_back_getconn(&op2, rs, LDAP_BACK_SENDERR); + if (!lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR )) { return -1; } c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; @@ -359,7 +400,7 @@ retry: &rs->sr_err); if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) { do_retry = 0; - if ( ldap_back_retry( lc, op, rs ) ) + if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) goto retry; } ldap_back_freeconn( op, lc ); diff --git a/servers/slapd/back-ldap/delete.c b/servers/slapd/back-ldap/delete.c index 4b0ce6b25c..3d6575be57 100644 --- a/servers/slapd/back-ldap/delete.c +++ b/servers/slapd/back-ldap/delete.c @@ -42,9 +42,9 @@ ldap_back_delete( int do_retry = 1; int rc = LDAP_SUCCESS; - lc = ldap_back_getconn( op, rs ); + lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); - if ( !lc || !ldap_back_dobind( lc, op, rs ) ) { + if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { rc = -1; goto cleanup; } @@ -60,10 +60,10 @@ ldap_back_delete( retry: rs->sr_err = ldap_delete_ext( lc->lc_ld, op->o_req_ndn.bv_val, ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, 1 ); + rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) { do_retry = 0; - if ( ldap_back_retry (lc, op, rs ) ) { + if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { goto retry; } } diff --git a/servers/slapd/back-ldap/extended.c b/servers/slapd/back-ldap/extended.c index d4202d4c2b..8fb7e44a53 100644 --- a/servers/slapd/back-ldap/extended.c +++ b/servers/slapd/back-ldap/extended.c @@ -56,8 +56,8 @@ ldap_back_extended( * called twice; maybe we could avoid the * ldap_back_dobind() call inside each extended() * call ... */ - lc = ldap_back_getconn( op, rs ); - if ( !lc || !ldap_back_dobind( lc, op, rs ) ) { + lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); + if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { return -1; } @@ -99,8 +99,8 @@ ldap_back_exop_passwd( int rc, isproxy; int do_retry = 1; - lc = ldap_back_getconn( op, rs ); - if ( !lc || !ldap_back_dobind( lc, op, rs ) ) { + lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); + if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { return -1; } @@ -154,7 +154,7 @@ retry: rs->sr_err = slap_map_api2result( rs ); if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; - if ( ldap_back_retry(lc, op, rs ) ) { + if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { goto retry; } } diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c index b00c579d36..84f47becbd 100644 --- a/servers/slapd/back-ldap/init.c +++ b/servers/slapd/back-ldap/init.c @@ -144,10 +144,10 @@ ldap_back_db_open( BackendDB *be ) /* FIXME: disabled because namingContexts doesn't have * a matching rule, and using an MRA filter doesn't work * because the normalized assertion is compared to the - * non-normalized value, which in general differ. - * See ITS#3406 */ + * non-normalized value, which in general differs from + * the normalized one. See ITS#3406 */ struct berval filter, - base = BER_BVC( "cn=Databases,cn=Monitor" ); + base = BER_BVC( "cn=Databases," SLAPD_MONITOR ); struct berval vals[ 2 ]; Attribute a = { 0 }; diff --git a/servers/slapd/back-ldap/modify.c b/servers/slapd/back-ldap/modify.c index cc551243a1..0936bb4e0f 100644 --- a/servers/slapd/back-ldap/modify.c +++ b/servers/slapd/back-ldap/modify.c @@ -46,8 +46,8 @@ ldap_back_modify( int do_retry = 1; LDAPControl **ctrls = NULL; - lc = ldap_back_getconn( op, rs ); - if ( !lc || !ldap_back_dobind( lc, op, rs ) ) { + lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); + if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { return -1; } @@ -106,10 +106,10 @@ ldap_back_modify( retry: rs->sr_err = ldap_modify_ext( lc->lc_ld, op->o_req_ndn.bv_val, modv, ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, 1 ); + rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; - if ( ldap_back_retry(lc, op, rs ) ) { + if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { goto retry; } } diff --git a/servers/slapd/back-ldap/modrdn.c b/servers/slapd/back-ldap/modrdn.c index 92cce0a749..22554b2430 100644 --- a/servers/slapd/back-ldap/modrdn.c +++ b/servers/slapd/back-ldap/modrdn.c @@ -43,8 +43,8 @@ ldap_back_modrdn( int rc = LDAP_SUCCESS; char *newSup = NULL; - lc = ldap_back_getconn( op, rs ); - if ( !lc || !ldap_back_dobind( lc, op, rs ) ) { + lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); + if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { return( -1 ); } @@ -67,10 +67,10 @@ retry: rs->sr_err = ldap_rename( lc->lc_ld, op->o_req_ndn.bv_val, op->orr_newrdn.bv_val, newSup, op->orr_deleteoldrdn, ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, 1 ); + rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) { do_retry = 0; - if ( ldap_back_retry( lc, op, rs ) ) { + if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { goto retry; } } diff --git a/servers/slapd/back-ldap/proto-ldap.h b/servers/slapd/back-ldap/proto-ldap.h index eadc7d3949..8c85f507f4 100644 --- a/servers/slapd/back-ldap/proto-ldap.h +++ b/servers/slapd/back-ldap/proto-ldap.h @@ -49,12 +49,12 @@ extern BI_connection_destroy ldap_back_conn_destroy; extern BI_entry_get_rw ldap_back_entry_get; int ldap_back_freeconn( Operation *op, struct ldapconn *lc ); -struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs); -int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs); -int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs); +struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs, ldap_back_send_t sendok); +int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok); +int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok); int ldap_back_map_result(SlapReply *rs); int ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs, - ber_int_t msgid, int sendok); + ber_int_t msgid, ldap_back_send_t sendok); int back_ldap_LTX_init_module(int argc, char *argv[]); extern int ldap_back_conn_cmp( const void *c1, const void *c2); diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index bf78dec637..b42352614f 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -60,17 +60,17 @@ ldap_back_search( int do_retry = 1; LDAPControl **ctrls = NULL; - lc = ldap_back_getconn( op, rs ); + lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); if ( !lc ) { - return -1; + return rs->sr_err; } /* * FIXME: in case of values return filter, we might want * to map attrs and maybe rewrite value */ - if ( !ldap_back_dobind( lc, op, rs ) ) { - return -1; + if ( !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { + return rs->sr_err; } /* should we check return values? */ @@ -120,7 +120,7 @@ retry: if ( rs->sr_err != LDAP_SUCCESS ) { fail:; - rc = ldap_back_op_result( lc, op, rs, msgid, 0 ); + rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR ); if ( freeconn ) { ldap_back_freeconn( op, lc ); lc = NULL; @@ -249,7 +249,7 @@ fail:; if ( rc == -1 ) { if ( do_retry ) { do_retry = 0; - if ( ldap_back_retry( lc, op, rs ) ) { + if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) ) { goto retry; } } @@ -500,7 +500,6 @@ ldap_back_entry_get( *e = NULL; char *gattr[3]; char *filter = NULL; - Connection *oconn; SlapReply rs; int do_retry = 1; LDAPControl **ctrls = NULL; @@ -508,16 +507,12 @@ ldap_back_entry_get( /* Tell getconn this is a privileged op */ do_not_cache = op->o_do_not_cache; op->o_do_not_cache = 1; - lc = ldap_back_getconn( op, &rs ); - oconn = op->o_conn; - op->o_conn = NULL; - if ( !lc || !ldap_back_dobind( lc, op, &rs ) ) { + lc = ldap_back_getconn( op, &rs, LDAP_BACK_DONTSEND ); + if ( !lc || !ldap_back_dobind( lc, op, &rs, LDAP_BACK_DONTSEND ) ) { op->o_do_not_cache = do_not_cache; - op->o_conn = oconn; - return 1; + return rs.sr_err; } op->o_do_not_cache = do_not_cache; - op->o_conn = oconn; if ( at ) { if ( oc && at != slap_schema.si_ad_objectClass ) { @@ -555,7 +550,7 @@ retry: if ( rc != LDAP_SUCCESS ) { if ( rc == LDAP_SERVER_DOWN && do_retry ) { do_retry = 0; - if ( ldap_back_retry( lc, op, &rs ) ) { + if ( ldap_back_retry( lc, op, &rs, LDAP_BACK_DONTSEND ) ) { goto retry; } } diff --git a/servers/slapd/back-ldbm/id2entry.c b/servers/slapd/back-ldbm/id2entry.c index b5a7ec7fef..d45fb017b0 100644 --- a/servers/slapd/back-ldbm/id2entry.c +++ b/servers/slapd/back-ldbm/id2entry.c @@ -186,7 +186,7 @@ id2entry_rw( Backend *be, ID id, int rw ) return( NULL ); } - e = str2entry( data.dptr ); + e = str2entry2( data.dptr, 0 ); ldbm_datum_free( db->dbc_db, data ); ldbm_cache_close( be, db ); diff --git a/servers/slapd/back-ldbm/tools.c b/servers/slapd/back-ldbm/tools.c index 17f4571af1..4fffb1f9d5 100644 --- a/servers/slapd/back-ldbm/tools.c +++ b/servers/slapd/back-ldbm/tools.c @@ -158,7 +158,7 @@ Entry* ldbm_tool_entry_get( BackendDB *be, ID id ) return NULL; } - e = str2entry( data.dptr ); + e = str2entry2( data.dptr, 0 ); ldbm_datum_free( id2entry->dbc_db, data ); if( e != NULL ) { diff --git a/servers/slapd/back-meta/add.c b/servers/slapd/back-meta/add.c index 6f352696e0..15f13ee892 100644 --- a/servers/slapd/back-meta/add.c +++ b/servers/slapd/back-meta/add.c @@ -54,13 +54,14 @@ meta_back_add( Operation *op, SlapReply *rs ) &op->o_req_ndn, &candidate ); if ( !lc ) { send_ldap_result( op, rs ); + return rs->sr_err; } if ( !meta_back_dobind( lc, op ) || !meta_back_is_valid( lc, candidate ) ) { rs->sr_err = LDAP_UNAVAILABLE; send_ldap_result( op, rs ); - return -1; + return rs->sr_err; } /* @@ -73,7 +74,7 @@ meta_back_add( Operation *op, SlapReply *rs ) if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) { send_ldap_result( op, rs ); - return -1; + return rs->sr_err; } /* Count number of attributes in entry */ @@ -82,18 +83,27 @@ meta_back_add( Operation *op, SlapReply *rs ) /* Create array of LDAPMods for ldap_add() */ attrs = ch_malloc( sizeof( LDAPMod * )*i ); + dc.ctx = "addAttrDN"; isupdate = be_shadow_update( op ); for ( i = 0, a = op->ora_e->e_attrs; a; a = a->a_next ) { - int j; + int j, is_oc = 0; if ( !isupdate && a->a_desc->ad_type->sat_no_user_mod ) { continue; } - ldap_back_map( &li->targets[ candidate ]->mt_rwmap.rwm_at, - &a->a_desc->ad_cname, &mapped, BACKLDAP_MAP ); - if ( mapped.bv_val == NULL || mapped.bv_val[0] == '\0' ) { - continue; + if ( a->a_desc == slap_schema.si_ad_objectClass + || a->a_desc == slap_schema.si_ad_structuralObjectClass ) + { + is_oc = 1; + mapped = a->a_desc->ad_cname; + + } else { + ldap_back_map( &li->targets[ candidate ]->mt_rwmap.rwm_at, + &a->a_desc->ad_cname, &mapped, BACKLDAP_MAP ); + if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) { + continue; + } } attrs[ i ] = ch_malloc( sizeof( LDAPMod ) ); @@ -103,31 +113,65 @@ meta_back_add( Operation *op, SlapReply *rs ) attrs[ i ]->mod_op = LDAP_MOD_BVALUES; attrs[ i ]->mod_type = mapped.bv_val; - /* - * FIXME: dn-valued attrs should be rewritten - * to allow their use in ACLs at the back-ldap - * level. - */ - if ( a->a_desc->ad_type->sat_syntax == + if ( is_oc ) { + for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) + ; + + attrs[ i ]->mod_bvalues = + (struct berval **)ch_malloc( ( j + 1 ) * + sizeof( struct berval * ) ); + + for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); ) { + struct ldapmapping *mapping; + + ldap_back_mapping( &li->targets[ candidate ]->mt_rwmap.rwm_oc, + &a->a_vals[ j ], &mapping, BACKLDAP_MAP ); + + if ( mapping == NULL ) { + if ( li->targets[ candidate ]->mt_rwmap.rwm_oc.drop_missing ) { + continue; + } + attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ]; + + } else { + attrs[ i ]->mod_bvalues[ j ] = &mapping->dst; + } + j++; + } + attrs[ i ]->mod_bvalues[ j ] = NULL; + + } else { + /* + * FIXME: dn-valued attrs should be rewritten + * to allow their use in ACLs at the back-ldap + * level. + */ + if ( a->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) - { - (void)ldap_dnattr_rewrite( &dc, a->a_vals ); - } - - for ( j = 0; a->a_vals[ j ].bv_val; j++ ); - attrs[ i ]->mod_vals.modv_bvals = ch_malloc((j+1)*sizeof(struct berval *)); - for ( j = 0; a->a_vals[ j ].bv_val; j++ ) { - attrs[ i ]->mod_vals.modv_bvals[ j ] = &a->a_vals[ j ]; + { + (void)ldap_dnattr_rewrite( &dc, a->a_vals ); + if ( a->a_vals == NULL ) { + continue; + } + } + + for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) + ; + + attrs[ i ]->mod_bvalues = ch_malloc( ( j + 1 ) * sizeof( struct berval * ) ); + for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) { + attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ]; + } + attrs[ i ]->mod_bvalues[ j ] = NULL; } - attrs[ i ]->mod_vals.modv_bvals[ j ] = NULL; i++; } attrs[ i ] = NULL; - (void)ldap_add_ext_s( lc->mc_conns[ candidate ].msc_ld, mdn.bv_val, + rs->sr_err = ldap_add_ext_s( lc->mc_conns[ candidate ].msc_ld, mdn.bv_val, attrs, NULL, NULL ); for ( --i; i >= 0; --i ) { - free( attrs[ i ]->mod_vals.modv_bvals ); + free( attrs[ i ]->mod_bvalues ); free( attrs[ i ] ); } free( attrs ); diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index cd82865fb9..3ead454bb4 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -85,15 +85,6 @@ typedef struct dncookie { #define META_BIND_NRETRIES 3 #define META_BIND_TIMEOUT 1000 -int ldap_back_freeconn( Operation *op, struct ldapconn *lc ); -struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs); -int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs); -int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs); -int ldap_back_map_result(SlapReply *rs); -int ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs, - ber_int_t msgid, int sendok); -int back_ldap_LTX_init_module(int argc, char *argv[]); - int ldap_back_dn_massage(dncookie *dc, struct berval *dn, struct berval *res); @@ -106,6 +97,8 @@ int mapping_cmp (const void *, const void *); int mapping_dup (void *, void *); void ldap_back_map_init ( struct ldapmap *lm, struct ldapmapping ** ); +int ldap_back_mapping ( struct ldapmap *map, struct berval *s, + struct ldapmapping **m, int remap ); void ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *m, int remap ); #define BACKLDAP_MAP 0 diff --git a/servers/slapd/back-meta/config.c b/servers/slapd/back-meta/config.c index 1459cef1a6..9682b2d7af 100644 --- a/servers/slapd/back-meta/config.c +++ b/servers/slapd/back-meta/config.c @@ -302,7 +302,9 @@ meta_back_db_config( li->network_timeout = atol(argv[ 1 ]); /* name to use for meta_back_group */ - } else if ( strcasecmp( argv[ 0 ], "binddn" ) == 0 ) { + } else if ( strcasecmp( argv[ 0 ], "acl-authcDN" ) == 0 + || strcasecmp( argv[ 0 ], "binddn" ) == 0 ) + { int i = li->ntargets-1; struct berval dn; @@ -320,6 +322,14 @@ meta_back_db_config( return 1; } + if ( strcasecmp( argv[ 0 ], "binddn" ) == 0 ) { + fprintf( stderr, "%s: line %d: " + "\"binddn\" statement is deprecated; " + "use \"acl-authcDN\" instead\n", + fname, lineno ); + /* FIXME: some day we'll need to throw an error */ + } + dn.bv_val = argv[ 1 ]; dn.bv_len = strlen( argv[ 1 ] ); if ( dnNormalize( 0, NULL, NULL, &dn, &li->targets[ i ]->mt_binddn, @@ -332,7 +342,9 @@ meta_back_db_config( } /* password to use for meta_back_group */ - } else if ( strcasecmp( argv[ 0 ], "bindpw" ) == 0 ) { + } else if ( strcasecmp( argv[ 0 ], "acl-passwd" ) == 0 + || strcasecmp( argv[ 0 ], "bindpw" ) == 0 ) + { int i = li->ntargets-1; if ( i < 0 ) { @@ -348,6 +360,15 @@ meta_back_db_config( fname, lineno ); return 1; } + + if ( strcasecmp( argv[ 0 ], "bindpw" ) == 0 ) { + fprintf( stderr, "%s: line %d: " + "\"bindpw\" statement is deprecated; " + "use \"acl-passwd\" instead\n", + fname, lineno ); + /* FIXME: some day we'll need to throw an error */ + } + ber_str2bv( argv[ 1 ], 0L, 1, &li->targets[ i ]->mt_bindpw ); /* save bind creds for referral rebinds? */ diff --git a/servers/slapd/back-meta/map.c b/servers/slapd/back-meta/map.c index a607369b7e..5021fc5c59 100644 --- a/servers/slapd/back-meta/map.c +++ b/servers/slapd/back-meta/map.c @@ -109,12 +109,14 @@ ldap_back_map_init ( struct ldapmap *lm, struct ldapmapping **m ) *m = mapping; } -void -ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv, +int +ldap_back_mapping ( struct ldapmap *map, struct berval *s, struct ldapmapping **m, int remap ) { Avlnode *tree; - struct ldapmapping *mapping, fmapping; + struct ldapmapping fmapping; + + assert( m ); if ( remap == BACKLDAP_REMAP ) { tree = map->remap; @@ -122,9 +124,23 @@ ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv, tree = map->map; } - BER_BVZERO( bv ); fmapping.src = *s; - mapping = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp ); + *m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp ); + if ( *m == NULL ) { + return map->drop_missing; + } + + return 0; +} + +void +ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv, + int remap ) +{ + struct ldapmapping *mapping; + + BER_BVZERO( bv ); + ( void )ldap_back_mapping( map, s, &mapping, remap ); if ( mapping != NULL ) { if ( !BER_BVISNULL( &mapping->dst ) ) { *bv = mapping->dst; @@ -135,8 +151,6 @@ ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv, if ( !map->drop_missing ) { *bv = *s; } - - return; } int diff --git a/servers/slapd/back-meta/modify.c b/servers/slapd/back-meta/modify.c index 77e92da145..40709354a4 100644 --- a/servers/slapd/back-meta/modify.c +++ b/servers/slapd/back-meta/modify.c @@ -134,15 +134,22 @@ meta_back_modify( Operation *op, SlapReply *rs ) mods[ i ].mod_bvalues = (struct berval **)ch_malloc( ( j + 1 ) * sizeof( struct berval * ) ); - for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) { - ldap_back_map( &li->targets[ candidate ]->mt_rwmap.rwm_oc, - &ml->sml_values[ j ], - &mapped, BACKLDAP_MAP ); - if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) - { - continue; + for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); ) { + struct ldapmapping *mapping; + + ldap_back_mapping( &li->targets[ candidate ]->mt_rwmap.rwm_oc, + &ml->sml_values[ j ], &mapping, BACKLDAP_MAP ); + + if ( mapping == NULL ) { + if ( li->targets[ candidate ]->mt_rwmap.rwm_oc.drop_missing ) { + continue; + } + mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ]; + + } else { + mods[ i ].mod_bvalues[ j ] = &mapping->dst; } - mods[ i ].mod_bvalues[ j ] = &mapped; + j++; } mods[ i ].mod_bvalues[ j ] = NULL; diff --git a/servers/slapd/back-null/null.c b/servers/slapd/back-null/null.c index 5093d23edf..76b448dd12 100644 --- a/servers/slapd/back-null/null.c +++ b/servers/slapd/back-null/null.c @@ -14,7 +14,7 @@ * . */ /* ACKNOWLEDGEMENTS: - * This work was originally developed by Howard Chu for inclusion + * This work was originally developed by Hallvard Furuseth for inclusion * in OpenLDAP Software. */ diff --git a/servers/slapd/back-sql/back-sql.h b/servers/slapd/back-sql/back-sql.h index 8079471686..49af9ed694 100644 --- a/servers/slapd/back-sql/back-sql.h +++ b/servers/slapd/back-sql/back-sql.h @@ -245,8 +245,9 @@ typedef struct { * in quotes. This is especially true for those that do not * allow keywords used as aliases. */ -/* #define BACKSQL_ALIASING_QUOTE '"' */ -/* #define BACKSQL_ALIASING_QUOTE '\'' */ +#define BACKSQL_ALIASING_QUOTE "" +/* #define BACKSQL_ALIASING_QUOTE "\"" */ +/* #define BACKSQL_ALIASING_QUOTE "'" */ /* * API diff --git a/servers/slapd/back-sql/init.c b/servers/slapd/back-sql/init.c index 678d106d41..69c72e85c7 100644 --- a/servers/slapd/back-sql/init.c +++ b/servers/slapd/back-sql/init.c @@ -456,8 +456,9 @@ backsql_db_open( bb.bb_val.bv_len = 0; bb.bb_len = 0; backsql_strfcat( &bb, "sb", - "SELECT COUNT(distinct subordinates.id) FROM ldap_entries,ldap_entries subordinates WHERE subordinates.parent=ldap_entries.id AND ", - + "SELECT COUNT(distinct subordinates.id) " + "FROM ldap_entries,ldap_entries " BACKSQL_ALIASING "subordinates " + "WHERE subordinates.parent=ldap_entries.id AND ", &bi->sql_children_cond ); bi->sql_has_children_query = bb.bb_val.bv_val; diff --git a/servers/slapd/back-sql/schema-map.c b/servers/slapd/back-sql/schema-map.c index 7d7be83a8f..9ce43498d3 100644 --- a/servers/slapd/back-sql/schema-map.c +++ b/servers/slapd/back-sql/schema-map.c @@ -105,35 +105,20 @@ backsql_make_attr_query( { struct berbuf bb = BB_NULL; -#ifdef BACKSQL_ALIASING_QUOTE - backsql_strfcat( &bb, "lblcbclblbcbl", - (ber_len_t)STRLENOF( "SELECT " ), "SELECT ", - &at_map->bam_sel_expr, - (ber_len_t)STRLENOF( " " BACKSQL_ALIASING ), " " BACKSQL_ALIASING, - BACKSQL_ALIASING_QUOTE, - &at_map->bam_ad->ad_cname, - BACKSQL_ALIASING_QUOTE, - (ber_len_t)STRLENOF( " FROM " ), " FROM ", - &at_map->bam_from_tbls, - (ber_len_t)STRLENOF( " WHERE " ), " WHERE ", - &oc_map->bom_keytbl, - '.', - &oc_map->bom_keycol, - (ber_len_t)STRLENOF( "=?" ), "=?" ); -#else /* ! BACKSQL_ALIASING_QUOTE */ backsql_strfcat( &bb, "lblblblbcbl", (ber_len_t)STRLENOF( "SELECT " ), "SELECT ", &at_map->bam_sel_expr, - (ber_len_t)STRLENOF( " " BACKSQL_ALIASING ), " " BACKSQL_ALIASING, + (ber_len_t)STRLENOF( " " BACKSQL_ALIASING BACKSQL_ALIASING_QUOTE ), + " " BACKSQL_ALIASING BACKSQL_ALIASING_QUOTE, &at_map->bam_ad->ad_cname, - (ber_len_t)STRLENOF( " FROM " ), " FROM ", + (ber_len_t)STRLENOF( BACKSQL_ALIASING_QUOTE " FROM " ), + BACKSQL_ALIASING_QUOTE " FROM ", &at_map->bam_from_tbls, (ber_len_t)STRLENOF( " WHERE " ), " WHERE ", &oc_map->bom_keytbl, '.', &oc_map->bom_keycol, (ber_len_t)STRLENOF( "=?" ), "=?" ); -#endif /* ! BACKSQL_ALIASING_QUOTE */ if ( !BER_BVISNULL( &at_map->bam_join_where ) ) { backsql_strfcat( &bb, "lb", @@ -141,17 +126,12 @@ backsql_make_attr_query( &at_map->bam_join_where ); } -#ifdef BACKSQL_ALIASING_QUOTE - backsql_strfcat( &bb, "lcbc", - (ber_len_t)STRLENOF( " ORDER BY " ), " ORDER BY ", - BACKSQL_ALIASING_QUOTE, + backsql_strfcat( &bb, "lbl", + (ber_len_t)STRLENOF( " ORDER BY " BACKSQL_ALIASING_QUOTE ), + " ORDER BY " BACKSQL_ALIASING_QUOTE, &at_map->bam_sel_expr, - BACKSQL_ALIASING_QUOTE ); -#else /* ! BACKSQL_ALIASING_QUOTE */ - backsql_strfcat( &bb, "lb", - (ber_len_t)STRLENOF( " ORDER BY " ), " ORDER BY ", - &at_map->bam_sel_expr ); -#endif /* ! BACKSQL_ALIASING_QUOTE */ + (ber_len_t)STRLENOF( BACKSQL_ALIASING_QUOTE ), + BACKSQL_ALIASING_QUOTE ); at_map->bam_query = bb.bb_val.bv_val; diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c index e99842c67f..0381f6974f 100644 --- a/servers/slapd/back-sql/search.c +++ b/servers/slapd/back-sql/search.c @@ -1289,21 +1289,13 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) &bsi->bsi_oc->bom_oc->soc_cname, '\'' ); } -#ifdef BACKSQL_ALIASING_QUOTE - backsql_strfcat( &bsi->bsi_sel, "lclcl", - (ber_len_t)STRLENOF( " " BACKSQL_ALIASING ), - " " BACKSQL_ALIASING, - BACKSQL_ALIASING_QUOTE, - (ber_len_t)STRLENOF( "objectClass" ), - "objectClass", - BACKSQL_ALIASING_QUOTE, - (ber_len_t)STRLENOF( ",ldap_entries.dn " BACKSQL_ALIASING "dn" ), - ",ldap_entries.dn " BACKSQL_ALIASING "dn" ); -#else /* ! BACKSQL_ALIASING_QUOTE */ backsql_strfcat( &bsi->bsi_sel, "l", - (ber_len_t)STRLENOF( " " BACKSQL_ALIASING "objectClass,ldap_entries.dn " BACKSQL_ALIASING "dn" ), - " " BACKSQL_ALIASING "objectClass,ldap_entries.dn " BACKSQL_ALIASING "dn" ); -#endif /* ! BACKSQL_ALIASING_QUOTE */ + (ber_len_t)STRLENOF( " " BACKSQL_ALIASING + BACKSQL_ALIASING_QUOTE "objectClass" BACKSQL_ALIASING_QUOTE + ",ldap_entries.dn " BACKSQL_ALIASING BACKSQL_ALIASING_QUOTE "dn" BACKSQL_ALIASING_QUOTE ), + " " BACKSQL_ALIASING + BACKSQL_ALIASING_QUOTE "objectClass" BACKSQL_ALIASING_QUOTE + ",ldap_entries.dn " BACKSQL_ALIASING BACKSQL_ALIASING_QUOTE "dn" BACKSQL_ALIASING_QUOTE ); backsql_strfcat( &bsi->bsi_from, "lb", (ber_len_t)STRLENOF( " FROM ldap_entries," ), diff --git a/servers/slapd/back-sql/sql-wrap.c b/servers/slapd/back-sql/sql-wrap.c index 13d715395f..61beb4f14a 100644 --- a/servers/slapd/back-sql/sql-wrap.c +++ b/servers/slapd/back-sql/sql-wrap.c @@ -126,7 +126,7 @@ backsql_Prepare( SQLHDBC dbh, SQLHSTMT *sth, char *query, int timeout ) 0, 0, 0 ); #endif /* BACKSQL_TRACE */ - return SQLPrepare( *sth, query, SQL_NTS ); + return SQLPrepare( *sth, (SQLCHAR *)query, SQL_NTS ); } RETCODE @@ -174,7 +174,7 @@ backsql_BindRowAsStrings( SQLHSTMT sth, BACKSQL_ROW_NTS *row ) (SQLUINTEGER)( sizeof( colname ) - 1 ), &name_len, &col_type, &col_prec, &col_scale, &col_null ); - ber_str2bv( colname, 0, 1, &row->col_names[ i - 1 ] ); + ber_str2bv( (char *)colname, 0, 1, &row->col_names[ i - 1 ] ); #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: " "col_name=%s, col_prec[%d]=%d\n", diff --git a/servers/slapd/back-sql/util.c b/servers/slapd/back-sql/util.c index 641abc7eb1..ab4042e926 100644 --- a/servers/slapd/back-sql/util.c +++ b/servers/slapd/back-sql/util.c @@ -312,12 +312,7 @@ backsql_get_table_spec( char **p ) } /* oracle doesn't understand "AS" :( and other RDBMSes don't need it */ -#ifdef BACKSQL_ALIASING_QUOTE - backsql_strfcat( &res, "scsc", " " BACKSQL_ALIASING, - BACKSQL_ALIASING_QUOTE, s, BACKSQL_ALIASING_QUOTE ); -#else /* ! BACKSQL_ALIASING */ - backsql_strcat( &res, " " BACKSQL_ALIASING, s, NULL ); -#endif /* ! BACKSQL_ALIASING */ + backsql_strcat( &res, " " BACKSQL_ALIASING BACKSQL_ALIASING_QUOTE, s, BACKSQL_ALIASING_QUOTE, NULL ); return res.bb_val.bv_val; } diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 9e63b862d1..105dffe4f9 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -1439,7 +1439,8 @@ backend_attribute( rc = backend_operational( op, &rs ); - if ( rc == LDAP_SUCCESS ) { + if ( rc == LDAP_SUCCESS && rs.sr_operational_attrs ) { + freeattr = 1; a = rs.sr_operational_attrs; } } diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c index cbc6abd83e..c39caea9f6 100644 --- a/servers/slapd/bind.c +++ b/servers/slapd/bind.c @@ -464,7 +464,9 @@ fe_op_bind( Operation *op, SlapReply *rs ) /* don't return referral for bind requests */ /* noSuchObject is not allowed to be returned by bind */ rs->sr_err = LDAP_INVALID_CREDENTIALS; + op->o_bd = frontendDB; send_ldap_result( op, rs ); + op->o_bd = NULL; goto cleanup; } diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c index ed575fd1e8..d6596c2487 100644 --- a/servers/slapd/compare.c +++ b/servers/slapd/compare.c @@ -208,7 +208,9 @@ fe_op_compare( Operation *op, SlapReply *rs ) rs->sr_err = LDAP_REFERRAL; if (!rs->sr_ref) rs->sr_ref = default_referral; + op->o_bd = frontendDB; send_ldap_result( op, rs ); + op->o_bd = NULL; if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref ); rs->sr_err = 0; diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index 1712234757..147400ee84 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -1714,10 +1714,12 @@ slapd_daemon_task( case 0: /* timeout - let threads run */ ebadf = 0; +#ifndef HAVE_YIELDING_SELECT Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n", 0, 0, 0 ); ldap_pvt_thread_yield(); +#endif continue; default: /* something happened - deal with it */ @@ -1770,7 +1772,9 @@ slapd_daemon_task( /* bypass the following tests if no descriptors left */ if ( ns <= 0 ) { +#ifndef HAVE_YIELDING_SELECT ldap_pvt_thread_yield(); +#endif continue; } @@ -1966,7 +1970,9 @@ slapd_daemon_task( } #endif /* SLAP_EVENTS_ARE_INDEXED */ +#ifndef HAVE_YIELDING_SELECT ldap_pvt_thread_yield(); +#endif } if( slapd_shutdown == 1 ) { diff --git a/servers/slapd/delete.c b/servers/slapd/delete.c index a1004f7967..6762093c4a 100644 --- a/servers/slapd/delete.c +++ b/servers/slapd/delete.c @@ -124,12 +124,16 @@ fe_op_delete( Operation *op, SlapReply *rs ) if ( rs->sr_ref != NULL ) { rs->sr_err = LDAP_REFERRAL; + op->o_bd = frontendDB; send_ldap_result( op, rs ); + op->o_bd = NULL; if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref ); } else { + op->o_bd = frontendDB; send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "no global superior knowledge" ); + op->o_bd = NULL; } goto cleanup; } diff --git a/servers/slapd/entry.c b/servers/slapd/entry.c index 11dfa83022..bd0274fb39 100644 --- a/servers/slapd/entry.c +++ b/servers/slapd/entry.c @@ -61,17 +61,24 @@ int entry_destroy(void) Entry * str2entry( char *s ) +{ + return str2entry2( s, 1 ); +} + +Entry * +str2entry2( char *s, int checkvals ) { int rc; Entry *e; - struct berval type; - struct berval vals[2]; - struct berval nvals[2], *nvalsp; + struct berval *nvalsp; + struct berval *type, *vals, *nvals; + char *freeval; AttributeDescription *ad, *ad_prev; const char *text; char *next; int attr_cnt; - int freeval; + int i, lines; + Attribute ahead, *atail; /* * LDIF is used as the string format. @@ -105,75 +112,154 @@ str2entry( char *s ) e->e_id = NOID; /* dn + attributes */ - vals[1].bv_len = 0; - vals[1].bv_val = NULL; - + atail = &ahead; + ahead.a_next = NULL; ad = NULL; ad_prev = NULL; attr_cnt = 0; next = s; + + lines = ldif_countlines( s ); + type = ch_calloc( 1, (lines+1)*3*sizeof(struct berval)+lines ); + vals = type+lines+1; + nvals = vals+lines+1; + freeval = (char *)(nvals+lines+1); + i = -1; + + /* parse into individual values, record DN */ while ( (s = ldif_getline( &next )) != NULL ) { + int freev; if ( *s == '\n' || *s == '\0' ) { break; } + i++; - if ( ldif_parse_line2( s, &type, vals, &freeval ) != 0 ) { + rc = ldif_parse_line2( s, type+i, vals+i, &freev ); + freeval[i] = freev; + if ( rc ) { Debug( LDAP_DEBUG_TRACE, "<= str2entry NULL (parse_line)\n", 0, 0, 0 ); continue; } - if ( type.bv_len == dn_bv.bv_len && - strcasecmp( type.bv_val, dn_bv.bv_val ) == 0 ) { + if ( type[i].bv_len == dn_bv.bv_len && + strcasecmp( type[i].bv_val, dn_bv.bv_val ) == 0 ) { if ( e->e_dn != NULL ) { Debug( LDAP_DEBUG_ANY, "str2entry: " "entry %ld has multiple DNs \"%s\" and \"%s\"\n", - (long) e->e_id, e->e_dn, vals[0].bv_val ); - if ( freeval ) free( vals[0].bv_val ); - entry_free( e ); - return NULL; + (long) e->e_id, e->e_dn, vals[i].bv_val ); + goto fail; } - rc = dnPrettyNormal( NULL, &vals[0], &e->e_name, &e->e_nname, NULL ); - if ( freeval ) free( vals[0].bv_val ); + rc = dnPrettyNormal( NULL, &vals[i], &e->e_name, &e->e_nname, NULL ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "str2entry: " "entry %ld has invalid DN \"%s\"\n", - (long) e->e_id, vals[0].bv_val, 0 ); - entry_free( e ); - return NULL; + (long) e->e_id, vals[i].bv_val, 0 ); + goto fail; } + if ( freeval[i] ) free( vals[i].bv_val ); + vals[i].bv_val = NULL; + i--; continue; } + } + lines = i+1; - ad_prev = ad; - ad = NULL; - rc = slap_bv2ad( &type, &ad, &text ); + /* check to make sure there was a dn: line */ + if ( BER_BVISNULL( &e->e_name )) { + Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n", + (long) e->e_id, 0, 0 ); + goto fail; + } - if( rc != LDAP_SUCCESS ) { - Debug( slapMode & SLAP_TOOL_MODE - ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE, - "<= str2entry: str2ad(%s): %s\n", type.bv_val, text, 0 ); - if( slapMode & SLAP_TOOL_MODE ) { - entry_free( e ); - if ( freeval ) free( vals[0].bv_val ); - return NULL; + /* Make sure all attributes with multiple values are contiguous */ + if ( checkvals ) { + int j, k; + struct berval bv; + int fv; + + for (i=0; ik; l-- ) { + type[l] = type[l-1]; + vals[l] = vals[l-1]; + freeval[l] = freeval[l-1]; + } + type[l] = type[i]; + vals[l] = bv; + freeval[l] = fv; + } + i = k = j; + } } + } + } + + for ( i=0; i<=lines; i++ ) { + ad_prev = ad; + if ( !ad || ( iad_cname ))) { + ad = NULL; + rc = slap_bv2ad( type+i, &ad, &text ); - rc = slap_bv2undef_ad( &type, &ad, &text ); if( rc != LDAP_SUCCESS ) { - Debug( LDAP_DEBUG_ANY, - "<= str2entry: str2undef_ad(%s): %s\n", - type.bv_val, text, 0 ); - entry_free( e ); - if ( freeval ) free( vals[0].bv_val ); - return NULL; + Debug( slapMode & SLAP_TOOL_MODE + ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE, + "<= str2entry: str2ad(%s): %s\n", type[i].bv_val, text, 0 ); + if( slapMode & SLAP_TOOL_MODE ) { + goto fail; + } + + rc = slap_bv2undef_ad( type+i, &ad, &text ); + if( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, + "<= str2entry: str2undef_ad(%s): %s\n", + type[i].bv_val, text, 0 ); + goto fail; + } } } - if ( ad != ad_prev ) { + if (( ad_prev && ad != ad_prev ) || ( i == lines )) { + int j, k; + atail->a_next = (Attribute *) ch_malloc( sizeof(Attribute) ); + atail = atail->a_next; + atail->a_desc = ad_prev; + atail->a_vals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); + if( ad_prev->ad_type->sat_equality && + ad_prev->ad_type->sat_equality->smr_normalize ) + atail->a_nvals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); + else + atail->a_nvals = NULL; + k = i - attr_cnt; + for ( j=0; ja_vals[j] = vals[k]; + else + ber_dupbv( atail->a_vals+j, &vals[k] ); + vals[k].bv_val = NULL; + if ( atail->a_nvals ) { + atail->a_nvals[j] = nvals[k]; + nvals[k].bv_val = NULL; + } + k++; + } + BER_BVZERO( &atail->a_vals[j] ); + if ( atail->a_nvals ) { + BER_BVZERO( &atail->a_nvals[j] ); + } else { + atail->a_nvals = atail->a_vals; + } attr_cnt = 0; + if ( i == lines ) break; } if( slapMode & SLAP_TOOL_MODE ) { @@ -185,13 +271,13 @@ str2entry( char *s ) if( pretty ) { rc = pretty( ad->ad_type->sat_syntax, - &vals[0], &pval, NULL ); + &vals[i], &pval, NULL ); } else if( validate ) { /* * validate value per syntax */ - rc = validate( ad->ad_type->sat_syntax, &vals[0] ); + rc = validate( ad->ad_type->sat_syntax, &vals[i] ); } else { Debug( LDAP_DEBUG_ANY, @@ -199,9 +285,7 @@ str2entry( char *s ) "no validator for syntax %s\n", ad->ad_cname.bv_val, attr_cnt, ad->ad_type->sat_syntax->ssyn_oid ); - entry_free( e ); - if ( freeval ) free( vals[0].bv_val ); - return NULL; + goto fail; } if( rc != 0 ) { @@ -210,21 +294,16 @@ str2entry( char *s ) "for attributeType %s #%d (syntax %s)\n", ad->ad_cname.bv_val, attr_cnt, ad->ad_type->sat_syntax->ssyn_oid ); - entry_free( e ); - if ( freeval ) free( vals[0].bv_val ); - return NULL; + goto fail; } if( pretty ) { - if ( freeval ) free( vals[0].bv_val ); - vals[0] = pval; - freeval = 1; + if ( freeval[i] ) free( vals[i].bv_val ); + vals[i] = pval; + freeval[i] = 1; } } - nvalsp = NULL; - nvals[0].bv_val = NULL; - if( ad->ad_type->sat_equality && ad->ad_type->sat_equality->smr_normalize ) { @@ -232,49 +311,34 @@ str2entry( char *s ) SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, ad->ad_type->sat_syntax, ad->ad_type->sat_equality, - &vals[0], &nvals[0], NULL ); + &vals[i], &nvals[i], NULL ); if( rc ) { Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (smr_normalize %d)\n", rc, 0, 0 ); - - entry_free( e ); - if ( freeval ) free( vals[0].bv_val ); - return NULL; + goto fail; } - - nvals[1].bv_len = 0; - nvals[1].bv_val = NULL; - - nvalsp = &nvals[0]; } - rc = attr_merge( e, ad, vals, nvalsp ); - if( rc != 0 ) { - Debug( LDAP_DEBUG_ANY, - "<= str2entry NULL (attr_merge)\n", 0, 0, 0 ); - entry_free( e ); - if ( freeval ) free( vals[0].bv_val ); - return( NULL ); - } - - if ( freeval ) free( vals[0].bv_val ); - free( nvals[0].bv_val ); - attr_cnt++; } - /* check to make sure there was a dn: line */ - if ( e->e_dn == NULL ) { - Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n", - (long) e->e_id, 0, 0 ); - entry_free( e ); - return NULL; - } + free( type ); + atail->a_next = NULL; + e->e_attrs = ahead.a_next; Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> 0x%lx\n", e->e_dn, (unsigned long) e, 0 ); return( e ); + +fail: + for ( i=0; ima_dnattrs ) { + if ( mra->ma_dnattrs && !BER_BVISEMPTY( &e->e_nname ) ) { LDAPDN dn = NULL; int iRDN, iAVA; int rc; diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index 88a120bd74..ea961ef57f 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -316,12 +316,16 @@ fe_op_modify( Operation *op, SlapReply *rs ) if (rs->sr_ref != NULL ) { rs->sr_err = LDAP_REFERRAL; + op->o_bd = frontendDB; send_ldap_result( op, rs ); + op->o_bd = NULL; if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref ); } else { + op->o_bd = frontendDB; send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "no global superior knowledge" ); + op->o_bd = NULL; } goto cleanup; } diff --git a/servers/slapd/modrdn.c b/servers/slapd/modrdn.c index 44f97d059e..c9e6c02dac 100644 --- a/servers/slapd/modrdn.c +++ b/servers/slapd/modrdn.c @@ -238,12 +238,16 @@ fe_op_modrdn( Operation *op, SlapReply *rs ) if ( rs->sr_ref != NULL ) { rs->sr_err = LDAP_REFERRAL; + op->o_bd = frontendDB; send_ldap_result( op, rs ); + op->o_bd = NULL; if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref ); } else { + op->o_bd = frontendDB; send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "no global superior knowledge" ); + op->o_bd = NULL; } goto cleanup; } diff --git a/servers/slapd/oc.c b/servers/slapd/oc.c index b7ac0ba4e0..4afb1e1751 100644 --- a/servers/slapd/oc.c +++ b/servers/slapd/oc.c @@ -119,6 +119,7 @@ struct oindexrec { }; static Avlnode *oc_index = NULL; +static Avlnode *oc_cache = NULL; static LDAP_SLIST_HEAD(OCList, slap_object_class) oc_list = LDAP_SLIST_HEAD_INITIALIZER(&oc_list); @@ -161,9 +162,17 @@ oc_bvfind( struct berval *ocname ) { struct oindexrec *oir; + if ( oc_cache ) { + oir = avl_find( oc_cache, ocname, oc_index_name_cmp ); + if ( oir ) return oir->oir_oc; + } oir = avl_find( oc_index, ocname, oc_index_name_cmp ); if ( oir != NULL ) { + if ( at_oc_cache ) { + avl_insert( &oc_cache, (caddr_t) oir, + oc_index_cmp, avl_dup_error ); + } return( oir->oir_oc ); } diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c index f627cd9ad4..d9ca042554 100644 --- a/servers/slapd/overlays/rwm.c +++ b/servers/slapd/overlays/rwm.c @@ -121,55 +121,97 @@ rwm_op_add( Operation *op, SlapReply *rs ) /* Count number of attributes in entry */ isupdate = be_shadow_update( op ); for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) { - struct berval mapped; Attribute *a; - if ( !isupdate && (*ap)->a_desc->ad_type->sat_no_user_mod ) { + if ( (*ap)->a_desc == slap_schema.si_ad_objectClass || + (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass ) + { + int j, last; + + for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[ last ] ); last++ ) + /* count values */ ; + last--; + for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) { + struct ldapmapping *mapping = NULL; + + ( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ], + &mapping, RWM_MAP ); + if ( mapping == NULL ) { + if ( rwmap->rwm_at.drop_missing ) { + /* FIXME: we allow to remove objectClasses as well; + * if the resulting entry is inconsistent, that's + * the relayed database's business... + */ + ch_free( (*ap)->a_vals[ j ].bv_val ); + if ( last > j ) { + (*ap)->a_vals[ j ] = (*ap)->a_vals[ last ]; + } + BER_BVZERO( &(*ap)->a_vals[ last ] ); + last--; + j--; + } + + } else { + ch_free( (*ap)->a_vals[ j ].bv_val ); + ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst ); + } + } + + } else if ( !isupdate && (*ap)->a_desc->ad_type->sat_no_user_mod ) { goto next_attr; - } - rwm_map( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname, - &mapped, RWM_MAP ); - if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) { - goto cleanup_attr; - } + } else { + struct ldapmapping *mapping = NULL; - if ( (*ap)->a_desc->ad_type->sat_syntax - == slap_schema.si_syn_distinguishedName ) - { - /* - * FIXME: rewrite could fail; in this case - * the operation should give up, right? - */ + ( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname, + &mapping, RWM_MAP ); + if ( mapping == NULL ) { + if ( rwmap->rwm_at.drop_missing ) { + goto cleanup_attr; + } + } + + if ( (*ap)->a_desc->ad_type->sat_syntax + == slap_schema.si_syn_distinguishedName ) + { + /* + * FIXME: rewrite could fail; in this case + * the operation should give up, right? + */ #ifdef ENABLE_REWRITE - rc = rwm_dnattr_rewrite( op, rs, "addAttrDN", - (*ap)->a_vals, - (*ap)->a_nvals ? &(*ap)->a_nvals : NULL ); + rc = rwm_dnattr_rewrite( op, rs, "addAttrDN", + (*ap)->a_vals, + (*ap)->a_nvals ? &(*ap)->a_nvals : NULL ); #else /* ! ENABLE_REWRITE */ - rc = 1; - rc = rwm_dnattr_rewrite( op, rs, &rc, (*ap)->a_vals, - (*ap)->a_nvals ? &(*ap)->a_nvals : NULL ); + rc = 1; + rc = rwm_dnattr_rewrite( op, rs, &rc, (*ap)->a_vals, + (*ap)->a_nvals ? &(*ap)->a_nvals : NULL ); #endif /* ! ENABLE_REWRITE */ - if ( rc ) { - goto cleanup_attr; - } + if ( rc ) { + goto cleanup_attr; + } - } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) { + } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) { #ifdef ENABLE_REWRITE - rc = rwm_referral_rewrite( op, rs, "referralAttrDN", - (*ap)->a_vals, - (*ap)->a_nvals ? &(*ap)->a_nvals : NULL ); + rc = rwm_referral_rewrite( op, rs, "referralAttrDN", + (*ap)->a_vals, + (*ap)->a_nvals ? &(*ap)->a_nvals : NULL ); #else /* ! ENABLE_REWRITE */ - rc = 1; - rc = rwm_referral_rewrite( op, rs, &rc, (*ap)->a_vals, - (*ap)->a_nvals ? &(*ap)->a_nvals : NULL ); + rc = 1; + rc = rwm_referral_rewrite( op, rs, &rc, (*ap)->a_vals, + (*ap)->a_nvals ? &(*ap)->a_nvals : NULL ); #endif /* ! ENABLE_REWRITE */ - if ( rc != LDAP_SUCCESS ) { - goto cleanup_attr; + if ( rc != LDAP_SUCCESS ) { + goto cleanup_attr; + } + } + + if ( mapping != NULL ) { + assert( mapping->m_dst_ad ); + (*ap)->a_desc = mapping->m_dst_ad; } } - next_attr:; ap = &(*ap)->a_next; continue; @@ -281,6 +323,7 @@ rwm_op_compare( Operation *op, SlapReply *rs ) } } else { + assert( mapping->m_dst_ad ); ad = mapping->m_dst_ad; } @@ -360,65 +403,61 @@ rwm_op_modify( Operation *op, SlapReply *rs ) isupdate = be_shadow_update( op ); for ( mlp = &op->oq_modify.rs_modlist; *mlp; ) { - int is_oc = 0; - Modifications *ml; - - if ( !isupdate && (*mlp)->sml_desc->ad_type->sat_no_user_mod ) { - goto next_mod; - } + int is_oc = 0; + Modifications *ml; + struct ldapmapping *mapping = NULL; if ( (*mlp)->sml_desc == slap_schema.si_ad_objectClass - || (*mlp)->sml_desc == slap_schema.si_ad_structuralObjectClass ) { + || (*mlp)->sml_desc == slap_schema.si_ad_structuralObjectClass ) + { is_oc = 1; + } else if ( !isupdate && (*mlp)->sml_desc->ad_type->sat_no_user_mod ) { + goto next_mod; + } else { - struct ldapmapping *m; int drop_missing; - drop_missing = rwm_mapping( &rwmap->rwm_at, &(*mlp)->sml_desc->ad_cname, &m, RWM_MAP ); - if ( drop_missing || ( m != NULL && BER_BVISNULL( &m->m_dst ) ) ) + drop_missing = rwm_mapping( &rwmap->rwm_at, + &(*mlp)->sml_desc->ad_cname, + &mapping, RWM_MAP ); + if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) ) { goto cleanup_mod; } - - if ( m ) { - /* use new attribute description */ - assert( m->m_dst_ad ); - (*mlp)->sml_desc = m->m_dst_ad; - } } if ( (*mlp)->sml_values != NULL ) { if ( is_oc ) { int last, j; - for ( last = 0; !BER_BVISNULL( &(*mlp)->sml_values[last] ); last++ ) + for ( last = 0; !BER_BVISNULL( &(*mlp)->sml_values[ last ] ); last++ ) /* count values */ ; last--; - for ( j = 0; !BER_BVISNULL( &(*mlp)->sml_values[j] ); j++ ) { - struct berval mapped = BER_BVNULL; - - rwm_map( &rwmap->rwm_oc, - &(*mlp)->sml_values[j], - &mapped, RWM_MAP ); - if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) { - /* FIXME: we allow to remove objectClasses as well; - * if the resulting entry is inconsistent, that's - * the relayed database's business... - */ -#if 0 - goto cleanup_mod; -#endif - if ( last > j ) { - (*mlp)->sml_values[j] = (*mlp)->sml_values[last]; - BER_BVZERO( &(*mlp)->sml_values[last] ); + for ( j = 0; !BER_BVISNULL( &(*mlp)->sml_values[ j ] ); j++ ) { + struct ldapmapping *mapping = NULL; + + ( void )rwm_mapping( &rwmap->rwm_oc, &(*mlp)->sml_values[ j ], + &mapping, RWM_MAP ); + if ( mapping == NULL ) { + if ( rwmap->rwm_at.drop_missing ) { + /* FIXME: we allow to remove objectClasses as well; + * if the resulting entry is inconsistent, that's + * the relayed database's business... + */ + ch_free( (*mlp)->sml_values[ j ].bv_val ); + if ( last > j ) { + (*mlp)->sml_values[ j ] = (*mlp)->sml_values[ last ]; + } + BER_BVZERO( &(*mlp)->sml_values[ last ] ); + last--; + j--; } - last--; - + } else { - ch_free( (*mlp)->sml_values[j].bv_val ); - ber_dupbv( &(*mlp)->sml_values[j], &mapped ); + ch_free( (*mlp)->sml_values[ j ].bv_val ); + ber_dupbv( &(*mlp)->sml_values[ j ], &mapping->m_dst ); } } @@ -461,6 +500,12 @@ rwm_op_modify( Operation *op, SlapReply *rs ) } next_mod:; + if ( mapping != NULL ) { + /* use new attribute description */ + assert( mapping->m_dst_ad ); + (*mlp)->sml_desc = mapping->m_dst_ad; + } + mlp = &(*mlp)->sml_next; continue; @@ -777,7 +822,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first ) * about duplicate values?) */ isupdate = be_shadow_update( op ); for ( ap = a_first; *ap; ) { - struct ldapmapping *m; + struct ldapmapping *mapping; int drop_missing; int last; Attribute *a; @@ -786,10 +831,28 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first ) { /* go on */ ; - } else if ( op->ors_attrs != NULL && - !SLAP_USERATTRS( rs->sr_attr_flags ) && - !ad_inlist( (*ap)->a_desc, op->ors_attrs ) ) - { + } else { + 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 ) ) ) + { + goto cleanup_attr; + } + + 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 ) { + /* will be generated by frontend */ goto cleanup_attr; } @@ -799,12 +862,6 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first ) goto next_attr; } - drop_missing = rwm_mapping( &rwmap->rwm_at, - &(*ap)->a_desc->ad_cname, &m, RWM_REMAP ); - if ( drop_missing || ( m != NULL && BER_BVISEMPTY( &m->m_dst ) ) ) { - goto cleanup_attr; - } - for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ ) /* just count */ ; @@ -877,10 +934,10 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first ) } } - if ( m != NULL ) { + if ( mapping != NULL ) { /* rewrite the attribute description */ - assert( m->m_dst_ad ); - (*ap)->a_desc = m->m_dst_ad; + assert( mapping->m_dst_ad ); + (*ap)->a_desc = mapping->m_dst_ad; } next_attr:; diff --git a/servers/slapd/overlays/rwmdn.c b/servers/slapd/overlays/rwmdn.c index 931687b70d..dd7203c3cd 100644 --- a/servers/slapd/overlays/rwmdn.c +++ b/servers/slapd/overlays/rwmdn.c @@ -16,7 +16,7 @@ * . */ /* ACKNOWLEDGEMENTS: - * This work was initially developed by the Howard Chu for inclusion + * This work was initially developed by Howard Chu for inclusion * in OpenLDAP Software and subsequently enhanced by Pierangelo * Masarati. */ diff --git a/servers/slapd/overlays/rwmmap.c b/servers/slapd/overlays/rwmmap.c index 9662661622..e551f3568a 100644 --- a/servers/slapd/overlays/rwmmap.c +++ b/servers/slapd/overlays/rwmmap.c @@ -321,40 +321,46 @@ rwm_map_attrs( return LDAP_SUCCESS; } - for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) { + for ( i = 0; !BER_BVISNULL( &an[ i ].an_name ); i++ ) { /* */ } na = (char **)ch_calloc( i + 1, sizeof( char * ) ); - if (na == NULL) { + if ( na == NULL ) { *mapped_attrs = NULL; return LDAP_NO_MEMORY; } for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) { - struct ldapmapping *m; + struct ldapmapping *mapping; - if ( rwm_mapping( at_map, &an[i].an_name, &m, remap ) ) { + if ( rwm_mapping( at_map, &an[i].an_name, &mapping, remap ) ) { continue; } - if ( !m || ( m && !BER_BVISNULL( &m->m_dst ) ) ) { - na[j++] = m->m_dst.bv_val; + if ( !mapping ) { + na[ j++ ] = an[ i ].an_name.bv_val; + + } else if ( !BER_BVISNULL( &mapping->m_dst ) ) { + na[ j++ ] = mapping->m_dst.bv_val; } } + if ( j == 0 && i != 0 ) { - na[j++] = LDAP_NO_ATTRS; + na[ j++ ] = LDAP_NO_ATTRS; } - na[j] = NULL; + + na[ j ] = NULL; *mapped_attrs = na; + return LDAP_SUCCESS; } static int map_attr_value( dncookie *dc, - AttributeDescription *ad, + AttributeDescription **adp, struct berval *mapped_attr, struct berval *value, struct berval *mapped_value, @@ -362,65 +368,72 @@ map_attr_value( { struct berval vtmp = BER_BVNULL; int freeval = 0; + AttributeDescription *ad = *adp; + struct ldapmapping *mapping = NULL; - rwm_map( &dc->rwmap->rwm_at, &ad->ad_cname, mapped_attr, remap ); - if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) { - /* - * FIXME: are we sure we need to search oc_map if at_map fails? - */ - rwm_map( &dc->rwmap->rwm_oc, &ad->ad_cname, mapped_attr, remap ); - if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) - { - *mapped_attr = ad->ad_cname; + rwm_mapping( &dc->rwmap->rwm_at, &ad->ad_cname, &mapping, remap ); + if ( mapping == NULL ) { + if ( dc->rwmap->rwm_at.drop_missing ) { + return -1; } - } - if ( value == NULL ) { - return 0; + *mapped_attr = ad->ad_cname; + + } else { + *mapped_attr = mapping->m_dst; } - if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) - { - dncookie fdc = *dc; - int rc; + if ( value != NULL ) { + assert( mapped_value != NULL ); + + if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) + { + dncookie fdc = *dc; + int rc; #ifdef ENABLE_REWRITE - fdc.ctx = "searchFilterAttrDN"; + fdc.ctx = "searchFilterAttrDN"; #endif /* ENABLE_REWRITE */ - vtmp = *value; - rc = rwm_dn_massage_normalize( &fdc, value, &vtmp ); - switch ( rc ) { - case LDAP_SUCCESS: - if ( vtmp.bv_val != value->bv_val ) { - freeval = 1; - } - break; + vtmp = *value; + rc = rwm_dn_massage_normalize( &fdc, value, &vtmp ); + switch ( rc ) { + case LDAP_SUCCESS: + if ( vtmp.bv_val != value->bv_val ) { + freeval = 1; + } + break; - case LDAP_UNWILLING_TO_PERFORM: - case LDAP_OTHER: - default: - return -1; - } + case LDAP_UNWILLING_TO_PERFORM: + case LDAP_OTHER: + default: + return -1; + } - } else if ( ad == slap_schema.si_ad_objectClass - || ad == slap_schema.si_ad_structuralObjectClass ) - { - rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap ); - if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) { + } else if ( ad == slap_schema.si_ad_objectClass + || ad == slap_schema.si_ad_structuralObjectClass ) + { + rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap ); + if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) { + vtmp = *value; + } + + } else { vtmp = *value; } - - } else { - vtmp = *value; - } - filter_escape_value( &vtmp, mapped_value ); + filter_escape_value( &vtmp, mapped_value ); - if ( freeval ) { - ch_free( vtmp.bv_val ); + if ( freeval ) { + ch_free( vtmp.bv_val ); + } } + if ( mapping != NULL ) { + assert( mapping->m_dst_ad != NULL ); + *adp = mapping->m_dst_ad; + } + return 0; } @@ -451,7 +464,7 @@ rwm_int_filter_map_rewrite( switch ( f->f_choice ) { case LDAP_FILTER_EQUALITY: - if ( map_attr_value( dc, f->f_av_desc, &atmp, + if ( map_attr_value( dc, &f->f_av_desc, &atmp, &f->f_av_value, &vtmp, RWM_MAP ) ) { return -1; @@ -467,7 +480,7 @@ rwm_int_filter_map_rewrite( break; case LDAP_FILTER_GE: - if ( map_attr_value( dc, f->f_av_desc, &atmp, + if ( map_attr_value( dc, &f->f_av_desc, &atmp, &f->f_av_value, &vtmp, RWM_MAP ) ) { return -1; @@ -483,7 +496,7 @@ rwm_int_filter_map_rewrite( break; case LDAP_FILTER_LE: - if ( map_attr_value( dc, f->f_av_desc, &atmp, + if ( map_attr_value( dc, &f->f_av_desc, &atmp, &f->f_av_value, &vtmp, RWM_MAP ) ) { return -1; @@ -499,7 +512,7 @@ rwm_int_filter_map_rewrite( break; case LDAP_FILTER_APPROX: - if ( map_attr_value( dc, f->f_av_desc, &atmp, + if ( map_attr_value( dc, &f->f_av_desc, &atmp, &f->f_av_value, &vtmp, RWM_MAP ) ) { return -1; @@ -515,7 +528,7 @@ rwm_int_filter_map_rewrite( break; case LDAP_FILTER_SUBSTRINGS: - if ( map_attr_value( dc, f->f_sub_desc, &atmp, + if ( map_attr_value( dc, &f->f_sub_desc, &atmp, NULL, NULL, RWM_MAP ) ) { return -1; @@ -577,7 +590,7 @@ rwm_int_filter_map_rewrite( break; case LDAP_FILTER_PRESENT: - if ( map_attr_value( dc, f->f_desc, &atmp, + if ( map_attr_value( dc, &f->f_desc, &atmp, NULL, NULL, RWM_MAP ) ) { return -1; @@ -621,7 +634,7 @@ rwm_int_filter_map_rewrite( case LDAP_FILTER_EXT: { if ( f->f_mr_desc ) { - if ( map_attr_value( dc, f->f_mr_desc, &atmp, + if ( map_attr_value( dc, &f->f_mr_desc, &atmp, &f->f_mr_value, &vtmp, RWM_MAP ) ) { return -1; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 2f91d7928f..bacc1b3772 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -144,6 +144,7 @@ LDAP_SLAPD_F (int) slap_entry2mods LDAP_P(( Entry *e, /* * at.c */ +LDAP_SLAPD_V(int) at_oc_cache; LDAP_SLAPD_F (void) at_config LDAP_P(( const char *fname, int lineno, int argc, char **argv )); @@ -626,6 +627,7 @@ LDAP_SLAPD_V (const Entry) slap_entry_root; LDAP_SLAPD_F (int) entry_destroy LDAP_P((void)); LDAP_SLAPD_F (Entry *) str2entry LDAP_P(( char *s )); +LDAP_SLAPD_F (Entry *) str2entry2 LDAP_P(( char *s, int checkvals )); LDAP_SLAPD_F (char *) entry2str LDAP_P(( Entry *e, int *len )); LDAP_SLAPD_F (void) entry_flatsize LDAP_P(( diff --git a/servers/slapd/saslauthz.c b/servers/slapd/saslauthz.c index 1c0c1339c6..28e44248cd 100644 --- a/servers/slapd/saslauthz.c +++ b/servers/slapd/saslauthz.c @@ -1101,8 +1101,7 @@ void slap_sasl2dn( Operation *opx, "converting SASL name %s to a DN\n", saslname->bv_val, 0,0 ); - sasldn->bv_val = NULL; - sasldn->bv_len = 0; + BER_BVZERO( sasldn ); cb.sc_private = sasldn; /* Convert the SASL name into a minimal URI */ diff --git a/servers/slapd/schema/README b/servers/slapd/schema/README index 958a8ab40b..0c0edfd4f4 100644 --- a/servers/slapd/schema/README +++ b/servers/slapd/schema/README @@ -11,7 +11,7 @@ dyngroup.schema Dynamic Group (experimental) inetorgperson.schema InetOrgPerson java.schema Java Object misc.schema Miscellaneous Schema (experimental) -nis.schema Network Information Service +nis.schema Network Information Service (experimental) openldap.schema OpenLDAP Project (FYI) ppolicy.schema Password Policy Schema (work in progress) diff --git a/servers/slapd/search.c b/servers/slapd/search.c index 283fb6dfcf..a162b20068 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -353,7 +353,9 @@ fe_op_search( Operation *op, SlapReply *rs ) if (!rs->sr_ref) rs->sr_ref = default_referral; rs->sr_err = LDAP_REFERRAL; + op->o_bd = frontendDB; send_ldap_result( op, rs ); + op->o_bd = NULL; if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref ); diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 5cc6f3274a..79d3a38c13 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1389,6 +1389,7 @@ LDAP_SLAPD_V (int) slapMode; #define SLAP_TRUNCATE_MODE 0x0100 #define SLAP_TOOL_READMAIN 0x0200 #define SLAP_TOOL_READONLY 0x0400 +#define SLAP_TOOL_QUICK 0x0800 struct slap_replica_info { char *ri_host; /* supersedes be_replica */ diff --git a/servers/slapd/slapadd.c b/servers/slapd/slapadd.c index 788100e615..1d45cd8a73 100644 --- a/servers/slapd/slapadd.c +++ b/servers/slapd/slapadd.c @@ -40,6 +40,66 @@ static char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ]; static char maxcsnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ]; +static const char *progname = "slapadd"; + +static ldap_pvt_thread_cond_t put_cond1; +static ldap_pvt_thread_cond_t put_cond2; +static ldap_pvt_thread_mutex_t put_mutex1; +static ldap_pvt_thread_mutex_t put_mutex2; +static Entry *put_e; +static struct berval bvtext; +static int put_lineno; +static int put_rc; + +static int use_thread = 0; /*FIXME need a new switch for this */ + +static void *do_put(void *ptr) +{ + ID id; + Entry *e; + int lineno; + + ldap_pvt_thread_mutex_lock( &put_mutex1 ); + do { + ldap_pvt_thread_cond_wait( &put_cond1, &put_mutex1 ); + if ( put_rc ) { + break; + } + ldap_pvt_thread_mutex_lock( &put_mutex2 ); + ldap_pvt_thread_cond_signal( &put_cond2 ); + ldap_pvt_thread_mutex_unlock( &put_mutex2 ); + + e = put_e; + lineno = put_lineno; + + if ( !dryrun ) { + id = be->be_entry_put( be, e, &bvtext ); + if( id == NOID ) { + fprintf( stderr, "%s: could not add entry dn=\"%s\" " + "(line=%d): %s\n", progname, e->e_dn, + lineno, bvtext.bv_val ); + entry_free( e ); + if ( continuemode ) continue; + put_rc = EXIT_FAILURE; + break; + } + } + + if ( verbose ) { + if ( dryrun ) { + fprintf( stderr, "added: \"%s\"\n", + e->e_dn ); + } else { + fprintf( stderr, "added: \"%s\" (%08lx)\n", + e->e_dn, (long) id ); + } + } + + entry_free( e ); + + } while (1); + ldap_pvt_thread_mutex_unlock( &put_mutex1 ); +} int slapadd( int argc, char **argv ) @@ -52,7 +112,6 @@ slapadd( int argc, char **argv ) const char *text; char textbuf[SLAP_TEXT_BUFLEN] = { '\0' }; size_t textlen = sizeof textbuf; - const char *progname = "slapadd"; struct berval csn; struct berval maxcsn; @@ -61,9 +120,10 @@ slapadd( int argc, char **argv ) Entry *ctxcsn_e; ID ctxcsn_id, id; int ret; - struct berval bvtext; - int i; + int i, checkvals; struct berval mc; + ldap_pvt_thread_t put_tid; + slap_tool_init( progname, SLAPADD, argc, argv ); if( !be->be_entry_open || @@ -80,6 +140,23 @@ slapadd( int argc, char **argv ) } } + checkvals = (slapMode & SLAP_TOOL_QUICK) ? 0 : 1; + + if ( use_thread ) { + ldap_pvt_thread_initialize(); + ldap_pvt_thread_cond_init( &put_cond1 ); + ldap_pvt_thread_cond_init( &put_cond2 ); + ldap_pvt_thread_mutex_init( &put_mutex1 ); + ldap_pvt_thread_mutex_init( &put_mutex2 ); + rc = ldap_pvt_thread_create( &put_tid, 0, do_put, NULL ); + if ( rc ) { + fprintf( stderr, "%s: could not create thread.\n", + progname ); + exit( EXIT_FAILURE ); + } + ldap_pvt_thread_mutex_lock( &put_mutex2 ); + } + lmax = 0; lineno = 0; @@ -95,7 +172,7 @@ slapadd( int argc, char **argv ) } while( ldif_read_record( ldiffp, &lineno, &buf, &lmax ) ) { - Entry *e = str2entry( buf ); + Entry *e = str2entry2( buf, checkvals ); /* * Initialize text buffer @@ -292,6 +369,22 @@ slapadd( int argc, char **argv ) } } + if ( use_thread ) { + ldap_pvt_thread_mutex_lock( &put_mutex1 ); + if (put_rc) { + rc = put_rc; + ldap_pvt_thread_mutex_unlock( &put_mutex1 ); + break; + } + put_e = e; + put_lineno = lineno; + ldap_pvt_thread_cond_signal( &put_cond1 ); + ldap_pvt_thread_mutex_unlock( &put_mutex1 ); + /* Make sure writer wakes up */ + ldap_pvt_thread_cond_wait( &put_cond2, &put_mutex2 ); + continue; + } + if ( !dryrun ) { id = be->be_entry_put( be, e, &bvtext ); if( id == NOID ) { @@ -315,15 +408,30 @@ slapadd( int argc, char **argv ) } } -done:; entry_free( e ); } + if ( use_thread ) { + ldap_pvt_thread_mutex_unlock( &put_mutex2 ); + ldap_pvt_thread_mutex_lock( &put_mutex1 ); + /* Tell child thread to stop if it hasn't aborted */ + if ( !put_rc ) { + put_rc = EXIT_FAILURE; + ldap_pvt_thread_cond_signal( &put_cond1 ); + } + ldap_pvt_thread_mutex_unlock( &put_mutex1 ); + ldap_pvt_thread_join( put_tid, NULL ); + ldap_pvt_thread_mutex_destroy( &put_mutex2 ); + ldap_pvt_thread_mutex_destroy( &put_mutex1 ); + ldap_pvt_thread_cond_destroy( &put_cond2 ); + ldap_pvt_thread_cond_destroy( &put_cond1 ); + } + bvtext.bv_len = textlen; bvtext.bv_val = textbuf; bvtext.bv_val[0] = '\0'; - if ( update_ctxcsn && !dryrun && maxcsn.bv_len ) { + if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && maxcsn.bv_len ) { ctxcsn_id = be->be_dn2id_get( be, be->be_nsuffix ); if ( ctxcsn_id == NOID ) { fprintf( stderr, "%s: context entry is missing\n", progname ); diff --git a/servers/slapd/slapcommon.c b/servers/slapd/slapcommon.c index bafe34dafe..c768f52f3e 100644 --- a/servers/slapd/slapcommon.c +++ b/servers/slapd/slapcommon.c @@ -127,7 +127,7 @@ slap_tool_init( switch( tool ) { case SLAPADD: - options = "b:cd:f:l:n:tuvw"; + options = "b:cd:f:l:n:qtuvw"; break; case SLAPCAT: @@ -204,6 +204,10 @@ slap_tool_init( dbnum = atoi( optarg ) - 1; break; + case 'q': /* turn on quick */ + mode |= SLAP_TOOL_QUICK; + break; + case 'R': realm = optarg; break; @@ -337,6 +341,7 @@ slap_tool_init( exit( EXIT_FAILURE ); } + at_oc_cache = 1; ldap_syslog = 0; switch ( tool ) { diff --git a/tests/data/chain.out b/tests/data/chain.out index 3d53473989..985f5dd4df 100644 --- a/tests/data/chain.out +++ b/tests/data/chain.out @@ -386,6 +386,10 @@ pager: +1 313 555 7671 facsimileTelephoneNumber: +1 313 555 7762 telephoneNumber: +1 313 555 4177 +dn: ou=Other,dc=example,dc=com +objectClass: organizationalUnit +ou: Other + dn: ou=People,dc=example,dc=com objectClass: organizationalUnit objectClass: extensibleObject diff --git a/tests/data/chainmod.out b/tests/data/chainmod.out index a15e26f528..67970afc2f 100644 --- a/tests/data/chainmod.out +++ b/tests/data/chainmod.out @@ -365,6 +365,10 @@ pager: +1 313 555 7671 facsimileTelephoneNumber: +1 313 555 7762 telephoneNumber: +1 313 555 4177 +dn: ou=Other,dc=example,dc=com +objectClass: organizationalUnit +ou: Other + dn: ou=People,dc=example,dc=com objectClass: organizationalUnit objectClass: extensibleObject diff --git a/tests/data/chainref.out b/tests/data/chainref.out new file mode 100644 index 0000000000..bec32503cb --- /dev/null +++ b/tests/data/chainref.out @@ -0,0 +1,4 @@ +dn: ou=Other,dc=example,dc=com +objectClass: organizationalUnit +ou: Other + diff --git a/tests/data/relay.out b/tests/data/relay.out index b3ef32295c..9588fd7db7 100644 --- a/tests/data/relay.out +++ b/tests/data/relay.out @@ -414,8 +414,8 @@ dn: o=Example,c=US objectClass: top objectClass: organization objectClass: domainRelatedObject -objectClass: dcObject -dc: example +objectClass: uidObject +uid: example l: Anytown, Michigan st: Michigan o: Example, Inc. @@ -680,14 +680,14 @@ dn: cn=ITD Staff,ou=Groups,o=Example,c=US owner: cn=Manager,o=Example,c=US description: All ITD Staff cn: ITD Staff -objectClass: groupOfUniqueNames -uniqueMember: cn=Manager,dc=example,dc=com -uniqueMember: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc= - example,dc=com -uniqueMember: cn=James A Jones 2,ou=Information Technology Division,ou=People, - dc=example,dc=com -uniqueMember: cn=John Doe,ou=Information Technology Division,ou=People,dc=exam - ple,dc=com +objectClass: groupOfNames +member: cn=Manager,o=Example,c=US +member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Example + ,c=US +member: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Exam + ple,c=US +member: cn=John Doe,ou=Information Technology Division,ou=People,o=Example,c=U + S dn: cn=James A Jones 1,ou=Alumni Association,ou=People,o=Example,c=US objectClass: OpenLDAPperson @@ -1642,13 +1642,13 @@ pager: +1 313 555 2844 facsimileTelephoneNumber: +1 313 555 9700 telephoneNumber: +1 313 555 5331 -# searching base="o=Beispiel,c=DE"... -dn: o=Beispiel,c=DE +# searching base="o=Example,c=US"... +dn: o=Example,c=US objectClass: top objectClass: organization objectClass: domainRelatedObject -objectClass: dcObject -dc: example +objectClass: uidObject +uid: example l: Anytown, Michigan st: Michigan o: Example, Inc. @@ -1659,22 +1659,22 @@ postalAddress: Example, Inc. $ 535 W. William St. $ Anytown, MI 48109 $ US telephoneNumber: +1 313 555 1817 associatedDomain: example.com -dn: ou=People,o=Beispiel,c=DE +dn: ou=People,o=Example,c=US objectClass: organizationalUnit objectClass: extensibleObject ou: People uidNumber: 0 gidNumber: 0 -dn: ou=Groups,o=Beispiel,c=DE +dn: ou=Groups,o=Example,c=US objectClass: organizationalUnit ou: Groups -dn: ou=Alumni Association,ou=People,o=Beispiel,c=DE +dn: ou=Alumni Association,ou=People,o=Example,c=US objectClass: organizationalUnit ou: Alumni Association -dn: ou=Information Technology Division,ou=People,o=Beispiel,c=DE +dn: ou=Information Technology Division,ou=People,o=Example,c=US objectClass: organizationalUnit ou: Information Technology Division description:: aMODwoPDgsKCw4PCgsOCwotFVlZQw4PCg8OCwoPDg8KCw4LCv0zDg8KDw4LCgsOD @@ -1817,42 +1817,42 @@ description:: UF7Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgsOC 8ODwoLDgsKow4PCg8OCwoPDg8KCw4LCl8ODwoPDgsKDw4PCgsOCwrtWw4PCg8OCwoLDg8KCw4LCi8 ODwoPDgsKDw4PCgsOCwo3Dg8KDw4LCg8ODwoLDgsKow4PCg8OCwoLDg8KCw4LCnw== -dn: cn=All Staff,ou=Groups,o=Beispiel,c=DE -member: cn=Manager,o=Beispiel,c=DE -member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Beisp - iel,c=DE -member: cn=Jane Doe,ou=Alumni Association,ou=People,o=Beispiel,c=DE -member: cn=John Doe,ou=Information Technology Division,ou=People,o=Beispiel,c= - DE -member: cn=Mark Elliot,ou=Alumni Association,ou=People,o=Beispiel,c=DE -member: cn=James A Jones 1,ou=Alumni Association,ou=People,o=Beispiel,c=DE -member: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Beis - piel,c=DE -member: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=Beispiel,c=DE -member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=Beispiel,c=DE -member: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=Beispiel,c=DE -member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Beispie - l,c=DE -owner: cn=Manager,o=Beispiel,c=DE +dn: cn=All Staff,ou=Groups,o=Example,c=US +member: cn=Manager,o=Example,c=US +member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Examp + le,c=US +member: cn=Jane Doe,ou=Alumni Association,ou=People,o=Example,c=US +member: cn=John Doe,ou=Information Technology Division,ou=People,o=Example,c=U + S +member: cn=Mark Elliot,ou=Alumni Association,ou=People,o=Example,c=US +member: cn=James A Jones 1,ou=Alumni Association,ou=People,o=Example,c=US +member: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Exam + ple,c=US +member: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=Example,c=US +member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=Example,c=US +member: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=Example,c=US +member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Example + ,c=US +owner: cn=Manager,o=Example,c=US cn: All Staff description: Everyone in the sample data objectClass: groupOfNames -dn: cn=Alumni Assoc Staff,ou=Groups,o=Beispiel,c=DE -member: cn=Manager,o=Beispiel,c=DE -member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=Beispiel,c=DE -member: cn=James A Jones 1,ou=Alumni Association,ou=People,o=Beispiel,c=DE -member: cn=Jane Doe,ou=Alumni Association,ou=People,o=Beispiel,c=DE -member: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=Beispiel,c=DE -member: cn=Mark Elliot,ou=Alumni Association,ou=People,o=Beispiel,c=DE -member: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=Beispiel,c=DE -owner: cn=Manager,o=Beispiel,c=DE +dn: cn=Alumni Assoc Staff,ou=Groups,o=Example,c=US +member: cn=Manager,o=Example,c=US +member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=Example,c=US +member: cn=James A Jones 1,ou=Alumni Association,ou=People,o=Example,c=US +member: cn=Jane Doe,ou=Alumni Association,ou=People,o=Example,c=US +member: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=Example,c=US +member: cn=Mark Elliot,ou=Alumni Association,ou=People,o=Example,c=US +member: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=Example,c=US +owner: cn=Manager,o=Example,c=US description: All Alumni Assoc Staff cn: Alumni Assoc Staff objectClass: groupOfNames -dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Beispiel, - c=DE +dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,o=Example,c + =US objectClass: OpenLDAPperson cn: Barbara Jensen cn: Babs Jensen @@ -1861,7 +1861,7 @@ uid: bjensen title: Mythical Manager, Research Systems postalAddress: ITD Prod Dev & Deployment $ 535 W. William St. Room 4212 $ Anyt own, MI 48103-4943 -seeAlso: cn=All Staff,ou=Groups,o=Beispiel,c=DE +seeAlso: cn=All Staff,ou=Groups,o=Example,c=US userPassword:: YmplbnNlbg== mail: bjensen@mailgw.example.com homePostalAddress: 123 Wesley $ Anytown, MI 48103 @@ -1872,14 +1872,14 @@ pager: +1 313 555 3233 facsimileTelephoneNumber: +1 313 555 2274 telephoneNumber: +1 313 555 9022 -dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Beispiel,c= - DE +dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Example,c=U + S objectClass: OpenLDAPperson cn: Bjorn Jensen cn: Biiff Jensen sn: Jensen uid: bjorn -seeAlso: cn=All Staff,ou=Groups,o=Beispiel,c=DE +seeAlso: cn=All Staff,ou=Groups,o=Example,c=US userPassword:: Ympvcm4= homePostalAddress: 19923 Seven Mile Rd. $ South Lyon, MI 49999 drink: Iced Tea @@ -1892,7 +1892,7 @@ pager: +1 313 555 4474 facsimileTelephoneNumber: +1 313 555 2177 telephoneNumber: +1 313 555 0355 -dn: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=Beispiel,c=DE +dn: cn=Dorothy Stevens,ou=Alumni Association,ou=People,o=Example,c=US objectClass: OpenLDAPperson cn: Dorothy Stevens cn: Dot Stevens @@ -1900,7 +1900,7 @@ sn: Stevens uid: dots title: Secretary, UM Alumni Association postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109 -seeAlso: cn=All Staff,ou=Groups,o=Beispiel,c=DE +seeAlso: cn=All Staff,ou=Groups,o=Example,c=US drink: Lemonade homePostalAddress: 377 White St. Apt. 3 $ Anytown, MI 48104 description: Very tall @@ -1909,20 +1909,20 @@ telephoneNumber: +1 313 555 3664 mail: dots@mail.alumni.example.com homePhone: +1 313 555 0454 -dn: cn=ITD Staff,ou=Groups,o=Beispiel,c=DE -owner: cn=Manager,o=Beispiel,c=DE +dn: cn=ITD Staff,ou=Groups,o=Example,c=US +owner: cn=Manager,o=Example,c=US description: All ITD Staff cn: ITD Staff -objectClass: groupOfUniqueNames -uniqueMember: cn=Manager,dc=example,dc=com -uniqueMember: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc= - example,dc=com -uniqueMember: cn=James A Jones 2,ou=Information Technology Division,ou=People, - dc=example,dc=com -uniqueMember: cn=John Doe,ou=Information Technology Division,ou=People,dc=exam - ple,dc=com +objectClass: groupOfNames +member: cn=Manager,o=Example,c=US +member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,o=Example + ,c=US +member: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Exam + ple,c=US +member: cn=John Doe,ou=Information Technology Division,ou=People,o=Example,c=U + S -dn: cn=James A Jones 1,ou=Alumni Association,ou=People,o=Beispiel,c=DE +dn: cn=James A Jones 1,ou=Alumni Association,ou=People,o=Example,c=US objectClass: OpenLDAPperson cn: James A Jones 1 cn: James Jones @@ -1930,7 +1930,7 @@ cn: Jim Jones sn: Jones uid: jaj postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109 -seeAlso: cn=All Staff,ou=Groups,o=Beispiel,c=DE +seeAlso: cn=All Staff,ou=Groups,o=Example,c=US userPassword:: amFq homePostalAddress: 3882 Beverly Rd. $ Anytown, MI 48105 homePhone: +1 313 555 4772 @@ -1941,15 +1941,15 @@ mail: jaj@mail.alumni.example.com facsimileTelephoneNumber: +1 313 555 4332 telephoneNumber: +1 313 555 0895 -dn: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Beispiel - ,c=DE +dn: cn=James A Jones 2,ou=Information Technology Division,ou=People,o=Example, + c=US objectClass: OpenLDAPperson cn: James A Jones 2 cn: James Jones cn: Jim Jones sn: Doe uid: jjones -seeAlso: cn=All Staff,ou=Groups,o=Beispiel,c=DE +seeAlso: cn=All Staff,ou=Groups,o=Example,c=US homePostalAddress: 933 Brooks $ Anytown, MI 48104 homePhone: +1 313 555 8838 title: Senior Manager, Information Technology Division @@ -1960,8 +1960,7 @@ pager: +1 313 555 2833 facsimileTelephoneNumber: +1 313 555 8688 telephoneNumber: +1 313 555 7334 -dn: cn=Jane Q. Doe,ou=Information Technology Division,ou=People,o=Beispiel,c=D - E +dn: cn=Jane Q. Doe,ou=Information Technology Division,ou=People,o=Example,c=US objectClass: OpenLDAPperson cn: Jane Alverson cn: Jane Q. Doe @@ -1970,7 +1969,6 @@ sn: Doe uid: jdoe title: Programmer Analyst, UM Alumni Association postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109 -seeAlso: cn=All Staff,ou=Groups,o=Beispiel,c=DE homePostalAddress: 123 Anystreet $ Anytown, MI 48104 drink: diet coke description: Enthusiastic @@ -1979,15 +1977,16 @@ homePhone: +1 313 555 5445 pager: +1 313 555 1220 facsimileTelephoneNumber: +1 313 555 2311 telephoneNumber: +1 313 555 4774 +seeAlso: cn=All Staff,ou=Groups,o=Example,c=US -dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=Beispiel,c=DE +dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=Example,c=US objectClass: OpenLDAPperson cn: Jennifer Smith cn: Jen Smith sn: Smith uid: jen postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109 -seeAlso: cn=All Staff,ou=Groups,o=Beispiel,c=DE +seeAlso: cn=All Staff,ou=Groups,o=Example,c=US drink: Sam Adams homePostalAddress: 1000 Maple #44 $ Anytown, MI 48103 title: Telemarketer, UM Alumni Association @@ -1997,15 +1996,14 @@ pager: +1 313 555 6442 facsimileTelephoneNumber: +1 313 555 2756 telephoneNumber: +1 313 555 8232 -dn: cn=John P. Doe,ou=Information Technology Division,ou=People,o=Beispiel,c=D - E +dn: cn=John P. Doe,ou=Information Technology Division,ou=People,o=Example,c=US objectClass: OpenLDAPperson cn: Jonathon Doe cn: John P. Doe sn: Doe uid: johnd postalAddress: ITD $ 535 W. William $ Anytown, MI 48109 -seeAlso: cn=All Staff,ou=Groups,o=Beispiel,c=DE +seeAlso: cn=All Staff,ou=Groups,o=Example,c=US homePostalAddress: 912 East Bllvd $ Anytown, MI 48104 title: System Administrator, Information Technology Division description: overworked! @@ -2015,7 +2013,7 @@ pager: +1 313 555 6573 facsimileTelephoneNumber: +1 313 555 4544 telephoneNumber: +1 313 555 9394 -dn: cn=Manager,o=Beispiel,c=DE +dn: cn=Manager,o=Example,c=US objectClass: person cn: Manager cn: Directory Manager @@ -2024,15 +2022,15 @@ sn: Manager description: Manager of the directory userPassword:: c2VjcmV0 -dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=Beispiel,c=DE +dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=Example,c=US objectClass: OpenLDAPperson cn: Ursula Hampster sn: Hampster uid: uham title: Secretary, UM Alumni Association postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109 -seeAlso: cn=All Staff,ou=Groups,o=Beispiel,c=DE -seeAlso: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=Beispiel,c=DE +seeAlso: cn=All Staff,ou=Groups,o=Example,c=US +seeAlso: cn=Ursula Hampster,ou=Alumni Association,ou=People,o=Example,c=US homePostalAddress: 123 Anystreet $ Anytown, MI 48104 mail: uham@mail.alumni.example.com homePhone: +1 313 555 8421 @@ -2042,12 +2040,12 @@ telephoneNumber: +1 313 555 5331 description: Just added self to seeAlso in o=Beispiel,c=DE virtual naming cont ext -dn: cn=Added User,ou=Alumni Association,ou=People,o=Beispiel,c=DE +dn: cn=Added User,ou=Alumni Association,ou=People,o=Example,c=US objectClass: OpenLDAPperson cn: Added User sn: User uid: auser -seeAlso: cn=All Staff,ou=Groups,o=Beispiel,c=DE +seeAlso: cn=All Staff,ou=Groups,o=Example,c=US homePhone: +49 1234567890 drink: Beer mail: auser@mail.alumni.example.com @@ -2056,6 +2054,19 @@ description: Just added in o=Beispiel,c=DE naming context # refldap://localhost:9010/ou=Referrals,o=Beispiel,c=DE??sub +dn: cn=Added Group,ou=Groups,o=Example,c=US +objectClass: groupOfNames +cn: Added Group +member: cn=Added Group,ou=Groups,o=Example,c=US + +dn: cn=Another Added Group,ou=Groups,o=Example,c=US +objectClass: groupOfNames +objectClass: uidObject +cn: Another Added Group +member: cn=Added Group,ou=Groups,o=Example,c=US +member: cn=Another Added Group,ou=Groups,o=Example,c=US +uid: added + # searching base="o=Esempio,c=IT"... dn: o=Esempio,c=IT objectClass: top @@ -2383,7 +2394,6 @@ sn: Doe uid: jdoe title: Programmer Analyst, UM Alumni Association postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109 -seeAlso: cn=All Staff,ou=Groups,o=Esempio,c=IT homePostalAddress: 123 Anystreet $ Anytown, MI 48104 drink: diet coke description: Enthusiastic @@ -2392,6 +2402,7 @@ homePhone: +1 313 555 5445 pager: +1 313 555 1220 facsimileTelephoneNumber: +1 313 555 2311 telephoneNumber: +1 313 555 4774 +seeAlso: cn=All Staff,ou=Groups,o=Esempio,c=IT dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,o=Esempio,c=IT objectClass: OpenLDAPperson @@ -2468,6 +2479,19 @@ description: Just added in o=Beispiel,c=DE naming context # refldap://localhost:9010/ou=Referrals,o=Beispiel,c=DE??sub +dn: cn=Added Group,ou=Groups,o=Esempio,c=IT +objectClass: groupOfUniqueNames +cn: Added Group +uniqueMember: cn=Added Group,ou=Groups,dc=example,dc=com + +dn: cn=Another Added Group,ou=Groups,o=Esempio,c=IT +objectClass: groupOfUniqueNames +objectClass: dcObject +cn: Another Added Group +uniqueMember: cn=Added Group,ou=Groups,dc=example,dc=com +uniqueMember: cn=Another Added Group,ou=Groups,dc=example,dc=com +dc: added + # searching filter="(objectClass=referral)" # attrs="'*' ref" # base="dc=example,dc=com"... @@ -2542,3 +2566,12 @@ seeAlso: cn=All Staff,ou=Groups,o=Example,c=US # 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"... +# refldap://localhost:9010/ou=Referrals,o=Beispiel,c=DE??sub + +dn: cn=Another Added Group,ou=Groups,o=Example,c=US +member: cn=Added Group,ou=Groups,o=Example,c=US +member: cn=Another Added Group,ou=Groups,o=Example,c=US + diff --git a/tests/data/slapd-relay.conf b/tests/data/slapd-relay.conf index e13e66f1c6..b16e2d5deb 100644 --- a/tests/data/slapd-relay.conf +++ b/tests/data/slapd-relay.conf @@ -50,12 +50,24 @@ database @RELAY@ suffix "o=Example,c=US" ### back-relay can automatically instantiate the rwm overlay #relay#relay "dc=example,dc=com" massage +#relay#rwm-map objectClass groupOfNames groupOfUniqueNames +#relay#rwm-map objectClass uidObject dcObject +#relay#rwm-map attribute member uniqueMember +#relay#rwm-map attribute uid dc ### back-ldap needs explicit instantiation of the rwm overlay #ldap#uri "@URI1@" #ldap#overlay rwm #ldap#rwm-suffixmassage "dc=example,dc=com" +#ldap#rwm-map objectClass groupOfNames groupOfUniqueNames +#ldap#rwm-map objectClass uidObject dcObject +#ldap#rwm-map attribute member uniqueMember +#ldap#rwm-map attribute uid dc #meta#uri "@URI1@o=Example,c=US" #meta#suffixmassage "o=Example,c=US" "dc=example,dc=com" +#meta#map objectClass groupOfNames groupOfUniqueNames +#meta#map objectClass uidObject dcObject +#meta#map attribute member uniqueMember +#meta#map attribute uid dc database @RELAY@ suffix "o=Esempio,c=IT" diff --git a/tests/data/test-chain1.ldif b/tests/data/test-chain1.ldif index 7f419fd20c..76e22f7629 100644 --- a/tests/data/test-chain1.ldif +++ b/tests/data/test-chain1.ldif @@ -29,6 +29,14 @@ objectclass: extensibleobject ou: Groups ref: @URI2@ou=Groups,dc=example,dc=com +dn: ou=Other,dc=example,dc=com +objectclass: referral +objectclass: extensibleobject +ou: Other +# invalid URI first to test failover capabilities (search only) +ref: @URI3@ou=Other,dc=example,dc=com +ref: @URI2@ou=Other,dc=example,dc=com + dn: ou=Alumni Association,ou=People,dc=example,dc=com objectclass: organizationalUnit ou: Alumni Association diff --git a/tests/data/test-chain2.ldif b/tests/data/test-chain2.ldif index fe0cd3e920..e1fb680216 100644 --- a/tests/data/test-chain2.ldif +++ b/tests/data/test-chain2.ldif @@ -81,3 +81,8 @@ cn: Dir Man sn: Manager description: Manager of the directory userpassword:: c2VjcmV0 + +dn: ou=Other,dc=example,dc=com +objectclass: organizationalUnit +ou: Other + diff --git a/tests/scripts/defines.sh b/tests/scripts/defines.sh index c083e666d8..bb6d4011d4 100755 --- a/tests/scripts/defines.sh +++ b/tests/scripts/defines.sh @@ -235,6 +235,7 @@ LDAPGLUEOUT=$DATADIR/ldapglue.out LDAPGLUEANONYMOUSOUT=$DATADIR/ldapglueanonymous.out RELAYOUT=$DATADIR/relay.out CHAINOUT=$DATADIR/chain.out +CHAINREFOUT=$DATADIR/chainref.out CHAINMODOUT=$DATADIR/chainmod.out SQLREAD=$DATADIR/sql-read.out SQLWRITE=$DATADIR/sql-write.out diff --git a/tests/scripts/relay b/tests/scripts/relay index 5902876c17..befaee6cff 100755 --- a/tests/scripts/relay +++ b/tests/scripts/relay @@ -148,6 +148,15 @@ changetype: modify add: cn cn: Jane Qissapaolo Doe - +# This operation (delete of DN-valued attribute) triggered ITS#3498 +delete: seeAlso +- + +dn: cn=Jane Q. Doe,ou=Information Technology Division,ou=People,$BASEDN +changetype: modify +add: seeAlso +seeAlso: cn=All Staff,ou=Groups,$BASEDN +- dn: ou=Referrals,$BASEDN changetype: add @@ -174,6 +183,51 @@ if test $RC != 0 ; then exit $RC fi +BASEDN="o=Example,c=US" +echo "Modifying database \"$BASEDN\"..." +$LDAPMODIFY -v -D "cn=Manager,$BASEDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \ + -M >> $TESTOUT 2>&1 << EOMODS +# These operations (updates with objectClass mapping) triggered ITS#3499 +dn: cn=Added Group,ou=Groups,$BASEDN +changetype: add +objectClass: groupOfNames +objectClass: uidObject +cn: Added Group +member: cn=Added Group,ou=Groups,$BASEDN +uid: added + +dn: cn=Another Added Group,ou=Groups,$BASEDN +changetype: add +objectClass: groupOfNames +cn: Another Added Group +member: cn=Added Group,ou=Groups,$BASEDN +member: cn=Another Added Group,ou=Groups,$BASEDN + +dn: cn=Another Added Group,ou=Groups,$BASEDN +changetype: modify +add: objectClass +objectClass: uidObject +- +add: uid +uid: added +- + +dn: cn=Added Group,ou=Groups,$BASEDN +changetype: modify +delete: objectClass +objectClass: uidObject +- +delete: uid +- +EOMODS + +RC=$? +if test $RC != 0 ; then + echo "Modify failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + echo "Searching base=\"$BASEDN\"..." echo "# searching base=\"$BASEDN\"..." >> $SEARCHOUT $LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" >> $SEARCHOUT 2>&1 @@ -204,7 +258,7 @@ echo "# attrs=\"'*' ref\"" >> $SEARCHOUT BASEDN="dc=example,dc=com" echo " base=\"$BASEDN\"..." echo "# base=\"$BASEDN\"..." >> $SEARCHOUT -$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -M "$FILTER" "*" ref \ +$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -M "$FILTER" '*' ref \ >> $SEARCHOUT 2>&1 RC=$? if test $RC != 0 ; then @@ -216,7 +270,7 @@ fi BASEDN="o=Example,c=US" echo " base=\"$BASEDN\"..." echo "# base=\"$BASEDN\"..." >> $SEARCHOUT -$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -M "$FILTER" "*" ref \ +$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -M "$FILTER" '*' ref \ >> $SEARCHOUT 2>&1 RC=$? if test $RC != 0 ; then @@ -228,7 +282,7 @@ fi BASEDN="o=Esempio,c=IT" echo " base=\"$BASEDN\"..." echo "# base=\"$BASEDN\"..." >> $SEARCHOUT -$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -M "$FILTER" "*" ref \ +$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" -M "$FILTER" '*' ref \ >> $SEARCHOUT 2>&1 RC=$? if test $RC != 0 ; then @@ -254,6 +308,23 @@ if test $RC != 0 ; then exit $RC fi +BASEDN="o=Example,c=US" +FILTER="(member=cn=Another Added Group,ou=Groups,$BASEDN)" +echo "Searching filter=\"$FILTER\"" +echo " attrs=\"member\"" +echo " base=\"$BASEDN\"..." +echo "# searching filter=\"$FILTER\"" >> $SEARCHOUT +echo "# attrs=\"member\"" >> $SEARCHOUT +echo "# base=\"$BASEDN\"..." >> $SEARCHOUT +$LDAPSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" "$FILTER" member \ + >> $SEARCHOUT 2>&1 +RC=$? +if test $RC != 0 ; then + echo "Search failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + echo "Filtering ldapsearch results..." . $LDIFFILTER < $SEARCHOUT > $SEARCHFLT echo "Filtering original ldif used to create database..." diff --git a/tests/scripts/test032-chain b/tests/scripts/test032-chain index de27ec0fce..7bf073a3fd 100755 --- a/tests/scripts/test032-chain +++ b/tests/scripts/test032-chain @@ -110,6 +110,31 @@ for P in $PORT1 $PORT2 ; do test $KILLSERVERS != no && kill -HUP $KILLPIDS exit 1 fi + + echo "Reading the referral entry "ou=Other,$BASEDN" as anonymous on port $P..." + $LDAPSEARCH -h $LOCALHOST -p $P -b "ou=Other,$BASEDN" -S "" \ + > $SEARCHOUT 2>&1 + + RC=$? + if test $RC != 0 ; then + echo "ldapsearch failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC + fi + + echo "Filtering ldapsearch results..." + . $LDIFFILTER < $SEARCHOUT > $SEARCHFLT + echo "Filtering original ldif used to create database..." + . $LDIFFILTER < $CHAINREFOUT > $LDIFFLT + echo "Comparing filter output..." + $CMP $SEARCHFLT $LDIFFLT > $CMPOUT + + if test $? != 0 ; then + echo "comparison failed - chained search didn't succeed" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit 1 +fi + done # -- 2.39.5