Commit 5bf7c9a6 authored by Quanah Gibson-Mount's avatar Quanah Gibson-Mount
Browse files

ITS#6442

parent 302e8d5f
......@@ -2,6 +2,7 @@ OpenLDAP 2.4 Change Log
OpenLDAP 2.4.22 Engineering
Added slapd SLAP_SCHEMA_EXPOSE flag for hidden schema elements (ITS#6435)
Added slapd tools selective iterations (ITS#6442)
Added slapo-pbind
Fixed libldap GnuTLS serial length (ITS#6460)
Fixed slapd certificateListValidate (ITS#6466)
......
......@@ -2,11 +2,11 @@ Tools ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
slapacl D F U X b d f o uv
slapadd F S bcd fg j l no q s uvw
slapauth F M R U X d f o v
slapcat F abcd fg l no s v
slapcat F H abcd fg l no s v
slapdn F N P d f o v
slapindex F bcd fg no q t v
slappasswd T c h s uv
slapschema F abcd fg l no s v
slapschema F H abcd fg l no s v
slaptest F Q d f no uv
* General flags:
......
......@@ -21,6 +21,8 @@ slapcat \- SLAPD database to LDIF utility
[\c
.BR \-g ]
[\c
.BI \-H URI\fR]
[\c
.BI \-l ldif-file\fR]
[\c
.BI \-n dbnum\fR]
......@@ -69,6 +71,7 @@ slapcat \-a \\
will dump all but the "ou=People,dc=example,dc=com" subtree
of the "dc=example,dc=com" database.
Deprecated; use \fB-H\fP \fIldap:///???(filter)\fP instead.
.TP
.BI \-b \ suffix
Use the specified \fIsuffix\fR to determine which database to
......@@ -109,6 +112,9 @@ default config file is ignored.
disable subordinate gluing. Only the specified database will be
processed, and not its glued subordinates (if any).
.TP
.B \-H \ URI
use dn, scope and filter from URI to only handle matching entries.
.TP
.BI \-l \ ldif-file
Write LDIF to specified file instead of standard output.
.TP
......@@ -147,6 +153,7 @@ Implies \fB\-b\fP \fIsubtree-dn\fP if no
or
.B \-n
option is given.
Deprecated; use \fB-H\fP \fIldap:///subtree-dn\fP instead.
.TP
.B \-v
Enable verbose mode.
......
......@@ -21,6 +21,8 @@ slapschema \- SLAPD in-database schema checking utility
[\c
.BR \-g ]
[\c
.BI \-H URI\fR]
[\c
.BI \-l error-file\fR]
[\c
.BI \-n dbnum\fR]
......@@ -72,6 +74,7 @@ slapschema \-a \\
will check all but the "ou=People,dc=example,dc=com" subtree
of the "dc=example,dc=com" database.
Deprecated; use \fB-H\fP \fIldap:///???(filter)\fP instead.
.TP
.BI \-b \ suffix
Use the specified \fIsuffix\fR to determine which database to
......@@ -112,6 +115,9 @@ default config file is ignored.
disable subordinate gluing. Only the specified database will be
processed, and not its glued subordinates (if any).
.TP
.B \-H \ URI
use dn, scope and filter from URI to only handle matching entries.
.TP
.BI \-l \ error-file
Write errors to specified file instead of standard output.
.TP
......@@ -149,6 +155,7 @@ Implies \fB\-b\fP \fIsubtree-dn\fP if no
nor
.B \-n
option is given.
Deprecated; use \fB-H\fP \fIldap:///subtree-dn\fP instead.
.TP
.B \-v
Enable verbose mode.
......
......@@ -830,7 +830,8 @@ bdb_back_initialize(
*/
bi->bi_tool_entry_open = bdb_tool_entry_open;
bi->bi_tool_entry_close = bdb_tool_entry_close;
bi->bi_tool_entry_first = bdb_tool_entry_next;
bi->bi_tool_entry_first = backend_tool_entry_first;
bi->bi_tool_entry_first_x = bdb_tool_entry_first_x;
bi->bi_tool_entry_next = bdb_tool_entry_next;
bi->bi_tool_entry_get = bdb_tool_entry_get;
bi->bi_tool_entry_put = bdb_tool_entry_put;
......
......@@ -627,6 +627,7 @@ bdb_trans_backoff( int num_retries );
#define bdb_hasSubordinates BDB_SYMBOL(hasSubordinates)
#define bdb_tool_entry_open BDB_SYMBOL(tool_entry_open)
#define bdb_tool_entry_close BDB_SYMBOL(tool_entry_close)
#define bdb_tool_entry_first_x BDB_SYMBOL(tool_entry_first_x)
#define bdb_tool_entry_next BDB_SYMBOL(tool_entry_next)
#define bdb_tool_entry_get BDB_SYMBOL(tool_entry_get)
#define bdb_tool_entry_put BDB_SYMBOL(tool_entry_put)
......@@ -657,6 +658,7 @@ extern BI_has_subordinates bdb_hasSubordinates;
/* tools.c */
extern BI_tool_entry_open bdb_tool_entry_open;
extern BI_tool_entry_close bdb_tool_entry_close;
extern BI_tool_entry_first_x bdb_tool_entry_first_x;
extern BI_tool_entry_next bdb_tool_entry_next;
extern BI_tool_entry_get bdb_tool_entry_get;
extern BI_tool_entry_put bdb_tool_entry_put;
......
......@@ -42,6 +42,11 @@ static unsigned nholes;
static int index_nattrs;
static struct berval *tool_base;
static int tool_scope;
static Filter *tool_filter;
static Entry *tool_next_entry;
#ifdef BDB_TOOL_IDL_CACHING
#define bdb_tool_idl_cmp BDB_SYMBOL(tool_idl_cmp)
#define bdb_tool_idl_flush_one BDB_SYMBOL(tool_idl_flush_one)
......@@ -91,6 +96,9 @@ static void * bdb_tool_trickle_task( void *ctx, void *ptr );
static void * bdb_tool_index_task( void *ctx, void *ptr );
static int
bdb_tool_entry_get_int( BackendDB *be, ID id, Entry **ep );
int bdb_tool_entry_open(
BackendDB *be, int mode )
{
......@@ -187,6 +195,20 @@ int bdb_tool_entry_close(
return 0;
}
ID
bdb_tool_entry_first_x(
BackendDB *be,
struct berval *base,
int scope,
Filter *f )
{
tool_base = base;
tool_scope = scope;
tool_filter = f;
return bdb_tool_entry_next( be );
}
ID bdb_tool_entry_next(
BackendDB *be )
{
......@@ -198,6 +220,7 @@ ID bdb_tool_entry_next(
assert( slapMode & SLAP_TOOL_MODE );
assert( bdb != NULL );
next:;
/* Get the header */
data.ulen = data.dlen = sizeof( ehbuf );
data.data = ehbuf;
......@@ -224,6 +247,47 @@ ID bdb_tool_entry_next(
BDB_DISK2ID( key.data, &id );
previd = id;
if ( tool_filter || tool_base ) {
static Operation op = {0};
static Opheader ohdr = {0};
op.o_hdr = &ohdr;
op.o_bd = be;
op.o_tmpmemctx = NULL;
op.o_tmpmfuncs = &ch_mfuncs;
if ( tool_next_entry ) {
bdb_entry_release( &op, tool_next_entry, 0 );
tool_next_entry = NULL;
}
rc = bdb_tool_entry_get_int( be, id, &tool_next_entry );
if ( rc == LDAP_NO_SUCH_OBJECT ) {
goto next;
}
assert( tool_next_entry != NULL );
#ifdef BDB_HIER
/* TODO: needed until BDB_HIER is handled accordingly
* in bdb_tool_entry_get_int() */
if ( tool_base && !dnIsSuffixScope( &tool_next_entry->e_nname, tool_base, tool_scope ) )
{
bdb_entry_release( &op, tool_next_entry, 0 );
tool_next_entry = NULL;
goto next;
}
#endif
if ( tool_filter && test_filter( NULL, tool_next_entry, tool_filter ) != LDAP_COMPARE_TRUE )
{
bdb_entry_release( &op, tool_next_entry, 0 );
tool_next_entry = NULL;
goto next;
}
}
return id;
}
......@@ -253,7 +317,8 @@ ID bdb_tool_dn2id_get(
return ei->bei_id;
}
Entry* bdb_tool_entry_get( BackendDB *be, ID id )
static int
bdb_tool_entry_get_int( BackendDB *be, ID id, Entry **ep )
{
Entry *e = NULL;
char *dptr;
......@@ -262,6 +327,12 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
assert( be != NULL );
assert( slapMode & SLAP_TOOL_MODE );
if ( ( tool_filter || tool_base ) && id == previd && tool_next_entry != NULL ) {
*ep = tool_next_entry;
tool_next_entry = NULL;
return LDAP_SUCCESS;
}
if ( id != previd ) {
data.ulen = data.dlen = sizeof( ehbuf );
data.data = ehbuf;
......@@ -269,7 +340,10 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
BDB_ID2DISK( id, &nid );
rc = cursor->c_get( cursor, &key, &data, DB_SET );
if ( rc ) goto done;
if ( rc ) {
rc = LDAP_OTHER;
goto done;
}
}
/* Get the header */
......@@ -279,13 +353,19 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
rc = entry_header( &eh );
eoff = eh.data - eh.bv.bv_val;
eh.bv.bv_val = dptr;
if ( rc ) goto done;
if ( rc ) {
rc = LDAP_OTHER;
goto done;
}
/* Get the size */
data.flags &= ~DB_DBT_PARTIAL;
data.ulen = 0;
rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
if ( rc != DB_BUFFER_SMALL ) goto done;
rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
if ( rc != DB_BUFFER_SMALL ) {
rc = LDAP_OTHER;
goto done;
}
/* Allocate a block and retrieve the data */
eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size;
......@@ -297,8 +377,23 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
/* Skip past already parsed nattr/nvals */
eh.data += eoff;
rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
if ( rc ) goto done;
rc = cursor->c_get( cursor, &key, &data, DB_CURRENT );
if ( rc ) {
rc = LDAP_OTHER;
goto done;
}
#ifndef BDB_HIER
/* TODO: handle BDB_HIER accordingly */
if ( tool_base != NULL ) {
struct berval ndn;
entry_decode_dn( &eh, NULL, &ndn );
if ( !dnIsSuffixScope( &ndn, tool_base, tool_scope ) ) {
return LDAP_NO_SUCH_OBJECT;
}
}
#endif
#ifdef SLAP_ZONE_ALLOC
/* FIXME: will add ctx later */
......@@ -334,7 +429,23 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
#endif
}
done:
return e;
if ( e != NULL ) {
*ep = e;
}
return rc;
}
Entry*
bdb_tool_entry_get( BackendDB *be, ID id )
{
Entry *e = NULL;
int rc;
rc = bdb_tool_entry_get_int( be, id, &e );
if ( rc == LDAP_SUCCESS ) {
return e;
}
}
static int bdb_tool_next_id(
......@@ -610,6 +721,9 @@ int bdb_tool_entry_reindex(
Operation op = {0};
Opheader ohdr = {0};
assert( tool_base == NULL );
assert( tool_filter == NULL );
Debug( LDAP_DEBUG_ARGS,
"=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld )\n",
(long) id, 0, 0 );
......
......@@ -37,6 +37,9 @@ struct ldif_tool {
ID ecount; /* number of entries */
ID ecurrent; /* bi_tool_entry_next() position */
# define ENTRY_BUFF_INCREMENT 500 /* initial entries[] length */
struct berval *tl_base;
int tl_scope;
Filter *tl_filter;
};
/* Per-database data */
......@@ -1581,17 +1584,38 @@ ldif_tool_entry_next( BackendDB *be )
{
struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
if ( tl->ecurrent >= tl->ecount )
return NOID;
else
return ++tl->ecurrent;
do {
Entry *e = tl->entries[ tl->ecurrent ];
if ( tl->ecurrent >= tl->ecount ) {
return NOID;
}
++tl->ecurrent;
if ( tl->tl_base && !dnIsSuffixScope( &e->e_nname, tl->tl_base, tl->tl_scope ) ) {
continue;
}
if ( tl->tl_filter && test_filter( NULL, e, tl->tl_filter ) != LDAP_COMPARE_TRUE ) {
continue;
}
break;
} while ( 1 );
return tl->ecurrent;
}
static ID
ldif_tool_entry_first( BackendDB *be )
ldif_tool_entry_first_x( BackendDB *be, struct berval *base, int scope, Filter *f )
{
struct ldif_tool *tl = &((struct ldif_info *) be->be_private)->li_tool;
tl->tl_base = base;
tl->tl_scope = scope;
tl->tl_filter = f;
if ( tl->entries == NULL ) {
Operation op = {0};
......@@ -1740,7 +1764,8 @@ ldif_back_initialize( BackendInfo *bi )
bi->bi_tool_entry_open = ldif_tool_entry_open;
bi->bi_tool_entry_close = ldif_tool_entry_close;
bi->bi_tool_entry_first = ldif_tool_entry_first;
bi->bi_tool_entry_first = backend_tool_entry_first;
bi->bi_tool_entry_first_x = ldif_tool_entry_first_x;
bi->bi_tool_entry_next = ldif_tool_entry_next;
bi->bi_tool_entry_get = ldif_tool_entry_get;
bi->bi_tool_entry_put = ldif_tool_entry_put;
......
......@@ -2061,6 +2061,7 @@ monitor_back_initialize(
bi->bi_tool_entry_open = 0;
bi->bi_tool_entry_close = 0;
bi->bi_tool_entry_first = 0;
bi->bi_tool_entry_first_x = 0;
bi->bi_tool_entry_next = 0;
bi->bi_tool_entry_get = 0;
bi->bi_tool_entry_put = 0;
......
......@@ -254,6 +254,12 @@ null_tool_entry_close( BackendDB *be )
return 0;
}
static ID
null_tool_entry_first_x( BackendDB *be, struct berval *base, int scope, Filter *f )
{
return NOID;
}
static ID
null_tool_entry_next( BackendDB *be )
{
......@@ -392,7 +398,8 @@ null_back_initialize( BackendInfo *bi )
bi->bi_tool_entry_open = null_tool_entry_open;
bi->bi_tool_entry_close = null_tool_entry_close;
bi->bi_tool_entry_first = null_tool_entry_next;
bi->bi_tool_entry_first = backend_tool_entry_first;
bi->bi_tool_entry_first_x = null_tool_entry_first_x;
bi->bi_tool_entry_next = null_tool_entry_next;
bi->bi_tool_entry_get = null_tool_entry_get;
bi->bi_tool_entry_put = null_tool_entry_put;
......
......@@ -1965,3 +1965,12 @@ int backend_operational( Operation *op, SlapReply *rs )
return rc;
}
/* helper that calls the bi_tool_entry_first_x() variant with default args;
* use to initialize a backend's bi_tool_entry_first() when appropriate
*/
ID
backend_tool_entry_first( BackendDB *be )
{
return be->bd_info->bi_tool_entry_first_x( be,
NULL, LDAP_SCOPE_DEFAULT, NULL );
}
......@@ -735,6 +735,10 @@ glue_entry_release_rw (
return rc;
}
static struct berval *glue_base;
static int glue_scope;
static Filter *glue_filter;
static ID
glue_tool_entry_first (
BackendDB *b0
......@@ -785,6 +789,66 @@ glue_tool_entry_first (
return rc;
}
static ID
glue_tool_entry_first_x (
BackendDB *b0,
struct berval *base,
int scope,
Filter *f
)
{
slap_overinst *on = glue_tool_inst( b0->bd_info );
glueinfo *gi = on->on_bi.bi_private;
int i;
ID rc;
glue_base = base;
glue_scope = scope;
glue_filter = f;
/* If we're starting from scratch, start at the most general */
if (!glueBack) {
if ( toolDB.be_entry_open && toolDB.be_entry_first_x ) {
glueBack = &toolDB;
} else {
for (i = gi->gi_nodes-1; i >= 0; i--) {
if (gi->gi_n[i].gn_be->be_entry_open &&
gi->gi_n[i].gn_be->be_entry_first_x)
{
glueBack = gi->gi_n[i].gn_be;
break;
}
}
}
}
if (!glueBack || !glueBack->be_entry_open || !glueBack->be_entry_first_x ||
glueBack->be_entry_open (glueBack, glueMode) != 0)
return NOID;
rc = glueBack->be_entry_first_x (glueBack,
glue_base, glue_scope, glue_filter);
while ( rc == NOID ) {
if ( glueBack && glueBack->be_entry_close )
glueBack->be_entry_close (glueBack);
for (i=0; i<gi->gi_nodes; i++) {
if (gi->gi_n[i].gn_be == glueBack)
break;
}
if (i == 0) {
glueBack = GLUEBACK_DONE;
break;
} else {
glueBack = gi->gi_n[i-1].gn_be;
rc = glue_tool_entry_first_x (b0,
glue_base, glue_scope, glue_filter);
if ( glueBack == GLUEBACK_DONE ) {
break;
}
}
}
return rc;
}
static ID
glue_tool_entry_next (
BackendDB *b0
......@@ -813,7 +877,15 @@ glue_tool_entry_next (
break;
} else {
glueBack = gi->gi_n[i-1].gn_be;
rc = glue_tool_entry_first (b0);
if ( glue_base || glue_filter ) {
/* using entry_first_x() */
rc = glue_tool_entry_first_x (b0,
glue_base, glue_scope, glue_filter);
} else {
/* using entry_first() */
rc = glue_tool_entry_first (b0);
}
if ( glueBack == GLUEBACK_DONE ) {
break;
}
......@@ -1012,6 +1084,9 @@ glue_db_init(
oi->oi_bi.bi_tool_entry_close = glue_tool_entry_close;
if ( bi->bi_tool_entry_first )
oi->oi_bi.bi_tool_entry_first = glue_tool_entry_first;
/* FIXME: check whether all support bi_tool_entry_first_x() ? */
if ( bi->bi_tool_entry_first_x )
oi->oi_bi.bi_tool_entry_first_x = glue_tool_entry_first_x;
if ( bi->bi_tool_entry_next )
oi->oi_bi.bi_tool_entry_next = glue_tool_entry_next;
if ( bi->bi_tool_entry_get )
......
......@@ -6789,10 +6789,30 @@ config_tool_entry_first( BackendDB *be )
CfBackInfo *cfb = be->be_private;
BackendInfo *bi = cfb->cb_db.bd_info;
if ( bi && bi->bi_tool_entry_first )
if ( bi && bi->bi_tool_entry_first ) {
return bi->bi_tool_entry_first( &cfb->cb_db );
else
return NOID;
}
if ( bi && bi->bi_tool_entry_first_x ) {
return bi->bi_tool_entry_first_x( &cfb->cb_db,
NULL, LDAP_SCOPE_DEFAULT, NULL );
}
return NOID;
}
static ID
config_tool_entry_first_x(
BackendDB *be,
struct berval *base,
int scope,
Filter *f )
{
CfBackInfo *cfb = be->be_private;
BackendInfo *bi = cfb->cb_db.bd_info;
if ( bi && bi->bi_tool_entry_first_x ) {
return bi->bi_tool_entry_first_x( &cfb->cb_db, base, scope, f );
}
return NOID;
}
static ID
......@@ -7039,6 +7059,7 @@ config_back_initialize( BackendInfo *bi )
bi->bi_tool_entry_open = config_tool_entry_open;
bi->bi_tool_entry_close = config_tool_entry_close;
bi->bi_tool_entry_first = config_tool_entry_first;
bi->bi_tool_entry_first_x = config_tool_entry_first_x;
bi->bi_tool_entry_next = config_tool_entry_next;
bi->bi_tool_entry_get = config_tool_entry_get;
bi->bi_tool_entry_put = config_tool_entry_put;
......
......@@ -428,6 +428,8 @@ LDAP_SLAPD_F (int) backend_operational LDAP_P((
SlapReply *rs
));
LDAP_SLAPD_F (ID) backend_tool_entry_first LDAP_P(( BackendDB *be ));
LDAP_SLAPD_V(BackendInfo) slap_binfo[];
/*
......
......@@ -1788,6 +1788,7 @@ struct BackendDB {
#define be_entry_open bd_info->bi_tool_entry_open
#define be_entry_close bd_info->bi_tool_entry_close
#define be_entry_first bd_info->bi_tool_entry_first
#define be_entry_first_x bd_info->bi_tool_entry_first_x
#define be_entry_next bd_info->bi_tool_entry_next
#define be_entry_reindex bd_info->bi_tool_entry_reindex
#define be_entry_get bd_info->bi_tool_entry_get
......@@ -2158,6 +2159,7 @@ typedef BI_conn_func BI_connection_destroy;
typedef int (BI_tool_entry_open) LDAP_P(( BackendDB *be, int mode ));
typedef int (BI_tool_entry_close) LDAP_P(( BackendDB *be ));
typedef ID (BI_tool_entry_first) LDAP_P(( BackendDB *be ));
typedef ID (BI_tool_entry_first_x) LDAP_P(( BackendDB *be, struct berval *base, int scope, Filter *f ));
typedef ID (BI_tool_entry_next) LDAP_P(( BackendDB *be ));
typedef Entry* (BI_tool_entry_get) LDAP_P(( BackendDB *be, ID id ));
typedef ID (BI_tool_entry_put) LDAP_P(( BackendDB *be, Entry *e,
......@@ -2257,7 +2259,8 @@ struct BackendInfo {
/* hooks for slap tools */
BI_tool_entry_open *bi_tool_entry_open;
BI_tool_entry_close *bi_tool_entry_close;
BI_tool_entry_first *bi_tool_entry_first;
BI_tool_entry_first *bi_tool_entry_first; /* deprecated */
BI_tool_entry_first_x *bi_tool_entry_first_x;