From b2b2825914b9514969888407ddd99787e5d5a0dc Mon Sep 17 00:00:00 2001 From: Jan Vcelak Date: Tue, 21 Feb 2012 15:44:56 +0100 Subject: [PATCH] fix: count constraint broken when using multiple modifications Resolves: #795766 --- openldap-constraint-count.patch | 190 ++++++++++++++++++++++++++++++++ openldap.spec | 4 + 2 files changed, 194 insertions(+) create mode 100644 openldap-constraint-count.patch diff --git a/openldap-constraint-count.patch b/openldap-constraint-count.patch new file mode 100644 index 0000000..1a7677a --- /dev/null +++ b/openldap-constraint-count.patch @@ -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 +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 + diff --git a/openldap.spec b/openldap.spec index d9b6909..6c73a24 100644 --- a/openldap.spec +++ b/openldap.spec @@ -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 2.4.29-3 - fix: ldap_result does not succeed for sssd (#771484) +- Jan Synáček : + + fix: count constraint broken when using multiple modifications (#795766) * Mon Feb 20 2012 Jan Vcelak 2.4.29-2 - fix update: provide ldif2ldbm, not ldib2ldbm (#437104)