From 040c492b4beb0efcd34b8420f682187441767055 Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Tue, 16 Jan 2018 09:46:49 -0500 Subject: [PATCH] CVE-2017-15134 389-ds-base: Remote DoS via search filters in slapi_filter_sprintf Description: Improper handling of a search filter in slapi_filter_sprintf in slapd/util.c can lead to remote server crash and denial of service. https://bugzilla.redhat.com/show_bug.cgi?id=1529117 --- ldap/servers/slapd/util.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c index 4ff6d4141..ffeeff6f3 100644 --- a/ldap/servers/slapd/util.c +++ b/ldap/servers/slapd/util.c @@ -224,9 +224,10 @@ escape_string_for_filename(const char *str, char buf[BUFSIZ]) struct filter_ctx { char *buf; - char attr[ATTRSIZE]; + char *attr; int attr_position; int attr_found; + size_t attr_size; int buf_size; int buf_len; int next_arg_needs_esc_norm; @@ -265,7 +266,7 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen) * Start collecting the attribute name so we can use the correct * syntax normalization func. */ - if(ctx->attr_found == 0 && ctx->attr_position < (ATTRSIZE - 1)){ + if(ctx->attr_found == 0 && ctx->attr_position < (ctx->attr_size - 1)) { if(ctx->attr[0] == '\0'){ if(strstr(val,"=")){ /* we have an attr we need to record */ @@ -279,6 +280,14 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen) * attr with val. The next pass should be '=', otherwise we will * reset it. */ + if (slen > ctx->attr_size) { + if (ctx->attr_size == ATTRSIZE) { + ctx->attr = slapi_ch_calloc(sizeof(char), slen+1); + } else { + ctx->attr = slapi_ch_realloc(ctx->attr, sizeof(char) * (slen+1)); + } + ctx->attr_size = slen+1; + } memcpy(ctx->attr, val, slen); ctx->attr_position = slen; } @@ -288,9 +297,20 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen) } else { if(special_attr_char(val[0])){ /* this is not an attribute, we should not be collecting this, reset everything */ - memset(ctx->attr, '\0', ATTRSIZE); + memset(ctx->attr, '\0', ctx->attr_size); ctx->attr_position = 0; } else { + /* we can be adding char by char and overrun allocated size */ + if (ctx->attr_position >= ctx->attr_size) { + if (ctx->attr_size == ATTRSIZE) { + char *ctxattr = slapi_ch_calloc(sizeof(char), ctx->attr_size + ATTRSIZE); + memcpy(ctxattr, ctx->attr, ctx->attr_size); + ctx->attr = ctxattr; + } else { + ctx->attr = slapi_ch_realloc(ctx->attr, sizeof(char) * (ctx->attr_size + ATTRSIZE)); + } + ctx->attr_size = ctx->attr_size + ATTRSIZE; + } memcpy(ctx->attr + ctx->attr_position, val, 1); ctx->attr_position++; } @@ -363,7 +383,7 @@ filter_stuff_func(void *arg, const char *val, PRUint32 slen) ctx->next_arg_needs_esc_norm = 0; ctx->attr_found = 0; ctx->attr_position = 0; - memset(ctx->attr, '\0', ATTRSIZE); + memset(ctx->attr, '\0', ctx->attr_size); slapi_ch_free_string(&buf); return filter_len; @@ -402,13 +422,15 @@ slapi_filter_sprintf(const char *fmt, ...) { struct filter_ctx ctx = {0}; va_list args; + char attr_static[ATTRSIZE] = {0}; char *buf; int rc; buf = slapi_ch_calloc(sizeof(char), FILTER_BUF + 1); ctx.buf = buf; - memset(ctx.attr,'\0', ATTRSIZE); ctx.attr_position = 0; + ctx.attr = attr_static; + ctx.attr_size = ATTRSIZE; ctx.attr_found = 0; ctx.buf_len = FILTER_BUF; ctx.buf_size = 0; @@ -424,6 +446,10 @@ slapi_filter_sprintf(const char *fmt, ...) } va_end(args); + if (ctx.attr_size > ATTRSIZE) { + slapi_ch_free_string(&ctx.attr); + } + return ctx.buf; } -- 2.13.6