X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fconstraint.c;h=4e8b13dd6cd93a6539defe8816eecf6e4a9a2914;hb=f12a84a70e5497367ef65ff48299dc77ea238b90;hp=ec640d9dad044dfdcf8e02caf43adbf3eceb879e;hpb=8a34d439bc9441451b1d6e406a5cc9ffa97293b5;p=openldap diff --git a/servers/slapd/overlays/constraint.c b/servers/slapd/overlays/constraint.c index ec640d9dad..4e8b13dd6c 100644 --- a/servers/slapd/overlays/constraint.c +++ b/servers/slapd/overlays/constraint.c @@ -145,6 +145,8 @@ constraint_cf_gen( ConfigArgs *c ) char *tstr = NULL; int quotes = 0; int j; + size_t val; + char val_buf[SLAP_TEXT_BUFLEN] = { '\0' }; bv.bv_len = STRLENOF(" "); for (j = 0; cp->ap[j]; j++) { @@ -156,6 +158,7 @@ constraint_cf_gen( ConfigArgs *c ) if (cp->re) { tstr = REGEX_STR; + quotes = 1; } else if (cp->lud) { tstr = URI_STR; quotes = 1; @@ -164,8 +167,10 @@ constraint_cf_gen( ConfigArgs *c ) quotes = 1; } else if (cp->size) { tstr = SIZE_STR; + val = cp->size; } else if (cp->count) { tstr = COUNT_STR; + val = cp->count; } bv.bv_len += strlen(tstr); @@ -175,6 +180,15 @@ 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 (len <= 0) { + /* error */ + return -1; + } + bv.bv_len += len; + } + s = bv.bv_val = ch_malloc(bv.bv_len + 1); s = lutil_strncopy( s, cp->ap[0]->ad_cname.bv_val, cp->ap[0]->ad_cname.bv_len ); @@ -185,9 +199,13 @@ constraint_cf_gen( ConfigArgs *c ) *s++ = ' '; s = lutil_strcopy( s, tstr ); *s++ = ' '; - if ( quotes ) *s++ = '"'; - s = lutil_strncopy( s, cp->val.bv_val, cp->val.bv_len ); - if ( quotes ) *s++ = '"'; + if (cp->count || cp->size) { + s = lutil_strcopy( s, val_buf ); + } else { + if ( quotes ) *s++ = '"'; + s = lutil_strncopy( s, cp->val.bv_val, cp->val.bv_len ); + if ( quotes ) *s++ = '"'; + } if (cp->restrict_lud != NULL) { s = lutil_strcopy( s, " restrict=\"" ); s = lutil_strncopy( s, cp->restrict_val.bv_val, cp->restrict_val.bv_len ); @@ -471,7 +489,7 @@ constraint_cf_gen( ConfigArgs *c ) } } - ber_str2bv(c->argv[argidx], 0, 1, &ap.restrict_val); + ber_str2bv(c->argv[argidx] + STRLENOF("restrict="), 0, 1, &ap.restrict_val); } else { /* cleanup */ @@ -541,7 +559,7 @@ constraint_uri_cb( Operation *op, SlapReply *rs ) } static int -constraint_violation( constraint *c, struct berval *bv, Operation *op, SlapReply *rs) +constraint_violation( constraint *c, struct berval *bv, Operation *op ) { if ((!c) || (!bv)) return LDAP_SUCCESS; @@ -556,19 +574,13 @@ constraint_violation( constraint *c, struct berval *bv, Operation *op, SlapReply Operation nop = *op; slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; slap_callback cb; - SlapReply nrs = { REP_RESULT }; int i; - int found; + int found = 0; int rc; size_t len; struct berval filterstr; char *ptr; - found = 0; - - nrs.sr_entry = NULL; - nrs.sr_nentries = 0; - cb.sc_next = NULL; cb.sc_response = constraint_uri_cb; cb.sc_cleanup = NULL; @@ -645,6 +657,8 @@ constraint_violation( constraint *c, struct berval *bv, Operation *op, SlapReply rc = LDAP_OTHER; } else { + SlapReply nrs = { REP_RESULT }; + Debug(LDAP_DEBUG_TRACE, "==> constraint_violation uri filter = %s\n", filterstr.bv_val, 0, 0); @@ -663,7 +677,6 @@ constraint_violation( constraint *c, struct berval *bv, Operation *op, SlapReply if (!found) return LDAP_CONSTRAINT_VIOLATION; /* constraint violation */ - } return LDAP_SUCCESS; @@ -758,7 +771,7 @@ constraint_add( Operation *op, SlapReply *rs ) int rc; char *msg = NULL; - if (get_relax(op)) { + if (get_relax(op) || SLAPD_SYNC_IS_SYNCCONN( op->o_connid )) { return SLAP_CB_CONTINUE; } @@ -796,7 +809,7 @@ constraint_add( Operation *op, SlapReply *rs ) } for ( i = 0; b[i].bv_val; i++ ) { - rc = constraint_violation( cp, &b[i], op, rs ); + rc = constraint_violation( cp, &b[i], op ); if ( rc ) { goto add_violation; } @@ -824,6 +837,64 @@ 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++ ) { + /* 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 ) { + ca = m->sml_numvals; + switch ( m->sml_op ) { + case LDAP_MOD_DELETE: + case SLAP_MOD_SOFTDEL: + if ( !ca || ca > ce ) { + ce = 0; + } else { + /* No need to check for values' validity. Invalid values + * cause the whole transaction to die anyway. */ + ce -= ca; + } + break; + + case LDAP_MOD_ADD: + case SLAP_MOD_SOFTADD: + ce += ca; + break; + + case LDAP_MOD_REPLACE: + ce = ca; + break; + +#if 0 + /* TODO */ + case handle SLAP_MOD_ADD_IF_NOT_PRESENT: +#endif + + 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 ) { @@ -837,8 +908,9 @@ constraint_update( Operation *op, SlapReply *rs ) struct berval rsv = BER_BVC("modify breaks constraint"); int rc; char *msg = NULL; + int is_v; - if (get_relax(op)) { + if (get_relax(op) || SLAPD_SYNC_IS_SYNCCONN( op->o_connid )) { return SLAP_CB_CONTINUE; } @@ -864,13 +936,17 @@ constraint_update( Operation *op, SlapReply *rs ) return(rs->sr_err); } + 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; + + /* let the backend send the error */ + if ( target_entry == NULL ) + return SLAP_CB_CONTINUE; + /* 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 (cp->count != 0) { if (rc != 0 || target_entry == NULL) { Debug(LDAP_DEBUG_TRACE, "==> constraint_update rc = %d DN=\"%s\"%s\n", @@ -880,7 +956,20 @@ constraint_update( Operation *op, SlapReply *rs ) rc = LDAP_CONSTRAINT_VIOLATION; goto mod_violation; } - break; + + if (cp->restrict_lud && constraint_check_restrict(op, cp, target_entry) == 0) { + continue; + } + + 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; + } } } @@ -899,10 +988,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++) { @@ -916,40 +1001,12 @@ 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; for ( i = 0; b[i].bv_val; i++ ) { - rc = constraint_violation( cp, &b[i], op, rs ); + rc = constraint_violation( cp, &b[i], op ); if ( rc ) { goto mod_violation; } @@ -1027,6 +1084,29 @@ constraint_update( Operation *op, SlapReply *rs ) } break; + case SLAP_MOD_SOFTDEL: + mod->sm_op = LDAP_MOD_ADD; + err = modify_delete_values( target_entry_copy, + mod, get_permissiveModify(op), + &text, textbuf, textlen ); + mod->sm_op = SLAP_MOD_SOFTDEL; + if ( err == LDAP_NO_SUCH_ATTRIBUTE ) { + err = LDAP_SUCCESS; + } + break; + + case SLAP_MOD_ADD_IF_NOT_PRESENT: + if ( attr_find( target_entry_copy->e_attrs, mod->sm_desc ) ) { + err = LDAP_SUCCESS; + break; + } + mod->sm_op = LDAP_MOD_ADD; + err = modify_add_values( target_entry_copy, + mod, get_permissiveModify(op), + &text, textbuf, textlen ); + mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT; + break; + default: err = LDAP_OTHER; break;