]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/constraint.c
ITS#7178 fix uninit'd op->ors_deref
[openldap] / servers / slapd / overlays / constraint.c
index bc320804240c03de334ffa14cf4bb20dc4434210..e6a9267ba7d15e3639e900b97e22584e98b596b2 100644 (file)
@@ -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), "%d", 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;
@@ -642,8 +654,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);
@@ -656,13 +671,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;
@@ -757,6 +771,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,
@@ -782,8 +800,8 @@ constraint_add( Operation *op, SlapReply *rs )
 
                        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;
@@ -791,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;
                                }
@@ -820,24 +838,42 @@ 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);
        }
 
@@ -850,7 +886,7 @@ constraint_modify( Operation *op, SlapReply *rs )
 
                        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 ) 
@@ -863,7 +899,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;
 
@@ -894,7 +930,7 @@ constraint_modify( Operation *op, SlapReply *rs )
                        }
 
                        if (cp->count != 0) {
-                               int ca;
+                               unsigned ca;
 
                                if (m->sml_op == LDAP_MOD_DELETE)
                                        ce = 0;
@@ -902,9 +938,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) {
@@ -926,7 +962,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;
                                }
@@ -938,11 +974,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];
@@ -985,6 +1040,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;
@@ -997,7 +1075,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;
@@ -1067,7 +1144,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;