X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fconstraint.c;h=fcb2830ee88cbf2e45d344ba3537fdfac10ee36e;hb=6da3e3473c4c93e24c75dbff56ff1d21c89a9a18;hp=711790080f4799b22fc7a864720f057ef75e7f77;hpb=151d5aec667848c30ef5c85e38d704df71b81e1f;p=openldap diff --git a/servers/slapd/overlays/constraint.c b/servers/slapd/overlays/constraint.c index 711790080f..fcb2830ee8 100644 --- a/servers/slapd/overlays/constraint.c +++ b/servers/slapd/overlays/constraint.c @@ -56,6 +56,12 @@ typedef struct constraint { struct constraint *ap_next; AttributeDescription **ap; + + LDAPURLDesc *restrict_lud; + struct berval restrict_ndn; + Filter *restrict_filter; + struct berval restrict_val; + regex_t *re; LDAPURLDesc *lud; int set; @@ -74,10 +80,10 @@ enum { static ConfigDriver constraint_cf_gen; static ConfigTable constraintcfg[] = { - { "constraint_attribute", "attribute> (regex|uri) (regex|uri|set|size|count) []", + 4, 0, 0, ARG_MAGIC | CONSTRAINT_ATTRIBUTE, constraint_cf_gen, "( OLcfgOvAt:13.1 NAME 'olcConstraintAttribute' " - "DESC 'regular expression constraint for attribute' " + "DESC 'constraint for list of attributes' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString )", NULL, NULL }, { NULL, NULL, 0, 0, 0, ARG_IGNORED } @@ -94,8 +100,16 @@ static ConfigOCs constraintocs[] = { }; static void -constraint_free( constraint *cp ) +constraint_free( constraint *cp, int freeme ) { + if (cp->restrict_lud) + ldap_free_urldesc(cp->restrict_lud); + if (!BER_BVISNULL(&cp->restrict_ndn)) + ch_free(cp->restrict_ndn.bv_val); + if (cp->restrict_filter != NULL && cp->restrict_filter != slap_filter_objectClass_pres) + filter_free(cp->restrict_filter); + if (!BER_BVISNULL(&cp->restrict_val)) + ch_free(cp->restrict_val.bv_val); if (cp->re) { regfree(cp->re); ch_free(cp->re); @@ -108,7 +122,8 @@ constraint_free( constraint *cp ) ch_free(cp->attrs); if (cp->ap) ch_free(cp->ap); - ch_free(cp); + if (freeme) + ch_free(cp); } static int @@ -118,7 +133,7 @@ constraint_cf_gen( ConfigArgs *c ) constraint *cn = on->on_bi.bi_private, *cp; struct berval bv; int i, rc = 0; - constraint ap = { NULL, NULL, NULL }, *a2 = NULL; + constraint ap = { NULL }; const char *text = NULL; switch ( c->op ) { @@ -143,6 +158,7 @@ constraint_cf_gen( ConfigArgs *c ) tstr = REGEX_STR; } else if (cp->lud) { tstr = URI_STR; + quotes = 1; } else if (cp->set) { tstr = SET_STR; quotes = 1; @@ -155,6 +171,10 @@ constraint_cf_gen( ConfigArgs *c ) bv.bv_len += strlen(tstr); bv.bv_len += cp->val.bv_len + 2*quotes; + if (cp->restrict_lud != NULL) { + bv.bv_len += cp->restrict_val.bv_len + STRLENOF(" restrict=\"\""); + } + 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 ); @@ -168,6 +188,11 @@ constraint_cf_gen( ConfigArgs *c ) 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 ); + *s++ = '"'; + } *s = '\0'; rc = value_add_one( &c->rvalue_vals, &bv ); @@ -191,7 +216,7 @@ constraint_cf_gen( ConfigArgs *c ) /* zap all constraints */ while (cn) { cp = cn->ap_next; - constraint_free( cn ); + constraint_free( cn, 1 ); cn = cp; } @@ -207,7 +232,7 @@ constraint_cf_gen( ConfigArgs *c ) if (cp) { /* zap cp, and join cpp to cp->ap_next */ *cpp = cp->ap_next; - constraint_free( cp ); + constraint_free( cp, 1 ); } on->on_bi.bi_private = cn; } @@ -232,13 +257,10 @@ constraint_cf_gen( ConfigArgs *c ) if ( slap_str2ad( attrs[j], &ap.ap[j], &text ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s <%s>: %s\n", c->argv[0], attrs[j], text ); - Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, - "%s: %s\n", c->log, c->cr_msg, 0 ); - ldap_memvfree((void**)attrs); - return( ARG_BAD_CONF ); + rc = ARG_BAD_CONF; + goto done; } } - ldap_memvfree((void**)attrs); if ( strcasecmp( c->argv[2], REGEX_STR ) == 0) { int err; @@ -251,12 +273,11 @@ constraint_cf_gen( ConfigArgs *c ) regerror( err, ap.re, errmsg, sizeof(errmsg) ); ch_free(ap.re); snprintf( c->cr_msg, sizeof( c->cr_msg ), - "%s %s: Illegal regular expression \"%s\": Error %s", - c->argv[0], c->argv[1], c->argv[3], errmsg); - Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, - "%s: %s\n", c->log, c->cr_msg, 0 ); + "%s %s: Illegal regular expression \"%s\": Error %s", + c->argv[0], c->argv[1], c->argv[3], errmsg); ap.re = NULL; - return( ARG_BAD_CONF ); + rc = ARG_BAD_CONF; + goto done; } ber_str2bv( c->argv[3], 0, 1, &ap.val ); } else if ( strcasecmp( c->argv[2], SIZE_STR ) == 0 ) { @@ -277,21 +298,17 @@ constraint_cf_gen( ConfigArgs *c ) snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: Invalid URI \"%s\"", c->argv[0], c->argv[1], c->argv[3]); - Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, - "%s: %s\n", c->log, c->cr_msg, 0 ); - return( ARG_BAD_CONF ); + rc = ARG_BAD_CONF; + goto done; } if (ap.lud->lud_host != NULL) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: unsupported hostname in URI \"%s\"", c->argv[0], c->argv[1], c->argv[3]); - Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, - "%s: %s\n", c->log, c->cr_msg, 0 ); - ldap_free_urldesc(ap.lud); - - return( ARG_BAD_CONF ); + rc = ARG_BAD_CONF; + goto done; } for ( i=0; ap.lud->lud_attrs[i]; i++); @@ -304,23 +321,43 @@ constraint_cf_gen( ConfigArgs *c ) ch_free( ap.attrs ); snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s <%s>: %s\n", c->argv[0], ap.lud->lud_attrs[i], text ); - Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, - "%s: %s\n", c->log, c->cr_msg, 0 ); - return( ARG_BAD_CONF ); + rc = ARG_BAD_CONF; + goto done; } } ap.attrs[i] = NULL; } - if (ap.lud->lud_dn == NULL) + if (ap.lud->lud_dn == NULL) { ap.lud->lud_dn = ch_strdup(""); + } else { + struct berval dn, ndn; + + ber_str2bv( ap.lud->lud_dn, 0, 0, &dn ); + if (dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ) ) { + /* cleanup */ + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "%s %s: URI %s DN normalization failed", + c->argv[0], c->argv[1], c->argv[3] ); + Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, + "%s: %s\n", c->log, c->cr_msg, 0 ); + rc = ARG_BAD_CONF; + goto done; + } + ldap_memfree( ap.lud->lud_dn ); + ap.lud->lud_dn = ndn.bv_val; + } if (ap.lud->lud_filter == NULL) { ap.lud->lud_filter = ch_strdup("objectClass=*"); } else if ( ap.lud->lud_filter[0] == '(' ) { ber_len_t len = strlen( ap.lud->lud_filter ); if ( ap.lud->lud_filter[len - 1] != ')' ) { - return( ARG_BAD_CONF ); + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "%s %s: invalid URI filter: %s", + c->argv[0], c->argv[1], ap.lud->lud_filter ); + rc = ARG_BAD_CONF; + goto done; } AC_MEMCPY( &ap.lud->lud_filter[0], &ap.lud->lud_filter[1], len - 2 ); ap.lud->lud_filter[len - 2] = '\0'; @@ -334,28 +371,148 @@ constraint_cf_gen( ConfigArgs *c ) } else { snprintf( c->cr_msg, sizeof( c->cr_msg ), - "%s %s: Unknown constraint type: %s", - c->argv[0], c->argv[1], c->argv[2] ); - Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, - "%s: %s\n", c->log, c->cr_msg, 0 ); - return ( ARG_BAD_CONF ); + "%s %s: Unknown constraint type: %s", + c->argv[0], c->argv[1], c->argv[2] ); + rc = ARG_BAD_CONF; + goto done; } - a2 = ch_calloc( sizeof(constraint), 1 ); - a2->ap_next = on->on_bi.bi_private; - a2->ap = ap.ap; - a2->re = ap.re; - a2->val = ap.val; - a2->lud = ap.lud; - a2->set = ap.set; - a2->size = ap.size; - a2->count = ap.count; - if ( a2->lud ) { - ber_str2bv(a2->lud->lud_dn, 0, 0, &a2->dn); - ber_str2bv(a2->lud->lud_filter, 0, 0, &a2->filter); + if ( c->argc > 4 ) { + int argidx; + + for ( argidx = 4; argidx < c->argc; argidx++ ) { + if ( strncasecmp( c->argv[argidx], "restrict=", STRLENOF("restrict=") ) == 0 ) { + int err; + char *arg = c->argv[argidx] + STRLENOF("restrict="); + + err = ldap_url_parse(arg, &ap.restrict_lud); + if ( err != LDAP_URL_SUCCESS ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "%s %s: Invalid restrict URI \"%s\"", + c->argv[0], c->argv[1], arg); + rc = ARG_BAD_CONF; + goto done; + } + + if (ap.restrict_lud->lud_host != NULL) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "%s %s: unsupported hostname in restrict URI \"%s\"", + c->argv[0], c->argv[1], arg); + rc = ARG_BAD_CONF; + goto done; + } + + if ( ap.restrict_lud->lud_attrs != NULL ) { + if ( ap.restrict_lud->lud_attrs[0] != '\0' ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "%s %s: attrs not allowed in restrict URI %s\n", + c->argv[0], c->argv[1], arg); + rc = ARG_BAD_CONF; + goto done; + } + ldap_memvfree((void *)ap.restrict_lud->lud_attrs); + ap.restrict_lud->lud_attrs = NULL; + } + + if (ap.restrict_lud->lud_dn != NULL) { + if (ap.restrict_lud->lud_dn[0] == '\0') { + ldap_memfree(ap.restrict_lud->lud_dn); + ap.restrict_lud->lud_dn = NULL; + + } else { + struct berval dn, ndn; + int j; + + ber_str2bv(ap.restrict_lud->lud_dn, 0, 0, &dn); + if (dnNormalize(0, NULL, NULL, &dn, &ndn, NULL)) { + /* cleanup */ + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "%s %s: restrict URI %s DN normalization failed", + c->argv[0], c->argv[1], arg ); + rc = ARG_BAD_CONF; + goto done; + } + + assert(c->be != NULL); + if (c->be->be_nsuffix == NULL) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "%s %s: restrict URI requires suffix", + c->argv[0], c->argv[1] ); + rc = ARG_BAD_CONF; + goto done; + } + + for ( j = 0; !BER_BVISNULL(&c->be->be_nsuffix[j]); j++) { + if (dnIsSuffix(&ndn, &c->be->be_nsuffix[j])) break; + } + + if (BER_BVISNULL(&c->be->be_nsuffix[j])) { + /* error */ + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "%s %s: restrict URI DN %s not within database naming context(s)", + c->argv[0], c->argv[1], dn.bv_val ); + rc = ARG_BAD_CONF; + goto done; + } + + ap.restrict_ndn = ndn; + } + } + + if (ap.restrict_lud->lud_filter != NULL) { + ap.restrict_filter = str2filter(ap.restrict_lud->lud_filter); + if (ap.restrict_filter == NULL) { + /* error */ + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "%s %s: restrict URI filter %s invalid", + c->argv[0], c->argv[1], ap.restrict_lud->lud_filter ); + rc = ARG_BAD_CONF; + goto done; + } + } + + ber_str2bv(c->argv[argidx], 0, 1, &ap.restrict_val); + + } else { + /* cleanup */ + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "%s %s: unrecognized arg #%d (%s)", + c->argv[0], c->argv[1], argidx, c->argv[argidx] ); + rc = ARG_BAD_CONF; + goto done; + } + } + } + +done:; + if ( rc == LDAP_SUCCESS ) { + constraint *a2 = ch_calloc( sizeof(constraint), 1 ); + a2->ap_next = on->on_bi.bi_private; + a2->ap = ap.ap; + a2->re = ap.re; + a2->val = ap.val; + a2->lud = ap.lud; + a2->set = ap.set; + a2->size = ap.size; + a2->count = ap.count; + if ( a2->lud ) { + ber_str2bv(a2->lud->lud_dn, 0, 0, &a2->dn); + ber_str2bv(a2->lud->lud_filter, 0, 0, &a2->filter); + } + a2->attrs = ap.attrs; + a2->restrict_lud = ap.restrict_lud; + a2->restrict_ndn = ap.restrict_ndn; + a2->restrict_filter = ap.restrict_filter; + a2->restrict_val = ap.restrict_val; + on->on_bi.bi_private = a2; + + } else { + Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, + "%s: %s\n", c->log, c->cr_msg, 0 ); + constraint_free( &ap, 0 ); } - a2->attrs = ap.attrs; - on->on_bi.bi_private = a2; + + ldap_memvfree((void**)attrs); } break; default: abort(); @@ -384,7 +541,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; @@ -399,19 +556,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; @@ -485,8 +636,11 @@ constraint_violation( constraint *c, struct berval *bv, Operation *op, SlapReply 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 }; + Debug(LDAP_DEBUG_TRACE, "==> constraint_violation uri filter = %s\n", filterstr.bv_val, 0, 0); @@ -499,13 +653,12 @@ constraint_violation( constraint *c, struct berval *bv, Operation *op, SlapReply } op->o_tmpfree(filterstr.bv_val, op->o_tmpmemctx); - if((rc != LDAP_SUCCESS) && (rc != LDAP_NO_SUCH_OBJECT)) { + if ((rc != LDAP_SUCCESS) && (rc != LDAP_NO_SUCH_OBJECT)) { return rc; /* unexpected error */ } if (!found) return LDAP_CONSTRAINT_VIOLATION; /* constraint violation */ - } return LDAP_SUCCESS; @@ -533,6 +686,61 @@ constraint_count_attr(Entry *e, AttributeDescription *ad) return 0; } +static int +constraint_check_restrict( Operation *op, constraint *c, Entry *e ) +{ + assert( c->restrict_lud != NULL ); + + if ( c->restrict_lud->lud_dn != NULL ) { + int diff = e->e_nname.bv_len - c->restrict_ndn.bv_len; + + if ( diff < 0 ) { + return 0; + } + + if ( c->restrict_lud->lud_scope == LDAP_SCOPE_BASE ) { + return bvmatch( &e->e_nname, &c->restrict_ndn ); + } + + if ( !dnIsSuffix( &e->e_nname, &c->restrict_ndn ) ) { + return 0; + } + + if ( c->restrict_lud->lud_scope != LDAP_SCOPE_SUBTREE ) { + struct berval pdn; + + if ( diff == 0 ) { + return 0; + } + + dnParent( &e->e_nname, &pdn ); + + if ( c->restrict_lud->lud_scope == LDAP_SCOPE_ONELEVEL + && pdn.bv_len != c->restrict_ndn.bv_len ) + { + return 0; + } + } + } + + if ( c->restrict_filter != NULL ) { + int rc; + struct berval save_dn = op->o_dn, save_ndn = op->o_ndn; + + op->o_dn = op->o_bd->be_rootdn; + op->o_ndn = op->o_bd->be_rootndn; + rc = test_filter( op, e, c->restrict_filter ); + op->o_dn = save_dn; + op->o_ndn = save_ndn; + + if ( rc != LDAP_COMPARE_TRUE ) { + return 0; + } + } + + return 1; +} + static int constraint_add( Operation *op, SlapReply *rs ) { @@ -545,6 +753,10 @@ constraint_add( Operation *op, SlapReply *rs ) int rc; char *msg = NULL; + if (get_relax(op)) { + return SLAP_CB_CONTINUE; + } + if ((a = op->ora_e->e_attrs) == NULL) { op->o_bd->bd_info = (BackendInfo *)(on->on_info); send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, @@ -563,11 +775,15 @@ constraint_add( Operation *op, SlapReply *rs ) } if (cp->ap[j] == NULL) continue; if ((b = a->a_vals) == NULL) continue; - + + if (cp->restrict_lud != NULL && constraint_check_restrict(op, cp, op->ora_e) == 0) { + continue; + } + Debug(LDAP_DEBUG_TRACE, "==> constraint_add, " - "a->a_numvals = %d, cp->count = %d\n", - a->a_numvals, cp->count, 0); + "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; @@ -575,7 +791,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; } @@ -604,37 +820,55 @@ add_violation: static int -constraint_modify( Operation *op, SlapReply *rs ) +constraint_update( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; Backend *be = op->o_bd; constraint *c = on->on_bi.bi_private, *cp; Entry *target_entry = NULL, *target_entry_copy = NULL; - Modifications *m; + Modifications *modlist, *m; BerVarray b = NULL; int i; struct berval rsv = BER_BVC("modify breaks constraint"); int rc; char *msg = NULL; + + if (get_relax(op)) { + return SLAP_CB_CONTINUE; + } + + switch ( op->o_tag ) { + case LDAP_REQ_MODIFY: + modlist = op->orm_modlist; + break; + + case LDAP_REQ_MODRDN: + modlist = op->orr_modlist; + break; + + default: + /* impossible! assert? */ + return LDAP_OTHER; + } - Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "constraint_modify()\n", 0,0,0); - if ((m = op->orm_modlist) == NULL) { + Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "constraint_update()\n", 0,0,0); + if ((m = modlist) == NULL) { op->o_bd->bd_info = (BackendInfo *)(on->on_info); send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, - "constraint_modify() got null orm_modlist"); + "constraint_update() got null modlist"); return(rs->sr_err); } /* Do we need to count attributes? */ for(cp = c; cp; cp = cp->ap_next) { - if (cp->count != 0 || cp->set) { + 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 (rc != 0 || target_entry == NULL) { Debug(LDAP_DEBUG_TRACE, - "==> constraint_modify rc = %d DN=\"%s\"%s\n", + "==> constraint_update rc = %d DN=\"%s\"%s\n", rc, op->o_req_ndn.bv_val, target_entry ? "" : " not found" ); if ( rc == 0 ) @@ -647,7 +881,7 @@ constraint_modify( Operation *op, SlapReply *rs ) rc = LDAP_CONSTRAINT_VIOLATION; for(;m; m = m->sml_next) { - int ce = 0; + unsigned ce = 0; if (is_at_operational( m->sml_desc->ad_type )) continue; @@ -672,9 +906,13 @@ constraint_modify( Operation *op, SlapReply *rs ) } } if (cp->ap[j] == NULL) continue; - + + if (cp->restrict_lud != NULL && constraint_check_restrict(op, cp, target_entry) == 0) { + continue; + } + if (cp->count != 0) { - int ca; + unsigned ca; if (m->sml_op == LDAP_MOD_DELETE) ce = 0; @@ -682,9 +920,9 @@ constraint_modify( Operation *op, SlapReply *rs ) for (ca = 0; b[ca].bv_val; ++ca); Debug(LDAP_DEBUG_TRACE, - "==> constraint_modify ce = %d, " - "ca = %d, cp->count = %d\n", - ce, ca, cp->count); + "==> 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) { @@ -706,7 +944,7 @@ constraint_modify( Operation *op, SlapReply *rs ) 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; } @@ -718,11 +956,30 @@ constraint_modify( Operation *op, SlapReply *rs ) target_entry_copy = entry_dup(target_entry); + /* if rename, set the new entry's name + * (in normalized form only) */ + if ( op->o_tag == LDAP_REQ_MODRDN ) { + struct berval pdn, ndn = BER_BVNULL; + + if ( op->orr_nnewSup ) { + pdn = *op->orr_nnewSup; + + } else { + dnParent( &target_entry_copy->e_nname, &pdn ); + } + + build_new_dn( &ndn, &pdn, &op->orr_nnewrdn, NULL ); + + ber_memfree( target_entry_copy->e_nname.bv_val ); + target_entry_copy->e_nname = ndn; + ber_bvreplace( &target_entry_copy->e_name, &ndn ); + } + /* apply modifications, in an attempt * to estimate what the entry would * look like in case all modifications * pass */ - for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) { + for ( ml = modlist; ml; ml = ml->sml_next ) { Modification *mod = &ml->sml_mod; const char *text; char textbuf[SLAP_TEXT_BUFLEN]; @@ -765,6 +1022,29 @@ constraint_modify( 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; @@ -777,7 +1057,6 @@ constraint_modify( Operation *op, SlapReply *rs ) } } - if ( acl_match_set(&cp->val, op, target_entry_copy, NULL) == 0) { rc = LDAP_CONSTRAINT_VIOLATION; goto mod_violation; @@ -829,7 +1108,7 @@ constraint_close( for ( ap = on->on_bi.bi_private; ap; ap = a2 ) { a2 = ap->ap_next; - constraint_free( ap ); + constraint_free( ap, 1 ); } return 0; @@ -847,7 +1126,8 @@ constraint_initialize( void ) { constraint_ovl.on_bi.bi_type = "constraint"; constraint_ovl.on_bi.bi_db_close = constraint_close; constraint_ovl.on_bi.bi_op_add = constraint_add; - constraint_ovl.on_bi.bi_op_modify = constraint_modify; + constraint_ovl.on_bi.bi_op_modify = constraint_update; + constraint_ovl.on_bi.bi_op_modrdn = constraint_update; constraint_ovl.on_bi.bi_private = NULL;