Author: nhosoi
Update of /cvs/dirsec/ldapserver/ldap/servers/slapd
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv26906/slapd
Modified Files:
entry.c filterentry.c getfilelist.c plugin_syntax.c
proto-slap.h regex.c sasl_map.c slapi-private.h vattr.c
Log Message:
Resoves: #448831
Summary: attacker can tie up CPU in regex code
Description: when substring search is requested, sets the time limit based upon
the nsslapd-timelimit value. Pass the timelimit (time_up) to the regular
expression function. When the time is up, it returns the "Timelimit exceeded"
error. Note: timelimit is applied non-Directory Manager users.
Index: entry.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/entry.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- entry.c 4 Jun 2008 22:22:55 -0000 1.15
+++ entry.c 30 Jun 2008 17:28:16 -0000 1.16
@@ -1843,7 +1843,7 @@
f->f_choice,
&f->f_ava );
} else if ( filter_type == FILTER_TYPE_SUBSTRING) {
- *rc = plugin_call_syntax_filter_sub( tmp_attr,
+ *rc = plugin_call_syntax_filter_sub( NULL, tmp_attr,
&f->f_sub);
} else if ( filter_type == FILTER_TYPE_PRES ) {
/* type is there, that's all we need to know. */
Index: filterentry.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/filterentry.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- filterentry.c 18 Apr 2008 20:20:22 -0000 1.7
+++ filterentry.c 30 Jun 2008 17:28:16 -0000 1.8
@@ -693,7 +693,7 @@
rc = -1;
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
if ( slapi_attr_type_cmp( f->f_sub_type, a->a_type, SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
- rc = plugin_call_syntax_filter_sub( a, &f->f_sub );
+ rc = plugin_call_syntax_filter_sub( pb, a, &f->f_sub );
if ( rc == 0 ) {
break;
}
@@ -726,8 +726,8 @@
rc = -1;
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
if ( slapi_attr_type_cmp( f->f_sub_type, a->a_type, SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
- rc = plugin_call_syntax_filter_sub( a, &f->f_sub );
- if ( rc == 0 ) {
+ rc = plugin_call_syntax_filter_sub( pb, a, &f->f_sub );
+ if ( rc == 0 || rc == LDAP_TIMELIMIT_EXCEEDED ) {
break;
}
}
Index: getfilelist.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/getfilelist.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- getfilelist.c 10 Nov 2006 23:45:40 -0000 1.7
+++ getfilelist.c 30 Jun 2008 17:28:16 -0000 1.8
@@ -130,7 +130,7 @@
slapd_re_lock();
s = slapd_re_comp((char *)pattern);
if (!s)
- match = slapd_re_exec((char *)filename);
+ match = slapd_re_exec((char *)filename, -1 /* no timelimit */);
slapd_re_unlock();
return match;
Index: plugin_syntax.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/plugin_syntax.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- plugin_syntax.c 10 Nov 2006 23:45:40 -0000 1.5
+++ plugin_syntax.c 30 Jun 2008 17:28:16 -0000 1.6
@@ -211,15 +211,17 @@
int
plugin_call_syntax_filter_sub(
+ Slapi_PBlock *pb,
Slapi_Attr *a,
struct subfilt *fsub
)
{
- return(plugin_call_syntax_filter_sub_sv(a,fsub));
+ return(plugin_call_syntax_filter_sub_sv(pb,a,fsub));
}
int
plugin_call_syntax_filter_sub_sv(
+ Slapi_PBlock *pb,
Slapi_Attr *a,
struct subfilt *fsub
)
@@ -240,6 +242,13 @@
{
Slapi_Value **va= valueset_get_valuearray(&a->a_present_values);
pblock_init( &pipb );
+ if (pb)
+ {
+ Operation *op = NULL;
+ /* to pass SLAPI_SEARCH_TIMELIMIT & SLAPI_OPINITATED_TIME */
+ slapi_pblock_get( pb, SLAPI_OPERATION, &op );
+ slapi_pblock_set( &pipb, SLAPI_OPERATION, op );
+ }
slapi_pblock_set( &pipb, SLAPI_PLUGIN, (void *) a->a_plugin );
rc = a->a_plugin->plg_syntax_filter_sub( &pipb,
fsub->sf_initial, fsub->sf_any, fsub->sf_final, va);
Index: proto-slap.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/proto-slap.h,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -r1.34 -r1.35
--- proto-slap.h 10 Jun 2008 18:50:07 -0000 1.34
+++ proto-slap.h 30 Jun 2008 17:28:16 -0000 1.35
@@ -745,8 +745,8 @@
struct slapdplugin *slapi_get_global_syntax_plugins();
int plugin_call_syntax_filter_ava( const Slapi_Attr *a, int ftype, struct ava *ava );
int plugin_call_syntax_filter_ava_sv( const Slapi_Attr *a, int ftype, struct ava *ava, Slapi_Value **retVal, int useDeletedValues );
-int plugin_call_syntax_filter_sub( Slapi_Attr *a, struct subfilt *fsub );
-int plugin_call_syntax_filter_sub_sv( Slapi_Attr *a, struct subfilt *fsub );
+int plugin_call_syntax_filter_sub( Slapi_PBlock *pb, Slapi_Attr *a, struct subfilt *fsub );
+int plugin_call_syntax_filter_sub_sv( Slapi_PBlock *pb, Slapi_Attr *a, struct subfilt *fsub );
int plugin_call_syntax_get_compare_fn(void *vpi, value_compare_fn_type *compare_fn);
struct slapdplugin *plugin_syntax_find( const char *nameoroid );
void plugin_syntax_enumerate( SyntaxEnumFunc sef, void *arg );
Index: regex.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/regex.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- regex.c 29 Apr 2008 00:38:36 -0000 1.6
+++ regex.c 30 Jun 2008 17:28:16 -0000 1.7
@@ -66,6 +66,14 @@
* Modification history:
*
* $Log$
+ * Revision 1.7 2008/06/30 17:28:16 nhosoi
+ * Resoves: #448831
+ * Summary: attacker can tie up CPU in regex code
+ * Description: when substring search is requested, sets the time limit based upon
+ * the nsslapd-timelimit value. Pass the timelimit (time_up) to the regular
+ * expression function. When the time is up, it returns the "Timelimit exceeded"
+ * error. Note: timelimit is applied non-Directory Manager users.
+ *
* Revision 1.6 2008/04/29 00:38:36 nhosoi
* Resolves: #182621 (#443955)
* Summary: Allow larger regex buffer to enable long substring filters
@@ -695,7 +703,7 @@
static UCHAR *bopat[MAXTAG];
static UCHAR *eopat[MAXTAG];
#ifdef NEEDPROTOS
-static UCHAR *pmatch( UCHAR *lp, UCHAR *ap );
+static UCHAR *pmatch( UCHAR *lp, UCHAR *ap, time_t time_up, int *err );
#else /* NEEDPROTOS */
static UCHAR *pmatch();
#endif /* NEEDPROTOS */
@@ -720,14 +728,18 @@
* to the beginning and the end of the matched fragment,
* respectively.
*
+ * return values: 0 -- did not match
+ * 1 -- matched
+ * othersise -- ldap error (TIMELIMIT_EXCEEDED only)
*/
int
-slapd_re_exec( char *lp )
+slapd_re_exec( char *lp, time_t time_up )
{
register UCHAR c;
register UCHAR *ep = 0;
register UCHAR *ap = nfa;
+ int ldaperror = 0;
bol = (UCHAR*)lp;
@@ -745,7 +757,7 @@
switch(*ap) {
case BOL: /* anchored: match from BOL only */
- ep = pmatch((UCHAR*)lp,ap);
+ ep = pmatch((UCHAR*)lp,ap,time_up,&ldaperror);
break;
case CHR: /* ordinary char: locate it fast */
c = *(ap+1);
@@ -755,7 +767,7 @@
return 0;
default: /* regular matching all the way. */
do {
- if ((ep = pmatch((UCHAR*)lp,ap)))
+ if ((ep = pmatch((UCHAR*)lp,ap,time_up,&ldaperror)))
break;
lp++;
} while (*lp);
@@ -764,6 +776,8 @@
case END: /* munged automaton. fail always */
return 0;
}
+ if (ldaperror)
+ return ldaperror;
if (!ep)
return 0;
@@ -844,13 +858,19 @@
#define CCLSKIP 18 /* [CLO] CCL 16bytes END ... */
static UCHAR *
-pmatch( UCHAR *lp, UCHAR *ap)
+pmatch( UCHAR *lp, UCHAR *ap, time_t time_up, int *err )
{
register int op, c, n;
register UCHAR *e; /* extra pointer for CLO */
register UCHAR *bp; /* beginning of subpat.. */
register UCHAR *ep; /* ending of subpat.. */
UCHAR *are; /* to save the line ptr. */
+ time_t curtime = current_time();
+
+ if ( time_up != -1 && curtime > time_up ) {
+ *err = LDAP_TIMELIMIT_EXCEEDED;
+ return 0;
+ }
while ((op = *ap++) != END)
switch(op) {
@@ -927,7 +947,7 @@
ap += n;
while (lp >= are) {
- if ((e = pmatch(lp, ap)) != NULL)
+ if ((e = pmatch(lp, ap, time_up, err)) != NULL)
return e;
--lp;
}
Index: sasl_map.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/sasl_map.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- sasl_map.c 10 Nov 2006 23:45:40 -0000 1.8
+++ sasl_map.c 30 Jun 2008 17:28:16 -0000 1.9
@@ -434,9 +434,10 @@
recomp_result = slapd_re_comp(dp->regular_expression);
if (recomp_result) {
LDAPDebug( LDAP_DEBUG_ANY, "sasl_map_check : re_comp failed for expression (%s)\n", dp->regular_expression, 0, 0 );
+ } else {
+ matched = slapd_re_exec(sasl_user_and_realm, -1 /* no timelimit */);
+ LDAPDebug( LDAP_DEBUG_TRACE, "regex: %s, id: %s, %s\n", dp->regular_expression, sasl_user_and_realm, matched ? "matched" : "didn't match" );
}
- matched = slapd_re_exec(sasl_user_and_realm);
- LDAPDebug( LDAP_DEBUG_TRACE, "regex: %s, id: %s, %s\n", dp->regular_expression, sasl_user_and_realm, matched ? "matched" : "didn't match" );
if (matched) {
if (matched == 1) {
/* Allocate buffers for the returned strings */
Index: slapi-private.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi-private.h,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- slapi-private.h 27 Jun 2008 19:28:21 -0000 1.24
+++ slapi-private.h 30 Jun 2008 17:28:16 -0000 1.25
@@ -1185,7 +1185,7 @@
void bervalarray_add_berval_fast(struct berval ***vals, const struct berval *addval, int nvals, int *maxvals);
-int slapd_re_exec( char *lp );
+int slapd_re_exec( char *lp, time_t time_up );
char *slapd_re_comp( char *pat );
int slapd_re_subs( char *src, char* dst );
void slapd_re_lock( void );
Index: vattr.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/vattr.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- vattr.c 1 Nov 2007 20:24:07 -0000 1.8
+++ vattr.c 30 Jun 2008 17:28:16 -0000 1.9
@@ -540,7 +540,7 @@
rc = plugin_call_syntax_filter_ava( a,
f->f_choice, &f->f_ava );
} else if ( filter_type == FILTER_TYPE_SUBSTRING) {
- rc = plugin_call_syntax_filter_sub( a,
+ rc = plugin_call_syntax_filter_sub( pb, a,
&f->f_sub);
}
@@ -611,7 +611,7 @@
} else if ( filter_type == FILTER_TYPE_SUBSTRING ) {
- rc = test_substring_filter( NULL, e, f, 0 /* no access check */,
+ rc = test_substring_filter( pb, e, f, 0 /* no access check */,
0 /* do test filter */, &acl_test_done);
} else if ( filter_type == FILTER_TYPE_PRES ) {