andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 4 months ago
Clone

Blame 0434-Ticket-49471-heap-buffer-overflow-in-ss_unescape.patch

dc8c34
From 4946b960d4786dc3dd1620d837355a89696ef7c0 Mon Sep 17 00:00:00 2001
dc8c34
From: Thierry Bordaz <tbordaz@redhat.com>
dc8c34
Date: Wed, 6 Dec 2017 15:14:57 +0100
dc8c34
Subject: [PATCH] Ticket 49471 - heap-buffer-overflow in ss_unescape
dc8c34
dc8c34
Bug Description:
dc8c34
	Two problems here
dc8c34
		- when searching for wildcard and escape char, ss_unescape assumes the string
dc8c34
		  is at least 3 chars longs. So memcmp can overflow a shorter string
dc8c34
		- while splitting a string into substring pattern, it loops over
dc8c34
		  wildcard and can overpass the string end
dc8c34
dc8c34
Fix Description:
dc8c34
	For the first problem, it checks the string size is long enough to memcmp
dc8c34
        a wildcard or an escape
dc8c34
	For the second it exits from the loop  as soon as the end of the string is reached
dc8c34
dc8c34
https://pagure.io/389-ds-base/issue/49471
dc8c34
dc8c34
Reviewed by: William Brown
dc8c34
dc8c34
Platforms tested: F23
dc8c34
dc8c34
Flag Day: no
dc8c34
dc8c34
Doc impact: no
dc8c34
dc8c34
(cherry picked from commit 5991388ce75fba8885579b769711d57acfd43cd3)
dc8c34
(cherry picked from commit 3fb1c408cb4065de8d9c0c1de050d08969d51bb0)
dc8c34
---
dc8c34
 dirsrvtests/tests/tickets/ticket49471_test.py | 79 +++++++++++++++++++++++++++
dc8c34
 ldap/servers/plugins/collation/orfilter.c     | 48 +++++++++-------
dc8c34
 2 files changed, 106 insertions(+), 21 deletions(-)
dc8c34
 create mode 100644 dirsrvtests/tests/tickets/ticket49471_test.py
dc8c34
dc8c34
diff --git a/dirsrvtests/tests/tickets/ticket49471_test.py b/dirsrvtests/tests/tickets/ticket49471_test.py
dc8c34
new file mode 100644
dc8c34
index 000000000..0456a5182
dc8c34
--- /dev/null
dc8c34
+++ b/dirsrvtests/tests/tickets/ticket49471_test.py
dc8c34
@@ -0,0 +1,79 @@
dc8c34
+import logging
dc8c34
+import pytest
dc8c34
+import os
dc8c34
+import time
dc8c34
+import ldap
dc8c34
+from lib389._constants import *
dc8c34
+from lib389.topologies import topology_st as topo
dc8c34
+from lib389 import Entry
dc8c34
+
dc8c34
+DEBUGGING = os.getenv("DEBUGGING", default=False)
dc8c34
+if DEBUGGING:
dc8c34
+    logging.getLogger(__name__).setLevel(logging.DEBUG)
dc8c34
+else:
dc8c34
+    logging.getLogger(__name__).setLevel(logging.INFO)
dc8c34
+log = logging.getLogger(__name__)
dc8c34
+
dc8c34
+
dc8c34
+USER_CN='user_'
dc8c34
+def _user_get_dn(no):
dc8c34
+    cn = '%s%d' % (USER_CN, no)
dc8c34
+    dn = 'cn=%s,ou=people,%s' % (cn, SUFFIX)
dc8c34
+    return (cn, dn)
dc8c34
+
dc8c34
+def add_user(server, no, desc='dummy', sleep=True):
dc8c34
+    (cn, dn) = _user_get_dn(no)
dc8c34
+    log.fatal('Adding user (%s): ' % dn)
dc8c34
+    server.add_s(Entry((dn, {'objectclass': ['top', 'person', 'inetuser', 'userSecurityInformation'],
dc8c34
+                             'cn': [cn],
dc8c34
+                             'description': [desc],
dc8c34
+                             'sn': [cn],
dc8c34
+                             'description': ['add on that host']})))
dc8c34
+    if sleep:
dc8c34
+        time.sleep(2)
dc8c34
+
dc8c34
+def test_ticket49471(topo):
dc8c34
+    """Specify a test case purpose or name here
dc8c34
+
dc8c34
+    :id: 457ab172-9455-4eb2-89a0-150e3de5993f
dc8c34
+    :setup: Fill in set up configuration here
dc8c34
+    :steps:
dc8c34
+        1. Fill in test case steps here
dc8c34
+        2. And indent them like this (RST format requirement)
dc8c34
+    :expectedresults:
dc8c34
+        1. Fill in the result that is expected
dc8c34
+        2. For each test step
dc8c34
+    """
dc8c34
+
dc8c34
+    # If you need any test suite initialization,
dc8c34
+    # please, write additional fixture for that (including finalizer).
dc8c34
+    # Topology for suites are predefined in lib389/topologies.py.
dc8c34
+
dc8c34
+    # If you need host, port or any other data about instance,
dc8c34
+    # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
dc8c34
+
dc8c34
+    S1 = topo.standalone
dc8c34
+    add_user(S1, 1)
dc8c34
+
dc8c34
+    Filter = "(description:2.16.840.1.113730.3.3.2.1.1.6:=\*on\*)"
dc8c34
+    ents = S1.search_s(SUFFIX, ldap.SCOPE_SUBTREE, Filter)
dc8c34
+    assert len(ents) == 1
dc8c34
+
dc8c34
+    #
dc8c34
+    # The following is for the test 49491
dc8c34
+    # skipped here else it crashes in ASAN
dc8c34
+    #Filter = "(description:2.16.840.1.113730.3.3.2.1.1.6:=\*host)"
dc8c34
+    #ents = S1.search_s(SUFFIX, ldap.SCOPE_SUBTREE, Filter)
dc8c34
+    #assert len(ents) == 1
dc8c34
+
dc8c34
+    if DEBUGGING:
dc8c34
+        # Add debugging steps(if any)...
dc8c34
+        pass
dc8c34
+
dc8c34
+
dc8c34
+if __name__ == '__main__':
dc8c34
+    # Run isolated
dc8c34
+    # -s for DEBUG mode
dc8c34
+    CURRENT_FILE = os.path.realpath(__file__)
dc8c34
+    pytest.main("-s %s" % CURRENT_FILE)
dc8c34
+
dc8c34
diff --git a/ldap/servers/plugins/collation/orfilter.c b/ldap/servers/plugins/collation/orfilter.c
dc8c34
index d872ee01c..d22730f70 100644
dc8c34
--- a/ldap/servers/plugins/collation/orfilter.c
dc8c34
+++ b/ldap/servers/plugins/collation/orfilter.c
dc8c34
@@ -345,19 +345,21 @@ ss_unescape (struct berval* val)
dc8c34
     char* t = s;
