|
|
edc5f2 |
From ab7848a4a30d79c7433a1689ba1ea18897b73453 Mon Sep 17 00:00:00 2001
|
|
|
edc5f2 |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
edc5f2 |
Date: Tue, 18 Sep 2018 16:39:26 -0400
|
|
|
edc5f2 |
Subject: [PATCH] Bug 1624004 - potential denial of service attack
|
|
|
edc5f2 |
|
|
|
edc5f2 |
Bug: a search request passing 8MB of NULL bytes as search attributes will
|
|
|
edc5f2 |
keep one thread busy for a long time.
|
|
|
edc5f2 |
The reason is that the attr array is copied/normalized to the searchattrs in
|
|
|
edc5f2 |
the search operation and does this using charray_add() which iterates thru
|
|
|
edc5f2 |
the array to determine the size of the array and then allocate one element more.
|
|
|
edc5f2 |
so this means we iterat 8 million times an array with a then average size of
|
|
|
edc5f2 |
4 million elements.
|
|
|
edc5f2 |
|
|
|
edc5f2 |
Fix: We already have traversed the array once and know the size, so we can allocate
|
|
|
edc5f2 |
the needed size once and only copy the element.
|
|
|
edc5f2 |
In addition we check for the kind of degenerated attributes "" as used in this
|
|
|
edc5f2 |
test scenario.
|
|
|
edc5f2 |
So the fix will reject invalid attr liste and improve performance for valid ones
|
|
|
edc5f2 |
|
|
|
edc5f2 |
https://bugzilla.redhat.com/show_bug.cgi?id=1624004
|
|
|
edc5f2 |
---
|
|
|
edc5f2 |
ldap/servers/slapd/search.c | 16 ++++++++++++++--
|
|
|
edc5f2 |
ldap/servers/slapd/unbind.c | 4 ++--
|
|
|
edc5f2 |
2 files changed, 16 insertions(+), 4 deletions(-)
|
|
|
edc5f2 |
|
|
|
edc5f2 |
diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c
|
|
|
edc5f2 |
index 731c6519e..dc26fc4d2 100644
|
|
|
edc5f2 |
--- a/ldap/servers/slapd/search.c
|
|
|
edc5f2 |
+++ b/ldap/servers/slapd/search.c
|
|
|
edc5f2 |
@@ -209,6 +209,7 @@ do_search(Slapi_PBlock *pb)
|
|
|
edc5f2 |
if (attrs != NULL) {
|
|
|
edc5f2 |
char *normaci = slapi_attr_syntax_normalize("aci");
|
|
|
edc5f2 |
int replace_aci = 0;
|
|
|
edc5f2 |
+ int attr_count = 0;
|
|
|
edc5f2 |
if (!normaci) {
|
|
|
edc5f2 |
normaci = slapi_ch_strdup("aci");
|
|
|
edc5f2 |
} else if (strcasecmp(normaci, "aci")) {
|
|
|
edc5f2 |
@@ -218,9 +219,19 @@ do_search(Slapi_PBlock *pb)
|
|
|
edc5f2 |
/*
|
|
|
edc5f2 |
* . store gerattrs if any
|
|
|
edc5f2 |
* . add "aci" once if "*" is given
|
|
|
edc5f2 |
+ * . check that attrs are not degenerated
|
|
|
edc5f2 |
*/
|
|
|
edc5f2 |
for (i = 0; attrs[i] != NULL; i++) {
|
|
|
edc5f2 |
char *p = NULL;
|
|
|
edc5f2 |
+ attr_count++;
|
|
|
edc5f2 |
+
|
|
|
edc5f2 |
+ if ( attrs[i][0] == '\0') {
|
|
|
edc5f2 |
+ log_search_access(pb, base, scope, fstr, "invalid attribute request");
|
|
|
edc5f2 |
+ send_ldap_result(pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL);
|
|
|
edc5f2 |
+ slapi_ch_free_string(&normaci);
|
|
|
edc5f2 |
+ goto free_and_return;
|
|
|
edc5f2 |
+ }
|
|
|
edc5f2 |
+
|
|
|
edc5f2 |
/* check if @<objectclass> is included */
|
|
|
edc5f2 |
p = strchr(attrs[i], '@');
|
|
|
edc5f2 |
if (p) {
|
|
|
edc5f2 |
@@ -244,6 +255,7 @@ do_search(Slapi_PBlock *pb)
|
|
|
edc5f2 |
} else if (strcmp(attrs[i], LDAP_ALL_USER_ATTRS /* '*' */) == 0) {
|
|
|
edc5f2 |
if (!charray_inlist(attrs, normaci)) {
|
|
|
edc5f2 |
charray_add(&attrs, slapi_ch_strdup(normaci));
|
|
|
edc5f2 |
+ attr_count++;
|
|
|
edc5f2 |
}
|
|
|
edc5f2 |
} else if (replace_aci && (strcasecmp(attrs[i], "aci") == 0)) {
|
|
|
edc5f2 |
slapi_ch_free_string(&attrs[i]);
|
|
|
edc5f2 |
@@ -263,13 +275,13 @@ do_search(Slapi_PBlock *pb)
|
|
|
edc5f2 |
}
|
|
|
edc5f2 |
} else {
|
|
|
edc5f2 |
/* return the chopped type, e.g., "sn" */
|
|
|
edc5f2 |
- operation->o_searchattrs = NULL;
|
|
|
edc5f2 |
+ operation->o_searchattrs = (char **)slapi_ch_calloc(sizeof(char *), attr_count+1);
|
|
|
edc5f2 |
for (i = 0; attrs[i] != NULL; i++) {
|
|
|
edc5f2 |
char *type;
|
|
|
edc5f2 |
type = slapi_attr_syntax_normalize_ext(attrs[i],
|
|
|
edc5f2 |
ATTR_SYNTAX_NORM_ORIG_ATTR);
|
|
|
edc5f2 |
/* attrs[i] is consumed */
|
|
|
edc5f2 |
- charray_add(&operation->o_searchattrs, attrs[i]);
|
|
|
edc5f2 |
+ operation->o_searchattrs[i] = attrs[i];
|
|
|
edc5f2 |
attrs[i] = type;
|
|
|
edc5f2 |
}
|
|
|
edc5f2 |
}
|
|
|
edc5f2 |
diff --git a/ldap/servers/slapd/unbind.c b/ldap/servers/slapd/unbind.c
|
|
|
edc5f2 |
index 90f7b1546..686e27a8e 100644
|
|
|
edc5f2 |
--- a/ldap/servers/slapd/unbind.c
|
|
|
edc5f2 |
+++ b/ldap/servers/slapd/unbind.c
|
|
|
edc5f2 |
@@ -87,8 +87,8 @@ do_unbind(Slapi_PBlock *pb)
|
|
|
edc5f2 |
/* pass the unbind to all backends */
|
|
|
edc5f2 |
be_unbindall(pb_conn, operation);
|
|
|
edc5f2 |
|
|
|
edc5f2 |
+free_and_return:;
|
|
|
edc5f2 |
+
|
|
|
edc5f2 |
/* close the connection to the client */
|
|
|
edc5f2 |
disconnect_server(pb_conn, operation->o_connid, operation->o_opid, SLAPD_DISCONNECT_UNBIND, 0);
|
|
|
edc5f2 |
-
|
|
|
edc5f2 |
-free_and_return:;
|
|
|
edc5f2 |
}
|
|
|
edc5f2 |
--
|
|
|
edc5f2 |
2.17.1
|
|
|
edc5f2 |
|