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 ) {
389-commits@lists.fedoraproject.org