fix: count constraint broken when using multiple modifications

Resolves: #795766
This commit is contained in:
Jan Vcelak 2012-02-21 15:44:56 +01:00
parent 20125eca06
commit b2b2825914
2 changed files with 194 additions and 0 deletions

View File

@ -0,0 +1,190 @@
Fix count constraint when using multiple modifications
Constraint overlay doesn't take into account multiple modifications when using
count.
Example: If count for 'description' attribute is set e.g. to 2, the following
results in a constraint violation:
dn: cn=usr2, dc=my-domain,dc=com
add: description
description: d1
description: d2
description: d3-viol
However, this passes:
dn: cn=usr2, dc=my-domain,dc=com
add: description
description: d1
-
add: description
description: d2
-
add: description
description: d3
This patch fixes the behavior in case multiple modifications are used.
Author: Jan Synacek <jsynacek@redhat.com>
Upstream ITS: #7168
Resolves: #742163
diff --git a/servers/slapd/overlays/constraint.c b/servers/slapd/overlays/constraint.c
index e6a9267..2988af6 100644
--- a/servers/slapd/overlays/constraint.c
+++ b/servers/slapd/overlays/constraint.c
@@ -838,6 +838,60 @@ add_violation:
static int
+constraint_check_count_violation( Modifications *m, Entry *target_entry, constraint *cp )
+{
+ BerVarray b = NULL;
+ unsigned ce = 0;
+ unsigned ca;
+ int j;
+
+ for ( j = 0; cp->ap[j]; j++ ) {
+ ca = 0;
+
+ /* Get this attribute count */
+ if ( target_entry )
+ ce = constraint_count_attr( target_entry, cp->ap[j] );
+
+ for( ; m; m = m->sml_next ) {
+ if ( cp->ap[j] == m->sml_desc ) {
+ switch ( m->sml_op ) {
+ case LDAP_MOD_DELETE:
+ ce = 0;
+ break;
+
+ case LDAP_MOD_ADD:
+ if (( b = m->sml_values ) == NULL || b[0].bv_val == NULL )
+ continue;
+
+ for ( ca = 0; b[ca].bv_val; ++ca );
+ ce += ca;
+ break;
+
+ case LDAP_MOD_REPLACE:
+ if (( b = m->sml_values ) == NULL || b[0].bv_val == NULL )
+ continue;
+
+ for ( ca = 0; b[ca].bv_val; ++ca );
+ ce = ca;
+ break;
+
+ default:
+ /* impossible! assert? */
+ return 1;
+ }
+
+ Debug(LDAP_DEBUG_TRACE,
+ "==> constraint_check_count_violation ce = %u, "
+ "ca = %u, cp->count = %lu\n",
+ ce, ca, (unsigned long) cp->count);
+ }
+ }
+ }
+
+ return ( ce > cp->count );
+}
+
+static int
constraint_update( Operation *op, SlapReply *rs )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
@@ -850,6 +904,8 @@ constraint_update( Operation *op, SlapReply *rs )
struct berval rsv = BER_BVC("modify breaks constraint");
int rc;
char *msg = NULL;
+ int is_v;
+ int first = 1;
if (get_relax(op)) {
return SLAP_CB_CONTINUE;
@@ -880,10 +936,12 @@ constraint_update( Operation *op, SlapReply *rs )
/* Do we need to count attributes? */
for(cp = c; cp; cp = cp->ap_next) {
if (cp->count != 0 || cp->set || cp->restrict_lud != 0) {
- op->o_bd = on->on_info->oi_origdb;
- rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &target_entry );
- op->o_bd = be;
-
+ if (first) {
+ op->o_bd = on->on_info->oi_origdb;
+ rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &target_entry );
+ op->o_bd = be;
+ first = 0;
+ }
if (rc != 0 || target_entry == NULL) {
Debug(LDAP_DEBUG_TRACE,
"==> constraint_update rc = %d DN=\"%s\"%s\n",
@@ -893,7 +951,16 @@ constraint_update( Operation *op, SlapReply *rs )
rc = LDAP_CONSTRAINT_VIOLATION;
goto mod_violation;
}
- break;
+
+ is_v = constraint_check_count_violation(m, target_entry, cp);
+
+ Debug(LDAP_DEBUG_TRACE,
+ "==> constraint_update is_v: %d\n", is_v, 0, 0);
+
+ if (is_v) {
+ rc = LDAP_CONSTRAINT_VIOLATION;
+ goto mod_violation;
+ }
}
}
@@ -912,10 +979,6 @@ constraint_update( Operation *op, SlapReply *rs )
if ((( b = m->sml_values ) == NULL ) || (b[0].bv_val == NULL))
continue;
- /* Get this attribute count, if needed */
- if (target_entry)
- ce = constraint_count_attr(target_entry, m->sml_desc);
-
for(cp = c; cp; cp = cp->ap_next) {
int j;
for (j = 0; cp->ap[j]; j++) {
@@ -929,34 +992,6 @@ constraint_update( Operation *op, SlapReply *rs )
continue;
}
- if (cp->count != 0) {
- unsigned ca;
-
- if (m->sml_op == LDAP_MOD_DELETE)
- ce = 0;
-
- for (ca = 0; b[ca].bv_val; ++ca);
-
- Debug(LDAP_DEBUG_TRACE,
- "==> constraint_update ce = %u, "
- "ca = %u, cp->count = %lu\n",
- ce, ca, (unsigned long) cp->count);
-
- if (m->sml_op == LDAP_MOD_ADD) {
- if (ca + ce > cp->count) {
- rc = LDAP_CONSTRAINT_VIOLATION;
- goto mod_violation;
- }
- }
- if (m->sml_op == LDAP_MOD_REPLACE) {
- if (ca > cp->count) {
- rc = LDAP_CONSTRAINT_VIOLATION;
- goto mod_violation;
- }
- ce = ca;
- }
- }
-
/* DELETE are to be ignored beyond this point */
if (( m->sml_op & LDAP_MOD_OP ) == LDAP_MOD_DELETE)
continue;
--
1.7.7.6

View File

@ -38,6 +38,7 @@ Patch6: openldap-userconfig-setgid.patch
Patch7: openldap-dns-priority.patch
Patch8: openldap-syncrepl-unset-tls-options.patch
Patch9: openldap-result-write-polling.patch
Patch10: openldap-constraint-count.patch
# Fedora specific patches
Patch100: openldap-fedora-systemd.patch
@ -142,6 +143,7 @@ pushd openldap-%{version}
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch100 -p1
@ -655,6 +657,8 @@ exit 0
%changelog
* Tue Feb 21 2012 Jan Vcelak <jvcelak@redhat.com> 2.4.29-3
- fix: ldap_result does not succeed for sssd (#771484)
- Jan Synáček <jsynacek@redhat.com>:
+ fix: count constraint broken when using multiple modifications (#795766)
* Mon Feb 20 2012 Jan Vcelak <jvcelak@redhat.com> 2.4.29-2
- fix update: provide ldif2ldbm, not ldib2ldbm (#437104)