From 4051547dfa6c794e6339e950eb0e5001b8f2ddb9 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sat, 28 Jul 2001 11:24:22 +0000 Subject: [PATCH] handle regex-based per op_ndn time/size limits --- servers/slapd/Makefile.in | 2 + servers/slapd/config.c | 19 +++ servers/slapd/limits.c | 233 ++++++++++++++++++++++++++++++++++++ servers/slapd/proto-slap.h | 11 ++ servers/slapd/slap.h | 12 ++ servers/slapd/tools/mimic.c | 12 +- 6 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 servers/slapd/limits.c diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index 8255ac426e..be1e368b48 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -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 diff --git a/servers/slapd/config.c b/servers/slapd/config.c index f60e26c6e8..ed3d49646f 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -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 index 0000000000..2b4829a319 --- /dev/null +++ b/servers/slapd/limits.c @@ -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 + +#include +#include + +#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 \" line.\n", + fname, lineno )); +#else + Debug( LDAP_DEBUG_ANY, + "%s : line %d: missing arg(s) in " + "\"limits \" line.\n%s", + fname, lineno, "" ); +#endif + return( -1 ); + } + + timelimit = be->be_timelimit; + sizelimit = be->be_sizelimit; + + /* + * syntax: + * + * "limits" [ [ ... ] ] + * + * + * : + * + * [ "dn" [ "." { "exact" | "regex" } ] "=" ] + * + * + * : + * + * { "time" | "size" } "=" + */ + + 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}]=\" in " + "\"limits \" line.\n", + fname, lineno )); +#else + Debug( LDAP_DEBUG_ANY, + "%s : line %d: missing '=' in " + "\"dn[.{exact|regex}]=\" in " + "\"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 \" line " + "(ignored).\n", + fname, lineno, argv[i] )); +#else + Debug( LDAP_DEBUG_ANY, + "%s : line %d: unknown limit type \"%s\" in " + "\"limits \" line " + "(ignored).\n", + fname, lineno, argv[i] ); +#endif + } + } + + return( add_limits( be, type, pattern, timelimit, sizelimit ) ); +} + diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 0410374c5f..88af06bf2c 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -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 */ diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index ffa28d04e3..0dcecd3fa4 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -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) */ diff --git a/servers/slapd/tools/mimic.c b/servers/slapd/tools/mimic.c index ae67918dc4..f8ce0e07ab 100644 --- a/servers/slapd/tools/mimic.c +++ b/servers/slapd/tools/mimic.c @@ -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; +} + -- 2.39.5