]> git.sur5r.net Git - openldap/commitdiff
handle regex-based per op_ndn time/size limits
authorPierangelo Masarati <ando@openldap.org>
Sat, 28 Jul 2001 11:24:22 +0000 (11:24 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sat, 28 Jul 2001 11:24:22 +0000 (11:24 +0000)
servers/slapd/Makefile.in
servers/slapd/config.c
servers/slapd/limits.c [new file with mode: 0644]
servers/slapd/proto-slap.h
servers/slapd/slap.h
servers/slapd/tools/mimic.c

index 8255ac426e4003adb4997d407e95a97ae0056a2d..be1e368b4810ed38e6302d4117e207e823468695 100644 (file)
@@ -19,6 +19,7 @@ SRCS  = main.c daemon.c connection.c search.c filter.c add.c charray.c \
                schemaparse.c ad.c at.c mr.c syntax.c oc.c saslauthz.c \
                configinfo.c starttls.c index.c sets.c \
                root_dse.c sasl.c module.c suffixalias.c mra.c mods.c \
+               limits.c \
                $(@PLAT@_SRCS)
 
 OBJS   = main.o daemon.o connection.o search.o filter.o add.o charray.o \
@@ -31,6 +32,7 @@ OBJS  = main.o daemon.o connection.o search.o filter.o add.o charray.o \
                schemaparse.o ad.o at.o mr.o syntax.o oc.o saslauthz.o \
                configinfo.o starttls.o index.o sets.o \
                root_dse.o sasl.o module.o suffixalias.o mra.o mods.o \
+               limits.o \
                $(@PLAT@_OBJS)
 
 LDAP_INCDIR= ../../include
index f60e26c6e8286d243b91adbe4edbb9102cf3926d..ed3d49646fdbb858d837e945e1dff335c443632b 100644 (file)
@@ -727,6 +727,25 @@ read_config( const char *fname )
                                be->be_timelimit = atoi( cargv[1] );
                        }
 
+               /* set regex-based limits */
+               } else if ( strcasecmp( cargv[0], "limits" ) == 0 ) {
+                       if ( be == NULL ) {
+#ifdef NEW_LOGGING
+                               LDAP_LOG(( "config", LDAP_LEVEL_WARNING,
+                                          "%s: line %d \"limits\" allowed only in database environment.\n",
+                                          fname, lineno ));
+#else
+                               Debug( LDAP_DEBUG_ANY,
+       "%s: line %d \"limits\" allowed only in database environment.\n%s",
+                                       fname, lineno, "" );
+#endif
+                               return( 1 );
+                       }
+
+                       if ( parse_limits( be, fname, lineno, cargc, cargv ) ) {
+                               return( 1 );
+                       }
+
                /* set database suffix */
                } else if ( strcasecmp( cargv[0], "suffix" ) == 0 ) {
                        Backend *tmp_be;
diff --git a/servers/slapd/limits.c b/servers/slapd/limits.c
new file mode 100644 (file)
index 0000000..2b4829a
--- /dev/null
@@ -0,0 +1,233 @@
+/* limits.c - routines to handle regex-based size and time limits */
+/*
+ * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/regex.h>
+#include <ac/string.h>
+
+#include "slap.h"
+
+int
+get_limits( 
+       Backend         *be, 
+       const char      *ndn, 
+       int             *timelimit, 
+       int             *sizelimit 
+)
+{
+       struct slap_limits **lm;
+
+       /*
+        * default values
+        */
+       *timelimit = be->be_timelimit;
+       *sizelimit = be->be_sizelimit;
+
+       /*
+        * anonymous or no regex-based limits? 
+        */
+       if ( be->be_limits == NULL || ndn == NULL || ndn[0] == '\0' ) {
+               return( 0 );
+       }
+
+       for ( lm = be->be_limits; lm[0] != NULL; lm++ ) {
+               switch ( lm[0]->lm_type) {
+               case SLAP_LIMITS_EXACT:
+                       if ( strcmp( lm[0]->lm_dn_pat, ndn ) == 0 ) {
+                               *timelimit = lm[0]->lm_timelimit;
+                               *sizelimit = lm[0]->lm_sizelimit;
+                               return( 0 );
+                       }
+                       break;
+
+               case SLAP_LIMITS_REGEX:
+                       if ( regexec( &lm[0]->lm_dn_regex, ndn, 0, NULL, 0) == 0 ) {
+                               *timelimit = lm[0]->lm_timelimit;
+                               *sizelimit = lm[0]->lm_sizelimit;
+                               return( 0 );
+                       }
+                       break;
+                       
+               default:
+                       assert( 0 );    /* unreachable */
+                       return( -1 );
+               }
+       }
+
+       return( 0 );
+}
+
+int
+add_limits(
+       Backend         *be,
+       int             type,
+       const char      *pattern,
+       int             timelimit,
+       int             sizelimit
+)
+{
+       int                     i;
+       struct slap_limits      *lm;
+       
+       assert( be );
+       assert( pattern);
+
+       lm = ( struct slap_limits * )ch_calloc( sizeof( struct slap_limits ), 1 );
+
+       switch ( type ) {
+       case SLAP_LIMITS_EXACT:
+               lm->lm_type = SLAP_LIMITS_EXACT;
+               lm->lm_dn_pat = ch_strdup( pattern );
+               if ( dn_normalize( lm->lm_dn_pat ) == NULL ) {
+                       ch_free( lm->lm_dn_pat );
+                       ch_free( lm );
+                       return( -1 );
+               }
+               break;
+               
+       case SLAP_LIMITS_REGEX:
+       case SLAP_LIMITS_UNDEFINED:
+               lm->lm_type = SLAP_LIMITS_REGEX;
+               lm->lm_dn_pat = ch_strdup( pattern );
+               if ( regcomp( &lm->lm_dn_regex, lm->lm_dn_pat, REG_EXTENDED | REG_ICASE ) ) {
+                       ch_free( lm->lm_dn_pat );
+                       ch_free( lm );
+                       return( -1 );
+               }
+               break;
+       }
+
+       lm->lm_timelimit = timelimit;
+       lm->lm_sizelimit = sizelimit;
+
+       if ( be->be_limits == NULL ) {
+               i = 1;
+               be->be_limits = ( struct slap_limits ** )ch_calloc( sizeof( struct slap_limits * ), 2 );
+       } else {
+               for ( i = 0; be->be_limits[i]; i++ );
+               
+               be->be_limits = ( struct slap_limits ** )ch_realloc( be->be_limits,
+                       sizeof( struct slap_limits * ) * ( i + 1 ) );
+       }
+       be->be_limits[i] = lm;
+       
+       return( 0 );
+}
+
+int
+parse_limits(
+       Backend     *be,
+       const char  *fname,
+       int         lineno,
+       int         argc,
+       char        **argv
+)
+{
+       int     type = SLAP_LIMITS_UNDEFINED;
+       char    *pattern;
+       int     timelimit;
+       int     sizelimit;
+       int     i;
+
+       assert( be );
+
+       if ( argc < 3 ) {
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+                       "%s : line %d: missing arg(s) in "
+                       "\"limits <pattern> <limits>\" line.\n",
+                       fname, lineno ));
+#else
+               Debug( LDAP_DEBUG_ANY,
+                       "%s : line %d: missing arg(s) in "
+                       "\"limits <pattern> <limits>\" line.\n%s",
+                       fname, lineno, "" );
+#endif
+               return( -1 );
+       }
+
+       timelimit = be->be_timelimit;
+       sizelimit = be->be_sizelimit;
+
+       /*
+        * syntax:
+        *
+        * "limits" <pattern> <limit> [ <limit> [ ... ] ]
+        * 
+        * 
+        * <pattern>:
+        * 
+        * [ "dn" [ "." { "exact" | "regex" } ] "=" ] <dn pattern>
+        *
+        * 
+        * <limit>:
+        *
+        * { "time" | "size" } "=" <value>
+        */
+       
+       pattern = argv[1];
+       if ( strncasecmp( pattern, "dn", 2 ) == 0 ) {
+               pattern += 2;
+               if ( pattern[0] == '.' ) {
+                       pattern++;
+                       if ( strncasecmp( pattern, "exact", 5 ) == 0 ) {
+                               type = SLAP_LIMITS_EXACT;
+                               pattern += 5;
+                       } else if ( strncasecmp( pattern, "regex", 5 ) == 0 ) {
+                               type = SLAP_LIMITS_REGEX;
+                               pattern += 5;
+                       }
+               }
+
+               if ( pattern[0] != '=' ) {
+#ifdef NEW_LOGGING
+                       LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+                               "%s : line %d: missing '=' in "
+                               "\"dn[.{exact|regex}]=<pattern>\" in "
+                               "\"limits <pattern> <limits>\" line.\n",
+                       fname, lineno ));
+#else
+                       Debug( LDAP_DEBUG_ANY,
+                               "%s : line %d: missing '=' in "
+                               "\"dn[.{exact|regex}]=<pattern>\" in "
+                               "\"limits <pattern> <limits>\" line.\n%s",
+                       fname, lineno, "" );
+#endif
+                       return( -1 );
+               }
+
+               /* skip '=' (required) */
+               pattern++;
+       }
+
+       for ( i = 2; i < argc; i++ ) {
+               if ( strncasecmp( argv[i], "time=", 5) == 0 ) {
+                       timelimit = atoi( argv[i]+5 );
+               } else if ( strncasecmp( argv[i], "size=", 5) == 0 ) {
+                       sizelimit = atoi( argv[i]+5 );
+               } else {
+#ifdef NEW_LOGGING
+                       LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
+                               "%s : line %d: unknown limit type \"%s\" in "
+                               "\"limits <pattern> <limits>\" line "
+                               "(ignored).\n",
+                       fname, lineno, argv[i] ));
+#else
+                       Debug( LDAP_DEBUG_ANY,
+                               "%s : line %d: unknown limit type \"%s\" in "
+                               "\"limits <pattern> <limits>\" line "
+                               "(ignored).\n",
+                       fname, lineno, argv[i] );
+#endif
+               }
+       }
+       
+       return( add_limits( be, type, pattern, timelimit, sizelimit ) );
+}
+
index 0410374c5fd9d2c8c8527ef18d042d0975afbeed..88af06bf2c2ccc947319ef538d9adaa43ea87aaf 100644 (file)
@@ -396,6 +396,17 @@ LDAP_SLAPD_F (void) filter_print LDAP_P(( Filter *f ));
 LDAP_SLAPD_F (int) test_filter LDAP_P((
        Backend *be, Connection *conn, Operation *op, Entry *e, Filter  *f ));
 
+/*
+ * limits.c
+ */
+LDAP_SLAPD_F (int) get_limits LDAP_P((
+       Backend *be, const char *ndn, int *timelimit, int *sizelimit ));
+LDAP_SLAPD_F (int) add_limits LDAP_P((
+       Backend *be, int type, const char *pattern, 
+       int timelimit, int sizelimit ));
+LDAP_SLAPD_F (int) parse_limits LDAP_P((
+        Backend *be, const char *fname, int lineno, int argc, char **argv ));
+
 /*
  * lock.c
  */
index ffa28d04e37dc72b5914674f2ba4d97cd2bd8a27..0dcecd3fa4990449d7aef01710aa5e8dfd67d097 100644 (file)
@@ -814,6 +814,17 @@ struct slap_replica_info {
        char  **ri_nsuffix;     /* array of suffixes this replica accepts */
 };
 
+struct slap_limits {
+       int     lm_type;        /* type of pattern */
+#define SLAP_LIMITS_UNDEFINED  0x0000
+#define SLAP_LIMITS_EXACT      0x0001
+#define SLAP_LIMITS_REGEX      0x0002
+       regex_t lm_dn_regex;    /* regex-based size and time limits */
+       char   *lm_dn_pat;      /* ndn for EXACT; pattern for REGEX */
+       int     lm_timelimit;
+       int     lm_sizelimit;
+};
+
 /* temporary aliases */
 typedef BackendDB Backend;
 #define nbackends nBackendDB
@@ -911,6 +922,7 @@ struct slap_backend_db {
        unsigned int be_max_deref_depth;       /* limit for depth of an alias deref  */
        int     be_sizelimit;   /* size limit for this backend             */
        int     be_timelimit;   /* time limit for this backend             */
+       struct slap_limits **be_limits; /* regex-based size and time limits */
        AccessControl *be_acl;  /* access control list for this backend    */
        slap_access_t   be_dfltaccess;  /* access given if no acl matches          */
        struct slap_replica_info **be_replica;  /* replicas of this backend (in master) */
index ae67918dc4b56edf74829c935b1fe4ed9ca0f3d5..f8ce0e07ab07c9f96d8a5a6bc511fce80bcd4c6a 100644 (file)
@@ -203,4 +203,14 @@ int add_replica_info( Backend *be, const char *host )
 {
        return 0;
 }
-       
+
+int parse_limits( Backend *be, const char *fname, int lineno, int argc, char **argv )
+{
+       return 0;
+}
+
+int get_limits( Backend *be, const char *ndn, int *timelimit, int *sizelimit )
+{
+       return 0;
+}
+