]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/constraint.c
ITS#8063 don't block our own thread
[openldap] / servers / slapd / overlays / constraint.c
index e101cd86568bc3a31ab1cf761adfa7bc0864d196..33323e399d4225ba41563a9fde98d1003867e8fc 100644 (file)
@@ -62,6 +62,7 @@ typedef struct constraint {
        Filter *restrict_filter;
        struct berval restrict_val;
 
+       int type;
        regex_t *re;
        LDAPURLDesc *lud;
        int set;
@@ -74,7 +75,12 @@ typedef struct constraint {
 } constraint;
 
 enum {
-       CONSTRAINT_ATTRIBUTE = 1
+       CONSTRAINT_ATTRIBUTE = 1,
+       CONSTRAINT_COUNT,
+       CONSTRAINT_SIZE,
+       CONSTRAINT_REGEX,
+       CONSTRAINT_SET,
+       CONSTRAINT_URI,
 };
 
 static ConfigDriver constraint_cf_gen;
@@ -143,7 +149,7 @@ constraint_cf_gen( ConfigArgs *c )
                        for (cp=cn; cp; cp=cp->ap_next) {
                                char *s;
                                char *tstr = NULL;
-                               int quotes = 0;
+                               int quotes = 0, numeric = 0;
                                int j;
                                size_t val;
                                char val_buf[SLAP_TEXT_BUFLEN] = { '\0' };
@@ -156,21 +162,31 @@ constraint_cf_gen( ConfigArgs *c )
                                /* room for commas */
                                bv.bv_len += j - 1;
 
-                               if (cp->re) {
-                                       tstr = REGEX_STR;
-                                       quotes = 1;
-                               } else if (cp->lud) {
-                                       tstr = URI_STR;
-                                       quotes = 1;
-                               } else if (cp->set) {
-                                       tstr = SET_STR;
-                                       quotes = 1;
-                               } else if (cp->size) {
-                                       tstr = SIZE_STR;
-                                       val = cp->size;
-                               } else if (cp->count) {
-                                       tstr = COUNT_STR;
-                                       val = cp->count;
+                               switch (cp->type) {
+                                       case CONSTRAINT_COUNT:
+                                               tstr = COUNT_STR;
+                                               val = cp->count;
+                                               numeric = 1;
+                                               break;
+                                       case CONSTRAINT_SIZE:
+                                               tstr = SIZE_STR;
+                                               val = cp->size;
+                                               numeric = 1;
+                                               break;
+                                       case CONSTRAINT_REGEX:
+                                               tstr = REGEX_STR;
+                                               quotes = 1;
+                                               break;
+                                       case CONSTRAINT_SET:
+                                               tstr = SET_STR;
+                                               quotes = 1;
+                                               break;
+                                       case CONSTRAINT_URI:
+                                               tstr = URI_STR;
+                                               quotes = 1;
+                                               break;
+                                       default:
+                                               abort();
                                }
 
                                bv.bv_len += strlen(tstr);
@@ -180,8 +196,8 @@ 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 (numeric) {
+                                       int len = snprintf(val_buf, sizeof(val_buf), "%zu", val);
                                        if (len <= 0) {
                                                /* error */
                                                return -1;
@@ -199,7 +215,7 @@ constraint_cf_gen( ConfigArgs *c )
                                *s++ = ' ';
                                s = lutil_strcopy( s, tstr );
                                *s++ = ' ';
-                               if (cp->count || cp->size) {
+                               if (numeric) {
                                        s = lutil_strcopy( s, val_buf );
                                } else {
                                        if ( quotes ) *s++ = '"';
@@ -283,6 +299,7 @@ constraint_cf_gen( ConfigArgs *c )
                        if ( strcasecmp( c->argv[2], REGEX_STR ) == 0) {
                                int err;
                        
+                               ap.type = CONSTRAINT_REGEX;
                                ap.re = ch_malloc( sizeof(regex_t) );
                                if ((err = regcomp( ap.re,
                                        c->argv[3], REG_EXTENDED )) != 0) {
@@ -300,17 +317,24 @@ constraint_cf_gen( ConfigArgs *c )
                                ber_str2bv( c->argv[3], 0, 1, &ap.val );
                        } else if ( strcasecmp( c->argv[2], SIZE_STR ) == 0 ) {
                                size_t size;
+                               char *endptr;
 
-                               if ( ( size = atoi(c->argv[3]) ) != 0 )
-                                       ap.size = size; 
+                               ap.type = CONSTRAINT_SIZE;
+                               ap.size = strtoull(c->argv[3], &endptr, 10);
+                               if ( *endptr )
+                                       rc = ARG_BAD_CONF;
                        } else if ( strcasecmp( c->argv[2], COUNT_STR ) == 0 ) {
                                size_t count;
+                               char *endptr;
 
-                               if ( ( count = atoi(c->argv[3]) ) != 0 )
-                                       ap.count = count;       
+                               ap.type = CONSTRAINT_COUNT;
+                               ap.count = strtoull(c->argv[3], &endptr, 10);
+                               if ( *endptr )
+                                       rc = ARG_BAD_CONF;
                        } else if ( strcasecmp( c->argv[2], URI_STR ) == 0 ) {
                                int err;
                        
+                               ap.type = CONSTRAINT_URI;
                                err = ldap_url_parse(c->argv[3], &ap.lud);
                                if ( err != LDAP_URL_SUCCESS ) {
                                        snprintf( c->cr_msg, sizeof( c->cr_msg ),
@@ -386,6 +410,7 @@ constraint_cf_gen( ConfigArgs *c )
                        } else if ( strcasecmp( c->argv[2], SET_STR ) == 0 ) {
                                ap.set = 1;
                                ber_str2bv( c->argv[3], 0, 1, &ap.val );
+                               ap.type = CONSTRAINT_SET;
 
                        } else {
                                snprintf( c->cr_msg, sizeof( c->cr_msg ),
@@ -507,6 +532,7 @@ done:;
                                constraint *a2 = ch_calloc( sizeof(constraint), 1 );
                                a2->ap_next = on->on_bi.bi_private;
                                a2->ap = ap.ap;
+                               a2->type = ap.type;
                                a2->re = ap.re;
                                a2->val = ap.val;
                                a2->lud = ap.lud;
@@ -563,120 +589,124 @@ constraint_violation( constraint *c, struct berval *bv, Operation *op )
 {
        if ((!c) || (!bv)) return LDAP_SUCCESS;
        
-       if ((c->re) &&
-               (regexec(c->re, bv->bv_val, 0, NULL, 0) == REG_NOMATCH))
-               return LDAP_CONSTRAINT_VIOLATION; /* regular expression violation */
-
-       if ((c->size) && (bv->bv_len > c->size))
-               return LDAP_CONSTRAINT_VIOLATION; /* size violation */
-
-       if (c->lud) {
-               Operation nop = *op;
-               slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
-               slap_callback cb;
-               int i;
-               int found = 0;
-               int rc;
-               size_t len;
-               struct berval filterstr;
-               char *ptr;
-
-               cb.sc_next = NULL;
-               cb.sc_response = constraint_uri_cb;
-               cb.sc_cleanup = NULL;
-               cb.sc_private = &found;
-
-               nop.o_protocol = LDAP_VERSION3;
-               nop.o_tag = LDAP_REQ_SEARCH;
-               nop.o_time = slap_get_time();
-               if (c->lud->lud_dn) {
-                       struct berval dn;
-
-                       ber_str2bv(c->lud->lud_dn, 0, 0, &dn);
-                       nop.o_req_dn = dn;
-                       nop.o_req_ndn = dn;
-                       nop.o_bd = select_backend(&nop.o_req_ndn, 1 );
-                       if (!nop.o_bd) {
-                               return LDAP_NO_SUCH_OBJECT; /* unexpected error */
+       switch (c->type) {
+               case CONSTRAINT_SIZE:
+                       if (bv->bv_len > c->size)
+                               return LDAP_CONSTRAINT_VIOLATION; /* size violation */
+                       break;
+               case CONSTRAINT_REGEX:
+                       if (regexec(c->re, bv->bv_val, 0, NULL, 0) == REG_NOMATCH)
+                               return LDAP_CONSTRAINT_VIOLATION; /* regular expression violation */
+                       break;
+               case CONSTRAINT_URI: {
+                       Operation nop = *op;
+                       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+                       slap_callback cb;
+                       int i;
+                       int found = 0;
+                       int rc;
+                       size_t len;
+                       struct berval filterstr;
+                       char *ptr;
+
+                       cb.sc_next = NULL;
+                       cb.sc_response = constraint_uri_cb;
+                       cb.sc_cleanup = NULL;
+                       cb.sc_private = &found;
+
+                       nop.o_protocol = LDAP_VERSION3;
+                       nop.o_tag = LDAP_REQ_SEARCH;
+                       nop.o_time = slap_get_time();
+                       if (c->lud->lud_dn) {
+                               struct berval dn;
+
+                               ber_str2bv(c->lud->lud_dn, 0, 0, &dn);
+                               nop.o_req_dn = dn;
+                               nop.o_req_ndn = dn;
+                               nop.o_bd = select_backend(&nop.o_req_ndn, 1 );
+                               if (!nop.o_bd) {
+                                       return LDAP_NO_SUCH_OBJECT; /* unexpected error */
+                               }
+                               if (!nop.o_bd->be_search) {
+                                       return LDAP_OTHER; /* unexpected error */
+                               }
+                       } else {
+                               nop.o_req_dn = nop.o_bd->be_nsuffix[0];
+                               nop.o_req_ndn = nop.o_bd->be_nsuffix[0];
+                               nop.o_bd = on->on_info->oi_origdb;
                        }
-                       if (!nop.o_bd->be_search) {
-                               return LDAP_OTHER; /* unexpected error */
+                       nop.o_do_not_cache = 1;
+                       nop.o_callback = &cb;
+
+                       nop.ors_scope = c->lud->lud_scope;
+                       nop.ors_deref = LDAP_DEREF_NEVER;
+                       nop.ors_slimit = SLAP_NO_LIMIT;
+                       nop.ors_tlimit = SLAP_NO_LIMIT;
+                       nop.ors_limit = NULL;
+
+                       nop.ors_attrsonly = 0;
+                       nop.ors_attrs = slap_anlist_no_attrs;
+
+                       len = STRLENOF("(&(") +
+                                 c->filter.bv_len +
+                                 STRLENOF(")(|");
+
+                       for (i = 0; c->attrs[i]; i++) {
+                               len += STRLENOF("(") +
+                                          c->attrs[i]->ad_cname.bv_len +
+                                          STRLENOF("=") +
+                                          bv->bv_len +
+                                          STRLENOF(")");
                        }
-               } else {
-                       nop.o_req_dn = nop.o_bd->be_nsuffix[0];
-                       nop.o_req_ndn = nop.o_bd->be_nsuffix[0];
-                       nop.o_bd = on->on_info->oi_origdb;
-               }
-               nop.o_do_not_cache = 1;
-               nop.o_callback = &cb;
-
-               nop.ors_scope = c->lud->lud_scope;
-               nop.ors_deref = LDAP_DEREF_NEVER;
-               nop.ors_slimit = SLAP_NO_LIMIT;
-               nop.ors_tlimit = SLAP_NO_LIMIT;
-               nop.ors_limit = NULL;
-
-               nop.ors_attrsonly = 0;
-               nop.ors_attrs = slap_anlist_no_attrs;
-
-               len = STRLENOF("(&(") + 
-                         c->filter.bv_len +
-                         STRLENOF(")(|");
-
-               for (i = 0; c->attrs[i]; i++) {
-                       len += STRLENOF("(") +
-                                  c->attrs[i]->ad_cname.bv_len +
-                                  STRLENOF("=") + 
-                                  bv->bv_len +
-                                  STRLENOF(")");
-               }
 
-               len += STRLENOF("))");
-               filterstr.bv_len = len;
-               filterstr.bv_val = op->o_tmpalloc(len + 1, op->o_tmpmemctx);
-
-               ptr = filterstr.bv_val +
-                       snprintf(filterstr.bv_val, len, "(&(%s)(|", c->lud->lud_filter);
-               for (i = 0; c->attrs[i]; i++) {
-                       *ptr++ = '(';
-                       ptr = lutil_strcopy( ptr, c->attrs[i]->ad_cname.bv_val );
-                       *ptr++ = '=';
-                       ptr = lutil_strcopy( ptr, bv->bv_val );
+                       len += STRLENOF("))");
+                       filterstr.bv_len = len;
+                       filterstr.bv_val = op->o_tmpalloc(len + 1, op->o_tmpmemctx);
+
+                       ptr = filterstr.bv_val +
+                               snprintf(filterstr.bv_val, len, "(&(%s)(|", c->lud->lud_filter);
+                       for (i = 0; c->attrs[i]; i++) {
+                               *ptr++ = '(';
+                               ptr = lutil_strcopy( ptr, c->attrs[i]->ad_cname.bv_val );
+                               *ptr++ = '=';
+                               ptr = lutil_strcopy( ptr, bv->bv_val );
+                               *ptr++ = ')';
+                       }
                        *ptr++ = ')';
-               }
-               *ptr++ = ')';
-               *ptr++ = ')';
-               *ptr++ = '\0';
+                       *ptr++ = ')';
+                       *ptr++ = '\0';
 
-               nop.ors_filterstr = filterstr;
-               nop.ors_filter = str2filter_x(&nop, filterstr.bv_val);
-               if ( nop.ors_filter == NULL ) {
-                       Debug( LDAP_DEBUG_ANY,
-                               "%s constraint_violation uri filter=\"%s\" invalid\n",
-                               op->o_log_prefix, filterstr.bv_val, 0 );
-                       rc = LDAP_OTHER;
+                       nop.ors_filterstr = filterstr;
+                       nop.ors_filter = str2filter_x(&nop, filterstr.bv_val);
+                       if ( nop.ors_filter == NULL ) {
+                               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 };
+                       } else {
+                               SlapReply nrs = { REP_RESULT };
 
-                       Debug(LDAP_DEBUG_TRACE, 
-                               "==> constraint_violation uri filter = %s\n",
-                               filterstr.bv_val, 0, 0);
+                               Debug(LDAP_DEBUG_TRACE,
+                                       "==> constraint_violation uri filter = %s\n",
+                                       filterstr.bv_val, 0, 0);
 
-                       rc = nop.o_bd->be_search( &nop, &nrs );
-               
-                       Debug(LDAP_DEBUG_TRACE, 
-                               "==> constraint_violation uri rc = %d, found = %d\n",
-                               rc, found, 0);
-               }
-               op->o_tmpfree(filterstr.bv_val, op->o_tmpmemctx);
+                               rc = nop.o_bd->be_search( &nop, &nrs );
 
-               if ((rc != LDAP_SUCCESS) && (rc != LDAP_NO_SUCH_OBJECT)) {
-                       return rc; /* unexpected error */
-               }
+                               Debug(LDAP_DEBUG_TRACE,
+                                       "==> constraint_violation uri rc = %d, found = %d\n",
+                                       rc, found, 0);
+                       }
+                       op->o_tmpfree(filterstr.bv_val, op->o_tmpmemctx);
 
-               if (!found)
-                       return LDAP_CONSTRAINT_VIOLATION; /* constraint violation */
+                       if ((rc != LDAP_SUCCESS) && (rc != LDAP_NO_SUCH_OBJECT)) {
+                               return rc; /* unexpected error */
+                       }
+
+                       if (!found)
+                               return LDAP_CONSTRAINT_VIOLATION; /* constraint violation */
+                       break;
+               }
        }
 
        return LDAP_SUCCESS;
@@ -768,7 +798,7 @@ constraint_add( Operation *op, SlapReply *rs )
        BerVarray b = NULL;
        int i;
        struct berval rsv = BER_BVC("add breaks constraint");
-       int rc;
+       int rc = 0;
        char *msg = NULL;
 
        if (get_relax(op) || SLAPD_SYNC_IS_SYNCCONN( op->o_connid )) {
@@ -803,22 +833,25 @@ constraint_add( Operation *op, SlapReply *rs )
                                "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;
-                               goto add_violation;
-                       }
-
-                       for ( i = 0; b[i].bv_val; i++ ) {
-                               rc = constraint_violation( cp, &b[i], op );
-                               if ( rc ) {
-                                       goto add_violation;
+                       switch (cp->type) {
+                               case CONSTRAINT_COUNT:
+                                       if (a->a_numvals > cp->count)
+                                               rc = LDAP_CONSTRAINT_VIOLATION;
+                                       break;
+                               case CONSTRAINT_SET:
+                                       if (acl_match_set(&cp->val, op, op->ora_e, NULL) == 0)
+                                               rc = LDAP_CONSTRAINT_VIOLATION;
+                                       break;
+                               default:
+                                       for ( i = 0; b[i].bv_val; i++ ) {
+                                               rc = constraint_violation( cp, &b[i], op );
+                                               if ( rc ) {
+                                                       goto add_violation;
+                                               }
+                                       }
                                }
-                       }
-
-                       if (cp->set && acl_match_set(&cp->val, op, op->ora_e, NULL) == 0) {
-                               rc = LDAP_CONSTRAINT_VIOLATION;
-                               goto add_violation; /* constraint violation */
-                       }
+                       if ( rc )
+                               goto add_violation;
 
                }
        }
@@ -946,17 +979,7 @@ constraint_update( Operation *op, SlapReply *rs )
 
        /* Do we need to count attributes? */
        for(cp = c; cp; cp = cp->ap_next) {
-               if (cp->count != 0) {
-                       if (rc != 0 || target_entry == NULL) {
-                               Debug(LDAP_DEBUG_TRACE, 
-                                       "==> constraint_update rc = %d DN=\"%s\"%s\n",
-                                       rc, op->o_req_ndn.bv_val,
-                                       target_entry ? "" : " not found" );
-                               if ( rc == 0 ) 
-                                       rc = LDAP_CONSTRAINT_VIOLATION;
-                               goto mod_violation;
-                       }
-
+               if (cp->type == CONSTRAINT_COUNT) {
                        if (cp->restrict_lud && constraint_check_restrict(op, cp, target_entry) == 0) {
                                continue;
                        }
@@ -1012,7 +1035,7 @@ constraint_update( Operation *op, SlapReply *rs )
                                }
                        }
 
-                       if (cp->set && target_entry) {
+                       if (cp->type == CONSTRAINT_SET && target_entry) {
                                if (target_entry_copy == NULL) {
                                        Modifications *ml;