Commit 7bcdfe95 authored by Howard Chu's avatar Howard Chu
Browse files

ITS#5153 from HEAD - sorted values

parent 988418f7
......@@ -479,6 +479,8 @@ lookup. The default is 2. For example, with the default values, a search
using this filter "cn=*abcdefgh*" would generate index lookups for
"abcd", "cdef", and "efgh".
Note: Indexing support depends on the particular backend in use.
.TP
.B olcLocalSSF: <SSF>
Specifies the Security Strength Factor (SSF) to be given local LDAP sessions,
......@@ -616,42 +618,6 @@ versions of crypt(3) to use an MD5 algorithm and provides
8 random characters of salt. The default is "%s", which
provides 31 characters of salt.
.TP
.B olcPasswordHash: <hash> [<hash>...]
This option configures one or more hashes to be used in generation of user
passwords stored in the userPassword attribute during processing of
LDAP Password Modify Extended Operations (RFC 3062).
The <hash> must be one of
.BR {SSHA} ,
.BR {SHA} ,
.BR {SMD5} ,
.BR {MD5} ,
.BR {CRYPT} ,
and
.BR {CLEARTEXT} .
The default is
.BR {SSHA} .
.B {SHA}
and
.B {SSHA}
use the SHA-1 algorithm (FIPS 160-1), the latter with a seed.
.B {MD5}
and
.B {SMD5}
use the MD5 algorithm (RFC 1321), the latter with a seed.
.B {CRYPT}
uses the
.BR crypt (3).
.B {CLEARTEXT}
indicates that the new password should be
added to userPassword as clear text.
Note that this option does not alter the normal user applications
handling of userPassword during LDAP Add, Modify, or other LDAP operations.
.TP
.B olcPidFile: <filename>
The ( absolute ) name of a file that will hold the
.B slapd
......@@ -1079,6 +1045,43 @@ non-base search request with an empty base DN.
Base scoped search requests with an empty base DN are not affected.
This setting is only allowed in the frontend entry.
.TP
.B olcPasswordHash: <hash> [<hash>...]
This option configures one or more hashes to be used in generation of user
passwords stored in the userPassword attribute during processing of
LDAP Password Modify Extended Operations (RFC 3062).
The <hash> must be one of
.BR {SSHA} ,
.BR {SHA} ,
.BR {SMD5} ,
.BR {MD5} ,
.BR {CRYPT} ,
and
.BR {CLEARTEXT} .
The default is
.BR {SSHA} .
.B {SHA}
and
.B {SSHA}
use the SHA-1 algorithm (FIPS 160-1), the latter with a seed.
.B {MD5}
and
.B {SMD5}
use the MD5 algorithm (RFC 1321), the latter with a seed.
.B {CRYPT}
uses the
.BR crypt (3).
.B {CLEARTEXT}
indicates that the new password should be
added to userPassword as clear text.
Note that this option does not alter the normal user applications
handling of userPassword during LDAP Add, Modify, or other LDAP operations.
This setting is only allowed in the frontend entry.
.TP
.B olcReadOnly: TRUE | FALSE
This option puts the database into "read-only" mode. Any attempts to
modify the database will return an "unwilling to perform" error. By
......@@ -1189,6 +1192,15 @@ See
.BR olcLimits
for an explanation of the different flags.
.TP
.B olcSortVals <attr> [...]
Specify a list of multi-valued attributes whose values will always
be maintained in sorted order. Using this option will allow Modify,
Compare, and filter evaluations on these attributes to be performed
more efficiently. The resulting sort order depends on the
attributes' syntax and matching rules and may not correspond to
lexical order or any other recognizable order.
This setting is only allowed in the frontend entry.
.TP
.B olcTimeLimit: {<integer>|unlimited}
.TP
.B olcTimeLimit: time[.{soft|hard}]=<integer> [...]
......
......@@ -495,6 +495,9 @@ for the segments of a filter string that are processed for a subany index
lookup. The default is 2. For example, with the default values, a search
using this filter "cn=*abcdefgh*" would generate index lookups for
"abcd", "cdef", and "efgh".
Note: Indexing support depends on the particular backend in use.
.TP
.B localSSF <SSF>
Specifies the Security Strength Factor (SSF) to be given local LDAP sessions,
......@@ -891,6 +894,14 @@ The default is 262143.
Specify the maximum incoming LDAP PDU size for authenticated sessions.
The default is 4194303.
.TP
.B sortvals <attr> [...]
Specify a list of multi-valued attributes whose values will always
be maintained in sorted order. Using this option will allow Modify,
Compare, and filter evaluations on these attributes to be performed
more efficiently. The resulting sort order depends on the
attributes' syntax and matching rules and may not correspond to
lexical order or any other recognizable order.
.TP
.B threads <integer>
Specify the maximum size of the primary thread pool.
The default is 16; the minimum value is 2.
......
......@@ -592,11 +592,10 @@ aci_mask(
at != NULL;
at = attrs_find( at->a_next, ad ) )
{
if ( value_find_ex( ad,
if ( attr_valfind( at,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
at->a_nvals,
&op->o_ndn, op->o_tmpmemctx ) == 0 )
&op->o_ndn, NULL, op->o_tmpmemctx ) == 0 )
{
rc = 1;
break;
......
......@@ -974,11 +974,10 @@ acl_mask_dnattr(
at != NULL;
at = attrs_find( at->a_next, bdn->a_at ) )
{
if ( value_find_ex( bdn->a_at,
if ( attr_valfind( at,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
at->a_nvals,
&bv, op->o_tmpmemctx ) == 0 )
&bv, NULL, op->o_tmpmemctx ) == 0 )
{
/* found it */
match = 1;
......@@ -2043,11 +2042,6 @@ acl_set_cb_gather( Operation *op, SlapReply *rs )
a = attr_find( rs->sr_entry->e_attrs, desc );
if ( a != NULL ) {
int i;
for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ )
;
bvalsp = a->a_nvals;
}
}
......
......@@ -380,6 +380,7 @@ slap_mods2entry(
char *textbuf, size_t textlen )
{
Attribute **tail;
int i;
if ( initial ) {
assert( (*e)->e_attrs == NULL );
......@@ -400,7 +401,7 @@ slap_mods2entry(
if( attr != NULL ) {
#define SLURPD_FRIENDLY
#ifdef SLURPD_FRIENDLY
ber_len_t i,j;
int j;
if ( !initial ) {
/*
......@@ -413,12 +414,9 @@ slap_mods2entry(
return LDAP_SUCCESS;
}
for( i=0; attr->a_vals[i].bv_val; i++ ) {
/* count them */
}
for( j=0; mods->sml_values[j].bv_val; j++ ) {
/* count them */
}
i = attr->a_numvals;
j = mods->sml_numvals;
attr->a_numvals += j;
j++; /* NULL */
attr->a_vals = ch_realloc( attr->a_vals,
......@@ -466,9 +464,9 @@ slap_mods2entry(
attr = attr_alloc( mods->sml_desc );
/* move values to attr structure */
i = mods->sml_numvals;
attr->a_numvals = mods->sml_numvals;
if ( dup ) {
int i;
for ( i = 0; mods->sml_values[i].bv_val; i++ ) /* EMPTY */;
attr->a_vals = (BerVarray) ch_calloc( i+1, sizeof( BerValue ));
for ( i = 0; mods->sml_values[i].bv_val; i++ ) {
ber_dupbv( &attr->a_vals[i], &mods->sml_values[i] );
......@@ -480,8 +478,7 @@ slap_mods2entry(
if ( mods->sml_nvalues ) {
if ( dup ) {
int i;
for ( i = 0; mods->sml_nvalues[i].bv_val; i++ ) /* EMPTY */;
i = mods->sml_numvals;
attr->a_nvals = (BerVarray) ch_calloc( i+1, sizeof( BerValue ));
for ( i = 0; mods->sml_nvalues[i].bv_val; i++ ) {
ber_dupbv( &attr->a_nvals[i], &mods->sml_nvalues[i] );
......@@ -493,6 +490,9 @@ slap_mods2entry(
} else {
attr->a_nvals = attr->a_vals;
}
/* slap_mods_check() gives us sorted results */
if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL )
attr->a_flags |= SLAP_ATTR_SORTED_VALS;
*tail = attr;
tail = &attr->a_next;
......@@ -528,7 +528,8 @@ slap_entry2mods(
mod->sml_type = a_new_desc->ad_cname;
for ( count = 0; a_new->a_vals[count].bv_val; count++ ) /* EMPTY */;
count = a_new->a_numvals;
mod->sml_numvals = a_new->a_numvals;
mod->sml_values = (struct berval*) malloc(
(count+1) * sizeof( struct berval) );
......
......@@ -153,6 +153,7 @@ attr_clean( Attribute *a )
a->a_comp_data = NULL;
#endif
a->a_flags = 0;
a->a_numvals = 0;
}
void
......@@ -210,15 +211,13 @@ attrs_free( Attribute *a )
static void
attr_dup2( Attribute *tmp, Attribute *a )
{
tmp->a_flags = a->a_flags & SLAP_ATTR_PERSISTENT_FLAGS;
if ( a->a_vals != NULL ) {
int i;
for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
/* EMPTY */ ;
}
tmp->a_vals = ch_malloc( (i + 1) * sizeof(struct berval) );
for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) {
tmp->a_numvals = a->a_numvals;
tmp->a_vals = ch_malloc( (tmp->a_numvals + 1) * sizeof(struct berval) );
for ( i = 0; i < tmp->a_numvals; i++ ) {
ber_dupbv( &tmp->a_vals[i], &a->a_vals[i] );
if ( BER_BVISNULL( &tmp->a_vals[i] ) ) break;
/* FIXME: error? */
......@@ -231,7 +230,7 @@ attr_dup2( Attribute *tmp, Attribute *a )
if ( a->a_nvals != a->a_vals ) {
int j;
tmp->a_nvals = ch_malloc( (i + 1) * sizeof(struct berval) );
tmp->a_nvals = ch_malloc( (tmp->a_numvals + 1) * sizeof(struct berval) );
for ( j = 0; !BER_BVISNULL( &a->a_nvals[j] ); j++ ) {
assert( j < i );
ber_dupbv( &tmp->a_nvals[j], &a->a_nvals[j] );
......@@ -283,6 +282,163 @@ attrs_dup( Attribute *a )
return anew;
}
int
attr_valfind(
Attribute *a,
unsigned flags,
struct berval *val,
unsigned *slot,
void *ctx )
{
struct berval nval = BER_BVNULL, *cval;
MatchingRule *mr;
const char *text;
int match = -1, rc;
unsigned i;
if ( flags & SLAP_MR_ORDERING )
mr = a->a_desc->ad_type->sat_ordering;
else
mr = a->a_desc->ad_type->sat_equality;
if( !SLAP_IS_MR_ASSERTED_VALUE_NORMALIZED_MATCH( flags ) &&
mr->smr_normalize )
{
rc = (mr->smr_normalize)(
flags & (SLAP_MR_TYPE_MASK|SLAP_MR_SUBTYPE_MASK|SLAP_MR_VALUE_OF_SYNTAX),
a->a_desc->ad_type->sat_syntax,
mr, val, &nval, ctx );
if( rc != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
cval = &nval;
} else {
cval = val;
}
if ( a->a_flags & SLAP_ATTR_SORTED_VALS ) {
/* Binary search */
unsigned base = 0, n = a->a_numvals;
int val = 0;
while ( 0 < n ) {
unsigned pivot = n >> 1;
i = base + pivot;
if ( i >= a->a_numvals ) {
i = a->a_numvals - 1;
break;
}
rc = value_match( &match, a->a_desc, mr, flags,
&a->a_nvals[i], cval, &text );
if ( rc == LDAP_SUCCESS && match == 0 )
break;
n = pivot;
if ( match < 0 )
base = i+1;
}
if ( match < 0 )
i++;
} else {
/* Linear search */
for ( i = 0; i < a->a_numvals; i++ ) {
const char *text;
rc = ordered_value_match( &match, a->a_desc, mr, flags,
&a->a_nvals[i], cval, &text );
if ( rc == LDAP_SUCCESS && match == 0 )
break;
}
}
if ( slot )
*slot = i;
if ( match )
rc = LDAP_NO_SUCH_ATTRIBUTE;
if ( nval.bv_val )
slap_sl_free( nval.bv_val, ctx );
return rc;
}
int
attr_valadd(
Attribute *a,
BerVarray vals,
BerVarray nvals,
int nn )
{
int i;
BerVarray v2;
v2 = (BerVarray) SLAP_REALLOC( (char *) a->a_vals,
(a->a_numvals + nn + 1) * sizeof(struct berval) );
if( v2 == NULL ) {
Debug(LDAP_DEBUG_TRACE,
"attr_valadd: SLAP_REALLOC failed.\n", 0, 0, 0 );
return LBER_ERROR_MEMORY;
}
a->a_vals = v2;
if ( nvals ) {
v2 = (BerVarray) SLAP_REALLOC( (char *) a->a_nvals,
(a->a_numvals + nn + 1) * sizeof(struct berval) );
if( v2 == NULL ) {
Debug(LDAP_DEBUG_TRACE,
"attr_valadd: SLAP_REALLOC failed.\n", 0, 0, 0 );
return LBER_ERROR_MEMORY;
}
a->a_nvals = v2;
} else {
a->a_nvals = a->a_vals;
}
/* If sorted and old vals exist, must insert */
if (( a->a_flags & SLAP_ATTR_SORTED_VALS ) && a->a_numvals ) {
unsigned slot;
int j, rc;
v2 = nvals ? nvals : vals;
for ( i = 0; i < nn; i++ ) {
rc = attr_valfind( a, SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
&v2[i], &slot, NULL );
if ( rc != LDAP_NO_SUCH_ATTRIBUTE ) {
/* should never happen */
if ( rc == LDAP_SUCCESS )
rc = LDAP_TYPE_OR_VALUE_EXISTS;
return rc;
}
for ( j = a->a_numvals; j >= slot; j-- ) {
a->a_vals[j+1] = a->a_vals[j];
if ( nvals )
a->a_nvals[j+1] = a->a_nvals[j];
}
ber_dupbv( &a->a_nvals[slot], &v2[i] );
if ( nvals )
ber_dupbv( &a->a_vals[slot], &vals[i] );
a->a_numvals++;
}
BER_BVZERO( &a->a_vals[a->a_numvals] );
if ( a->a_vals != a->a_nvals )
BER_BVZERO( &a->a_nvals[a->a_numvals] );
} else {
v2 = &a->a_vals[a->a_numvals];
for ( i = 0 ; i < nn; i++ ) {
ber_dupbv( &v2[i], &vals[i] );
if ( BER_BVISNULL( &v2[i] ) ) break;
}
BER_BVZERO( &v2[i] );
if ( nvals ) {
v2 = &a->a_nvals[a->a_numvals];
for ( i = 0 ; i < nn; i++ ) {
ber_dupbv( &v2[i], &nvals[i] );
if ( BER_BVISNULL( &v2[i] ) ) break;
}
BER_BVZERO( &v2[i] );
}
a->a_numvals += i;
}
return 0;
}
/*
* attr_merge - merge the given type and value with the list of
......@@ -302,7 +458,7 @@ attr_merge(
BerVarray vals,
BerVarray nvals )
{
int rc;
int i = 0;
Attribute **a;
......@@ -325,18 +481,10 @@ attr_merge(
|| ( (*a)->a_nvals != (*a)->a_vals ) ) ) );
}
rc = value_add( &(*a)->a_vals, vals );
if ( rc == LDAP_SUCCESS ) {
if ( nvals ) {
rc = value_add( &(*a)->a_nvals, nvals );
/* FIXME: what if rc != LDAP_SUCCESS ? */
} else {
(*a)->a_nvals = (*a)->a_vals;
}
if ( vals != NULL ) {
for ( ; !BER_BVISNULL( &vals[i] ); i++ ) ;
}
return rc;
return attr_valadd( *a, vals, nvals, i );
}
/*
......@@ -415,7 +563,6 @@ attr_merge_one(
struct berval *val,
struct berval *nval )
{
int rc;
Attribute **a;
for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) {
......@@ -428,17 +575,7 @@ attr_merge_one(
*a = attr_alloc( desc );
}
rc = value_add_one( &(*a)->a_vals, val );
if ( rc == LDAP_SUCCESS ) {
if ( nval ) {
rc = value_add_one( &(*a)->a_nvals, nval );
/* FIXME: what if rc != LDAP_SUCCESS ? */
} else {
(*a)->a_nvals = (*a)->a_vals;
}
}
return rc;
return attr_valadd( *a, val, nval, 1 );
}
/*
......
......@@ -158,10 +158,10 @@ dn2entry_retry:
{
rs->sr_err = LDAP_COMPARE_FALSE;
if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
if ( attr_valfind( a,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
a->a_nvals, &op->oq_compare.rs_ava->aa_value,
&op->oq_compare.rs_ava->aa_value, NULL,
op->o_tmpmemctx ) == 0 )
{
rs->sr_err = LDAP_COMPARE_TRUE;
......
......@@ -210,6 +210,7 @@ bdb_monitor_free(
mod.sm_op = LDAP_MOD_DELETE;
mod.sm_desc = slap_schema.si_ad_objectClass;
mod.sm_values = values;
mod.sm_numvals = 1;
values[ 0 ] = oc_olmBDBDatabase->soc_cname;
BER_BVZERO( &values[ 1 ] );
......@@ -218,9 +219,10 @@ bdb_monitor_free(
/* don't care too much about return code... */
/* remove attrs */
mod.sm_values = NULL;
mod.sm_numvals = 0;
for ( i = 0; s_at[ i ].desc != NULL; i++ ) {
mod.sm_desc = *s_at[ i ].ad;
mod.sm_values = NULL;
rc = modify_delete_values( e, &mod, 1, &text,
textbuf, sizeof( textbuf ) );
/* don't care too much about return code... */
......@@ -371,26 +373,22 @@ bdb_monitor_db_open( BackendDB *be )
}
a->a_desc = slap_schema.si_ad_objectClass;
value_add_one( &a->a_vals, &oc_olmBDBDatabase->soc_cname );
a->a_nvals = a->a_vals;
attr_valadd( a, &oc_olmBDBDatabase->soc_cname, NULL, 1 );
next = a->a_next;
{
struct berval bv = BER_BVC( "0" );
next->a_desc = ad_olmBDBEntryCache;
value_add_one( &next->a_vals, &bv );
next->a_nvals = next->a_vals;
attr_valadd( next, &bv, NULL, 1 );
next = next->a_next;
next->a_desc = ad_olmBDBDNCache;
value_add_one( &next->a_vals, &bv );
next->a_nvals = next->a_vals;
attr_valadd( next, &bv, NULL, 1 );
next = next->a_next;
next->a_desc = ad_olmBDBIDLCache;
value_add_one( &next->a_vals, &bv );
next->a_nvals = next->a_vals;
attr_valadd( next, &bv, NULL, 1 );
next = next->a_next;
}
......@@ -432,6 +430,7 @@ bdb_monitor_db_open( BackendDB *be )
next->a_desc = ad_olmDbDirectory;
next->a_vals = ch_calloc( sizeof( struct berval ), 2 );
next->a_vals[ 0 ] = bv;
next->a_numvals = 1;
if ( BER_BVISNULL( &nbv ) ) {
next->a_nvals = next->a_vals;
......
......@@ -676,11 +676,6 @@ ldap_build_entry(
* values result filter
*/
attr->a_vals = (struct berval *)&slap_dummy_bv;
last = 0;
} else {
for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); last++ )
/* just count vals */ ;
}
validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
......@@ -692,7 +687,7 @@ ldap_build_entry(
goto next_attr;
}
for ( i = 0; i < last; i++ ) {
for ( i = 0; !BER_BVISNULL( &attr->a_vals[i] ); i++ ) {
struct berval pval;
int rc;
......@@ -724,6 +719,7 @@ ldap_build_entry(
attr->a_vals[i] = pval;
}
}
attr->a_numvals = last = i;
if ( last && attr->a_desc->ad_type->sat_equality &&
attr->a_desc->ad_type->sat_equality->smr_normalize )
......
......@@ -1885,6 +1885,7 @@ meta_send_entry(
for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); ++last )
;
}
attr->a_numvals = last;
validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
</