mhonek / rpms / openldap

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