Projects
Mega:23.09
libssh
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 3
View file
_service:tar_scm:libssh.spec
Changed
@@ -1,6 +1,6 @@ Name: libssh Version: 0.10.5 -Release: 1 +Release: 2 Summary: A library implementing the SSH protocol License: LGPLv2+ URL: http://www.libssh.org @@ -9,6 +9,26 @@ Source1: https://www.libssh.org/files/0.10/%{name}-%{version}.tar.xz.asc Source2: https://cryptomilk.org/gpgkey-8DFF53E18F2ABC8D8F3C92237EE0FC4DCC014E3D.gpg#/%{name}.keyring +Patch1: backport-0001-CVE-2023-6004-torture_config-Allow-multiple-in-usern.patch +Patch2: backport-0002-CVE-2023-6004-config_parser-Allow-multiple-in-userna.patch +Patch3: backport-0003-CVE-2023-6004-options-Simplify-the-hostname-parsing-.patch +Patch4: backport-0004-CVE-2023-6004-misc-Add-function-to-check-allowed-cha.patch +Patch5: backport-0005-CVE-2023-6004-torture_misc-Add-test-for-ssh_check_ho.patch +Patch6: backport-0006-CVE-2023-6004-config_parser-Check-for-valid-syntax-o.patch +Patch7: backport-0007-CVE-2023-6004-torture_proxycommand-Add-test-for-prox.patch +Patch8: backport-0008-CVE-2023-6004-torture_misc-Add-test-for-ssh_is_ipadd.patch +Patch9: backport-0009-CVE-2023-6004-misc-Add-ipv6-link-local-check-for-an-.patch +Patch10: backport-0010-CVE-2023-6004-torture_misc-Add-tests-for-ipv6-link-l.patch +Patch11: backport-0011-CVE-2023-48795-client-side-mitigation.patch +Patch12: backport-0012-CVE-2023-48795-Server-side-mitigations.patch +Patch13: backport-0013-CVE-2023-48795-Strip-extensions-from-both-kex-lists-.patch +Patch14: backport-0014-CVE-2023-48795-tests-Adjust-calculation-to-strict-ke.patch +Patch15: backport-0015-CVE-2023-6918-kdf-Reformat.patch +Patch16: backport-0016-CVE-2023-6918-Remove-unused-evp-functions-and-types.patch +Patch17: backport-0017-CVE-2023-6918-Systematically-check-return-values-whe.patch +Patch18: backport-0018-CVE-2023-6918-kdf-Detect-context-init-failures.patch +Patch19: backport-0019-CVE-2023-6918-tests-Code-coverage-for-ssh_get_pubkey.patch + BuildRequires: cmake gcc-c++ gnupg2 openssl-devel pkgconfig zlib-devel BuildRequires: krb5-devel libcmocka-devel openssh-clients openssh-server BuildRequires: nmap-ncat @@ -93,6 +113,12 @@ %doc CHANGELOG README %changelog +* Thu Jan 4 2024 renmingshuai <renmingshuai@huawei.com> - 0.10.5-2 +- Type:CVE +- Id:CVE-2023-6004,CVE-2023-48795,CVE-2023-6918 +- SUG:NA +- DESC:fix CVE-2023-6004,CVE-2023-48795 and CVE-2023-6918 + * Mon Aug 7 2023 renmingshuai <renmingshuai@huawei.com> - 0.10.5-1 - Type:requirement - Id:NA
View file
_service:tar_scm:backport-0001-CVE-2023-6004-torture_config-Allow-multiple-in-usern.patch
Added
@@ -0,0 +1,112 @@ +From c2c56bacab00766d01671413321d564227aabf19 Mon Sep 17 00:00:00 2001 +From: Norbert Pocs <norbertpocs0@gmail.com> +Date: Sun, 5 Nov 2023 13:12:47 +0100 +Subject: PATCH 01/20 CVE-2023-6004: torture_config: Allow multiple '@' in + usernames + +Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +Reviewed-by: Jakub Jelen <jjelen@redhat.com> +--- + tests/unittests/torture_config.c | 56 +++++++++++++++++--------------- + 1 file changed, 30 insertions(+), 26 deletions(-) + +diff --git a/tests/unittests/torture_config.c b/tests/unittests/torture_config.c +index 406f1985..b7c763af 100644 +--- a/tests/unittests/torture_config.c ++++ b/tests/unittests/torture_config.c +@@ -995,23 +995,22 @@ static void torture_config_proxyjump(void **state, + assert_string_equal(session->opts.ProxyCommand, + "ssh -W '%h:%p' 2620:52:0::fed"); + +- /* In this part, we try various other config files and strings. */ +- +- /* Try to create some invalid configurations */ +- /* Non-numeric port */ +- config = "Host bad-port\n" +- "\tProxyJump jumpbox:22bad22\n"; ++ /* Multiple @ is allowed in second jump */ ++ config = "Host allowed-hostname\n" ++ "\tProxyJump localhost,user@principal.com@jumpbox:22\n"; + if (file != NULL) { + torture_write_file(file, config); + } else { + string = config; + } + torture_reset_config(session); +- ssh_options_set(session, SSH_OPTIONS_HOST, "bad-port"); +- _parse_config(session, file, string, SSH_ERROR); ++ ssh_options_set(session, SSH_OPTIONS_HOST, "allowed-hostname"); ++ _parse_config(session, file, string, SSH_OK); ++ assert_string_equal(session->opts.ProxyCommand, ++ "ssh -J user@principal.com@jumpbox:22 -W '%h:%p' localhost"); + +- /* Too many @ */ +- config = "Host bad-hostname\n" ++ /* Multiple @ is allowed */ ++ config = "Host allowed-hostname\n" + "\tProxyJump user@principal.com@jumpbox:22\n"; + if (file != NULL) { + torture_write_file(file, config); +@@ -1019,7 +1018,24 @@ static void torture_config_proxyjump(void **state, + string = config; + } + torture_reset_config(session); +- ssh_options_set(session, SSH_OPTIONS_HOST, "bad-hostname"); ++ ssh_options_set(session, SSH_OPTIONS_HOST, "allowed-hostname"); ++ _parse_config(session, file, string, SSH_OK); ++ assert_string_equal(session->opts.ProxyCommand, ++ "ssh -l user@principal.com -p 22 -W '%h:%p' jumpbox"); ++ ++ /* In this part, we try various other config files and strings. */ ++ ++ /* Try to create some invalid configurations */ ++ /* Non-numeric port */ ++ config = "Host bad-port\n" ++ "\tProxyJump jumpbox:22bad22\n"; ++ if (file != NULL) { ++ torture_write_file(file, config); ++ } else { ++ string = config; ++ } ++ torture_reset_config(session); ++ ssh_options_set(session, SSH_OPTIONS_HOST, "bad-port"); + _parse_config(session, file, string, SSH_ERROR); + + /* Braces mismatch in hostname */ +@@ -1094,18 +1110,6 @@ static void torture_config_proxyjump(void **state, + ssh_options_set(session, SSH_OPTIONS_HOST, "bad-port-2"); + _parse_config(session, file, string, SSH_ERROR); + +- /* Too many @ in second jump */ +- config = "Host bad-hostname\n" +- "\tProxyJump localhost,user@principal.com@jumpbox:22\n"; +- if (file != NULL) { +- torture_write_file(file, config); +- } else { +- string = config; +- } +- torture_reset_config(session); +- ssh_options_set(session, SSH_OPTIONS_HOST, "bad-hostname"); +- _parse_config(session, file, string, SSH_ERROR); +- + /* Braces mismatch in second jump */ + config = "Host mismatch\n" + "\tProxyJump localhost,::1:20\n"; +@@ -1448,10 +1452,10 @@ static void torture_config_parser_get_cmd(void **state) + } else if (pid == 0) { + ssh_execute_command(tok, fileno(outfile), fileno(outfile)); + /* Does not return */ +- } else { +- /* parent ++ } else { ++ /* parent + * wait child process */ +- wait(NULL); ++ wait(NULL); + infile = fopen("output.log", "r"); + assert_non_null(infile); + p = fgets(buffer, sizeof(buffer), infile); +-- +2.33.0 +
View file
_service:tar_scm:backport-0002-CVE-2023-6004-config_parser-Allow-multiple-in-userna.patch
Added
@@ -0,0 +1,29 @@ +From a66b4a6eae6614d200a3625862d77565b96a7cd3 Mon Sep 17 00:00:00 2001 +From: Norbert Pocs <norbertpocs0@gmail.com> +Date: Wed, 1 Nov 2023 11:24:43 +0100 +Subject: PATCH 02/20 CVE-2023-6004: config_parser: Allow multiple '@' in + usernames + +Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +Reviewed-by: Jakub Jelen <jjelen@redhat.com> +--- + src/config_parser.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/config_parser.c b/src/config_parser.c +index 0d988fec..cf83e2c5 100644 +--- a/src/config_parser.c ++++ b/src/config_parser.c +@@ -180,7 +180,7 @@ int ssh_config_parse_uri(const char *tok, + } + + /* Username part (optional) */ +- endp = strchr(tok, '@'); ++ endp = strrchr(tok, '@'); + if (endp != NULL) { + /* Zero-length username is not valid */ + if (tok == endp) { +-- +2.33.0 +
View file
_service:tar_scm:backport-0003-CVE-2023-6004-options-Simplify-the-hostname-parsing-.patch
Added
@@ -0,0 +1,80 @@ +From 8615c24647f773a5e04203c7459512715d698be1 Mon Sep 17 00:00:00 2001 +From: Norbert Pocs <norbertpocs0@gmail.com> +Date: Tue, 31 Oct 2023 09:48:52 +0100 +Subject: PATCH 03/20 CVE-2023-6004: options: Simplify the hostname parsing + in ssh_options_set + +Using ssh_config_parse_uri can simplify the parsing of the host +parsing inside the function of ssh_options_set + +Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +Reviewed-by: Jakub Jelen <jjelen@redhat.com> +--- + src/options.c | 40 ++++++++++++++++------------------------ + 1 file changed, 16 insertions(+), 24 deletions(-) + +diff --git a/src/options.c b/src/options.c +index 6f2c9397..38511455 100644 +--- a/src/options.c ++++ b/src/options.c +@@ -37,6 +37,7 @@ + #include "libssh/session.h" + #include "libssh/misc.h" + #include "libssh/options.h" ++#include "libssh/config_parser.h" + #ifdef WITH_SERVER + #include "libssh/server.h" + #include "libssh/bind.h" +@@ -515,33 +516,24 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, + ssh_set_error_invalid(session); + return -1; + } else { +- q = strdup(value); +- if (q == NULL) { +- ssh_set_error_oom(session); ++ char *username = NULL, *hostname = NULL, *port = NULL; ++ rc = ssh_config_parse_uri(value, &username, &hostname, &port); ++ if (rc != SSH_OK) { + return -1; + } +- p = strrchr(q, '@'); +- +- SAFE_FREE(session->opts.host); +- +- if (p) { +- *p = '\0'; +- session->opts.host = strdup(p + 1); +- if (session->opts.host == NULL) { +- SAFE_FREE(q); +- ssh_set_error_oom(session); +- return -1; +- } +- ++ if (port != NULL) { ++ SAFE_FREE(username); ++ SAFE_FREE(hostname); ++ SAFE_FREE(port); ++ return -1; ++ } ++ if (username != NULL) { + SAFE_FREE(session->opts.username); +- session->opts.username = strdup(q); +- SAFE_FREE(q); +- if (session->opts.username == NULL) { +- ssh_set_error_oom(session); +- return -1; +- } +- } else { +- session->opts.host = q; ++ session->opts.username = username; ++ } ++ if (hostname != NULL) { ++ SAFE_FREE(session->opts.host); ++ session->opts.host = hostname; + } + } + break; +-- +2.33.0 +
View file
_service:tar_scm:backport-0004-CVE-2023-6004-misc-Add-function-to-check-allowed-cha.patch
Added
@@ -0,0 +1,118 @@ +From c6180409677c765e6b9ae2b18a3a7a9671ac1dbe Mon Sep 17 00:00:00 2001 +From: Norbert Pocs <norbertpocs0@gmail.com> +Date: Tue, 10 Oct 2023 12:44:16 +0200 +Subject: PATCH 04/20 CVE-2023-6004: misc: Add function to check allowed + characters of a hostname + +The hostname can be a domain name or an ip address. The colon has to be +allowed because of IPv6 even it is prohibited in domain names. + +Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +Reviewed-by: Jakub Jelen <jjelen@redhat.com> +--- + include/libssh/misc.h | 3 ++ + src/misc.c | 68 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 71 insertions(+) + +diff --git a/include/libssh/misc.h b/include/libssh/misc.h +index 924da533..0924ba7f 100644 +--- a/include/libssh/misc.h ++++ b/include/libssh/misc.h +@@ -103,6 +103,9 @@ int ssh_newline_vis(const char *string, char *buf, size_t buf_len); + int ssh_tmpname(char *name); + + char *ssh_strreplace(const char *src, const char *pattern, const char *repl); ++ ++int ssh_check_hostname_syntax(const char *hostname); ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/misc.c b/src/misc.c +index 7c478a77..be6ee836 100644 +--- a/src/misc.c ++++ b/src/misc.c +@@ -94,6 +94,8 @@ + #define ZLIB_STRING "" + #endif + ++#define ARPA_DOMAIN_MAX_LEN 63 ++ + /** + * @defgroup libssh_misc The SSH helper functions + * @ingroup libssh +@@ -1974,4 +1976,70 @@ char *ssh_strerror(int err_num, char *buf, size_t buflen) + #endif /* defined(__linux__) && defined(__GLIBC__) && defined(_GNU_SOURCE) */ + } + ++/** ++ * @brief Checks syntax of a domain name ++ * ++ * The check is made based on the RFC1035 section 2.3.1 ++ * Allowed characters are: hyphen, period, digits (0-9) and letters (a-zA-Z) ++ * ++ * The label should be no longer than 63 characters ++ * The label should start with a letter and end with a letter or number ++ * The label in this implementation can start with a number to allow virtual ++ * URLs to pass. Note that this will make IPv4 addresses to pass ++ * this check too. ++ * ++ * @param hostname The domain name to be checked, has to be null terminated ++ * ++ * @return SSH_OK if the hostname passes syntax check ++ * SSH_ERROR otherwise or if hostname is NULL or empty string ++ */ ++int ssh_check_hostname_syntax(const char *hostname) ++{ ++ char *it = NULL, *s = NULL, *buf = NULL; ++ size_t it_len; ++ char c; ++ ++ if (hostname == NULL || strlen(hostname) == 0) { ++ return SSH_ERROR; ++ } ++ ++ /* strtok_r writes into the string, keep the input clean */ ++ s = strdup(hostname); ++ if (s == NULL) { ++ return SSH_ERROR; ++ } ++ ++ it = strtok_r(s, ".", &buf); ++ /* if the token has 0 length */ ++ if (it == NULL) { ++ free(s); ++ return SSH_ERROR; ++ } ++ do { ++ it_len = strlen(it); ++ if (it_len > ARPA_DOMAIN_MAX_LEN || ++ /* the first char must be a letter, but some virtual urls start ++ * with a number */ ++ isalnum(it0) == 0 || ++ isalnum(itit_len - 1) == 0) { ++ free(s); ++ return SSH_ERROR; ++ } ++ while (*it != '\0') { ++ c = *it; ++ /* the "." is allowed too, but tokenization removes it from the ++ * string */ ++ if (isalnum(c) == 0 && c != '-') { ++ free(s); ++ return SSH_ERROR; ++ } ++ it++; ++ } ++ } while ((it = strtok_r(NULL, ".", &buf)) != NULL); ++ ++ free(s); ++ ++ return SSH_OK; ++} ++ + /** @} */ +-- +2.33.0 +
View file
_service:tar_scm:backport-0005-CVE-2023-6004-torture_misc-Add-test-for-ssh_check_ho.patch
Added
@@ -0,0 +1,107 @@ +From 9bbb817c0c5434f03613d0783b2ef5f52235b901 Mon Sep 17 00:00:00 2001 +From: Norbert Pocs <norbertpocs0@gmail.com> +Date: Tue, 10 Oct 2023 12:45:28 +0200 +Subject: PATCH 05/20 CVE-2023-6004: torture_misc: Add test for + ssh_check_hostname_syntax + +Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +Reviewed-by: Jakub Jelen <jjelen@redhat.com> +--- + tests/unittests/torture_misc.c | 73 ++++++++++++++++++++++++++++++++++ + 1 file changed, 73 insertions(+) + +diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c +index 9e346ff8..e682b6d4 100644 +--- a/tests/unittests/torture_misc.c ++++ b/tests/unittests/torture_misc.c +@@ -760,6 +760,78 @@ static void torture_ssh_strerror(void **state) + assert_non_null(out); + } + ++static void torture_ssh_check_hostname_syntax(void **state) ++{ ++ int rc; ++ (void)state; ++ ++ rc = ssh_check_hostname_syntax("duckduckgo.com"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("www.libssh.org"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("Some-Thing.com"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("amazon.a23456789012345678901234567890123456789012345678901234567890123"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("amazon.a23456789012345678901234567890123456789012345678901234567890123.a23456789012345678901234567890123456789012345678901234567890123.ok"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("amazon.a23456789012345678901234567890123456789012345678901234567890123.a23456789012345678901234567890123456789012345678901234567890123.a23456789012345678901234567890123456789012345678901234567890123"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("lavabo-inter.innocentes-manus-meas"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("localhost"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("a"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("a-0.b-b"); ++ assert_int_equal(rc, SSH_OK); ++ rc = ssh_check_hostname_syntax("libssh."); ++ assert_int_equal(rc, SSH_OK); ++ ++ rc = ssh_check_hostname_syntax(NULL); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax(""); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("/"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("@"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax(""); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("`"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("{"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("&"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("|"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("\""); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("`"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax(" "); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("*the+giant&\"rooks\".c0m"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("!www.libssh.org"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("--.--"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("libssh.a234567890123456789012345678901234567890123456789012345678901234"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("libssh.a234567890123456789012345678901234567890123456789012345678901234.a234567890123456789012345678901234567890123456789012345678901234"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("libssh-"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("fe80::9656:d028:8652:66b6"); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax("."); ++ assert_int_equal(rc, SSH_ERROR); ++ rc = ssh_check_hostname_syntax(".."); ++ assert_int_equal(rc, SSH_ERROR); ++} ++ + int torture_run_tests(void) { + int rc; + struct CMUnitTest tests = { +@@ -784,6 +856,7 @@ int torture_run_tests(void) { + cmocka_unit_test(torture_ssh_quote_file_name), + cmocka_unit_test(torture_ssh_strreplace), + cmocka_unit_test(torture_ssh_strerror), ++ cmocka_unit_test(torture_ssh_check_hostname_syntax), + }; + + ssh_init(); +-- +2.33.0 +
View file
_service:tar_scm:backport-0006-CVE-2023-6004-config_parser-Check-for-valid-syntax-o.patch
Added
@@ -0,0 +1,63 @@ +From 22492b69bba22b102342afc574800d354a08e405 Mon Sep 17 00:00:00 2001 +From: Norbert Pocs <norbertpocs0@gmail.com> +Date: Tue, 10 Oct 2023 18:33:56 +0200 +Subject: PATCH 06/20 CVE-2023-6004: config_parser: Check for valid syntax of + a hostname if it is a domain name + +This prevents code injection. +The domain name syntax checker is based on RFC1035. + +Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +Reviewed-by: Jakub Jelen <jjelen@redhat.com> +--- + src/config_parser.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/src/config_parser.c b/src/config_parser.c +index cf83e2c5..b8b94611 100644 +--- a/src/config_parser.c ++++ b/src/config_parser.c +@@ -30,6 +30,7 @@ + + #include "libssh/config_parser.h" + #include "libssh/priv.h" ++#include "libssh/misc.h" + + /* Returns the original string after skipping the leading whitespace + * until finding LF. +@@ -47,7 +48,7 @@ char *ssh_config_get_cmd(char **str) + break; + } + } +- ++ + for (r = c; *c; c++) { + if (*c == '\n') { + *c = '\0'; +@@ -167,6 +168,7 @@ int ssh_config_parse_uri(const char *tok, + { + char *endp = NULL; + long port_n; ++ int rc; + + /* Sanitize inputs */ + if (username != NULL) { +@@ -224,6 +226,14 @@ int ssh_config_parse_uri(const char *tok, + if (*hostname == NULL) { + goto error; + } ++ /* if not an ip, check syntax */ ++ rc = ssh_is_ipaddr(*hostname); ++ if (rc == 0) { ++ rc = ssh_check_hostname_syntax(*hostname); ++ if (rc != SSH_OK) { ++ goto error; ++ } ++ } + } + /* Skip also the closing bracket */ + if (*endp == '') { +-- +2.33.0 +
View file
_service:tar_scm:backport-0007-CVE-2023-6004-torture_proxycommand-Add-test-for-prox.patch
Added
@@ -0,0 +1,87 @@ +From d7467498fd988949edde9c6384973250fd454a8b Mon Sep 17 00:00:00 2001 +From: Norbert Pocs <norbertpocs0@gmail.com> +Date: Tue, 10 Oct 2023 10:28:47 +0200 +Subject: PATCH 07/20 CVE-2023-6004: torture_proxycommand: Add test for + proxycommand injection + +Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +Reviewed-by: Jakub Jelen <jjelen@redhat.com> +--- + tests/client/torture_proxycommand.c | 53 +++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +diff --git a/tests/client/torture_proxycommand.c b/tests/client/torture_proxycommand.c +index 9b8019ca..1bad4ccc 100644 +--- a/tests/client/torture_proxycommand.c ++++ b/tests/client/torture_proxycommand.c +@@ -166,6 +166,56 @@ static void torture_options_set_proxycommand_ssh_stderr(void **state) + assert_int_equal(rc & O_RDWR, O_RDWR); + } + ++static void torture_options_proxycommand_injection(void **state) ++{ ++ struct torture_state *s = *state; ++ struct passwd *pwd = NULL; ++ const char *malicious_host = "`echo foo > mfile`"; ++ const char *command = "nc %h %p"; ++ char *current_dir = NULL; ++ char *malicious_file_path = NULL; ++ int mfp_len; ++ int verbosity = torture_libssh_verbosity(); ++ struct stat sb; ++ int rc; ++ ++ pwd = getpwnam("bob"); ++ assert_non_null(pwd); ++ ++ rc = setuid(pwd->pw_uid); ++ assert_return_code(rc, errno); ++ ++ s->ssh.session = ssh_new(); ++ assert_non_null(s->ssh.session); ++ ++ ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ++ // if we would be checking the rc, this should fail ++ ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, malicious_host); ++ ++ ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); ++ ++ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROXYCOMMAND, command); ++ assert_int_equal(rc, 0); ++ rc = ssh_connect(s->ssh.session); ++ assert_ssh_return_code_equal(s->ssh.session, rc, SSH_ERROR); ++ ++ current_dir = torture_get_current_working_dir(); ++ assert_non_null(current_dir); ++ mfp_len = strlen(current_dir) + 6; ++ malicious_file_path = malloc(mfp_len); ++ assert_non_null(malicious_file_path); ++ rc = snprintf(malicious_file_path, mfp_len, ++ "%s/mfile", current_dir); ++ assert_int_equal(rc, mfp_len); ++ free(current_dir); ++ rc = stat(malicious_file_path, &sb); ++ assert_int_not_equal(rc, 0); ++ ++ // cleanup ++ remove(malicious_file_path); ++ free(malicious_file_path); ++} ++ + int torture_run_tests(void) { + int rc; + struct CMUnitTest tests = { +@@ -181,6 +231,9 @@ int torture_run_tests(void) { + cmocka_unit_test_setup_teardown(torture_options_set_proxycommand_ssh_stderr, + session_setup, + session_teardown), ++ cmocka_unit_test_setup_teardown(torture_options_proxycommand_injection, ++ NULL, ++ session_teardown), + }; + + +-- +2.33.0 +
View file
_service:tar_scm:backport-0008-CVE-2023-6004-torture_misc-Add-test-for-ssh_is_ipadd.patch
Added
@@ -0,0 +1,59 @@ +From 62d3101c1f76b6891b70c50154e0e934d6b8cb57 Mon Sep 17 00:00:00 2001 +From: Norbert Pocs <norbertpocs0@gmail.com> +Date: Mon, 6 Nov 2023 20:11:38 +0100 +Subject: PATCH 08/20 CVE-2023-6004: torture_misc: Add test for ssh_is_ipaddr + +Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +Reviewed-by: Jakub Jelen <jjelen@redhat.com> +--- + tests/unittests/torture_misc.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c +index e682b6d4..b07392ab 100644 +--- a/tests/unittests/torture_misc.c ++++ b/tests/unittests/torture_misc.c +@@ -832,6 +832,31 @@ static void torture_ssh_check_hostname_syntax(void **state) + assert_int_equal(rc, SSH_ERROR); + } + ++static void torture_ssh_is_ipaddr(void **state) { ++ int rc; ++ (void)state; ++ ++ rc = ssh_is_ipaddr("201.255.3.69"); ++ assert_int_equal(rc, 1); ++ rc = ssh_is_ipaddr("::1"); ++ assert_int_equal(rc, 1); ++ rc = ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); ++ assert_int_equal(rc, 1); ++ ++ rc = ssh_is_ipaddr(".."); ++ assert_int_equal(rc, 0); ++ rc = ssh_is_ipaddr(":::"); ++ assert_int_equal(rc, 0); ++ rc = ssh_is_ipaddr("1.1.1.1.1"); ++ assert_int_equal(rc, 0); ++ rc = ssh_is_ipaddr("1.1"); ++ assert_int_equal(rc, 0); ++ rc = ssh_is_ipaddr("caesar"); ++ assert_int_equal(rc, 0); ++ rc = ssh_is_ipaddr("::xa:1"); ++ assert_int_equal(rc, 0); ++} ++ + int torture_run_tests(void) { + int rc; + struct CMUnitTest tests = { +@@ -857,6 +882,7 @@ int torture_run_tests(void) { + cmocka_unit_test(torture_ssh_strreplace), + cmocka_unit_test(torture_ssh_strerror), + cmocka_unit_test(torture_ssh_check_hostname_syntax), ++ cmocka_unit_test(torture_ssh_is_ipaddr), + }; + + ssh_init(); +-- +2.33.0 +
View file
_service:tar_scm:backport-0009-CVE-2023-6004-misc-Add-ipv6-link-local-check-for-an-.patch
Added
@@ -0,0 +1,140 @@ +From cea841d71c025f9c998b7d5fc9f2a2839df62921 Mon Sep 17 00:00:00 2001 +From: Norbert Pocs <norbertpocs0@gmail.com> +Date: Tue, 28 Nov 2023 15:26:45 +0100 +Subject: PATCH 09/20 CVE-2023-6004 misc: Add ipv6 link-local check for an ip + address + +Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +Reviewed-by: Jakub Jelen <jjelen@redhat.com> +--- + src/CMakeLists.txt | 1 + + src/connect.c | 2 +- + src/misc.c | 44 ++++++++++++++++++++++++++++++++++++++------ + 3 files changed, 40 insertions(+), 7 deletions(-) + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index d6245c0d..807313b5 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -91,6 +91,7 @@ endif() + if (WIN32) + set(LIBSSH_LINK_LIBRARIES + ${LIBSSH_LINK_LIBRARIES} ++ iphlpapi + ws2_32 + ) + endif (WIN32) +diff --git a/src/connect.c b/src/connect.c +index 57e37e63..15cae644 100644 +--- a/src/connect.c ++++ b/src/connect.c +@@ -136,7 +136,7 @@ static int getai(const char *host, int port, struct addrinfo **ai) + #endif + } + +- if (ssh_is_ipaddr(host)) { ++ if (ssh_is_ipaddr(host) == 1) { + /* this is an IP address */ + SSH_LOG(SSH_LOG_PACKET, "host %s matches an IP address", host); + hints.ai_flags |= AI_NUMERICHOST; +diff --git a/src/misc.c b/src/misc.c +index be6ee836..7081f12a 100644 +--- a/src/misc.c ++++ b/src/misc.c +@@ -32,6 +32,7 @@ + #include <sys/socket.h> + #include <netinet/in.h> + #include <arpa/inet.h> ++#include <net/if.h> + + #endif /* _WIN32 */ + +@@ -59,6 +60,7 @@ + #include <ws2tcpip.h> + #include <shlobj.h> + #include <direct.h> ++#include <netioapi.h> + + #ifdef HAVE_IO_H + #include <io.h> +@@ -222,22 +224,37 @@ int ssh_is_ipaddr_v4(const char *str) + int ssh_is_ipaddr(const char *str) + { + int rc = SOCKET_ERROR; ++ char *s = strdup(str); + +- if (strchr(str, ':')) { ++ if (s == NULL) { ++ return -1; ++ } ++ if (strchr(s, ':')) { + struct sockaddr_storage ss; + int sslen = sizeof(ss); ++ char *network_interface = strchr(s, '%'); + +- /* TODO link-local (IP:v6:addr%ifname). */ +- rc = WSAStringToAddressA((LPSTR) str, ++ /* link-local (IP:v6:addr%ifname). */ ++ if (network_interface != NULL) { ++ rc = if_nametoindex(network_interface + 1); ++ if (rc == 0) { ++ free(s); ++ return 0; ++ } ++ *network_interface = '\0'; ++ } ++ rc = WSAStringToAddressA((LPSTR) s, + AF_INET6, + NULL, + (struct sockaddr*)&ss, + &sslen); + if (rc == 0) { ++ free(s); + return 1; + } + } + ++ free(s); + return ssh_is_ipaddr_v4(str); + } + #else /* _WIN32 */ +@@ -343,17 +360,32 @@ int ssh_is_ipaddr_v4(const char *str) + int ssh_is_ipaddr(const char *str) + { + int rc = -1; ++ char *s = strdup(str); + +- if (strchr(str, ':')) { ++ if (s == NULL) { ++ return -1; ++ } ++ if (strchr(s, ':')) { + struct in6_addr dest6; ++ char *network_interface = strchr(s, '%'); + +- /* TODO link-local (IP:v6:addr%ifname). */ +- rc = inet_pton(AF_INET6, str, &dest6); ++ /* link-local (IP:v6:addr%ifname). */ ++ if (network_interface != NULL) { ++ rc = if_nametoindex(network_interface + 1); ++ if (rc == 0) { ++ free(s); ++ return 0; ++ } ++ *network_interface = '\0'; ++ } ++ rc = inet_pton(AF_INET6, s, &dest6); + if (rc > 0) { ++ free(s); + return 1; + } + } + ++ free(s); + return ssh_is_ipaddr_v4(str); + } + +-- +2.33.0 +
View file
_service:tar_scm:backport-0010-CVE-2023-6004-torture_misc-Add-tests-for-ipv6-link-l.patch
Added
@@ -0,0 +1,63 @@ +From 2c492ee179d5caa2718c5e768bab6e0b2b64a8b0 Mon Sep 17 00:00:00 2001 +From: Norbert Pocs <norbertpocs0@gmail.com> +Date: Tue, 28 Nov 2023 15:27:31 +0100 +Subject: PATCH 10/20 CVE-2023-6004: torture_misc: Add tests for ipv6 + link-local + +Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +Reviewed-by: Jakub Jelen <jjelen@redhat.com> +--- + tests/unittests/torture_misc.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c +index b07392ab..77166759 100644 +--- a/tests/unittests/torture_misc.c ++++ b/tests/unittests/torture_misc.c +@@ -17,7 +17,14 @@ + #include "torture.h" + #include "error.c" + ++#ifdef _WIN32 ++#include <netioapi.h> ++#else ++#include <net/if.h> ++#endif ++ + #define TORTURE_TEST_DIR "/usr/local/bin/truc/much/.." ++#define TORTURE_IPV6_LOCAL_LINK "fe80::98e1:82ff:fe8d:28b3%%%s" + + const char template = "temp_dir_XXXXXX"; + +@@ -834,14 +841,27 @@ static void torture_ssh_check_hostname_syntax(void **state) + + static void torture_ssh_is_ipaddr(void **state) { + int rc; ++ char *interf = malloc(64); ++ char *test_interf = malloc(128); + (void)state; + ++ assert_non_null(interf); ++ assert_non_null(test_interf); + rc = ssh_is_ipaddr("201.255.3.69"); + assert_int_equal(rc, 1); + rc = ssh_is_ipaddr("::1"); + assert_int_equal(rc, 1); + rc = ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + assert_int_equal(rc, 1); ++ if_indextoname(1, interf); ++ assert_non_null(interf); ++ rc = sprintf(test_interf, TORTURE_IPV6_LOCAL_LINK, interf); ++ /* the "%%s" is not written */ ++ assert_int_equal(rc, strlen(interf) + strlen(TORTURE_IPV6_LOCAL_LINK) - 3); ++ rc = ssh_is_ipaddr(test_interf); ++ assert_int_equal(rc, 1); ++ free(interf); ++ free(test_interf); + + rc = ssh_is_ipaddr(".."); + assert_int_equal(rc, 0); +-- +2.33.0 +
View file
_service:tar_scm:backport-0011-CVE-2023-48795-client-side-mitigation.patch
Added
@@ -0,0 +1,450 @@ +From 4cef5e965a46e9271aed62631b152e4bd23c1e3c Mon Sep 17 00:00:00 2001 +From: Aris Adamantiadis <aris@0xbadc0de.be> +Date: Tue, 12 Dec 2023 23:09:57 +0100 +Subject: PATCH 11/20 CVE-2023-48795: client side mitigation + +Signed-off-by: Aris Adamantiadis <aris@0xbadc0de.be> +Signed-off-by: Jakub Jelen <jjelen@redhat.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +--- + include/libssh/packet.h | 1 + + include/libssh/session.h | 6 +++++ + src/curve25519.c | 19 +++---------- + src/dh-gex.c | 7 +---- + src/dh.c | 17 +++--------- + src/ecdh.c | 8 +----- + src/ecdh_crypto.c | 12 +++------ + src/ecdh_gcrypt.c | 10 +++---- + src/ecdh_mbedcrypto.c | 11 +++----- + src/kex.c | 34 +++++++++++++++++++---- + src/packet.c | 58 ++++++++++++++++++++++++++++++++++++++++ + src/packet_cb.c | 12 +++++++++ + 12 files changed, 126 insertions(+), 69 deletions(-) + +diff --git a/include/libssh/packet.h b/include/libssh/packet.h +index 7f10a709..f0c8cb20 100644 +--- a/include/libssh/packet.h ++++ b/include/libssh/packet.h +@@ -67,6 +67,7 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info); + SSH_PACKET_CALLBACK(ssh_packet_kexdh_init); + #endif + ++int ssh_packet_send_newkeys(ssh_session session); + int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum); + int ssh_packet_parse_type(ssh_session session); + //int packet_flush(ssh_session session, int enforce_blocking); +diff --git a/include/libssh/session.h b/include/libssh/session.h +index eb14e97a..97936195 100644 +--- a/include/libssh/session.h ++++ b/include/libssh/session.h +@@ -81,6 +81,12 @@ enum ssh_pending_call_e { + * sending it twice during key exchange to simplify the state machine. */ + #define SSH_SESSION_FLAG_KEXINIT_SENT 4 + ++/* The current SSH2 session implements the "strict KEX" feature and should behave ++ * differently on SSH2_MSG_NEWKEYS. */ ++#define SSH_SESSION_FLAG_KEX_STRICT 0x0010 ++/* Unexpected packets have been sent while the session was still unencrypted */ ++#define SSH_SESSION_FLAG_KEX_TAINTED 0x0020 ++ + /* codes to use with ssh_handle_packets*() */ + /* Infinite timeout */ + #define SSH_TIMEOUT_INFINITE -1 +diff --git a/src/curve25519.c b/src/curve25519.c +index 66291b5f..4aeb4756 100644 +--- a/src/curve25519.c ++++ b/src/curve25519.c +@@ -335,16 +335,10 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){ + } + + /* Send the MSG_NEWKEYS */ +- if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { +- goto error; +- } +- +- rc=ssh_packet_send(session); ++ rc = ssh_packet_send_newkeys(session); + if (rc == SSH_ERROR) { + goto error; + } +- +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + + return SSH_PACKET_USED; +@@ -502,18 +496,13 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){ + return SSH_ERROR; + } + +- /* Send the MSG_NEWKEYS */ +- rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); +- if (rc < 0) { +- goto error; +- } +- + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; +- rc = ssh_packet_send(session); ++ ++ /* Send the MSG_NEWKEYS */ ++ rc = ssh_packet_send_newkeys(session); + if (rc == SSH_ERROR) { + goto error; + } +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); + + return SSH_PACKET_USED; + error: +diff --git a/src/dh-gex.c b/src/dh-gex.c +index 91617081..642a88ae 100644 +--- a/src/dh-gex.c ++++ b/src/dh-gex.c +@@ -297,15 +297,10 @@ static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply) + } + + /* Send the MSG_NEWKEYS */ +- if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { +- goto error; +- } +- +- rc = ssh_packet_send(session); ++ rc = ssh_packet_send_newkeys(session); + if (rc == SSH_ERROR) { + goto error; + } +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + + return SSH_PACKET_USED; +diff --git a/src/dh.c b/src/dh.c +index 011d97b3..e19e43d1 100644 +--- a/src/dh.c ++++ b/src/dh.c +@@ -398,16 +398,10 @@ SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){ + } + + /* Send the MSG_NEWKEYS */ +- if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { +- goto error; +- } +- +- rc=ssh_packet_send(session); ++ rc = ssh_packet_send_newkeys(session); + if (rc == SSH_ERROR) { + goto error; + } +- +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + return SSH_PACKET_USED; + error: +@@ -551,15 +545,12 @@ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet) + } + SSH_LOG(SSH_LOG_DEBUG, "Sent KEX_DH_GEX_REPLY"); + +- if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { +- ssh_buffer_reinit(session->out_buffer); +- goto error; +- } + session->dh_handshake_state=DH_STATE_NEWKEYS_SENT; +- if (ssh_packet_send(session) == SSH_ERROR) { ++ /* Send the MSG_NEWKEYS */ ++ rc = ssh_packet_send_newkeys(session); ++ if (rc == SSH_ERROR) { + goto error; + } +- SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent"); + + return SSH_OK; + error: +diff --git a/src/ecdh.c b/src/ecdh.c +index e5b11ba9..af80beec 100644 +--- a/src/ecdh.c ++++ b/src/ecdh.c +@@ -93,16 +93,10 @@ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){ + } + + /* Send the MSG_NEWKEYS */ +- if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { +- goto error; +- } +- +- rc=ssh_packet_send(session); ++ rc = ssh_packet_send_newkeys(session); + if (rc == SSH_ERROR) { + goto error; + } +- +- SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; + + return SSH_PACKET_USED; +diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c +index 51084b7a..069b1372 100644 +--- a/src/ecdh_crypto.c ++++ b/src/ecdh_crypto.c +@@ -619,18 +619,12 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ + goto error; + } + +- /* Send the MSG_NEWKEYS */ +- rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); +- if (rc < 0) { +- goto error; +- } +- + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; +- rc = ssh_packet_send(session); +- if (rc == SSH_ERROR){ ++ /* Send the MSG_NEWKEYS */ ++ rc = ssh_packet_send_newkeys(session);
View file
_service:tar_scm:backport-0012-CVE-2023-48795-Server-side-mitigations.patch
Added
@@ -0,0 +1,122 @@ +From 0870c8db28be9eb457ee3d4f9a168959d9507efd Mon Sep 17 00:00:00 2001 +From: Aris Adamantiadis <aris@0xbadc0de.be> +Date: Tue, 12 Dec 2023 23:30:26 +0100 +Subject: PATCH 12/20 CVE-2023-48795: Server side mitigations + +Signed-off-by: Aris Adamantiadis <aris@0xbadc0de.be> +Signed-off-by: Jakub Jelen <jjelen@redhat.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +--- + include/libssh/kex.h | 1 + + src/kex.c | 46 ++++++++++++++++++++++++++++++++++---------- + src/server.c | 8 +++++++- + 3 files changed, 44 insertions(+), 11 deletions(-) + +diff --git a/include/libssh/kex.h b/include/libssh/kex.h +index ede7fa8a..ba98fded 100644 +--- a/include/libssh/kex.h ++++ b/include/libssh/kex.h +@@ -40,6 +40,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit); + int ssh_send_kex(ssh_session session); + void ssh_list_kex(struct ssh_kex_struct *kex); + int ssh_set_client_kex(ssh_session session); ++int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex); + int ssh_kex_select_methods(ssh_session session); + int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name); + char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list); +diff --git a/src/kex.c b/src/kex.c +index 3818297b..9ad671db 100644 +--- a/src/kex.c ++++ b/src/kex.c +@@ -763,11 +763,8 @@ int ssh_set_client_kex(ssh_session session) + { + struct ssh_kex_struct *client = &session->next_crypto->client_kex; + const char *wanted; +- char *kex = NULL; +- char *kex_tmp = NULL; + int ok; + int i; +- size_t kex_len, len; + + /* Skip if already set, for example for the rekey or when we do the guessing + * it could have been already used to make some protocol decisions. */ +@@ -816,11 +813,33 @@ int ssh_set_client_kex(ssh_session session) + return SSH_OK; + } + +- /* Here we append ext-info-c and kex-strict-c-v00@openssh.com to the list of kex algorithms */ +- kex = client->methodsSSH_KEX; ++ ok = ssh_kex_append_extensions(session, client); ++ if (ok != SSH_OK){ ++ return ok; ++ } ++ ++ return SSH_OK; ++} ++ ++int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex) ++{ ++ char *kex = NULL; ++ char *kex_tmp = NULL; ++ size_t kex_len, len; ++ ++ /* Here we append ext-info-c and kex-strict-c-v00@openssh.com for client ++ * and kex-strict-s-v00@openssh.com for server to the list of kex algorithms ++ */ ++ kex = pkex->methodsSSH_KEX; + len = strlen(kex); +- /* Comma, comma, nul byte */ +- kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 + strlen(KEX_STRICT_CLIENT ) + 1; ++ if (session->server) { ++ /* Comma, nul byte */ ++ kex_len = len + 1 + strlen(KEX_STRICT_SERVER) + 1; ++ } else { ++ /* Comma, comma, nul byte */ ++ kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 + ++ strlen(KEX_STRICT_CLIENT) + 1; ++ } + if (kex_len >= MAX_PACKET_LEN) { + /* Overflow */ + return SSH_ERROR; +@@ -830,9 +849,16 @@ int ssh_set_client_kex(ssh_session session) + ssh_set_error_oom(session); + return SSH_ERROR; + } +- snprintf(kex_tmp + len, kex_len - len, ",%s,%s", KEX_EXTENSION_CLIENT, KEX_STRICT_CLIENT); +- client->methodsSSH_KEX = kex_tmp; +- ++ if (session->server){ ++ snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_STRICT_SERVER); ++ } else { ++ snprintf(kex_tmp + len, ++ kex_len - len, ++ ",%s,%s", ++ KEX_EXTENSION_CLIENT, ++ KEX_STRICT_CLIENT); ++ } ++ pkex->methodsSSH_KEX = kex_tmp; + return SSH_OK; + } + +diff --git a/src/server.c b/src/server.c +index dc070a73..70b90899 100644 +--- a/src/server.c ++++ b/src/server.c +@@ -195,7 +195,13 @@ int server_set_kex(ssh_session session) + } + } + +- return 0; ++ /* Do not append the extensions during rekey */ ++ if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) { ++ return SSH_OK; ++ } ++ ++ rc = ssh_kex_append_extensions(session, server); ++ return rc; + } + + int ssh_server_init_kex(ssh_session session) { +-- +2.33.0 +
View file
_service:tar_scm:backport-0013-CVE-2023-48795-Strip-extensions-from-both-kex-lists-.patch
Added
@@ -0,0 +1,43 @@ +From 5846e57538c750c5ce67df887d09fa99861c79c6 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen <jjelen@redhat.com> +Date: Thu, 14 Dec 2023 12:22:01 +0100 +Subject: PATCH 13/20 CVE-2023-48795: Strip extensions from both kex lists + for matching + +Signed-off-by: Jakub Jelen <jjelen@redhat.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +--- + src/kex.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/src/kex.c b/src/kex.c +index 9ad671db..fbc70cf4 100644 +--- a/src/kex.c ++++ b/src/kex.c +@@ -961,11 +961,19 @@ int ssh_kex_select_methods (ssh_session session) + enum ssh_key_exchange_e kex_type; + int i; + +- /* Here we should drop the ext-info-c from the list so we avoid matching. ++ /* Here we should drop the extensions from the list so we avoid matching. + * it. We added it to the end, so we can just truncate the string here */ +- ext_start = strstr(client->methodsSSH_KEX, ","KEX_EXTENSION_CLIENT); +- if (ext_start != NULL) { +- ext_start0 = '\0'; ++ if (session->client) { ++ ext_start = strstr(client->methodsSSH_KEX, "," KEX_EXTENSION_CLIENT); ++ if (ext_start != NULL) { ++ ext_start0 = '\0'; ++ } ++ } ++ if (session->server) { ++ ext_start = strstr(server->methodsSSH_KEX, "," KEX_STRICT_SERVER); ++ if (ext_start != NULL) { ++ ext_start0 = '\0'; ++ } + } + + for (i = 0; i < SSH_KEX_METHODS; i++) { +-- +2.33.0 +
View file
_service:tar_scm:backport-0014-CVE-2023-48795-tests-Adjust-calculation-to-strict-ke.patch
Added
@@ -0,0 +1,105 @@ +From 89df759200d31fc79fbbe213d8eda0d329eebf6d Mon Sep 17 00:00:00 2001 +From: Jakub Jelen <jjelen@redhat.com> +Date: Thu, 14 Dec 2023 12:47:48 +0100 +Subject: PATCH 14/20 CVE-2023-48795: tests: Adjust calculation to strict kex + +Signed-off-by: Jakub Jelen <jjelen@redhat.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +--- + tests/client/torture_rekey.c | 55 ++++++++++++++++++++---------------- + 1 file changed, 31 insertions(+), 24 deletions(-) + +diff --git a/tests/client/torture_rekey.c b/tests/client/torture_rekey.c +index ccd5ae2c..57e03e3f 100644 +--- a/tests/client/torture_rekey.c ++++ b/tests/client/torture_rekey.c +@@ -148,6 +148,29 @@ static void torture_rekey_default(void **state) + ssh_disconnect(s->ssh.session); + } + ++static void sanity_check_session(void **state) ++{ ++ struct torture_state *s = *state; ++ struct ssh_crypto_struct *c = NULL; ++ ++ c = s->ssh.session->current_crypto; ++ assert_non_null(c); ++ assert_int_equal(c->in_cipher->max_blocks, ++ bytes / c->in_cipher->blocksize); ++ assert_int_equal(c->out_cipher->max_blocks, ++ bytes / c->out_cipher->blocksize); ++ /* when strict kex is used, the newkeys reset the sequence number */ ++ if ((s->ssh.session->flags & SSH_SESSION_FLAG_KEX_STRICT) != 0) { ++ assert_int_equal(c->out_cipher->packets, s->ssh.session->send_seq); ++ assert_int_equal(c->in_cipher->packets, s->ssh.session->recv_seq); ++ } else { ++ /* Otherwise we have less encrypted packets than transferred ++ * (first are not encrypted) */ ++ assert_true(c->out_cipher->packets < s->ssh.session->send_seq); ++ assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); ++ } ++} ++ + /* We lower the rekey limits manually and check that the rekey + * really happens when sending data + */ +@@ -166,16 +189,10 @@ static void torture_rekey_send(void **state) + rc = ssh_connect(s->ssh.session); + assert_ssh_return_code(s->ssh.session, rc); + +- /* The blocks limit is set correctly */ +- c = s->ssh.session->current_crypto; +- assert_int_equal(c->in_cipher->max_blocks, +- bytes / c->in_cipher->blocksize); +- assert_int_equal(c->out_cipher->max_blocks, +- bytes / c->out_cipher->blocksize); +- /* We should have less encrypted packets than transferred (first are not encrypted) */ +- assert_true(c->out_cipher->packets < s->ssh.session->send_seq); +- assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); ++ sanity_check_session(state); + /* Copy the initial secret hash = session_id so we know we changed keys later */ ++ c = s->ssh.session->current_crypto; ++ assert_non_null(c); + secret_hash = malloc(c->digest_len); + assert_non_null(secret_hash); + memcpy(secret_hash, c->secret_hash, c->digest_len); +@@ -273,15 +290,10 @@ static void torture_rekey_recv(void **state) + mode_t mask; + int rc; + +- /* The blocks limit is set correctly */ ++ sanity_check_session(state); ++ /* Copy the initial secret hash = session_id so we know we changed keys later */ + c = s->ssh.session->current_crypto; + assert_non_null(c); +- assert_int_equal(c->in_cipher->max_blocks, bytes / c->in_cipher->blocksize); +- assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize); +- /* We should have less encrypted packets than transferred (first are not encrypted) */ +- assert_true(c->out_cipher->packets < s->ssh.session->send_seq); +- assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); +- /* Copy the initial secret hash = session_id so we know we changed keys later */ + secret_hash = malloc(c->digest_len); + assert_non_null(secret_hash); + memcpy(secret_hash, c->secret_hash, c->digest_len); +@@ -468,15 +480,10 @@ static void torture_rekey_different_kex(void **state) + assert_ssh_return_code(s->ssh.session, rc); + + /* The blocks limit is set correctly */ +- c = s->ssh.session->current_crypto; +- assert_int_equal(c->in_cipher->max_blocks, +- bytes / c->in_cipher->blocksize); +- assert_int_equal(c->out_cipher->max_blocks, +- bytes / c->out_cipher->blocksize); +- /* We should have less encrypted packets than transferred (first are not encrypted) */ +- assert_true(c->out_cipher->packets < s->ssh.session->send_seq); +- assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); ++ sanity_check_session(state); + /* Copy the initial secret hash = session_id so we know we changed keys later */ ++ c = s->ssh.session->current_crypto; ++ assert_non_null(c); + secret_hash = malloc(c->digest_len); + assert_non_null(secret_hash); + memcpy(secret_hash, c->secret_hash, c->digest_len); +-- +2.33.0 +
View file
_service:tar_scm:backport-0015-CVE-2023-6918-kdf-Reformat.patch
Added
@@ -0,0 +1,72 @@ +From 610d7a09f99c601224ae2aa3d3de7e75b1d284dd Mon Sep 17 00:00:00 2001 +From: Jakub Jelen <jjelen@redhat.com> +Date: Fri, 15 Dec 2023 10:30:09 +0100 +Subject: PATCH 15/20 CVE-2023-6918: kdf: Reformat + +Signed-off-by: Jakub Jelen <jjelen@redhat.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +--- + src/kdf.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/src/kdf.c b/src/kdf.c +index 44f06631..987ae972 100644 +--- a/src/kdf.c ++++ b/src/kdf.c +@@ -58,7 +58,7 @@ static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type) + } + + ctx->digest_type = type; +- switch(type){ ++ switch (type) { + case SSH_KDF_SHA1: + ctx->ctx.sha1_ctx = sha1_init(); + return ctx; +@@ -79,7 +79,7 @@ static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type) + + static void ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len) + { +- switch(ctx->digest_type){ ++ switch (ctx->digest_type) { + case SSH_KDF_SHA1: + sha1_update(ctx->ctx.sha1_ctx, data, len); + break; +@@ -97,26 +97,28 @@ static void ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len) + + static void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) + { +- switch(ctx->digest_type){ ++ switch (ctx->digest_type) { + case SSH_KDF_SHA1: +- sha1_final(md,ctx->ctx.sha1_ctx); ++ sha1_final(md, ctx->ctx.sha1_ctx); + break; + case SSH_KDF_SHA256: +- sha256_final(md,ctx->ctx.sha256_ctx); ++ sha256_final(md, ctx->ctx.sha256_ctx); + break; + case SSH_KDF_SHA384: +- sha384_final(md,ctx->ctx.sha384_ctx); ++ sha384_final(md, ctx->ctx.sha384_ctx); + break; + case SSH_KDF_SHA512: +- sha512_final(md,ctx->ctx.sha512_ctx); ++ sha512_final(md, ctx->ctx.sha512_ctx); + break; + } + SAFE_FREE(ctx); + } + + int sshkdf_derive_key(struct ssh_crypto_struct *crypto, +- unsigned char *key, size_t key_len, +- uint8_t key_type, unsigned char *output, ++ unsigned char *key, ++ size_t key_len, ++ uint8_t key_type, ++ unsigned char *output, + size_t requested_len) + { + /* Can't use VLAs with Visual Studio, so allocate the biggest +-- +2.33.0 +
View file
_service:tar_scm:backport-0016-CVE-2023-6918-Remove-unused-evp-functions-and-types.patch
Added
@@ -0,0 +1,289 @@ +From 63ff242131c8e6d98917456f71f6d33b9ef3a763 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen <jjelen@redhat.com> +Date: Fri, 15 Dec 2023 12:55:27 +0100 +Subject: PATCH 16/20 CVE-2023-6918: Remove unused evp functions and types + +Signed-off-by: Jakub Jelen <jjelen@redhat.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +--- + include/libssh/libcrypto.h | 5 --- + include/libssh/libgcrypt.h | 1 - + include/libssh/libmbedcrypto.h | 1 - + include/libssh/wrapper.h | 4 -- + src/libcrypto.c | 54 ------------------------- + src/libgcrypt.c | 53 ------------------------ + src/libmbedcrypto.c | 74 ---------------------------------- + 7 files changed, 192 deletions(-) + +diff --git a/include/libssh/libcrypto.h b/include/libssh/libcrypto.h +index 16e5f98f..87f30a4d 100644 +--- a/include/libssh/libcrypto.h ++++ b/include/libssh/libcrypto.h +@@ -39,11 +39,6 @@ typedef EVP_MD_CTX* SHA384CTX; + typedef EVP_MD_CTX* SHA512CTX; + typedef EVP_MD_CTX* MD5CTX; + typedef EVP_MD_CTX* HMACCTX; +-#ifdef HAVE_ECC +-typedef EVP_MD_CTX *EVPCTX; +-#else +-typedef void *EVPCTX; +-#endif + + #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH + #define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH +diff --git a/include/libssh/libgcrypt.h b/include/libssh/libgcrypt.h +index e4087fd2..c6afc22e 100644 +--- a/include/libssh/libgcrypt.h ++++ b/include/libssh/libgcrypt.h +@@ -32,7 +32,6 @@ typedef gcry_md_hd_t SHA384CTX; + typedef gcry_md_hd_t SHA512CTX; + typedef gcry_md_hd_t MD5CTX; + typedef gcry_md_hd_t HMACCTX; +-typedef gcry_md_hd_t EVPCTX; + #define SHA_DIGEST_LENGTH 20 + #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH + #define MD5_DIGEST_LEN 16 +diff --git a/include/libssh/libmbedcrypto.h b/include/libssh/libmbedcrypto.h +index e6fc393c..540a025b 100644 +--- a/include/libssh/libmbedcrypto.h ++++ b/include/libssh/libmbedcrypto.h +@@ -41,7 +41,6 @@ typedef mbedtls_md_context_t *SHA384CTX; + typedef mbedtls_md_context_t *SHA512CTX; + typedef mbedtls_md_context_t *MD5CTX; + typedef mbedtls_md_context_t *HMACCTX; +-typedef mbedtls_md_context_t *EVPCTX; + + #define SHA_DIGEST_LENGTH 20 + #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH +diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h +index 36589cff..07e64018 100644 +--- a/include/libssh/wrapper.h ++++ b/include/libssh/wrapper.h +@@ -95,10 +95,6 @@ void sha512_update(SHA512CTX c, const void *data, size_t len); + void sha512_final(unsigned char *md,SHA512CTX c); + void sha512(const unsigned char *digest, size_t len, unsigned char *hash); + +-void evp(int nid, unsigned char *digest, size_t len, unsigned char *hash, unsigned int *hlen); +-EVPCTX evp_init(int nid); +-void evp_update(EVPCTX ctx, const void *data, size_t len); +-void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen); + + HMACCTX hmac_init(const void *key,size_t len, enum ssh_hmac_e type); + int hmac_update(HMACCTX c, const void *data, size_t len); +diff --git a/src/libcrypto.c b/src/libcrypto.c +index ebdca6e0..4f945d90 100644 +--- a/src/libcrypto.c ++++ b/src/libcrypto.c +@@ -125,60 +125,6 @@ ENGINE *pki_get_engine(void) + return engine; + } + +-#ifdef HAVE_OPENSSL_ECC +-static const EVP_MD *nid_to_evpmd(int nid) +-{ +- switch (nid) { +- case NID_X9_62_prime256v1: +- return EVP_sha256(); +- case NID_secp384r1: +- return EVP_sha384(); +- case NID_secp521r1: +- return EVP_sha512(); +- default: +- return NULL; +- } +- +- return NULL; +-} +- +-void evp(int nid, unsigned char *digest, size_t len, unsigned char *hash, unsigned int *hlen) +-{ +- const EVP_MD *evp_md = nid_to_evpmd(nid); +- EVP_MD_CTX *md = EVP_MD_CTX_new(); +- +- EVP_DigestInit(md, evp_md); +- EVP_DigestUpdate(md, digest, len); +- EVP_DigestFinal(md, hash, hlen); +- EVP_MD_CTX_free(md); +-} +- +-EVPCTX evp_init(int nid) +-{ +- const EVP_MD *evp_md = nid_to_evpmd(nid); +- +- EVPCTX ctx = EVP_MD_CTX_new(); +- if (ctx == NULL) { +- return NULL; +- } +- +- EVP_DigestInit(ctx, evp_md); +- +- return ctx; +-} +- +-void evp_update(EVPCTX ctx, const void *data, size_t len) +-{ +- EVP_DigestUpdate(ctx, data, len); +-} +- +-void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) +-{ +- EVP_DigestFinal(ctx, md, mdlen); +- EVP_MD_CTX_free(ctx); +-} +-#endif /* HAVE_OPENSSL_ECC */ +- + #ifdef HAVE_OPENSSL_EVP_KDF_CTX + #if OPENSSL_VERSION_NUMBER < 0x30000000L + static const EVP_MD *sshkdf_digest_to_md(enum ssh_kdf_digest digest_type) +diff --git a/src/libgcrypt.c b/src/libgcrypt.c +index 2e44a53c..f410d997 100644 +--- a/src/libgcrypt.c ++++ b/src/libgcrypt.c +@@ -69,59 +69,6 @@ static int alloc_key(struct ssh_cipher_struct *cipher) { + void ssh_reseed(void){ + } + +-#ifdef HAVE_GCRYPT_ECC +-static int nid_to_md_algo(int nid) +-{ +- switch (nid) { +- case NID_gcrypt_nistp256: +- return GCRY_MD_SHA256; +- case NID_gcrypt_nistp384: +- return GCRY_MD_SHA384; +- case NID_gcrypt_nistp521: +- return GCRY_MD_SHA512; +- } +- return GCRY_MD_NONE; +-} +- +-void evp(int nid, unsigned char *digest, size_t len, +- unsigned char *hash, unsigned int *hlen) +-{ +- int algo = nid_to_md_algo(nid); +- +- /* Note: What gcrypt calls 'hash' is called 'digest' here and +- vice-versa. */ +- gcry_md_hash_buffer(algo, hash, digest, len); +- *hlen = gcry_md_get_algo_dlen(algo); +-} +- +-EVPCTX evp_init(int nid) +-{ +- gcry_error_t err; +- int algo = nid_to_md_algo(nid); +- EVPCTX ctx; +- +- err = gcry_md_open(&ctx, algo, 0); +- if (err) { +- return NULL; +- } +- +- return ctx; +-} +- +-void evp_update(EVPCTX ctx, const void *data, size_t len) +-{ +- gcry_md_write(ctx, data, len); +-} +- +-void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) +-{ +- int algo = gcry_md_get_algo(ctx); +- *mdlen = gcry_md_get_algo_dlen(algo); +- memcpy(md, gcry_md_read(ctx, algo), *mdlen); +- gcry_md_close(ctx); +-} +-#endif +- + int ssh_kdf(struct ssh_crypto_struct *crypto,
View file
_service:tar_scm:backport-0017-CVE-2023-6918-Systematically-check-return-values-whe.patch
Added
@@ -0,0 +1,1094 @@ +From 8b66d037d575e5f3ce4d35964547ff8c7e75ff8e Mon Sep 17 00:00:00 2001 +From: Jakub Jelen <jjelen@redhat.com> +Date: Fri, 15 Dec 2023 12:55:54 +0100 +Subject: PATCH 17/20 CVE-2023-6918: Systematically check return values when + calculating digests + +with all crypto backends + +Signed-off-by: Jakub Jelen <jjelen@redhat.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +--- + include/libssh/wrapper.h | 34 ++++---- + src/kdf.c | 96 ++++++++++++++++++----- + src/md_crypto.c | 161 ++++++++++++++++++++++++++++++-------- + src/md_gcrypt.c | 107 +++++++++++++++++++++---- + src/md_mbedcrypto.c | 165 +++++++++++++++++++++++++++++++-------- + src/session.c | 72 ++++++++++++----- + 6 files changed, 504 insertions(+), 131 deletions(-) + +diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h +index 07e64018..b3e28eac 100644 +--- a/include/libssh/wrapper.h ++++ b/include/libssh/wrapper.h +@@ -72,29 +72,33 @@ struct ssh_crypto_struct; + + typedef struct ssh_mac_ctx_struct *ssh_mac_ctx; + MD5CTX md5_init(void); +-void md5_update(MD5CTX c, const void *data, size_t len); +-void md5_final(unsigned char *md,MD5CTX c); ++void md5_ctx_free(MD5CTX); ++int md5_update(MD5CTX c, const void *data, size_t len); ++int md5_final(unsigned char *md, MD5CTX c); + + SHACTX sha1_init(void); +-void sha1_update(SHACTX c, const void *data, size_t len); +-void sha1_final(unsigned char *md,SHACTX c); +-void sha1(const unsigned char *digest,size_t len,unsigned char *hash); ++void sha1_ctx_free(SHACTX); ++int sha1_update(SHACTX c, const void *data, size_t len); ++int sha1_final(unsigned char *md,SHACTX c); ++int sha1(const unsigned char *digest,size_t len, unsigned char *hash); + + SHA256CTX sha256_init(void); +-void sha256_update(SHA256CTX c, const void *data, size_t len); +-void sha256_final(unsigned char *md,SHA256CTX c); +-void sha256(const unsigned char *digest, size_t len, unsigned char *hash); ++void sha256_ctx_free(SHA256CTX); ++int sha256_update(SHA256CTX c, const void *data, size_t len); ++int sha256_final(unsigned char *md,SHA256CTX c); ++int sha256(const unsigned char *digest, size_t len, unsigned char *hash); + + SHA384CTX sha384_init(void); +-void sha384_update(SHA384CTX c, const void *data, size_t len); +-void sha384_final(unsigned char *md,SHA384CTX c); +-void sha384(const unsigned char *digest, size_t len, unsigned char *hash); ++void sha384_ctx_free(SHA384CTX); ++int sha384_update(SHA384CTX c, const void *data, size_t len); ++int sha384_final(unsigned char *md,SHA384CTX c); ++int sha384(const unsigned char *digest, size_t len, unsigned char *hash); + + SHA512CTX sha512_init(void); +-void sha512_update(SHA512CTX c, const void *data, size_t len); +-void sha512_final(unsigned char *md,SHA512CTX c); +-void sha512(const unsigned char *digest, size_t len, unsigned char *hash); +- ++void sha512_ctx_free(SHA512CTX); ++int sha512_update(SHA512CTX c, const void *data, size_t len); ++int sha512_final(unsigned char *md,SHA512CTX c); ++int sha512(const unsigned char *digest, size_t len, unsigned char *hash); + + HMACCTX hmac_init(const void *key,size_t len, enum ssh_hmac_e type); + int hmac_update(HMACCTX c, const void *data, size_t len); +diff --git a/src/kdf.c b/src/kdf.c +index 987ae972..a8e534e5 100644 +--- a/src/kdf.c ++++ b/src/kdf.c +@@ -77,41 +77,64 @@ static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type) + } + } + +-static void ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len) ++static void ssh_mac_ctx_free(ssh_mac_ctx ctx) + { ++ if (ctx == NULL) { ++ return; ++ } ++ + switch (ctx->digest_type) { + case SSH_KDF_SHA1: +- sha1_update(ctx->ctx.sha1_ctx, data, len); ++ sha1_ctx_free(ctx->ctx.sha1_ctx); + break; + case SSH_KDF_SHA256: +- sha256_update(ctx->ctx.sha256_ctx, data, len); ++ sha256_ctx_free(ctx->ctx.sha256_ctx); + break; + case SSH_KDF_SHA384: +- sha384_update(ctx->ctx.sha384_ctx, data, len); ++ sha384_ctx_free(ctx->ctx.sha384_ctx); + break; + case SSH_KDF_SHA512: +- sha512_update(ctx->ctx.sha512_ctx, data, len); ++ sha512_ctx_free(ctx->ctx.sha512_ctx); + break; + } ++ SAFE_FREE(ctx); ++} ++ ++static int ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len) ++{ ++ switch (ctx->digest_type) { ++ case SSH_KDF_SHA1: ++ return sha1_update(ctx->ctx.sha1_ctx, data, len); ++ case SSH_KDF_SHA256: ++ return sha256_update(ctx->ctx.sha256_ctx, data, len); ++ case SSH_KDF_SHA384: ++ return sha384_update(ctx->ctx.sha384_ctx, data, len); ++ case SSH_KDF_SHA512: ++ return sha512_update(ctx->ctx.sha512_ctx, data, len); ++ } ++ return SSH_ERROR; + } + +-static void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) ++static int ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) + { ++ int rc = SSH_ERROR; ++ + switch (ctx->digest_type) { + case SSH_KDF_SHA1: +- sha1_final(md, ctx->ctx.sha1_ctx); ++ rc = sha1_final(md, ctx->ctx.sha1_ctx); + break; + case SSH_KDF_SHA256: +- sha256_final(md, ctx->ctx.sha256_ctx); ++ rc = sha256_final(md, ctx->ctx.sha256_ctx); + break; + case SSH_KDF_SHA384: +- sha384_final(md, ctx->ctx.sha384_ctx); ++ rc = sha384_final(md, ctx->ctx.sha384_ctx); + break; + case SSH_KDF_SHA512: +- sha512_final(md, ctx->ctx.sha512_ctx); ++ rc = sha512_final(md, ctx->ctx.sha512_ctx); + break; + } + SAFE_FREE(ctx); ++ return rc; + } + + int sshkdf_derive_key(struct ssh_crypto_struct *crypto, +@@ -126,6 +149,7 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, + unsigned char digestDIGEST_MAX_LEN; + size_t output_len = crypto->digest_len; + ssh_mac_ctx ctx; ++ int rc; + + if (DIGEST_MAX_LEN < crypto->digest_len) { + return -1; +@@ -136,11 +160,30 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, + return -1; + } + +- ssh_mac_update(ctx, key, key_len); +- ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); +- ssh_mac_update(ctx, &key_type, 1); +- ssh_mac_update(ctx, crypto->session_id, crypto->session_id_len); +- ssh_mac_final(digest, ctx); ++ rc = ssh_mac_update(ctx, key, key_len); ++ if (rc != SSH_OK) { ++ ssh_mac_ctx_free(ctx); ++ return -1; ++ } ++ rc = ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); ++ if (rc != SSH_OK) { ++ ssh_mac_ctx_free(ctx); ++ return -1; ++ } ++ rc = ssh_mac_update(ctx, &key_type, 1); ++ if (rc != SSH_OK) { ++ ssh_mac_ctx_free(ctx); ++ return -1; ++ } ++ rc = ssh_mac_update(ctx, crypto->session_id, crypto->session_id_len); ++ if (rc != SSH_OK) { ++ ssh_mac_ctx_free(ctx); ++ return -1; ++ } ++ rc = ssh_mac_final(digest, ctx); ++ if (rc != SSH_OK) { ++ return -1; ++ } + + if (requested_len < output_len) { + output_len = requested_len; +@@ -152,10 +195,25 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, + if (ctx == NULL) { + return -1; + }
View file
_service:tar_scm:backport-0018-CVE-2023-6918-kdf-Detect-context-init-failures.patch
Added
@@ -0,0 +1,54 @@ +From 8977e246b6d7ae467cab008a49e0a9e3d84bc2a0 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen <jjelen@redhat.com> +Date: Fri, 15 Dec 2023 13:35:14 +0100 +Subject: PATCH 18/20 CVE-2023-6918: kdf: Detect context init failures + +Signed-off-by: Jakub Jelen <jjelen@redhat.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +--- + src/kdf.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/src/kdf.c b/src/kdf.c +index a8e534e5..6bc477ce 100644 +--- a/src/kdf.c ++++ b/src/kdf.c +@@ -61,20 +61,32 @@ static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type) + switch (type) { + case SSH_KDF_SHA1: + ctx->ctx.sha1_ctx = sha1_init(); ++ if (ctx->ctx.sha1_ctx == NULL) { ++ goto err; ++ } + return ctx; + case SSH_KDF_SHA256: + ctx->ctx.sha256_ctx = sha256_init(); ++ if (ctx->ctx.sha256_ctx == NULL) { ++ goto err; ++ } + return ctx; + case SSH_KDF_SHA384: + ctx->ctx.sha384_ctx = sha384_init(); ++ if (ctx->ctx.sha384_ctx == NULL) { ++ goto err; ++ } + return ctx; + case SSH_KDF_SHA512: + ctx->ctx.sha512_ctx = sha512_init(); ++ if (ctx->ctx.sha512_ctx == NULL) { ++ goto err; ++ } + return ctx; +- default: +- SAFE_FREE(ctx); +- return NULL; + } ++err: ++ SAFE_FREE(ctx); ++ return NULL; + } + + static void ssh_mac_ctx_free(ssh_mac_ctx ctx) +-- +2.33.0 +
View file
_service:tar_scm:backport-0019-CVE-2023-6918-tests-Code-coverage-for-ssh_get_pubkey.patch
Added
@@ -0,0 +1,68 @@ +From 622421018b58392ffecc29726b947e089b678221 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen <jjelen@redhat.com> +Date: Fri, 15 Dec 2023 15:39:12 +0100 +Subject: PATCH 19/20 CVE-2023-6918: tests: Code coverage for + ssh_get_pubkey_hash() + +Signed-off-by: Jakub Jelen <jjelen@redhat.com> +Reviewed-by: Andreas Schneider <asn@cryptomilk.org> +--- + tests/client/torture_session.c | 35 ++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/tests/client/torture_session.c b/tests/client/torture_session.c +index 27e8fc86..c437d421 100644 +--- a/tests/client/torture_session.c ++++ b/tests/client/torture_session.c +@@ -391,6 +391,38 @@ static void torture_freed_channel_get_exit_status(void **state) + assert_ssh_return_code_equal(session, rc, SSH_ERROR); + } + ++static void torture_pubkey_hash(void **state) ++{ ++ struct torture_state *s = *state; ++ ssh_session session = s->ssh.session; ++ char *hash = NULL; ++ char *hexa = NULL; ++ int rc = 0; ++ ++ /* bad arguments */ ++ rc = ssh_get_pubkey_hash(session, NULL); ++ assert_int_equal(rc, SSH_ERROR); ++ ++ rc = ssh_get_pubkey_hash(NULL, (unsigned char **)&hash); ++ assert_int_equal(rc, SSH_ERROR); ++ ++ /* deprecated, but should be covered by tests! */ ++ rc = ssh_get_pubkey_hash(session, (unsigned char **)&hash); ++ if (ssh_fips_mode()) { ++ /* When in FIPS mode, expect the call to fail */ ++ assert_int_equal(rc, SSH_ERROR); ++ } else { ++ assert_int_equal(rc, MD5_DIGEST_LEN); ++ ++ hexa = ssh_get_hexa((unsigned char *)hash, rc); ++ SSH_STRING_FREE_CHAR(hash); ++ assert_string_equal(hexa, ++ "ee:80:7f:61:f9:d5:be:f1:96:86:cc:96:7a:db:7a:7b"); ++ ++ SSH_STRING_FREE_CHAR(hexa); ++ } ++} ++ + int torture_run_tests(void) { + int rc; + struct CMUnitTest tests = { +@@ -421,6 +453,9 @@ int torture_run_tests(void) { + cmocka_unit_test_setup_teardown(torture_freed_channel_get_exit_status, + session_setup, + session_teardown), ++ cmocka_unit_test_setup_teardown(torture_pubkey_hash, ++ session_setup, ++ session_teardown), + }; + + ssh_init(); +-- +2.33.0 +
View file
_service
Changed
@@ -2,7 +2,7 @@ <service name="tar_scm"> <param name="url">git@gitee.com:src-openeuler/libssh.git</param> <param name="scm">git</param> - <param name="revision">openEuler-23.09</param> + <param name="revision">master</param> <param name="exclude">*</param> <param name="extract">*</param> </service>
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2