]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/constraint.c
Sync with HEAD for OL 2.4.5
[openldap] / servers / slapd / overlays / constraint.c
index 4173b746d93c282fc69fd18587c2c231c51dc053..aed82a66208e7b0352df91480926311baee2de35 100644 (file)
@@ -26,6 +26,7 @@
 #include <ac/regex.h>
 
 #include "slap.h"
+#include "config.h"
 
 /*
  * This overlay limits the values which can be placed into an
@@ -35,6 +36,8 @@
  * control the add and modify value mods of a modify)
  */
 
+#define REGEX_STR "regex"
+
 /*
  * Linked list of attribute constraints which we should enforce.
  * This is probably a sub optimal structure - some form of sorted
  * likely to be much bigger than 4 or 5. We stick with a list for
  * the moment.
  */
+
 typedef struct constraint {
     struct constraint *ap_next;
     AttributeDescription *ap;
     regex_t *re;
+    char *re_str; /* string representation of regex */
 } constraint;
 
+enum {
+    CONSTRAINT_ATTRIBUTE = 1
+};
+
+static ConfigDriver constraint_cf_gen;
+
+static ConfigTable constraintcfg[] = {
+    { "constraint_attribute", "attribute regex <regular expression>",
+      4, 4, 0, ARG_MAGIC | CONSTRAINT_ATTRIBUTE, constraint_cf_gen,
+      "( OLcfgOvAt:13.1 NAME 'olcConstraintAttribute' "
+      "DESC 'regular expression constraint for attribute' "
+         "EQUALITY caseIgnoreMatch "
+      "SYNTAX OMsDirectoryString )", NULL, NULL },
+    { NULL, NULL, 0, 0, 0, ARG_IGNORED }
+};
+
+static ConfigOCs constraintocs[] = {
+    { "( OLcfgOvOc:13.1 "
+      "NAME 'olcConstraintConfig' "
+      "DESC 'Constraint overlay configuration' "
+      "SUP olcOverlayConfig "
+      "MAY ( olcConstraintAttribute ) )",
+      Cft_Overlay, constraintcfg },
+    { NULL, 0, NULL }
+};
+
+static int
+constraint_cf_gen( ConfigArgs *c )
+{
+    slap_overinst *on = (slap_overinst *)(c->bi);
+    constraint *cn = on->on_bi.bi_private, *cp;
+    struct berval bv;
+    int i, rc = 0;
+    constraint ap = { NULL, NULL, NULL  }, *a2 = NULL;
+    const char *text = NULL;
+    
+    switch ( c->op ) {
+        case SLAP_CONFIG_EMIT:
+            switch (c->type) {
+                case CONSTRAINT_ATTRIBUTE:
+                    for (cp=cn; cp; cp=cp->ap_next) {
+                        int len;
+                        char *s;
+                        
+                        len = cp->ap->ad_cname.bv_len +
+                            strlen( REGEX_STR ) + strlen( cp->re_str) + 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);
+                        bv.bv_val = s;
+                        bv.bv_len = strlen(s);
+                        rc = value_add_one( &c->rvalue_vals, &bv );
+                        if (rc) return rc;
+                        rc = value_add_one( &c->rvalue_nvals, &bv );
+                        if (rc) return rc;
+                        ch_free(s);
+                    }
+                    break;
+                default:
+                    abort();
+                    break;
+            }
+            break;
+        case LDAP_MOD_DELETE:
+            switch (c->type) {
+                case CONSTRAINT_ATTRIBUTE:
+                    if (!cn) break; /* nothing to do */
+                    
+                    if (c->valx < 0) {
+                            /* zap all constraints */
+                        while (cn) {
+                            cp = cn->ap_next;
+                            if (cn->re) {
+                                regfree(cn->re);
+                                ch_free(cn->re);
+                            }
+                            if (cn->re_str) ch_free(cn->re_str);
+                            ch_free(cn);
+                            cn = cp;
+                        }
+                        
+                        on->on_bi.bi_private = NULL;
+                    } else {
+                        constraint **cpp;
+                        
+                            /* zap constraint numbered 'valx' */
+                        for(i=0, cp = cn, cpp = &cn;
+                            (cp) && (i<c->valx);
+                            i++, cpp = &cp->ap_next, cp = *cpp);
+
+                        if (cp) {
+                                /* zap cp, and join cpp to cp->ap_next */
+                            *cpp = cp->ap_next;
+                            if (cp->re) {
+                                regfree(cp->re);
+                                ch_free(cp->re);
+                            }
+                            if (cp->re_str) ch_free(cp->re_str);
+                            ch_free(cp);
+                        }
+                        on->on_bi.bi_private = cn;
+                    }
+                    
+                    break;
+                default:
+                    abort();
+                    break;
+            }
+            break;
+        case SLAP_CONFIG_ADD:
+        case LDAP_MOD_ADD:
+            switch (c->type) {
+                case CONSTRAINT_ATTRIBUTE:
+                    if ( slap_str2ad( c->argv[1], &ap.ap, &text ) ) {
+                                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                                       "%s <%s>: %s\n", c->argv[0], c->argv[1], text );
+                        Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
+                               "%s: %s\n", c->log, c->cr_msg, 0 );
+                        return( ARG_BAD_CONF );
+                    }
+
+                    if ( strcasecmp( c->argv[2], "regex" ) == 0) {
+                        int err;
+            
+                        ap.re = ch_malloc( sizeof(regex_t) );
+                        if ((err = regcomp( ap.re,
+                                            c->argv[3], REG_EXTENDED )) != 0) {
+                            char errmsg[1024];
+                            
+                            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 );
+                            ap.re = NULL;
+                            return( ARG_BAD_CONF );
+                        }
+                        ap.re_str = ch_strdup( c->argv[3] );
+                    } 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 );
+                    }
+                    
+
+                    a2 = ch_malloc( sizeof(constraint) );
+                    a2->ap_next = on->on_bi.bi_private;
+                    a2->ap = ap.ap;
+                    a2->re = ap.re;
+                    a2->re_str = ap.re_str;
+                    on->on_bi.bi_private = a2;
+                    break;
+                default:
+                    abort();
+                    break;
+            }
+            break;
+        default:
+            abort();
+    }
+
+    return rc;
+}
+
 static int
 constraint_violation( constraint *c, struct berval *bv )
 {
@@ -62,14 +237,14 @@ constraint_violation( constraint *c, struct berval *bv )
 }
 
 static char *
-print_message( const char *fmt, AttributeDescription *a )
+print_message( const char *errtext, AttributeDescription *a )
 {
     char *ret;
     int sz;
     
-    sz = strlen(fmt) + a->ad_cname.bv_len + 1;
+    sz = strlen(errtext) + sizeof(" on ") + a->ad_cname.bv_len;
     ret = ch_malloc(sz);
-    snprintf( ret, sz, fmt, a->ad_cname.bv_val );
+    snprintf( ret, sz, "%s on %s", errtext, a->ad_cname.bv_val );
     return ret;
 }
 
@@ -81,7 +256,7 @@ constraint_add( Operation *op, SlapReply *rs )
     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 regular expression constraint";
     char *msg;
     
     if ((a = op->ora_e->e_attrs) == NULL) {
@@ -126,7 +301,7 @@ constraint_modify( Operation *op, SlapReply *rs )
     Modifications *m;
     BerVarray b = NULL;
     int i;
-    const char *rsv = "modify breaks regular expression constraint on %s";
+    const char *rsv = "modify breaks regular expression constraint";
     char *msg;
     
     if ((m = op->orm_modlist) == NULL) {
@@ -166,85 +341,17 @@ constraint_modify( Operation *op, SlapReply *rs )
     return SLAP_CB_CONTINUE;
 }
 
-static int constraint_config(
-    BackendDB  *be,
-    const char *fname,
-    int                lineno,
-    int                argc,
-    char       **argv
-    )
-{
-    slap_overinst *on = (slap_overinst *) be->bd_info;
-    constraint ap = { NULL, NULL, NULL  }, *a2 = NULL;
-    regmatch_t rm[2];
-    
-    if ( strcasecmp( argv[0], "constraint_attribute" ) == 0 ) {
-        const char *text;
-                
-        if ( argc != 4 ) {
-            Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                   "wrong number of parameters in"
-                   "\"constraint_attribute <attribute> <constraint> <constraint_value>\" line.\n",
-                   fname, lineno, 0 );
-            return( 1 );
-        }
-        if ( slap_str2ad( argv[1], &ap.ap, &text ) ) {
-            Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                   "attribute description unknown \"constraint_attribute\" line: %s.\n",
-                   fname, lineno, text );
-            return( 1 );
-        }
-
-        if ( strcasecmp( argv[2], "regex" ) == 0) {
-            int err;
-            
-            ap.re = ch_malloc( sizeof(regex_t) );
-            if ((err = regcomp( ap.re, argv[3], REG_EXTENDED )) != 0) {
-                const char *fmt = "%s: line %d: Illegal regular expression \"%s\": Error %s\n";
-                char errmsg[1024], *msg;
-                int i, l, msgsize;
-                
-                msgsize = regerror( err, ap.re, errmsg, sizeof(errmsg) );
-                msgsize += strlen(fmt) + strlen(argv[3]) + strlen(fname);
-                for(l=lineno; l>0; l/=10, msgsize++);
-                msgsize++;
-
-                msg = ch_malloc( msgsize + 1 );
-                snprintf( msg, msgsize, fmt, fname, lineno, argv[3], errmsg );
-                ch_free(ap.re);
-                Debug( LDAP_DEBUG_ANY, msg, 0, 0, 0);
-                ch_free(msg);
-                ap.re = NULL;
-                return(1);
-            }
-        } else
-            Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                   "Unknown constraint type: %s",
-                   fname, lineno, argv[2] );
-        
-
-        a2 = ch_malloc( sizeof(constraint) );
-        a2->ap_next = on->on_bi.bi_private;
-        a2->ap = ap.ap;
-        a2->re = ap.re;
-        on->on_bi.bi_private = a2;
-    } else {
-        return SLAP_CONF_UNKNOWN;
-    }
-    
-    return 0;
-}
-
 static int
 constraint_close(
-    BackendDB *be
-    )
+       BackendDB *be,
+       ConfigReply *cr )
 {
     slap_overinst *on = (slap_overinst *) be->bd_info;
     constraint *ap, *a2;
 
     for ( ap = on->on_bi.bi_private; ap; ap = a2 ) {
         a2 = ap->ap_next;
+        if (ap->re_str) ch_free(ap->re_str);
         if (ap->re) {
             regfree( ap->re );
             ch_free( ap->re );
@@ -263,19 +370,30 @@ static slap_overinst constraint_ovl;
  * initialized and registered by some other function inside slapd.
  */
 
-int constraint_init() {
+#if SLAPD_OVER_CONSTRAINT == SLAPD_MOD_DYNAMIC
+static
+#endif
+int
+constraint_initialize( void ) {
+    int rc;
+
     constraint_ovl.on_bi.bi_type = "constraint";
-    constraint_ovl.on_bi.bi_db_config = constraint_config;
     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_private = NULL;
+    
+    constraint_ovl.on_bi.bi_cf_ocs = constraintocs;
+    rc = config_register_schema( constraintcfg, constraintocs );
+    if (rc) return rc;
+    
     return overlay_register( &constraint_ovl );
 }
 
 #if SLAPD_OVER_CONSTRAINT == SLAPD_MOD_DYNAMIC
 int init_module(int argc, char *argv[]) {
-    return constraint_init();
+    return constraint_initialize();
 }
 #endif