[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: referential integrity (patch included)



On Mon, May 28, 2007 at 08:26:07PM +0000, Emmanuel Dreyfus wrote:
> Attached is a draft patch for review.

And as usual, the patch was missing. Here it is

-- 
Emmanuel Dreyfus
manu@netbsd.org
diff -r -U4 openldap-2.4.4alpha.orig/servers/slapd/overlays/constraint.c openldap-2.4.4alpha/servers/slapd/overlays/constraint.c
--- openldap-2.4.4alpha.orig/servers/slapd/overlays/constraint.c	2007-02-13 20:22:29.000000000 +0000
+++ openldap-2.4.4alpha/servers/slapd/overlays/constraint.c	2007-05-28 20:10:48.000000000 +0000
@@ -1,8 +1,9 @@
 /* constraint.c - Overlay to constrain attributes to certain values */
 /* 
  *
  * Copyright 2003-2004 Hewlett-Packard Company
+ * Copyright 2007 Emmanuel Dreyfus
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted only as authorized by the OpenLDAP
@@ -12,9 +13,10 @@
  * top-level directory of the distribution or, alternatively, at
  * <http://www.OpenLDAP.org/license.html>.
  */
 /*
- * Author: Neil Dunbar <neil.dunbar@hp.com>
+ * Authors: Neil Dunbar <neil.dunbar@hp.com>
+ *          Emmannuel Dreyfus <manu@netbsd.org>
  */
 #include "portable.h"
 
 #ifdef SLAPD_OVER_CONSTRAINT
@@ -36,8 +38,9 @@
  * control the add and modify value mods of a modify)
  */
 
 #define REGEX_STR "regex"
+#define KEY_STR "key"
 
 /*
  * Linked list of attribute constraints which we should enforce.
  * This is probably a sub optimal structure - some form of sorted
@@ -50,8 +53,9 @@
     struct constraint *ap_next;
     AttributeDescription *ap;
     regex_t *re;
     char *re_str; /* string representation of regex */
+    AttributeDescription *ap_key;
 } constraint;
 
 enum {
     CONSTRAINT_ATTRIBUTE = 1
@@ -65,8 +69,14 @@
       "( OLcfgOvAt:13.1 NAME 'olcConstraintAttribute' "
       "DESC 'regular expression constraint for attribute' "
 	  "EQUALITY caseIgnoreMatch "
       "SYNTAX OMsDirectoryString )", NULL, NULL },
+    { "constraint_attribute", "attribute key <attribute name>",
+      4, 4, 0, ARG_MAGIC | CONSTRAINT_ATTRIBUTE, constraint_cf_gen,
+      "( OLcfgOvAt:13.1 NAME 'olcConstraintAttribute' "
+      "DESC 'attribute value constraint for attribute' "
+	  "EQUALITY caseIgnoreMatch "
+      "SYNTAX OMsDirectoryString )", NULL, NULL },
     { NULL, NULL, 0, 0, 0, ARG_IGNORED }
 };
 
 static ConfigOCs constraintocs[] = {
@@ -95,15 +105,25 @@
                 case CONSTRAINT_ATTRIBUTE:
                     for (cp=cn; cp; cp=cp->ap_next) {
                         int len;
                         char *s;
+			char *tstr = NULL;
+			char *vstr = NULL;
                         
-                        len = cp->ap->ad_cname.bv_len +
-                            strlen( REGEX_STR ) + strlen( cp->re_str) + 3;
+			if (cp->re) {
+				tstr = REGEX_STR;
+				vstr = cp->re_str;
+			} else if (cp->ap_key) {
+				tstr = KEY_STR;
+				vstr = cp->ap_key->ad_cname.bv_val;
+			}
+
+                        len = cp->ap->ad_cname.bv_len 
+							+ strlen(tstr) + strlen(vstr); + 3; 
                         s = ch_malloc(len);
                         if (!s) continue;
                         snprintf(s, len, "%s %s %s", cp->ap->ad_cname.bv_val,
-                                 REGEX_STR, cp->re_str);
+                                 tstr, vstr);
                         bv.bv_val = s;
                         bv.bv_len = strlen(s);
                         rc = value_add_one( &c->rvalue_vals, &bv );
                         if (rc) return rc;
@@ -174,9 +194,17 @@
                                "%s: %s\n", c->log, c->msg, 0 );
                         return( ARG_BAD_CONF );
                     }
 
