Commit 4051547d authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

handle regex-based per op_ndn time/size limits

parent c842bf8b
......@@ -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
......
......@@ -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;
......
/* 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 ) );
}
......@@ -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
*/
......
......@@ -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) */
......
......@@ -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;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment