diff --git a/.gitignore b/.gitignore index 649e583..00c3753 100644 --- a/.gitignore +++ b/.gitignore @@ -219,3 +219,4 @@ /389-ds-base-2.4.4.tar.bz2 /389-ds-base-2.4.5.tar.bz2 /389-ds-base-2.5.1.tar.bz2 +/389-ds-base-2.5.2.tar.bz2 diff --git a/0001-CVE-2024-3657.patch b/0001-CVE-2024-3657.patch deleted file mode 100644 index dba55ff..0000000 --- a/0001-CVE-2024-3657.patch +++ /dev/null @@ -1,213 +0,0 @@ -From 5cfa136c48c477765cb20b007ad441ed21534e86 Mon Sep 17 00:00:00 2001 -From: Pierre Rogier -Date: Wed, 17 Apr 2024 18:18:04 +0200 -Subject: [PATCH] CVE-2024-3657 - ---- - .../tests/suites/filter/large_filter_test.py | 34 +++++- - ldap/servers/slapd/back-ldbm/index.c | 111 ++++++++++-------- - 2 files changed, 92 insertions(+), 53 deletions(-) - -diff --git a/dirsrvtests/tests/suites/filter/large_filter_test.py b/dirsrvtests/tests/suites/filter/large_filter_test.py -index 964facae5..5390a0f9c 100644 ---- a/dirsrvtests/tests/suites/filter/large_filter_test.py -+++ b/dirsrvtests/tests/suites/filter/large_filter_test.py -@@ -13,19 +13,29 @@ verify and testing Filter from a search - - import os - import pytest -+import ldap - --from lib389._constants import PW_DM -+from lib389._constants import PW_DM, DEFAULT_SUFFIX, ErrorLog - from lib389.topologies import topology_st as topo - from lib389.idm.user import UserAccounts, UserAccount - from lib389.idm.account import Accounts - from lib389.backend import Backends - from lib389.idm.domain import Domain -+from lib389.utils import get_ldapurl_from_serverid - - SUFFIX = 'dc=anuj,dc=com' - - pytestmark = pytest.mark.tier1 - - -+def open_new_ldapi_conn(dsinstance): -+ ldapurl, certdir = get_ldapurl_from_serverid(dsinstance) -+ assert 'ldapi://' in ldapurl -+ conn = ldap.initialize(ldapurl) -+ conn.sasl_interactive_bind_s("", ldap.sasl.external()) -+ return conn -+ -+ - @pytest.fixture(scope="module") - def _create_entries(request, topo): - """ -@@ -159,6 +169,28 @@ def test_large_filter(topo, _create_entries, real_value): - assert len(Accounts(conn, SUFFIX).filter(real_value)) == 3 - - -+def test_long_filter_value(topo): -+ """Exercise large eq filter with dn syntax attributes -+ -+ :id: b069ef72-fcc3-11ee-981c-482ae39447e5 -+ :setup: Standalone -+ :steps: -+ 1. Try to pass filter rules as per the condition. -+ :expectedresults: -+ 1. Pass -+ """ -+ inst = topo.standalone -+ conn = open_new_ldapi_conn(inst.serverid) -+ inst.config.loglevel(vals=(ErrorLog.DEFAULT,ErrorLog.TRACE,ErrorLog.SEARCH_FILTER)) -+ filter_value = "a\x1Edmin" * 1025 -+ conn.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, f'(cn={filter_value})') -+ filter_value = "aAdmin" * 1025 -+ conn.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, f'(cn={filter_value})') -+ filter_value = "*" -+ conn.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, f'(cn={filter_value})') -+ inst.config.loglevel(vals=(ErrorLog.DEFAULT,)) -+ -+ - if __name__ == '__main__': - CURRENT_FILE = os.path.realpath(__file__) - pytest.main("-s -v %s" % CURRENT_FILE) -diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c -index 86bc825fe..bdac0a616 100644 ---- a/ldap/servers/slapd/back-ldbm/index.c -+++ b/ldap/servers/slapd/back-ldbm/index.c -@@ -74,6 +74,32 @@ typedef struct _index_buffer_handle index_buffer_handle; - #define INDEX_BUFFER_FLAG_SERIALIZE 1 - #define INDEX_BUFFER_FLAG_STATS 2 - -+/* -+ * space needed to encode a byte: -+ * 0x00-0x31 and 0x7f-0xff requires 3 bytes: \xx -+ * 0x22 and 0x5C requires 2 bytes: \" and \\ -+ * other requires 1 byte: c -+ */ -+static char encode_size[] = { -+ /* 0x00 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+ /* 0x10 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+ /* 0x20 */ 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -+ /* 0x30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -+ /* 0x40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -+ /* 0x50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, -+ /* 0x60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -+ /* 0x70 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, -+ /* 0x80 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+ /* 0x90 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+ /* 0xA0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+ /* 0xB0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+ /* 0xC0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+ /* 0xD0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+ /* 0xE0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+ /* 0xF0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -+}; -+ -+ - /* Index buffering functions */ - - static int -@@ -802,65 +828,46 @@ index_add_mods( - - /* - * Convert a 'struct berval' into a displayable ASCII string -+ * returns the printable string - */ -- --#define SPECIAL(c) (c < 32 || c > 126 || c == '\\' || c == '"') -- - const char * - encode(const struct berval *data, char buf[BUFSIZ]) - { -- char *s; -- char *last; -- if (data == NULL || data->bv_len == 0) -- return ""; -- last = data->bv_val + data->bv_len - 1; -- for (s = data->bv_val; s < last; ++s) { -- if (SPECIAL(*s)) { -- char *first = data->bv_val; -- char *bufNext = buf; -- size_t bufSpace = BUFSIZ - 4; -- while (1) { -- /* printf ("%lu bytes ASCII\n", (unsigned long)(s - first)); */ -- if (bufSpace < (size_t)(s - first)) -- s = first + bufSpace - 1; -- if (s != first) { -- memcpy(bufNext, first, s - first); -- bufNext += (s - first); -- bufSpace -= (s - first); -- } -- do { -- if (bufSpace) { -- *bufNext++ = '\\'; -- --bufSpace; -- } -- if (bufSpace < 2) { -- memcpy(bufNext, "..", 2); -- bufNext += 2; -- goto bail; -- } -- if (*s == '\\' || *s == '"') { -- *bufNext++ = *s; -- --bufSpace; -- } else { -- sprintf(bufNext, "%02x", (unsigned)*(unsigned char *)s); -- bufNext += 2; -- bufSpace -= 2; -- } -- } while (++s <= last && SPECIAL(*s)); -- if (s > last) -- break; -- first = s; -- while (!SPECIAL(*s) && s <= last) -- ++s; -- } -- bail: -- *bufNext = '\0'; -- /* printf ("%lu chars in buffer\n", (unsigned long)(bufNext - buf)); */ -+ if (!data || !data->bv_val) { -+ strcpy(buf, ""); -+ return buf; -+ } -+ char *endbuff = &buf[BUFSIZ-4]; /* Reserve space to append "...\0" */ -+ char *ptout = buf; -+ unsigned char *ptin = (unsigned char*) data->bv_val; -+ unsigned char *endptin = ptin+data->bv_len; -+ -+ while (ptin < endptin) { -+ if (ptout >= endbuff) { -+ /* -+ * BUFSIZ(8K) > SLAPI_LOG_BUFSIZ(2K) so the error log message will be -+ * truncated anyway. So there is no real interrest to test if the original -+ * data contains no special characters and return it as is. -+ */ -+ strcpy(endbuff, "..."); - return buf; - } -+ switch (encode_size[*ptin]) { -+ case 1: -+ *ptout++ = *ptin++; -+ break; -+ case 2: -+ *ptout++ = '\\'; -+ *ptout++ = *ptin++; -+ break; -+ case 3: -+ sprintf(ptout, "\\%02x", *ptin++); -+ ptout += 3; -+ break; -+ } - } -- /* printf ("%lu bytes, all ASCII\n", (unsigned long)(s - data->bv_val)); */ -- return data->bv_val; -+ *ptout = 0; -+ return buf; - } - - static const char * --- -2.44.0 - diff --git a/0001-Issue-3527-Support-HAProxy-and-Instance-on-the-same-.patch b/0001-Issue-3527-Support-HAProxy-and-Instance-on-the-same-.patch deleted file mode 100644 index a8232ca..0000000 --- a/0001-Issue-3527-Support-HAProxy-and-Instance-on-the-same-.patch +++ /dev/null @@ -1,83 +0,0 @@ -From fcdeec3b876a28e06bb53a60fe502cb702403931 Mon Sep 17 00:00:00 2001 -From: Simon Pichugin -Date: Tue, 27 Feb 2024 16:30:47 -0800 -Subject: [PATCH] Issue 3527 - Support HAProxy and Instance on the same machine - configuration (#6107) - -Description: Improve how we handle HAProxy connections to work better when -the DS and HAProxy are on the same machine. -Ensure the client and header destination IPs are checked against the trusted IP list. - -Additionally, this change will also allow configuration having -HAProxy is listening on a different subnet than the one used to forward the request. - -Related: https://github.com/389ds/389-ds-base/issues/3527 - -Reviewed by: @progier389, @jchapma (Thanks!) ---- - ldap/servers/slapd/connection.c | 35 +++++++++++++++++++++++++-------- - 1 file changed, 27 insertions(+), 8 deletions(-) - -diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c -index a30511c97..07d629475 100644 ---- a/ldap/servers/slapd/connection.c -+++ b/ldap/servers/slapd/connection.c -@@ -1187,6 +1187,8 @@ connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, int * - char str_ip[INET6_ADDRSTRLEN + 1] = {0}; - char str_haproxy_ip[INET6_ADDRSTRLEN + 1] = {0}; - char str_haproxy_destip[INET6_ADDRSTRLEN + 1] = {0}; -+ int trusted_matches_ip_found = 0; -+ int trusted_matches_destip_found = 0; - struct berval **bvals = NULL; - int proxy_connection = 0; - -@@ -1245,21 +1247,38 @@ connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, int * - normalize_IPv4(conn->cin_addr, buf_ip, sizeof(buf_ip), str_ip, sizeof(str_ip)); - normalize_IPv4(&pr_netaddr_dest, buf_haproxy_destip, sizeof(buf_haproxy_destip), - str_haproxy_destip, sizeof(str_haproxy_destip)); -+ size_t ip_len = strlen(buf_ip); -+ size_t destip_len = strlen(buf_haproxy_destip); - - /* Now, reset RC and set it to 0 only if a match is found */ - haproxy_rc = -1; - -- /* Allow only: -- * Trusted IP == Original Client IP == HAProxy Header Destination IP */ -+ /* -+ * We need to allow a configuration where DS instance and HAProxy are on the same machine. -+ * In this case, we need to check if -+ * the HAProxy client IP (which will be a loopback address) matches one of the the trusted IP addresses, -+ * while still checking that -+ * the HAProxy header destination IP address matches one of the trusted IP addresses. -+ * Additionally, this change will also allow configuration having -+ * HAProxy listening on a different subnet than one used to forward the request. -+ */ - for (size_t i = 0; bvals[i] != NULL; ++i) { -- if ((strlen(bvals[i]->bv_val) == strlen(buf_ip)) && -- (strlen(bvals[i]->bv_val) == strlen(buf_haproxy_destip)) && -- (strncasecmp(bvals[i]->bv_val, buf_ip, strlen(buf_ip)) == 0) && -- (strncasecmp(bvals[i]->bv_val, buf_haproxy_destip, strlen(buf_haproxy_destip)) == 0)) { -- haproxy_rc = 0; -- break; -+ size_t bval_len = strlen(bvals[i]->bv_val); -+ -+ /* Check if the Client IP (HAProxy's machine IP) address matches the trusted IP address */ -+ if (!trusted_matches_ip_found) { -+ trusted_matches_ip_found = (bval_len == ip_len) && (strncasecmp(bvals[i]->bv_val, buf_ip, ip_len) == 0); -+ } -+ /* Check if the HAProxy header destination IP address matches the trusted IP address */ -+ if (!trusted_matches_destip_found) { -+ trusted_matches_destip_found = (bval_len == destip_len) && (strncasecmp(bvals[i]->bv_val, buf_haproxy_destip, destip_len) == 0); - } - } -+ -+ if (trusted_matches_ip_found && trusted_matches_destip_found) { -+ haproxy_rc = 0; -+ } -+ - if (haproxy_rc == -1) { - slapi_log_err(SLAPI_LOG_CONNS, "connection_read_operation", "HAProxy header received from unknown source.\n"); - disconnect_server_nomutex(conn, conn->c_connid, -1, SLAPD_DISCONNECT_PROXY_UNKNOWN, EPROTO); --- -2.43.0 - diff --git a/0002-CVE-2024-2199.patch b/0002-CVE-2024-2199.patch deleted file mode 100644 index d980f8c..0000000 --- a/0002-CVE-2024-2199.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 23956cfb86a312318667fb9376322574fa8ec7f4 Mon Sep 17 00:00:00 2001 -From: James Chapman -Date: Wed, 1 May 2024 15:01:33 +0100 -Subject: [PATCH] CVE-2024-2199 - ---- - .../tests/suites/password/password_test.py | 56 +++++++++++++++++++ - ldap/servers/slapd/modify.c | 8 ++- - 2 files changed, 62 insertions(+), 2 deletions(-) - -diff --git a/dirsrvtests/tests/suites/password/password_test.py b/dirsrvtests/tests/suites/password/password_test.py -index 1245feb31..e4abd9907 100644 ---- a/dirsrvtests/tests/suites/password/password_test.py -+++ b/dirsrvtests/tests/suites/password/password_test.py -@@ -63,6 +63,62 @@ def test_password_delete_specific_password(topology_st): - log.info('test_password_delete_specific_password: PASSED') - - -+def test_password_modify_non_utf8(topology_st): -+ """Attempt a modify of the userPassword attribute with -+ an invalid non utf8 value -+ -+ :id: a31af9d5-d665-42b9-8d6e-fea3d0837d36 -+ :setup: Standalone instance -+ :steps: -+ 1. Add a user if it doesnt exist and set its password -+ 2. Verify password with a bind -+ 3. Modify userPassword attr with invalid value -+ 4. Attempt a bind with invalid password value -+ 5. Verify original password with a bind -+ :expectedresults: -+ 1. The user with userPassword should be added successfully -+ 2. Operation should be successful -+ 3. Server returns ldap.UNWILLING_TO_PERFORM -+ 4. Server returns ldap.INVALID_CREDENTIALS -+ 5. Operation should be successful -+ """ -+ -+ log.info('Running test_password_modify_non_utf8...') -+ -+ # Create user and set password -+ standalone = topology_st.standalone -+ users = UserAccounts(standalone, DEFAULT_SUFFIX) -+ if not users.exists(TEST_USER_PROPERTIES['uid'][0]): -+ user = users.create(properties=TEST_USER_PROPERTIES) -+ else: -+ user = users.get(TEST_USER_PROPERTIES['uid'][0]) -+ user.set('userpassword', PASSWORD) -+ -+ # Verify password -+ try: -+ user.bind(PASSWORD) -+ except ldap.LDAPError as e: -+ log.fatal('Failed to bind as {}, error: '.format(user.dn) + e.args[0]['desc']) -+ assert False -+ -+ # Modify userPassword with an invalid value -+ password = b'tes\x82t-password' # A non UTF-8 encoded password -+ with pytest.raises(ldap.UNWILLING_TO_PERFORM): -+ user.replace('userpassword', password) -+ -+ # Verify a bind fails with invalid pasword -+ with pytest.raises(ldap.INVALID_CREDENTIALS): -+ user.bind(password) -+ -+ # Verify we can still bind with original password -+ try: -+ user.bind(PASSWORD) -+ except ldap.LDAPError as e: -+ log.fatal('Failed to bind as {}, error: '.format(user.dn) + e.args[0]['desc']) -+ assert False -+ -+ log.info('test_password_modify_non_utf8: PASSED') -+ - if __name__ == '__main__': - # Run isolated - # -s for DEBUG mode -diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c -index a20984e0b..fb65d58b3 100644 ---- a/ldap/servers/slapd/modify.c -+++ b/ldap/servers/slapd/modify.c -@@ -762,8 +762,10 @@ op_shared_modify(Slapi_PBlock *pb, int pw_change, char *old_pw) - * flagged - leave mod attributes alone */ - if (!repl_op && !skip_modified_attrs && lastmod) { - modify_update_last_modified_attr(pb, &smods); -+ slapi_pblock_set(pb, SLAPI_MODIFY_MODS, slapi_mods_get_ldapmods_byref(&smods)); - } - -+ - if (0 == slapi_mods_get_num_mods(&smods)) { - /* nothing to do - no mods - this is not an error - just - send back LDAP_SUCCESS */ -@@ -930,8 +932,10 @@ op_shared_modify(Slapi_PBlock *pb, int pw_change, char *old_pw) - - /* encode password */ - if (pw_encodevals_ext(pb, sdn, va)) { -- slapi_log_err(SLAPI_LOG_CRIT, "op_shared_modify", "Unable to hash userPassword attribute for %s.\n", slapi_entry_get_dn_const(e)); -- send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Unable to store attribute \"userPassword\" correctly\n", 0, NULL); -+ slapi_log_err(SLAPI_LOG_CRIT, "op_shared_modify", "Unable to hash userPassword attribute for %s, " -+ "check value is utf8 string.\n", slapi_entry_get_dn_const(e)); -+ send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Unable to hash \"userPassword\" attribute, " -+ "check value is utf8 string.\n", 0, NULL); - valuearray_free(&va); - goto free_and_return; - } --- -2.41.0 - diff --git a/0002-Issue-6112-RFE-add-new-operation-note-for-MFA-authen.patch b/0002-Issue-6112-RFE-add-new-operation-note-for-MFA-authen.patch deleted file mode 100644 index ad60607..0000000 --- a/0002-Issue-6112-RFE-add-new-operation-note-for-MFA-authen.patch +++ /dev/null @@ -1,237 +0,0 @@ -From 3cd7d30628007f839436c417af6dd8a056c6a165 Mon Sep 17 00:00:00 2001 -From: Mark Reynolds -Date: Fri, 1 Mar 2024 11:28:17 -0500 -Subject: [PATCH 2/3] Issue 6112 - RFE - add new operation note for MFA - authentications - -Add a new operation note to indicate that a MFA plugin performed the -BIND. This implies that the plugin must set the note itself as there is -no other way to detect this: - - slapi_pblock_set_flag_operation_notes(pb, SLAPI_OP_NOTE_MFA_AUTH); - -The purpose for this is for auditing needs - -Fixes: https://github.com/389ds/389-ds-base/issues/6112 - -Reviewed by: spichugi(Thanks!) ---- - ldap/admin/src/logconv.pl | 37 ++++++++++++++++++------------- - ldap/servers/slapd/log.c | 6 ++++- - ldap/servers/slapd/result.c | 2 +- - ldap/servers/slapd/slapi-plugin.h | 1 + - 4 files changed, 28 insertions(+), 18 deletions(-) - -diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl -index 5ba91e99c..10bd5d2aa 100755 ---- a/ldap/admin/src/logconv.pl -+++ b/ldap/admin/src/logconv.pl -@@ -2,11 +2,11 @@ - # - # BEGIN COPYRIGHT BLOCK - # Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. --# Copyright (C) 2022 Red Hat, Inc. -+# Copyright (C) 2010-2024 Red Hat, Inc. - # All rights reserved. - # - # License: GPL (version 3 or any later version). --# See LICENSE for details. -+# See LICENSE for details. - # END COPYRIGHT BLOCK - # - -@@ -218,6 +218,7 @@ my $sslClientFailedCount = 0; - my $objectclassTopCount= 0; - my $pagedSearchCount = 0; - my $invalidFilterCount = 0; -+my $mfaCount = 0; - my $bindCount = 0; - my $filterCount = 0; - my $baseCount = 0; -@@ -407,7 +408,7 @@ sub statusreport { - ########################################## - # # - # Parse Access Logs # --# # -+# # - ########################################## - - if ($files[$#files] =~ m/access.rotationinfo/) { -@@ -709,7 +710,7 @@ if($endTime){ - - # - # Get the start time in seconds --# -+# - my $logStart = $start; - my $startTotal = convertTimeToNanoseconds($logStart); - -@@ -890,6 +891,7 @@ $etimeAvg = $totalEtime / $etimeCount; - print sprintf "Average etime (elapsed time): %.9f\n", $etimeAvg; - - print "\n"; -+print "Multi-factor Authentications: $mfaCount\n"; - print "Proxied Auth Operations: $proxiedAuthCount\n"; - print "Persistent Searches: $persistentSrchCount\n"; - print "Internal Operations: $internalOpCount\n"; -@@ -1758,7 +1760,7 @@ if ($usage =~ /j/i || $verb eq "yes"){ - $recCount++; - } - if ($objectclassTopCount > ($srchCount *.25)){ -- print "\n $recCount. You have a high number of searches that query the entire search base. Although this is not necessarily bad, it could be resource intensive if the search base contains many entries.\n"; -+ print "\n $recCount. You have a high number of searches that query the entire search base. Although this is not necessarily bad, it could be resource intensive if the search base contains many entries.\n"; - $recCount++; - } - if ($recCount == 1){ -@@ -1792,7 +1794,7 @@ sub displayUsage { - - print " -h, --help help/usage\n"; - print " -d, --rootDN default is \"cn=directory manager\"\n"; -- print " -D, --data default is \"/tmp\"\n"; -+ print " -D, --data default is \"/tmp\"\n"; - print " -s, --sizeLimit default is 20\n"; - print " -X, --excludeIP E.g. Load balancers\n"; - print " -v, --version show version of tool\n"; -@@ -1800,8 +1802,8 @@ sub displayUsage { - print " E.g. \"[28/Mar/2002:13:14:22 -0800]\"\n"; - print " -E, --endTime