#! /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 <http://www.openldap.org/>.
#
## doc Makefile.in for OpenLDAP
# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
## Copyright 1998-2005 The OpenLDAP Foundation.
## All rights reserved.
##
# man Makefile.in for OpenLDAP
# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
## Copyright 1998-2005 The OpenLDAP Foundation.
## All rights reserved.
##
# man1 Makefile.in for OpenLDAP
# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
## Copyright 1998-2005 The OpenLDAP Foundation.
## All rights reserved.
##
# man3 Makefile.in for OpenLDAP
# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
## Copyright 1998-2005 The OpenLDAP Foundation.
## All rights reserved.
##
# man5 Makefile.in for OpenLDAP
# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
## Copyright 1998-2005 The OpenLDAP Foundation.
## All rights reserved.
##
.TP
.B acl-authcDN "<administrative DN for access control purposes>"
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
feature instead.
.TP
.B acl-passwd <password>
-Password used with the bind DN above.
+Password used with the
+.B
+acl-authcDN
+above.
.TP
.B idassert-authcdn "<administrative DN for proxyAuthz purposes>"
DN which is used to propagate the client's identity to the target
from 1.
Target <target> must be defined.
.TP
-.B binddn "<administrative DN for access control purposes>"
-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 "<administrative DN for access control purposes>"
+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 <password for access control purposes>
-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>
+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
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).
.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 <ldapuri>
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
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
rwm-rewriteEngine on
# all dataflow from client to server referring to DNs
rwm-rewriteContext default
-rwm-rewriteRule "(.*)<virtualnamingcontext>$" "$1<realnamingcontext>" ":"
+rwm-rewriteRule "(.+,)?<virtualnamingcontext>$" "$1<realnamingcontext>" ":"
# empty filter rule
rwm-rewriteContext searchFilter
# all dataflow from server to client
rwm-rewriteContext searchEntryDN
-rwm-rewriteRule "(.*)<realnamingcontext>$" "$1<virtualnamingcontext>" ":"
+rwm-rewriteRule "(.+,)?<realnamingcontext>$" "$1<virtualnamingcontext>" ":"
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).
# man8 Makefile.in for OpenLDAP
# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
## Copyright 1998-2005 The OpenLDAP Foundation.
## All rights reserved.
##
#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"
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,
* 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
* 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
/* 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
? 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 );
#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;
}
/*
/* fetch.c - routines for fetching data at URLs */
/* $OpenLDAP$ */
-/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2005 The OpenLDAP Foundation.
* 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 )
{
ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
- rc = REWRITE_NO_SUCH_OBJECT;
+ rc = LDAP_NO_SUCH_OBJECT;
break;
}
# servers Makefile.in for OpenLDAP
# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
## Copyright 1998-2005 The OpenLDAP Foundation.
## All rights reserved.
##
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;
}
};
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,
{
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;
}
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;
}
}
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;
}
}
AttributeDescription *desc )
{
for ( ; a != NULL; a = a->a_next ) {
- if ( ad_cmp( a->a_desc, desc ) == 0 ) {
+ if ( a->a_desc == desc ) {
return( a );
}
}
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 );
*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
#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
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;
#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 );
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 );
*/
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 );
}
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 );
/* 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 ) {
/* 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; i<count; i++ ) {
- rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_DUP | DB_RMW );
+ /* Delete all the records */
+ for ( i=1; i<count; i++ ) {
+ rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_DUP );
if ( rc != 0 ) {
err = "c_get next_dup";
goto fail;
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;
/* 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 ) {
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;
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;
}
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.
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 *) );
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.
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;
}
/* 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 );
#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,
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 ) {
text->bv_val, 0, 0 );
return NOID;
}
+ }
op.o_hdr = &ohdr;
op.o_bd = be;
done:
if( rc == 0 ) {
+ if ( !( slapMode & SLAP_TOOL_QUICK )) {
rc = TXN_COMMIT( tid, 0 );
if( rc != 0 ) {
snprintf( text->bv_val, text->bv_len,
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)",
Debug( LDAP_DEBUG_ANY,
"=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
text->bv_val, 0, 0 );
+ }
e->e_id = NOID;
}
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,
db_strerror(rc), rc, 0 );
goto done;
}
+ }
/*
* just (re)add them for now
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,
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 );
"=> " 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 ) {
text->bv_val, 0, 0 );
return NOID;
}
+ }
op.o_hdr = &ohdr;
op.o_bd = be;
done:
if( rc == 0 ) {
+ if (! (slapMode & SLAP_TOOL_QUICK)) {
rc = TXN_COMMIT( tid, 0 );
if( rc != 0 ) {
snprintf( text->bv_val, text->bv_len,
"%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)",
Debug( LDAP_DEBUG_ANY,
"=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
text->bv_val, 0, 0 );
+ }
e->e_id = NOID;
}
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;
}
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;
}
}
}
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;
}
/* 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"
* <http://www.OpenLDAP.org/license.html>.
*/
/* 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.
*/
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 )
{
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 ) ) {
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
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 );
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 */
/* 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 );
/* 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;
}
/*
* 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 ) {
/*
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;
}
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
*
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 );
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;
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 ) {
/* 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
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;
}
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
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 );
}
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 <DN>)
+ * 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 ) {
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;
}
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
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;
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;
/* 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
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;
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;
}
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" );
}
}
- 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;
}
ldapchain.on_response = ldap_chain_response;
-#if 0
- ldapchain.on_bi.bi_chk_referrals = ldap_chain_chk_referrals;
-#endif
-
return overlay_register( &ldapchain );
}
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;
}
rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls );
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
- rc = -1;
goto cleanup;
}
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;
}
}
cleanup:
(void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
- return rc;
+ return rs->sr_err;
}
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 <name>\" 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 <password>\" 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... */
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 ) {
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;
&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 );
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;
}
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;
}
}
* 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;
}
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;
}
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;
}
}
/* 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 };
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;
}
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;
}
}
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 );
}
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;
}
}
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);
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? */
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;
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;
}
}
*e = NULL;
char *gattr[3];
char *filter = NULL;
- Connection *oconn;
SlapReply rs;
int do_retry = 1;
LDAPControl **ctrls = NULL;
/* 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 ) {
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;
}
}
return( NULL );
}
- e = str2entry( data.dptr );
+ e = str2entry2( data.dptr, 0 );
ldbm_datum_free( db->dbc_db, data );
ldbm_cache_close( be, db );
return NULL;
}
- e = str2entry( data.dptr );
+ e = str2entry2( data.dptr, 0 );
ldbm_datum_free( id2entry->dbc_db, data );
if( e != NULL ) {
&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;
}
/*
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 */
/* 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 ) );
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 );
#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);
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
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;
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,
}
/* 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 ) {
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? */
*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;
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;
if ( !map->drop_missing ) {
*bv = *s;
}
-
- return;
}
int
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;
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
- * This work was originally developed by Howard Chu for inclusion
+ * This work was originally developed by Hallvard Furuseth for inclusion
* in OpenLDAP Software.
*/
* 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
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;
{
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",
&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;
&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," ),
0, 0, 0 );
#endif /* BACKSQL_TRACE */
- return SQLPrepare( *sth, query, SQL_NTS );
+ return SQLPrepare( *sth, (SQLCHAR *)query, SQL_NTS );
}
RETCODE
(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",
}
/* 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;
}
rc = backend_operational( op, &rs );
- if ( rc == LDAP_SUCCESS ) {
+ if ( rc == LDAP_SUCCESS && rs.sr_operational_attrs ) {
+ freeattr = 1;
a = rs.sr_operational_attrs;
}
}
/* 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;
}
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;
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 */
/* bypass the following tests if no descriptors left */
if ( ns <= 0 ) {
+#ifndef HAVE_YIELDING_SELECT
ldap_pvt_thread_yield();
+#endif
continue;
}
}
#endif /* SLAP_EVENTS_ARE_INDEXED */
+#ifndef HAVE_YIELDING_SELECT
ldap_pvt_thread_yield();
+#endif
}
if( slapd_shutdown == 1 ) {
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;
}
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.
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; i<lines; i++) {
+ k = i;
+ for ( j=i+1; j<lines; j++ ) {
+ if ( bvmatch( type+i, type+j )) {
+ /* out of order, move intervening attributes down */
+ if ( j != k+1 ) {
+ int l;
+ bv = vals[j];
+ fv = freeval[j];
+ for ( l=j; l>k; 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 || ( i<lines && !bvmatch( type+i, &ad->ad_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; j<attr_cnt; j++ ) {
+ if ( freeval[k] )
+ atail->a_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 ) {
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,
"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 ) {
"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 )
{
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; i<lines; i++ ) {
+ if ( freeval[i] ) free( vals[i].bv_val );
+ free( nvals[i].bv_val );
+ }
+ free( type );
+ entry_free( e );
+ return NULL;
}
}
/* check attrs in DN AVAs if required */
- if ( mra->ma_dnattrs ) {
+ if ( mra->ma_dnattrs && !BER_BVISEMPTY( &e->e_nname ) ) {
LDAPDN dn = NULL;
int iRDN, iAVA;
int rc;
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;
}
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;
}
};
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);
{
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 );
}
/* 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;
}
} else {
+ assert( mapping->m_dst_ad );
ad = mapping->m_dst_ad;
}
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 );
}
}
}
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;
* 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;
{
/* 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;
}
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 */ ;
}
}
- 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:;
* <http://www.OpenLDAP.org/license.html>.
*/
/* 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.
*/
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,
{
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;
}
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;
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;
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;
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;
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;
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;
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;
/*
* 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 ));
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((
"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 */
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)
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 );
#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 */
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 )
const char *text;
char textbuf[SLAP_TEXT_BUFLEN] = { '\0' };
size_t textlen = sizeof textbuf;
- const char *progname = "slapadd";
struct berval csn;
struct berval maxcsn;
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 ||
}
}
+ 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;
}
while( ldif_read_record( ldiffp, &lineno, &buf, &lmax ) ) {
- Entry *e = str2entry( buf );
+ Entry *e = str2entry2( buf, checkvals );
/*
* Initialize text buffer
}
}
+ 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 ) {
}
}
-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 );
switch( tool ) {
case SLAPADD:
- options = "b:cd:f:l:n:tuvw";
+ options = "b:cd:f:l:n:qtuvw";
break;
case SLAPCAT:
dbnum = atoi( optarg ) - 1;
break;
+ case 'q': /* turn on quick */
+ mode |= SLAP_TOOL_QUICK;
+ break;
+
case 'R':
realm = optarg;
break;
exit( EXIT_FAILURE );
}
+ at_oc_cache = 1;
ldap_syslog = 0;
switch ( tool ) {
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
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
--- /dev/null
+dn: ou=Other,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Other
+
objectClass: top
objectClass: organization
objectClass: domainRelatedObject
-objectClass: dcObject
-dc: example
+objectClass: uidObject
+uid: example
l: Anytown, Michigan
st: Michigan
o: Example, Inc.
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
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.
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
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
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
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
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
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
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
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
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
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
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
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
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!
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
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
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
# 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
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
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
# 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"...
# 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
+
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"
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
sn: Manager
description: Manager of the directory
userpassword:: c2VjcmV0
+
+dn: ou=Other,dc=example,dc=com
+objectclass: organizationalUnit
+ou: Other
+
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
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
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
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
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
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
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..."
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
#