Blame SOURCES/0008-Bug-1624004-potential-denial-of-service-attack.patch

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