Commit 99f968b5 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Initial support for pre/post read controls.

TODO:
	Fix transactional consistency
	Add client response control handling
parent f5cabd3a
......@@ -19,6 +19,7 @@
#include "lutil_ldap.h"
#include "ldap_defaults.h"
#include "ldap_pvt.h"
#include "common.h"
......@@ -41,10 +42,15 @@ char *sasl_secprops = NULL;
#endif
int use_tls = 0;
int assertctl;
char *assertion = NULL;
char *authzid = NULL;
int manageDSAit = 0;
int noop = 0;
int preread = 0;
char *preread_attrs = NULL;
int postread = 0;
char *postread_attrs = NULL;
int not = 0;
int want_bindpw = 0;
......@@ -75,10 +81,12 @@ N_(" -C chase referrals\n"),
N_(" -d level set LDAP debugging level to `level'\n"),
N_(" -D binddn bind DN\n"),
N_(" -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n")
N_(" [!]assert=<filter> (an RFC 2254 Filter)\n")
N_(" [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n")
N_(" [!]manageDSAit (alternate form, see -M)\n")
N_(" [!]assert=<filter> (an RFC 2254 Filter)\n")
N_(" [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n")
N_(" [!]manageDSAit\n")
N_(" [!]noop\n"),
N_(" [!]postread[=<attrs>] (a comma-separated attribute list)\n"),
N_(" [!]preread[=<attrs>] (a comma-separated attribute list)\n"),
N_(" -f file read operations from `file'\n"),
N_(" -h host LDAP server\n"),
N_(" -H URI LDAP Uniform Resource Indentifier(s)\n"),
......@@ -158,7 +166,7 @@ tool_args( int argc, char **argv )
}
if ( strcasecmp( control, "assert" ) == 0 ) {
if( assertion != NULL ) {
if( assertctl ) {
fprintf( stderr, "assert control previously specified\n");
exit( EXIT_FAILURE );
}
......@@ -167,6 +175,8 @@ tool_args( int argc, char **argv )
usage();
}
assertctl = 1 + crit;
assert( assertion == NULL );
assertion = cvalue;
......@@ -213,6 +223,24 @@ tool_args( int argc, char **argv )
noop = 1 + crit;
} else if ( strcasecmp( control, "preread" ) == 0 ) {
if( preread ) {
fprintf( stderr, "preread control previously specified\n");
exit( EXIT_FAILURE );
}
preread = 1 + crit;
preread_attrs = cvalue;
} else if ( strcasecmp( control, "postread" ) == 0 ) {
if( postread ) {
fprintf( stderr, "postread control previously specified\n");
exit( EXIT_FAILURE );
}
postread = 1 + crit;
postread_attrs = cvalue;
} else {
fprintf( stderr, "Invalid general control name: %s\n",
control );
......@@ -725,7 +753,7 @@ void
tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
{
int i = 0, j, crit = 0, err;
LDAPControl c[4], **ctrls;
LDAPControl c[6], **ctrls;
ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
if ( ctrls == NULL ) {
......@@ -733,11 +761,11 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
exit( EXIT_FAILURE );
}
if ( assertion ) {
if ( assertctl ) {
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
if( *assertion == '\0' ) {
if( assertion == NULL || *assertion == '\0' ) {
fprintf( stderr, "Assertion=<empty>\n" );
exit( EXIT_FAILURE );
}
......@@ -757,7 +785,7 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
}
c[i].ldctl_oid = LDAP_CONTROL_ASSERT;
c[i].ldctl_iscritical = 1;
c[i].ldctl_iscritical = assertctl > 1;
ctrls[i] = &c[i];
i++;
}
......@@ -789,6 +817,66 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
i++;
}
if ( preread ) {
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
char **attrs;
if( preread_attrs ) {
attrs = ldap_str2charray( preread_attrs, "," );
}
ber_init2( ber, NULL, LBER_USE_DER );
if( ber_printf( ber, "{v}", attrs ) == -1 ) {
fprintf( stderr, "preread attrs encode failed.\n" );
exit( EXIT_FAILURE );
}
err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
if( err < 0 ) {
fprintf( stderr, "preread flatten failed (%d)\n", err );
exit( EXIT_FAILURE );
}
c[i].ldctl_oid = LDAP_CONTROL_PRE_READ;
c[i].ldctl_iscritical = preread > 1;
ctrls[i] = &c[i];
i++;
if( attrs ) ldap_charray_free( attrs );
}
if ( postread ) {
char berbuf[LBER_ELEMENT_SIZEOF];
BerElement *ber = (BerElement *)berbuf;
char **attrs;
if( postread_attrs ) {
attrs = ldap_str2charray( postread_attrs, "," );
}
ber_init2( ber, NULL, LBER_USE_DER );
if( ber_printf( ber, "{v}", attrs ) == -1 ) {
fprintf( stderr, "postread attrs encode failed.\n" );
exit( EXIT_FAILURE );
}
err = ber_flatten2( ber, &c[i].ldctl_value, 0 );
if( err < 0 ) {
fprintf( stderr, "postread flatten failed (%d)\n", err );
exit( EXIT_FAILURE );
}
c[i].ldctl_oid = LDAP_CONTROL_POST_READ;
c[i].ldctl_iscritical = postread > 1;
ctrls[i] = &c[i];
i++;
if( attrs ) ldap_charray_free( attrs );
}
while ( count-- ) {
ctrls[i++] = extra_c++;
}
......
......@@ -33,6 +33,7 @@ extern char *assertion;
extern char *authzid;
extern int manageDSAit;
extern int noop;
extern int preread, postread;
extern int not;
extern int want_bindpw;
......
......@@ -225,7 +225,7 @@ main( int argc, char **argv )
rc = 0;
if ( assertion || authzid || manageDSAit || noop ) {
if ( assertion || authzid || manageDSAit || noop || preread || postread ) {
tool_server_controls( ld, NULL, 0 );
}
......
......@@ -532,9 +532,7 @@ LBER_V( Sockbuf_IO ) ber_sockbuf_io_tcp;
LBER_V( Sockbuf_IO ) ber_sockbuf_io_readahead;
LBER_V( Sockbuf_IO ) ber_sockbuf_io_fd;
LBER_V( Sockbuf_IO ) ber_sockbuf_io_debug;
#ifdef LDAP_CONNECTIONLESS
LBER_V( Sockbuf_IO ) ber_sockbuf_io_udp;
#endif
/*
* LBER memory.c
......
......@@ -182,8 +182,8 @@ typedef struct ldapcontrol {
/* LDAP Controls */
#define LDAP_CONTROL_ASSERT "1.3.6.1.4.1.4203.666.5.9"
#define LDAP_CONTROL_PRE_READ_BACK "1.3.6.1.4.1.4203.666.5.10.1"
#define LDAP_CONTROL_POST_READ_BACK "1.3.6.1.4.1.4203.666.5.10.2"
#define LDAP_CONTROL_PRE_READ "1.3.6.1.4.1.4203.666.5.10.1"
#define LDAP_CONTROL_POST_READ "1.3.6.1.4.1.4203.666.5.10.2"
#define LDAP_CONTROL_MODIFY_INCREMENT "1.3.6.1.4.1.4203.666.5.11"
#define LDAP_CONTROL_VALUESRETURNFILTER "1.2.826.0.1.334810.2.3"
......
......@@ -41,6 +41,9 @@ bdb_add(Operation *op, SlapReply *rs )
Entry *ctxcsn_e;
int ctxcsn_added = 0;
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
int num_ctrls = 0;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ARGS, "==> bdb_add: %s\n", op->oq_add.rs_e->e_name.bv_val, 0, 0 );
#else
......@@ -376,6 +379,23 @@ retry: /* transaction retry */
goto return_results;;
}
/* post-read */
if( op->o_postread ) {
if ( slap_read_controls( op, rs, op->oq_add.rs_e,
&slap_post_read_bv, &ctrls[num_ctrls] ) )
{
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_add: post-read failed!\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"<=- bdb_add: post-read failed!\n", 0, 0, 0 );
#endif
goto return_results;
}
ctrls[++num_ctrls] = NULL;
}
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
bdb->bi_db_opflags );
......@@ -465,7 +485,8 @@ retry: /* transaction retry */
}
if ( !op->o_bd->syncinfo ) {
rc = bdb_csn_commit( op, rs, ltid, ei, &suffix_ei, &ctxcsn_e, &ctxcsn_added, locker );
rc = bdb_csn_commit( op, rs, ltid, ei, &suffix_ei,
&ctxcsn_e, &ctxcsn_added, locker );
switch ( rc ) {
case BDB_CSN_ABORT :
goto return_results;
......@@ -527,28 +548,33 @@ retry: /* transaction retry */
ltid = NULL;
op->o_private = NULL;
if (rs->sr_err == LDAP_SUCCESS) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_add: added%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "", op->oq_add.rs_e->e_id, op->oq_add.rs_e->e_dn );
#else
Debug(LDAP_DEBUG_TRACE, "bdb_add: added%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "", op->oq_add.rs_e->e_id, op->oq_add.rs_e->e_dn );
#endif
rs->sr_text = NULL;
}
else {
if (rs->sr_err != LDAP_SUCCESS) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
"bdb_add: %s : %s (%d)\n", rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
"bdb_add: %s : %s (%d)\n", rs->sr_text,
db_strerror(rs->sr_err), rs->sr_err );
#else
Debug( LDAP_DEBUG_TRACE, "bdb_add: %s : %s (%d)\n",
rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
#endif
rs->sr_err = LDAP_OTHER;
goto return_results;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_add: added%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
op->oq_add.rs_e->e_id, op->oq_add.rs_e->e_dn );
#else
Debug(LDAP_DEBUG_TRACE, "bdb_add: added%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
op->oq_add.rs_e->e_id, op->oq_add.rs_e->e_dn );
#endif
rs->sr_text = NULL;
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
send_ldap_result( op, rs );
......@@ -565,7 +591,6 @@ return_results:
}
done:
if( ltid != NULL ) {
TXN_ABORT( ltid );
op->o_private = NULL;
......
......@@ -41,6 +41,9 @@ bdb_delete( Operation *op, SlapReply *rs )
Entry *ctxcsn_e;
int ctxcsn_added = 0;
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
int num_ctrls = 0;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ARGS, "==> bdb_delete: %s\n", op->o_req_dn.bv_val, 0, 0 );
#else
......@@ -319,6 +322,23 @@ retry: /* transaction retry */
goto done;
}
/* pre-read */
if( op->o_preread ) {
if( slap_read_controls( op, rs, e,
&slap_pre_read_bv, &ctrls[num_ctrls] ) )
{
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_delete: pre-read failed!\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"<=- bdb_delete: pre-read failed!\n", 0, 0, 0 );
#endif
goto return_results;
}
ctrls[++num_ctrls] = NULL;
}
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
bdb->bi_db_opflags );
......@@ -501,20 +521,22 @@ retry: /* transaction retry */
rs->sr_err = LDAP_OTHER;
rs->sr_text = "commit failed";
} else {
goto return_results;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_delete: deleted%s id=%08lx db=\"%s\"\n",
op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
LDAP_LOG ( OPERATION, RESULTS,
"bdb_delete: deleted%s id=%08lx db=\"%s\"\n",
op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_delete: deleted%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
e->e_id, e->e_dn );
Debug( LDAP_DEBUG_TRACE,
"bdb_delete: deleted%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
e->e_id, e->e_dn );
#endif
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
}
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
send_ldap_result( op, rs );
......
......@@ -328,6 +328,9 @@ bdb_modify( Operation *op, SlapReply *rs )
int num_retries = 0;
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
int num_ctrls = 0;
Operation* ps_list;
struct psid_entry *pm_list, *pm_prev;
int rc;
......@@ -495,6 +498,23 @@ retry: /* transaction retry */
}
}
if( op->o_preread ) {
if ( slap_read_controls( op, rs, e,
&slap_pre_read_bv, &ctrls[num_ctrls] ) )
{
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_modify: pre-read failed!\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"<=- bdb_modify: pre-read failed!\n", 0, 0, 0 );
#endif
goto return_results;
}
ctrls[++num_ctrls] = NULL;
op->o_preread = 0; /* prevent redo on retry */
}
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
bdb->bi_db_opflags );
......@@ -537,6 +557,24 @@ retry: /* transaction retry */
goto return_results;
}
if( op->o_postread ) {
if( slap_read_controls( op, rs, e,
&slap_post_read_bv, &ctrls[num_ctrls] ) )
{
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_modify: post-read failed!\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"<=- bdb_modify: post-read failed!\n", 0, 0, 0 );
#endif
goto return_results;
}
ctrls[++num_ctrls] = NULL;
op->o_postread = 0; /* prevent redo on retry */
/* FIXME: should read entry on the last retry */
}
/* change the entry itself */
rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
if ( rs->sr_err != 0 ) {
......@@ -556,6 +594,7 @@ retry: /* transaction retry */
rs->sr_text = "entry update failed";
goto return_results;
}
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
......@@ -563,7 +602,8 @@ retry: /* transaction retry */
}
if ( !op->o_bd->syncinfo ) {
rc = bdb_csn_commit( op, rs, ltid, ei, &suffix_ei, &ctxcsn_e, &ctxcsn_added, locker );
rc = bdb_csn_commit( op, rs, ltid, ei, &suffix_ei,
&ctxcsn_e, &ctxcsn_added, locker );
switch ( rc ) {
case BDB_CSN_ABORT :
goto return_results;
......@@ -598,12 +638,12 @@ retry: /* transaction retry */
ltid = NULL;
op->o_private = NULL;
if( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
"bdb_modify: txn_%s failed %s (%d)\n",
op->o_noop ? "abort (no_op)" : "commit", db_strerror(rs->sr_err), rs->sr_err );
op->o_noop ? "abort (no_op)" : "commit",
db_strerror(rs->sr_err), rs->sr_err );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_modify: txn_%s failed: %s (%d)\n",
......@@ -613,20 +653,23 @@ retry: /* transaction retry */
rs->sr_err = LDAP_OTHER;
rs->sr_text = "commit failed";
} else {
goto return_results;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"bdb_modify: updated%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no_op)" : "", e->e_id, e->e_dn );
LDAP_LOG ( OPERATION, DETAIL1,
"bdb_modify: updated%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no_op)" : "", e->e_id, e->e_dn );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_modify: updated%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
e->e_id, e->e_dn );
Debug( LDAP_DEBUG_TRACE,
"bdb_modify: updated%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
e->e_id, e->e_dn );
#endif
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
}
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
send_ldap_result( op, rs );
......
......@@ -53,6 +53,9 @@ bdb_modrdn( Operation *op, SlapReply *rs )
int num_retries = 0;
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
int num_ctrls = 0;
Operation *ps_list;
struct psid_entry *pm_list, *pm_prev;
int rc;
......@@ -763,6 +766,23 @@ retry: /* transaction retry */
}
}
if( op->o_preread ) {
if( slap_read_controls( op, rs, e,
&slap_pre_read_bv, &ctrls[num_ctrls] ) )
{
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 );
#endif
goto return_results;
}
ctrls[++num_ctrls] = NULL;
op->o_preread = 0; /* prevent redo on retry */
}
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
bdb->bi_db_opflags );
......@@ -874,7 +894,25 @@ retry: /* transaction retry */
}
goto return_results;
}
if( op->o_postread ) {
if( slap_read_controls( op, rs, e,
&slap_post_read_bv, &ctrls[num_ctrls] ) )
{
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 );
#endif
goto return_results;
}
ctrls[++num_ctrls] = NULL;
op->o_postread = 0; /* prevent redo on retry */
/* FIXME: should read entry on the last retry */
}
/* id2entry index */
rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, e );
if ( rs->sr_err != 0 ) {
......@@ -953,18 +991,7 @@ retry: /* transaction retry */
ltid = NULL;
op->o_private = NULL;
if( rs->sr_err == LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
#else
Debug(LDAP_DEBUG_TRACE,
"bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
#endif
rs->sr_text = NULL;
} else {
if( rs->sr_err != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS, "bdb_modrdn: %s : %s (%d)\n",
rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
......@@ -973,8 +1000,22 @@ retry: /* transaction retry */
rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
#endif
rs->sr_err = LDAP_OTHER;
goto return_results;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
#else
Debug(LDAP_DEBUG_TRACE,
"bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
#endif
rs->sr_text = NULL;
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
send_ldap_result( op, rs );
......