Sync from SUSE:ALP:Source:Standard:1.0 openvpn revision 1f2b462f5fa0253be14b8323e36ecb1d
This commit is contained in:
217
openvpn-CVE-2024-5594.patch
Normal file
217
openvpn-CVE-2024-5594.patch
Normal file
@@ -0,0 +1,217 @@
|
||||
diff -Naurp openvpn-2.6.8.orig/src/openvpn/buffer.c openvpn-2.6.8/src/openvpn/buffer.c
|
||||
--- openvpn-2.6.8.orig/src/openvpn/buffer.c 2025-01-23 04:48:24.052746115 +0100
|
||||
+++ openvpn-2.6.8/src/openvpn/buffer.c 2025-01-23 05:21:09.502643515 +0100
|
||||
@@ -1113,6 +1113,21 @@ string_mod(char *str, const unsigned int
|
||||
return ret;
|
||||
}
|
||||
|
||||
+bool
|
||||
+string_check_buf(struct buffer *buf, const unsigned int inclusive, const unsigned int exclusive)
|
||||
+{
|
||||
+ ASSERT(buf);
|
||||
+ for (int i = 0; i < BLEN(buf); i++)
|
||||
+ {
|
||||
+ char c = BSTR(buf)[i];
|
||||
+ if (!char_inc_exc(c, inclusive, exclusive))
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
const char *
|
||||
string_mod_const(const char *str,
|
||||
const unsigned int inclusive,
|
||||
diff -Naurp openvpn-2.6.8.orig/src/openvpn/buffer.h openvpn-2.6.8/src/openvpn/buffer.h
|
||||
--- openvpn-2.6.8.orig/src/openvpn/buffer.h 2025-01-23 04:48:24.052746115 +0100
|
||||
+++ openvpn-2.6.8/src/openvpn/buffer.h 2025-01-23 05:24:03.153919112 +0100
|
||||
@@ -945,6 +945,17 @@ bool string_class(const char *str, const
|
||||
|
||||
bool string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace);
|
||||
|
||||
+/**
|
||||
+ * Check a buffer if it only consists of allowed characters.
|
||||
+ *
|
||||
+ * @param buf The buffer to be checked.
|
||||
+ * @param inclusive The character classes that are allowed.
|
||||
+ * @param exclusive Character classes that are not allowed even if they are also in inclusive.
|
||||
+ * @return True if the string consists only of allowed characters, false otherwise.
|
||||
+ */
|
||||
+bool
|
||||
+string_check_buf(struct buffer *buf, const unsigned int inclusive, const unsigned int exclusive);
|
||||
+
|
||||
const char *string_mod_const(const char *str,
|
||||
const unsigned int inclusive,
|
||||
const unsigned int exclusive,
|
||||
diff -Naurp openvpn-2.6.8.orig/src/openvpn/forward.c openvpn-2.6.8/src/openvpn/forward.c
|
||||
--- openvpn-2.6.8.orig/src/openvpn/forward.c 2025-01-23 04:48:24.053746124 +0100
|
||||
+++ openvpn-2.6.8/src/openvpn/forward.c 2025-01-23 05:54:53.264399254 +0100
|
||||
@@ -230,6 +230,51 @@ check_tls(struct context *c)
|
||||
}
|
||||
}
|
||||
|
||||
+static void
|
||||
+parse_incoming_control_channel_command(struct context *c, struct buffer *buf)
|
||||
+{
|
||||
+ if (buf_string_match_head_str(buf, "AUTH_FAILED"))
|
||||
+ {
|
||||
+ receive_auth_failed(c, buf);
|
||||
+ }
|
||||
+ else if (buf_string_match_head_str(buf, "PUSH_"))
|
||||
+ {
|
||||
+ incoming_push_message(c, buf);
|
||||
+ }
|
||||
+ else if (buf_string_match_head_str(buf, "RESTART"))
|
||||
+ {
|
||||
+ server_pushed_signal(c, buf, true, 7);
|
||||
+ }
|
||||
+ else if (buf_string_match_head_str(buf, "HALT"))
|
||||
+ {
|
||||
+ server_pushed_signal(c, buf, false, 4);
|
||||
+ }
|
||||
+ else if (buf_string_match_head_str(buf, "INFO_PRE"))
|
||||
+ {
|
||||
+ server_pushed_info(c, buf, 8);
|
||||
+ }
|
||||
+ else if (buf_string_match_head_str(buf, "INFO"))
|
||||
+ {
|
||||
+ server_pushed_info(c, buf, 4);
|
||||
+ }
|
||||
+ else if (buf_string_match_head_str(buf, "CR_RESPONSE"))
|
||||
+ {
|
||||
+ receive_cr_response(c, buf);
|
||||
+ }
|
||||
+ else if (buf_string_match_head_str(buf, "AUTH_PENDING"))
|
||||
+ {
|
||||
+ receive_auth_pending(c, buf);
|
||||
+ }
|
||||
+ else if (buf_string_match_head_str(buf, "EXIT"))
|
||||
+ {
|
||||
+ receive_exit_message(c);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ msg(D_PUSH_ERRORS, "WARNING: Received unknown control message: %s", BSTR(buf));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Handle incoming configuration
|
||||
* messages on the control channel.
|
||||
@@ -245,51 +290,37 @@ check_incoming_control_channel(struct co
|
||||
struct buffer buf = alloc_buf_gc(len, &gc);
|
||||
if (tls_rec_payload(c->c2.tls_multi, &buf))
|
||||
{
|
||||
- /* force null termination of message */
|
||||
- buf_null_terminate(&buf);
|
||||
-
|
||||
- /* enforce character class restrictions */
|
||||
- string_mod(BSTR(&buf), CC_PRINT, CC_CRLF, 0);
|
||||
-
|
||||
- if (buf_string_match_head_str(&buf, "AUTH_FAILED"))
|
||||
- {
|
||||
- receive_auth_failed(c, &buf);
|
||||
- }
|
||||
- else if (buf_string_match_head_str(&buf, "PUSH_"))
|
||||
- {
|
||||
- incoming_push_message(c, &buf);
|
||||
- }
|
||||
- else if (buf_string_match_head_str(&buf, "RESTART"))
|
||||
- {
|
||||
- server_pushed_signal(c, &buf, true, 7);
|
||||
- }
|
||||
- else if (buf_string_match_head_str(&buf, "HALT"))
|
||||
- {
|
||||
- server_pushed_signal(c, &buf, false, 4);
|
||||
- }
|
||||
- else if (buf_string_match_head_str(&buf, "INFO_PRE"))
|
||||
- {
|
||||
- server_pushed_info(c, &buf, 8);
|
||||
- }
|
||||
- else if (buf_string_match_head_str(&buf, "INFO"))
|
||||
- {
|
||||
- server_pushed_info(c, &buf, 4);
|
||||
- }
|
||||
- else if (buf_string_match_head_str(&buf, "CR_RESPONSE"))
|
||||
- {
|
||||
- receive_cr_response(c, &buf);
|
||||
- }
|
||||
- else if (buf_string_match_head_str(&buf, "AUTH_PENDING"))
|
||||
- {
|
||||
- receive_auth_pending(c, &buf);
|
||||
- }
|
||||
- else if (buf_string_match_head_str(&buf, "EXIT"))
|
||||
- {
|
||||
- receive_exit_message(c);
|
||||
- }
|
||||
- else
|
||||
+ while (BLEN(&buf) > 1)
|
||||
{
|
||||
- msg(D_PUSH_ERRORS, "WARNING: Received unknown control message: %s", BSTR(&buf));
|
||||
+ /* commands on the control channel are seperated by 0x00 bytes.
|
||||
+ * cmdlen does not include the 0 byte of the string */
|
||||
+ int cmdlen = (int)strnlen(BSTR(&buf), BLEN(&buf));
|
||||
+ if (cmdlen < BLEN(&buf))
|
||||
+ {
|
||||
+ /* include the NUL byte and ensure NUL termination */
|
||||
+ int cmdlen = (int)strlen(BSTR(&buf)) + 1;
|
||||
+ /* Construct a buffer that only holds the current command and
|
||||
+ * its closing NUL byte */
|
||||
+ struct buffer cmdbuf = alloc_buf_gc(cmdlen, &gc);
|
||||
+ buf_write(&cmdbuf, BPTR(&buf), cmdlen);
|
||||
+ /* check we have only printable characters or null byte in the
|
||||
+ * command string and no newlines */
|
||||
+ if (!string_check_buf(&buf, CC_PRINT | CC_NULL, CC_CRLF))
|
||||
+ {
|
||||
+ msg(D_PUSH_ERRORS, "WARNING: Received control with invalid characters: %s",
|
||||
+ format_hex(BPTR(&buf), BLEN(&buf), 256, &gc));
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ parse_incoming_control_channel_command(c, &cmdbuf);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ msg(D_PUSH_ERRORS, "WARNING: Ignoring control channel "
|
||||
+ "message command without NUL termination");
|
||||
+ }
|
||||
+ buf_advance(&buf, cmdlen);
|
||||
}
|
||||
}
|
||||
else
|
||||
diff -Naurp openvpn-2.6.8.orig/tests/unit_tests/openvpn/test_buffer.c openvpn-2.6.8/tests/unit_tests/openvpn/test_buffer.c
|
||||
--- openvpn-2.6.8.orig/tests/unit_tests/openvpn/test_buffer.c 2025-01-23 04:48:24.057746162 +0100
|
||||
+++ openvpn-2.6.8/tests/unit_tests/openvpn/test_buffer.c 2025-01-23 05:57:21.647699590 +0100
|
||||
@@ -259,6 +259,22 @@ test_buffer_gc_realloc(void **state)
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
+static void
|
||||
+test_character_string_mod_buf(void **state)
|
||||
+{
|
||||
+ struct gc_arena gc = gc_new();
|
||||
+ struct buffer buf = alloc_buf_gc(1024, &gc);
|
||||
+ const char test1[] = "There is a nice 1234\x00 year old tree!";
|
||||
+ buf_write(&buf, test1, sizeof(test1));
|
||||
+ /* allow the null bytes and string but not the ! */
|
||||
+ assert_false(string_check_buf(&buf, CC_ALNUM | CC_SPACE | CC_NULL, 0));
|
||||
+ /* remove final ! and null byte to pass */
|
||||
+ buf_inc_len(&buf, -2);
|
||||
+ assert_true(string_check_buf(&buf, CC_ALNUM | CC_SPACE | CC_NULL, 0));
|
||||
+ /* Check excluding digits works */
|
||||
+ assert_false(string_check_buf(&buf, CC_ALNUM | CC_SPACE | CC_NULL, CC_DIGIT));
|
||||
+ gc_free(&gc);
|
||||
+}
|
||||
|
||||
int
|
||||
main(void)
|
||||
@@ -289,6 +305,7 @@ main(void)
|
||||
cmocka_unit_test(test_buffer_free_gc_one),
|
||||
cmocka_unit_test(test_buffer_free_gc_two),
|
||||
cmocka_unit_test(test_buffer_gc_realloc),
|
||||
+ cmocka_unit_test(test_character_string_mod_buf)
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests_name("buffer", tests, NULL, NULL);
|
@@ -1,3 +1,10 @@
|
||||
-------------------------------------------------------------------
|
||||
Thu Jan 23 05:04:47 UTC 2025 - Rahul Jain <rahul.jain@suse.com>
|
||||
|
||||
-FIX VUL-0: CVE-2024-5594: openvpn properly handle null bytes and
|
||||
invalid characters in control messages(bsc#1235147 CVE-2024-5594)
|
||||
Patchname: openvpn-CVE-2024-5594.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Sep 24 08:31:15 UTC 2024 - Rahul Jain <rahul.jain@suse.com>
|
||||
|
||||
|
@@ -38,6 +38,7 @@ Source10: %{name}-tmpfile.conf
|
||||
Source11: rc%{name}
|
||||
Patch1: %{name}-2.3-plugin-man.dif
|
||||
Patch2: openvpn-CVE-2024-28882.patch
|
||||
Patch3: openvpn-CVE-2024-5594.patch
|
||||
BuildRequires: iproute2
|
||||
BuildRequires: libcap-ng-devel
|
||||
BuildRequires: liblz4-devel
|
||||
@@ -120,6 +121,7 @@ This package provides the header file to build external plugins.
|
||||
%setup -q
|
||||
%patch1
|
||||
%patch2 -p1
|
||||
%patch3 -p1
|
||||
|
||||
sed -e "s|\" __DATE__|$(date '+%%b %%e %%Y' -r version.m4)\"|g" \
|
||||
-i src/openvpn/options.c
|
||||
|
Reference in New Issue
Block a user