From 8958d2b7cbe1047c41fb4018692477825f4a6be4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ond=C5=99ej=20Kuzn=C3=ADk?= Date: Mon, 15 Sep 2014 22:34:17 +0100 Subject: [PATCH] ITS#7780,ITS#7781 Fix slapo-constraint with 0 count --- servers/slapd/overlays/constraint.c | 323 +++++++++++++++------------- 1 file changed, 178 insertions(+), 145 deletions(-) diff --git a/servers/slapd/overlays/constraint.c b/servers/slapd/overlays/constraint.c index e101cd8656..9e68d3b43a 100644 --- a/servers/slapd/overlays/constraint.c +++ b/servers/slapd/overlays/constraint.c @@ -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; -- 2.39.5