[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);