dc8c34
     char* limit = s + val->bv_len;
dc8c34
     while (s < limit) {
dc8c34
-	if (!memcmp (s, "\\2a", 3) ||
dc8c34
-	    !memcmp (s, "\\2A", 3)) {
dc8c34
-	    *t++ = WILDCARD;
dc8c34
-	    s += 3;
dc8c34
-	} else if (!memcmp (s, "\\5c", 3) ||
dc8c34
-		   !memcmp (s, "\\5C", 3)) {
dc8c34
-	    *t++ = '\\';
dc8c34
-	    s += 3;
dc8c34
-	} else {
dc8c34
-	    if (t == s) LDAP_UTF8INC (t);
dc8c34
-	    else t += LDAP_UTF8COPY (t, s);
dc8c34
-	    LDAP_UTF8INC (s);
dc8c34
-	}
dc8c34
+        if (((limit - s) >= 3) &&
dc8c34
+                (!memcmp(s, "\\2a", 3) || !memcmp(s, "\\2A", 3))) {
dc8c34
+            *t++ = WILDCARD;
dc8c34
+            s += 3;
dc8c34
+        } else if ((limit - s) >= 3 &&
dc8c34
+                (!memcmp(s, "\\5c", 3) || !memcmp(s, "\\5C", 3))) {
dc8c34
+            *t++ = '\\';
dc8c34
+            s += 3;
dc8c34
+        } else {
dc8c34
+            if (t == s)
dc8c34
+                LDAP_UTF8INC(t);
dc8c34
+            else
dc8c34
+                t += LDAP_UTF8COPY(t, s);
dc8c34
+            LDAP_UTF8INC(s);
dc8c34
+        }
dc8c34
     }
dc8c34
     val->bv_len = t - val->bv_val;
dc8c34
 }
dc8c34
@@ -433,14 +435,18 @@ ss_filter_values (struct berval* pattern, int* query_op)
dc8c34
     n = 0;
dc8c34
     s = pattern->bv_val;
dc8c34
     for (p = s; p < plimit; LDAP_UTF8INC(p)) {
dc8c34
-	switch (*p) {
dc8c34
-	  case WILDCARD:
dc8c34
-	    result[n++] = ss_filter_value (s, p-s, &val;;
dc8c34
-	    while (++p != plimit && *p == WILDCARD);
dc8c34
-	    s = p;
dc8c34
-	    break;
dc8c34
-	  default: break;
dc8c34
-	}
dc8c34
+        switch (*p) {
dc8c34
+        case WILDCARD:
dc8c34
+            result[n++] = ss_filter_value(s, p - s, &val;;
dc8c34
+            while (p != plimit && *p == WILDCARD) p++;
dc8c34
+            s = p;
dc8c34
+            break;
dc8c34
+        default:
dc8c34
+            break;
dc8c34
+        }
dc8c34
+        if (p >= plimit) {
dc8c34
+            break;
dc8c34
+        }
dc8c34
     }
dc8c34
     if (p != s || s == plimit) {
dc8c34
 	result[n++] = ss_filter_value (s, p-s, &val;;
dc8c34
-- 
dc8c34
2.13.6
dc8c34