-                    if ( strcasecmp( c->argv[2], "regex" ) == 0) {
+                    if ( strcasecmp( c->argv[2], KEY_STR ) == 0) {
+			    if ( slap_str2ad( c->argv[3], &ap.ap_key, &text ) ) {
+							snprintf( c->msg, sizeof( c->msg ),
+								"%s <%s>: %s\n", c->argv[0], c->argv[3], text );
+				Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+				       "%s: %s\n", c->log, c->msg, 0 );
+				return( ARG_BAD_CONF );
+			    }
+		    } else if ( strcasecmp( c->argv[2], REGEX_STR ) == 0) {
                         int err;
             
                         ap.re = ch_malloc( sizeof(regex_t) );
                         if ((err = regcomp( ap.re,
@@ -208,8 +236,9 @@
                     a2->ap_next = on->on_bi.bi_private;
                     a2->ap = ap.ap;
                     a2->re = ap.re;
                     a2->re_str = ap.re_str;
+                    a2->ap_key = ap.ap_key;
                     on->on_bi.bi_private = a2;
                     break;
                 default:
                     abort();
@@ -223,16 +252,112 @@
     return rc;
 }
 
 static int
-constraint_violation( constraint *c, struct berval *bv )
+constraint_key_cb( Operation *op, SlapReply *rs ) 
+{
+	int *foundp;
+
+	if(!op || !rs)
+		return(0);
+
+	if(rs->sr_type != REP_SEARCH) 
+		return 0;
+
+	foundp = (int *)op->o_callback->sc_private;
+	*foundp = 1;
+	
+	Debug(LDAP_DEBUG_TRACE, "==> constraint_key_cb <%s>\n",
+	    rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
+}
+
+static int
+constraint_violation( constraint *c, struct berval *bv, Operation *op, SlapReply *rs)
 {
     if ((!c) || (!bv)) return 0;
     
     if ((c->re) &&
         (regexec(c->re, bv->bv_val, 0, NULL, 0) == REG_NOMATCH))
-        
         return 1; /* regular expression violation */
+
+	if (c->ap_key) {
+		Connection conn = {0};
+		OperationBuffer opbuf;
+		Operation *nop = (Operation *) &opbuf;
+		slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+		slap_callback cb;
+		SlapReply nrs = { REP_RESULT };
+		AttributeAssertion ava;
+		Filter filter;
+		int rc;
+		int found = 0;
+		
+		connection_fake_init(&conn, nop, 
+				     ldap_pvt_thread_pool_context());
+
+		nrs.sr_entry = NULL;
+		nrs.sr_nentries = 0;
+
+		ava.aa_desc = c->ap_key;
+		rc = asserted_value_validate_normalize(c->ap_key,
+			ad_mr(c->ap_key, SLAP_MR_EQUALITY), 
+			SLAP_MR_EQUALITY,
+			bv, &ava.aa_value, 
+			&nrs.sr_text, nop->o_tmpmemctx);
+		if (rc != LDAP_SUCCESS) {
+			send_ldap_error(op, rs, rc, 
+				"constraint_violation key search failed");
+			return 1; /* unexpected error */
+		}
+#ifdef LDAP_COMP_MATCH 
+		ava.aa_cf = NULL;
+#endif
+
+		filter.f_choice = LDAP_FILTER_EQUALITY;
+		filter.f_ava = &ava;
+		filter.f_next = NULL;
+
+		cb.sc_next = NULL;
+		cb.sc_response = constraint_key_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();
+		nop->o_bd = on->on_info->oi_origdb;
+		nop->o_req_dn = nop->o_bd->be_suffix[0];
+		nop->o_req_ndn = nop->o_bd->be_nsuffix[0];
+		nop->o_do_not_cache = 1;
+		nop->o_callback = &cb;
+
+		nop->ors_scope = LDAP_SCOPE_SUBTREE;
+		nop->ors_deref = LDAP_DEREF_NEVER;
+		nop->ors_slimit = SLAP_NO_LIMIT;
+		nop->ors_tlimit = SLAP_NO_LIMIT;
+		nop->ors_limit = NULL;
+		nop->ors_attrs = slap_anlist_no_attrs;
+		nop->ors_attrsonly = 0;
+		nop->ors_filter = &filter;
+		filter2bv_x( nop, nop->ors_filter, &nop->ors_filterstr );
+
+		rc = nop->o_bd->be_search( nop, &nrs );
+		nop->o_tmpfree( nop->ors_filterstr.bv_val, nop->o_tmpmemctx );
+		
+		Debug(LDAP_DEBUG_TRACE, 
+			"==> constraint_violation key rc = %d, found = %d\n",
+			rc, found, 0);
+
+		if((rc != LDAP_SUCCESS) && (rc != LDAP_NO_SUCH_OBJECT)) {
+			send_ldap_error(op, rs, rc, 
+				"constraint_violation key search failed");
+			return 1; /* unexpected error */
+		}
+
+		if (!found)
+			return 1; /* constraint violation */
+			
+	}
     
     return 0;
 }
 
@@ -255,9 +380,9 @@
     Attribute *a;
     constraint *c = on->on_bi.bi_private, *cp;
     BerVarray b = NULL;
     int i;
-    const char *rsv = "add breaks regular expression constraint on %s";
+    const char *rsv = "add breaks constraint on %s";
     char *msg;
     
     if ((a = op->ora_e->e_attrs) == NULL) {
         op->o_bd->bd_info = (BackendInfo *)(on->on_info);
@@ -275,9 +400,9 @@
             if (cp->ap != a->a_desc) continue;
             if ((b = a->a_vals) == NULL) continue;
                 
             for(i=0; b[i].bv_val; i++) {
-                int cv = constraint_violation( cp, &b[i]);
+                int cv = constraint_violation( cp, &b[i], op, rs);
                     
                 if (cv) {
                         /* regex violation */
                     op->o_bd->bd_info = (BackendInfo *)(on->on_info);
@@ -300,9 +425,9 @@
     constraint *c = on->on_bi.bi_private, *cp;
     Modifications *m;
     BerVarray b = NULL;
     int i;
-    const char *rsv = "modify breaks regular expression constraint on %s";
+    const char *rsv = "modify breaks constraint on %s";
     char *msg;
     
     if ((m = op->orm_modlist) == NULL) {
         op->o_bd->bd_info = (BackendInfo *)(on->on_info);
@@ -323,9 +448,9 @@
         for(cp = c; cp; cp = cp->ap_next) {
             if (cp->ap != m->sml_desc) continue;
             
             for(i=0; b[i].bv_val; i++) {
-                int cv = constraint_violation( cp, &b[i]);
+                int cv = constraint_violation( cp, &b[i], op, rs);
                 
                 if (cv) {
                         /* regex violation */
                     op->o_bd->bd_info = (BackendInfo *)(on->on_info);