Skip to content
Snippets Groups Projects
Commit 47f43436 authored by Ondřej Kuzník's avatar Ondřej Kuzník Committed by Quanah Gibson-Mount
Browse files

ITS#7780,ITS#7781 Fix slapo-constraint with 0 count

parent 1df97d1e
No related branches found
No related tags found
No related merge requests found
......@@ -62,6 +62,7 @@ typedef struct constraint {
Filter *restrict_filter;
struct berval restrict_val;
int type;
regex_t *re;
LDAPURLDesc *lud;
int set;
......@@ -74,7 +75,12 @@ typedef struct constraint {
} constraint;
enum {
CONSTRAINT_ATTRIBUTE = 1
CONSTRAINT_ATTRIBUTE = 1,
CONSTRAINT_COUNT,
CONSTRAINT_SIZE,
CONSTRAINT_REGEX,
CONSTRAINT_SET,
CONSTRAINT_URI,
};
static ConfigDriver constraint_cf_gen;
......@@ -143,7 +149,7 @@ constraint_cf_gen( ConfigArgs *c )
for (cp=cn; cp; cp=cp->ap_next) {
char *s;
char *tstr = NULL;
int quotes = 0;
int quotes = 0, numeric = 0;
int j;
size_t val;
char val_buf[SLAP_TEXT_BUFLEN] = { '\0' };
......@@ -156,21 +162,31 @@ constraint_cf_gen( ConfigArgs *c )
/* room for commas */
bv.bv_len += j - 1;
if (cp->re) {
tstr = REGEX_STR;
quotes = 1;
} else if (cp->lud) {
tstr = URI_STR;
quotes = 1;
} else if (cp->set) {
tstr = SET_STR;
quotes = 1;
} else if (cp->size) {
tstr = SIZE_STR;
val = cp->size;
} else if (cp->count) {
tstr = COUNT_STR;
val = cp->count;
switch (cp->type) {
case CONSTRAINT_COUNT:
tstr = COUNT_STR;
val = cp->count;
numeric = 1;
break;
case CONSTRAINT_SIZE:
tstr = SIZE_STR;
val = cp->size;
numeric = 1;
break;
case CONSTRAINT_REGEX:
tstr = REGEX_STR;
quotes = 1;
break;
case CONSTRAINT_SET:
tstr = SET_STR;
quotes = 1;
break;
case CONSTRAINT_URI:
tstr = URI_STR;
quotes = 1;
break;
default:
abort();
}
bv.bv_len += strlen(tstr);
......@@ -180,8 +196,8 @@ constraint_cf_gen( ConfigArgs *c )
bv.bv_len += cp->restrict_val.bv_len + STRLENOF(" restrict=\"\"");
}
if (cp->count || cp->size) {
int len = snprintf(val_buf, sizeof(val_buf), "%zd", val);
if (numeric) {
int len = snprintf(val_buf, sizeof(val_buf), "%zu", val);
if (len <= 0) {
/* error */
return -1;
......@@ -199,7 +215,7 @@ constraint_cf_gen( ConfigArgs *c )
*s++ = ' ';
s = lutil_strcopy( s, tstr );
*s++ = ' ';
if (cp->count || cp->size) {
if (numeric) {
s = lutil_strcopy( s, val_buf );
} else {
if ( quotes ) *s++ = '"';
......@@ -283,6 +299,7 @@ constraint_cf_gen( ConfigArgs *c )
if ( strcasecmp( c->argv[2], REGEX_STR ) == 0) {
int err;
ap.type = CONSTRAINT_REGEX;
ap.re = ch_malloc( sizeof(regex_t) );
if ((err = regcomp( ap.re,
c->argv[3], REG_EXTENDED )) != 0) {
......@@ -300,17 +317,24 @@ constraint_cf_gen( ConfigArgs *c )
ber_str2bv( c->argv[3], 0, 1, &ap.val );
} else if ( strcasecmp( c->argv[2], SIZE_STR ) == 0 ) {
size_t size;
char *endptr;
if ( ( size = atoi(c->argv[3]) ) != 0 )
ap.size = size;
ap.type = CONSTRAINT_SIZE;
ap.size = strtoull(c->argv[3], &endptr, 10);
if ( *endptr )
rc = ARG_BAD_CONF;
} else if ( strcasecmp( c->argv[2], COUNT_STR ) == 0 ) {
size_t count;
char *endptr;
if ( ( count = atoi(c->argv[3]) ) != 0 )
ap.count = count;
ap.type = CONSTRAINT_COUNT;
ap.count = strtoull(c->argv[3], &endptr, 10);
if ( *endptr )
rc = ARG_BAD_CONF;
} else if ( strcasecmp( c->argv[2], URI_STR ) == 0 ) {
int err;
ap.type = CONSTRAINT_URI;
err = ldap_url_parse(c->argv[3], &ap.lud);
if ( err != LDAP_URL_SUCCESS ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
......@@ -386,6 +410,7 @@ constraint_cf_gen( ConfigArgs *c )
} else if ( strcasecmp( c->argv[2], SET_STR ) == 0 ) {
ap.set = 1;
ber_str2bv( c->argv[3], 0, 1, &ap.val );
ap.type = CONSTRAINT_SET;
} else {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
......@@ -507,6 +532,7 @@ done:;
constraint *a2 = ch_calloc( sizeof(constraint), 1 );
a2->ap_next = on->on_bi.bi_private;
a2->ap = ap.ap;
a2->type = ap.type;
a2->re = ap.re;
a2->val = ap.val;
a2->lud = ap.lud;
......@@ -563,120 +589,124 @@ constraint_violation( constraint *c, struct berval *bv, Operation *op )
{
if ((!c) || (!bv)) return LDAP_SUCCESS;
if ((c->re) &&
(regexec(c->re, bv->bv_val, 0, NULL, 0) == REG_NOMATCH))
return LDAP_CONSTRAINT_VIOLATION; /* regular expression violation */
if ((c->size) && (bv->bv_len > c->size))
return LDAP_CONSTRAINT_VIOLATION; /* size violation */
if (c->lud) {
Operation nop = *op;
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
slap_callback cb;
int i;
int found = 0;
int rc;
size_t len;
struct berval filterstr;
char *ptr;
cb.sc_next = NULL;
cb.sc_response = constraint_uri_cb;
cb.sc_cleanup = NULL;
cb.sc_private = &found;
nop.o_protocol = LDAP_VERSION3;
nop.o_tag = LDAP_REQ_SEARCH;
nop.o_time = slap_get_time();
if (c->lud->lud_dn) {
struct berval dn;
ber_str2bv(c->lud->lud_dn, 0, 0, &dn);
nop.o_req_dn = dn;
nop.o_req_ndn = dn;
nop.o_bd = select_backend(&nop.o_req_ndn, 1 );
if (!nop.o_bd) {
return LDAP_NO_SUCH_OBJECT; /* unexpected error */
switch (c->type) {
case CONSTRAINT_SIZE:
if (bv->bv_len > c->size)
return LDAP_CONSTRAINT_VIOLATION; /* size violation */
break;
case CONSTRAINT_REGEX:
if (regexec(c->re, bv->bv_val, 0, NULL, 0) == REG_NOMATCH)
return LDAP_CONSTRAINT_VIOLATION; /* regular expression violation */
break;
case CONSTRAINT_URI: {
Operation nop = *op;
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
slap_callback cb;
int i;
int found = 0;
int rc;
size_t len;
struct berval filterstr;
char *ptr;
cb.sc_next = NULL;
cb.sc_response = constraint_uri_cb;
cb.sc_cleanup = NULL;
cb.sc_private = &found;
nop.o_protocol = LDAP_VERSION3;
nop.o_tag = LDAP_REQ_SEARCH;
nop.o_time = slap_get_time();
if (c->lud->lud_dn) {
struct berval dn;
ber_str2bv(c->lud->lud_dn, 0, 0, &dn);
nop.o_req_dn = dn;
nop.o_req_ndn = dn;
nop.o_bd = select_backend(&nop.o_req_ndn, 1 );
if (!nop.o_bd) {
return LDAP_NO_SUCH_OBJECT; /* unexpected error */
}
if (!nop.o_bd->be_search) {
return LDAP_OTHER; /* unexpected error */
}
} else {
nop.o_req_dn = nop.o_bd->be_nsuffix[0];
nop.o_req_ndn = nop.o_bd->be_nsuffix[0];
nop.o_bd = on->on_info->oi_origdb;
}
if (!nop.o_bd->be_search) {
return LDAP_OTHER; /* unexpected error */
nop.o_do_not_cache = 1;
nop.o_callback = &cb;
nop.ors_scope = c->lud->lud_scope;
nop.ors_deref = LDAP_DEREF_NEVER;
nop.ors_slimit = SLAP_NO_LIMIT;
nop.ors_tlimit = SLAP_NO_LIMIT;
nop.ors_limit = NULL;
nop.ors_attrsonly = 0;
nop.ors_attrs = slap_anlist_no_attrs;
len = STRLENOF("(&(") +
c->filter.bv_len +
STRLENOF(")(|");
for (i = 0; c->attrs[i]; i++) {
len += STRLENOF("(") +
c->attrs[i]->ad_cname.bv_len +
STRLENOF("=") +
bv->bv_len +
STRLENOF(")");
}
} else {
nop.o_req_dn = nop.o_bd->be_nsuffix[0];
nop.o_req_ndn = nop.o_bd->be_nsuffix[0];
nop.o_bd = on->on_info->oi_origdb;
}
nop.o_do_not_cache = 1;
nop.o_callback = &cb;
nop.ors_scope = c->lud->lud_scope;
nop.ors_deref = LDAP_DEREF_NEVER;
nop.ors_slimit = SLAP_NO_LIMIT;
nop.ors_tlimit = SLAP_NO_LIMIT;
nop.ors_limit = NULL;
nop.ors_attrsonly = 0;
nop.ors_attrs = slap_anlist_no_attrs;
len = STRLENOF("(&(") +
c->filter.bv_len +
STRLENOF(")(|");
for (i = 0; c->attrs[i]; i++) {
len += STRLENOF("(") +
c->attrs[i]->ad_cname.bv_len +
STRLENOF("=") +
bv->bv_len +
STRLENOF(")");
}
len += STRLENOF("))");
filterstr.bv_len = len;
filterstr.bv_val = op->o_tmpalloc(len + 1, op->o_tmpmemctx);
ptr = filterstr.bv_val +
snprintf(filterstr.bv_val, len, "(&(%s)(|", c->lud->lud_filter);
for (i = 0; c->attrs[i]; i++) {
*ptr++ = '(';
ptr = lutil_strcopy( ptr, c->attrs[i]->ad_cname.bv_val );
*ptr++ = '=';
ptr = lutil_strcopy( ptr, bv->bv_val );
len += STRLENOF("))");
filterstr.bv_len = len;
filterstr.bv_val = op->o_tmpalloc(len + 1, op->o_tmpmemctx);
ptr = filterstr.bv_val +
snprintf(filterstr.bv_val, len, "(&(%s)(|", c->lud->lud_filter);
for (i = 0; c->attrs[i]; i++) {
*ptr++ = '(';
ptr = lutil_strcopy( ptr, c->attrs[i]->ad_cname.bv_val );
*ptr++ = '=';
ptr = lutil_strcopy( ptr, bv->bv_val );
*ptr++ = ')';
}
*ptr++ = ')';
}
*ptr++ = ')';
*ptr++ = ')';
*ptr++ = '\0';
*ptr++ = ')';
*ptr++ = '\0';
nop.ors_filterstr = filterstr;
nop.ors_filter = str2filter_x(&nop, filterstr.bv_val);
if ( nop.ors_filter == NULL ) {
Debug( LDAP_DEBUG_ANY,
"%s constraint_violation uri filter=\"%s\" invalid\n",
op->o_log_prefix, filterstr.bv_val, 0 );
rc = LDAP_OTHER;
nop.ors_filterstr = filterstr;
nop.ors_filter = str2filter_x(&nop, filterstr.bv_val);
if ( nop.ors_filter == NULL ) {
Debug( LDAP_DEBUG_ANY,
"%s constraint_violation uri filter=\"%s\" invalid\n",
op->o_log_prefix, filterstr.bv_val, 0 );
rc = LDAP_OTHER;
} else {
SlapReply nrs = { REP_RESULT };
} else {
SlapReply nrs = { REP_RESULT };
Debug(LDAP_DEBUG_TRACE,
"==> constraint_violation uri filter = %s\n",
filterstr.bv_val, 0, 0);
Debug(LDAP_DEBUG_TRACE,
"==> constraint_violation uri filter = %s\n",
filterstr.bv_val, 0, 0);
rc = nop.o_bd->be_search( &nop, &nrs );
Debug(LDAP_DEBUG_TRACE,
"==> constraint_violation uri rc = %d, found = %d\n",
rc, found, 0);
}
op->o_tmpfree(filterstr.bv_val, op->o_tmpmemctx);
rc = nop.o_bd->be_search( &nop, &nrs );
if ((rc != LDAP_SUCCESS) && (rc != LDAP_NO_SUCH_OBJECT)) {
return rc; /* unexpected error */
}
Debug(LDAP_DEBUG_TRACE,
"==> constraint_violation uri rc = %d, found = %d\n",
rc, found, 0);
}
op->o_tmpfree(filterstr.bv_val, op->o_tmpmemctx);
if (!found)
return LDAP_CONSTRAINT_VIOLATION; /* constraint violation */
if ((rc != LDAP_SUCCESS) && (rc != LDAP_NO_SUCH_OBJECT)) {
return rc; /* unexpected error */
}
if (!found)
return LDAP_CONSTRAINT_VIOLATION; /* constraint violation */
break;
}
}
return LDAP_SUCCESS;
......@@ -803,22 +833,25 @@ constraint_add( Operation *op, SlapReply *rs )
"a->a_numvals = %u, cp->count = %lu\n",
a->a_numvals, (unsigned long) cp->count, 0);
if ((cp->count != 0) && (a->a_numvals > cp->count)) {
rc = LDAP_CONSTRAINT_VIOLATION;
goto add_violation;
}
for ( i = 0; b[i].bv_val; i++ ) {
rc = constraint_violation( cp, &b[i], op );
if ( rc ) {
goto add_violation;
switch (cp->type) {
case CONSTRAINT_COUNT:
if (a->a_numvals > cp->count)
rc = LDAP_CONSTRAINT_VIOLATION;
break;
case CONSTRAINT_SET:
if (acl_match_set(&cp->val, op, op->ora_e, NULL) == 0)
rc = LDAP_CONSTRAINT_VIOLATION;
break;
default:
for ( i = 0; b[i].bv_val; i++ ) {
rc = constraint_violation( cp, &b[i], op );
if ( rc ) {
goto add_violation;
}
}
}
}
if (cp->set && acl_match_set(&cp->val, op, op->ora_e, NULL) == 0) {
rc = LDAP_CONSTRAINT_VIOLATION;
goto add_violation; /* constraint violation */
}
if ( rc )
goto add_violation;
}
}
......@@ -946,7 +979,7 @@ constraint_update( Operation *op, SlapReply *rs )
/* Do we need to count attributes? */
for(cp = c; cp; cp = cp->ap_next) {
if (cp->count != 0) {
if (cp->type == CONSTRAINT_COUNT) {
if (rc != 0 || target_entry == NULL) {
Debug(LDAP_DEBUG_TRACE,
"==> constraint_update rc = %d DN=\"%s\"%s\n",
......@@ -1012,7 +1045,7 @@ constraint_update( Operation *op, SlapReply *rs )
}
}
if (cp->set && target_entry) {
if (cp->type == CONSTRAINT_SET && target_entry) {
if (target_entry_copy == NULL) {
Modifications *ml;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment