Merge pull request !1 from Anonymous_Z/anonymous_z
This commit is contained in:
openeuler-ci-bot 2020-01-12 13:03:40 +08:00 committed by Gitee
commit a05e81132c
6 changed files with 1970 additions and 1 deletions

1390
0001-CVE-2019-14889.patch Normal file

File diff suppressed because it is too large Load Diff

169
0002-CVE-2019-14889.patch Normal file
View File

@ -0,0 +1,169 @@
From 82c375b7c99141a5495e62060e0b7f9c97981e7e Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Fri, 25 Oct 2019 13:24:28 +0200
Subject: CVE-2019-14889: scp: Log SCP warnings received from the server
Fixes T181
Previously, warnings received from the server were ignored. With this
change the warning message sent by the server will be logged.
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c75d417d06867fd792b788e6281334621c2cd335)
---
src/scp.c | 75 ++++++++++-----------------------------------------------------
1 file changed, 11 insertions(+), 64 deletions(-)
diff --git a/src/scp.c b/src/scp.c
index 5de0e6ff..166f3d2f 100644
--- a/src/scp.c
+++ b/src/scp.c
@@ -113,7 +113,6 @@ int ssh_scp_init(ssh_scp scp)
{
int rc;
char execbuffer[1024] = {0};
- uint8_t code;
if (scp == NULL) {
return SSH_ERROR;
@@ -157,19 +156,8 @@ int ssh_scp_init(ssh_scp scp)
}
if (scp->mode == SSH_SCP_WRITE) {
- rc = ssh_channel_read(scp->channel, &code, 1, 0);
- if (rc <= 0) {
- ssh_set_error(scp->session, SSH_FATAL,
- "Error reading status code: %s",
- ssh_get_error(scp->session));
- scp->state = SSH_SCP_ERROR;
- return SSH_ERROR;
- }
-
- if (code != 0) {
- ssh_set_error(scp->session, SSH_FATAL,
- "scp status code %ud not valid", code);
- scp->state = SSH_SCP_ERROR;
+ rc = ssh_scp_response(scp, NULL);
+ if (rc != 0) {
return SSH_ERROR;
}
} else {
@@ -277,7 +265,6 @@ int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode)
{
char buffer[1024] = {0};
int rc;
- uint8_t code;
char *dir = NULL;
char *perms = NULL;
@@ -303,19 +290,8 @@ int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode)
return SSH_ERROR;
}
- rc = ssh_channel_read(scp->channel, &code, 1, 0);
- if (rc <= 0) {
- ssh_set_error(scp->session, SSH_FATAL,
- "Error reading status code: %s",
- ssh_get_error(scp->session));
- scp->state = SSH_SCP_ERROR;
- return SSH_ERROR;
- }
-
- if (code != 0) {
- ssh_set_error(scp->session, SSH_FATAL, "scp status code %ud not valid",
- code);
- scp->state = SSH_SCP_ERROR;
+ rc = ssh_scp_response(scp, NULL);
+ if (rc != 0) {
return SSH_ERROR;
}
@@ -334,7 +310,6 @@ int ssh_scp_leave_directory(ssh_scp scp)
{
char buffer[] = "E\n";
int rc;
- uint8_t code;
if (scp == NULL) {
return SSH_ERROR;
@@ -352,18 +327,8 @@ int ssh_scp_leave_directory(ssh_scp scp)
return SSH_ERROR;
}
- rc = ssh_channel_read(scp->channel, &code, 1, 0);
- if (rc <= 0) {
- ssh_set_error(scp->session, SSH_FATAL, "Error reading status code: %s",
- ssh_get_error(scp->session));
- scp->state = SSH_SCP_ERROR;
- return SSH_ERROR;
- }
-
- if (code != 0) {
- ssh_set_error(scp->session, SSH_FATAL, "scp status code %ud not valid",
- code);
- scp->state = SSH_SCP_ERROR;
+ rc = ssh_scp_response(scp, NULL);
+ if (rc != 0) {
return SSH_ERROR;
}
@@ -395,7 +360,6 @@ int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size,
int rc;
char *file = NULL;
char *perms = NULL;
- uint8_t code;
if (scp == NULL) {
return SSH_ERROR;
@@ -422,19 +386,8 @@ int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size,
return SSH_ERROR;
}
- rc = ssh_channel_read(scp->channel, &code, 1, 0);
- if (rc <= 0) {
- ssh_set_error(scp->session, SSH_FATAL,
- "Error reading status code: %s",
- ssh_get_error(scp->session));
- scp->state = SSH_SCP_ERROR;
- return SSH_ERROR;
- }
-
- if (code != 0) {
- ssh_set_error(scp->session, SSH_FATAL,
- "scp status code %ud not valid", code);
- scp->state = SSH_SCP_ERROR;
+ rc = ssh_scp_response(scp, NULL);
+ if (rc != 0) {
return SSH_ERROR;
}
@@ -498,7 +451,7 @@ int ssh_scp_response(ssh_scp scp, char **response)
if (code > 2) {
ssh_set_error(scp->session, SSH_FATAL,
- "SCP: invalid status code %ud received", code);
+ "SCP: invalid status code %u received", code);
scp->state = SSH_SCP_ERROR;
return SSH_ERROR;
}
@@ -585,14 +538,8 @@ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len)
* and handle */
rc = ssh_channel_poll(scp->channel, 0);
if (rc > 0) {
- rc = ssh_channel_read(scp->channel, &code, 1, 0);
- if (rc == SSH_ERROR) {
- return SSH_ERROR;
- }
-
- if (code == 1 || code == 2) {
- ssh_set_error(scp->session, SSH_REQUEST_DENIED,
- "SCP: Error: status code %i received", code);
+ rc = ssh_scp_response(scp, NULL);
+ if (rc != 0) {
return SSH_ERROR;
}
}
--
cgit v1.2.1

238
0003-CVE-2019-14889.patch Normal file
View File

@ -0,0 +1,238 @@
From 2ba1dea5493fb2f5a5be2dd263ce46ccb5f8ec76 Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Tue, 22 Oct 2019 16:08:24 +0200
Subject: CVE-2019-14889: misc: Add function to quote file names
The added function quote file names strings to be used in a shell.
Special cases are treated for the charactes '\'' and '!'.
Fixes T181
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c4ad1aba9860e02fe03ef3f58a047964e9e765fc)
---
include/libssh/misc.h | 8 +++
src/misc.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 192 insertions(+)
diff --git a/include/libssh/misc.h b/include/libssh/misc.h
index bc50cff8..0531d4f3 100644
--- a/include/libssh/misc.h
+++ b/include/libssh/misc.h
@@ -50,6 +50,12 @@ struct ssh_timestamp {
long useconds;
};
+enum ssh_quote_state_e {
+ NO_QUOTE,
+ SINGLE_QUOTE,
+ DOUBLE_QUOTE
+};
+
struct ssh_list *ssh_list_new(void);
void ssh_list_free(struct ssh_list *list);
struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list);
@@ -81,4 +87,6 @@ int ssh_timeout_update(struct ssh_timestamp *ts, int timeout);
int ssh_match_group(const char *group, const char *object);
+int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len);
+
#endif /* MISC_H_ */
diff --git a/src/misc.c b/src/misc.c
index 18c9745e..b042b46d 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1108,4 +1108,188 @@ char *strndup(const char *s, size_t n)
}
#endif /* ! HAVE_STRNDUP */
+/**
+ * @internal
+ *
+ * @brief Quote file name to be used on shell.
+ *
+ * Try to put the given file name between single quotes. There are special
+ * cases:
+ *
+ * - When the '\'' char is found in the file name, it is double quoted
+ * - example:
+ * input: a'b
+ * output: 'a'"'"'b'
+ * - When the '!' char is found in the file name, it is replaced by an unquoted
+ * verbatim char "\!"
+ * - example:
+ * input: a!b
+ * output 'a'\!'b'
+ *
+ * @param[in] file_name File name string to be quoted before used on shell
+ * @param[out] buf Buffer to receive the final quoted file name. Must
+ * have room for the final quoted string. The maximum
+ * output length would be (3 * strlen(file_name) + 1)
+ * since in the worst case each character would be
+ * replaced by 3 characters, plus the terminating '\0'.
+ * @param[in] buf_len The size of the provided output buffer
+ *
+ * @returns SSH_ERROR on error; length of the resulting string not counting the
+ * string terminator '\0'
+ * */
+int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len)
+{
+ const char *src = NULL;
+ char *dst = NULL;
+ size_t required_buf_len;
+
+ enum ssh_quote_state_e state = NO_QUOTE;
+
+ if (file_name == NULL || buf == NULL || buf_len == 0) {
+ SSH_LOG(SSH_LOG_WARNING, "Invalid parameter");
+ return SSH_ERROR;
+ }
+
+ /* Only allow file names smaller than 32kb. */
+ if (strlen(file_name) > 32 * 1024) {
+ SSH_LOG(SSH_LOG_WARNING, "File name too long");
+ return SSH_ERROR;
+ }
+
+ /* Paranoia check */
+ required_buf_len = (size_t)3 * strlen(file_name) + 1;
+ if (required_buf_len > buf_len) {
+ SSH_LOG(SSH_LOG_WARNING, "Buffer too small");
+ return SSH_ERROR;
+ }
+
+ src = file_name;
+ dst = buf;
+
+ while ((*src != '\0')) {
+ switch (*src) {
+
+ /* The '\'' char is double quoted */
+
+ case '\'':
+ switch (state) {
+ case NO_QUOTE:
+ /* Start a new double quoted string. The '\'' char will be
+ * copied to the beginning of it at the end of the loop. */
+ *dst++ = '"';
+ break;
+ case SINGLE_QUOTE:
+ /* Close the current single quoted string and start a new double
+ * quoted string. The '\'' char will be copied to the beginning
+ * of it at the end of the loop. */
+ *dst++ = '\'';
+ *dst++ = '"';
+ break;
+ case DOUBLE_QUOTE:
+ /* If already in the double quoted string, keep copying the
+ * sequence of chars. */
+ break;
+ default:
+ /* Should never be reached */
+ goto error;
+ }
+
+ /* When the '\'' char is found, the resulting state will be
+ * DOUBLE_QUOTE in any case*/
+ state = DOUBLE_QUOTE;
+ break;
+
+ /* The '!' char is replaced by unquoted "\!" */
+
+ case '!':
+ switch (state) {
+ case NO_QUOTE:
+ /* The '!' char is interpreted in some shells (e.g. CSH) even
+ * when is quoted with single quotes. Replace it with unquoted
+ * "\!" which is correctly interpreted as the '!' character. */
+ *dst++ = '\\';
+ break;
+ case SINGLE_QUOTE:
+ /* Close the current quoted string and replace '!' for unquoted
+ * "\!" */
+ *dst++ = '\'';
+ *dst++ = '\\';
+ break;
+ case DOUBLE_QUOTE:
+ /* Close current quoted string and replace "!" for unquoted
+ * "\!" */
+ *dst++ = '"';
+ *dst++ = '\\';
+ break;
+ default:
+ /* Should never be reached */
+ goto error;
+ }
+
+ /* When the '!' char is found, the resulting state will be NO_QUOTE
+ * in any case*/
+ state = NO_QUOTE;
+ break;
+
+ /* Ordinary chars are single quoted */
+
+ default:
+ switch (state) {
+ case NO_QUOTE:
+ /* Start a new single quoted string */
+ *dst++ = '\'';
+ break;
+ case SINGLE_QUOTE:
+ /* If already in the single quoted string, keep copying the
+ * sequence of chars. */
+ break;
+ case DOUBLE_QUOTE:
+ /* Close current double quoted string and start a new single
+ * quoted string. */
+ *dst++ = '"';
+ *dst++ = '\'';
+ break;
+ default:
+ /* Should never be reached */
+ goto error;
+ }
+
+ /* When an ordinary char is found, the resulting state will be
+ * SINGLE_QUOTE in any case*/
+ state = SINGLE_QUOTE;
+ break;
+ }
+
+ /* Copy the current char to output */
+ *dst++ = *src++;
+ }
+
+ /* Close the quoted string when necessary */
+
+ switch (state) {
+ case NO_QUOTE:
+ /* No open string */
+ break;
+ case SINGLE_QUOTE:
+ /* Close current single quoted string */
+ *dst++ = '\'';
+ break;
+ case DOUBLE_QUOTE:
+ /* Close current double quoted string */
+ *dst++ = '"';
+ break;
+ default:
+ /* Should never be reached */
+ goto error;
+ }
+
+ /* Put the string terminator */
+ *dst = '\0';
+
+ return dst - buf;
+
+error:
+ return SSH_ERROR;
+}
+
/** @} */
--
cgit v1.2.1

33
0004-CVE-2019-14889.patch Normal file
View File

@ -0,0 +1,33 @@
From 391c78de9d0f7baec3a44d86a76f4e1324eb9529 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@cryptomilk.org>
Date: Fri, 6 Dec 2019 09:40:30 +0100
Subject: CVE-2019-14889: scp: Don't allow file path longer than 32kb
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 0b5ee397260b6e08dffa2c1ce515a153aaeda765)
---
src/scp.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/scp.c b/src/scp.c
index 166f3d2f..4b00aa5f 100644
--- a/src/scp.c
+++ b/src/scp.c
@@ -80,6 +80,12 @@ ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location)
goto error;
}
+ if (strlen(location) > 32 * 1024) {
+ ssh_set_error(session, SSH_FATAL,
+ "Location path is too long");
+ goto error;
+ }
+
scp->location = strdup(location);
if (scp->location == NULL) {
ssh_set_error(session, SSH_FATAL,
--
cgit v1.2.1

128
0005-CVE-2019-14889.patch Normal file
View File

@ -0,0 +1,128 @@
From b0edec4e8d01ad73b0d26ad4070d7e1a1e86dfc8 Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Thu, 31 Oct 2019 18:10:27 +0100
Subject: CVE-2019-14889: scp: Quote location to be used on shell
Single quote file paths to be used on commands to be executed on remote
shell.
Fixes T181
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 3830c7ae6eec751b7618d3fc159cb5bb3c8806a6)
---
src/scp.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 56 insertions(+), 6 deletions(-)
diff --git a/src/scp.c b/src/scp.c
index 4b00aa5f..652551e3 100644
--- a/src/scp.c
+++ b/src/scp.c
@@ -29,6 +29,7 @@
#include "libssh/priv.h"
#include "libssh/scp.h"
+#include "libssh/misc.h"
/**
* @defgroup libssh_scp The SSH scp functions
@@ -119,6 +120,9 @@ int ssh_scp_init(ssh_scp scp)
{
int rc;
char execbuffer[1024] = {0};
+ char *quoted_location = NULL;
+ size_t quoted_location_len = 0;
+ size_t scp_location_len;
if (scp == NULL) {
return SSH_ERROR;
@@ -130,33 +134,79 @@ int ssh_scp_init(ssh_scp scp)
return SSH_ERROR;
}
- SSH_LOG(SSH_LOG_PROTOCOL,
- "Initializing scp session %s %son location '%s'",
+ if (scp->location == NULL) {
+ ssh_set_error(scp->session, SSH_FATAL,
+ "Invalid scp context: location is NULL");
+ return SSH_ERROR;
+ }
+
+ SSH_LOG(SSH_LOG_PROTOCOL, "Initializing scp session %s %son location '%s'",
scp->mode == SSH_SCP_WRITE?"write":"read",
- scp->recursive?"recursive ":"",
+ scp->recursive ? "recursive " : "",
scp->location);
scp->channel = ssh_channel_new(scp->session);
if (scp->channel == NULL) {
+ ssh_set_error(scp->session, SSH_FATAL,
+ "Channel creation failed for scp");
scp->state = SSH_SCP_ERROR;
return SSH_ERROR;
}
rc = ssh_channel_open_session(scp->channel);
if (rc == SSH_ERROR) {
+ ssh_set_error(scp->session, SSH_FATAL,
+ "Failed to open channel for scp");
+ scp->state = SSH_SCP_ERROR;
+ return SSH_ERROR;
+ }
+
+ /* In the worst case, each character would be replaced by 3 plus the string
+ * terminator '\0' */
+ scp_location_len = strlen(scp->location);
+ quoted_location_len = ((size_t)3 * scp_location_len) + 1;
+ /* Paranoia check */
+ if (quoted_location_len < scp_location_len) {
+ ssh_set_error(scp->session, SSH_FATAL,
+ "Buffer overflow detected");
+ scp->state = SSH_SCP_ERROR;
+ return SSH_ERROR;
+ }
+
+ quoted_location = (char *)calloc(1, quoted_location_len);
+ if (quoted_location == NULL) {
+ ssh_set_error(scp->session, SSH_FATAL,
+ "Failed to allocate memory for quoted location");
+ scp->state = SSH_SCP_ERROR;
+ return SSH_ERROR;
+ }
+
+ rc = ssh_quote_file_name(scp->location, quoted_location,
+ quoted_location_len);
+ if (rc <= 0) {
+ ssh_set_error(scp->session, SSH_FATAL,
+ "Failed to single quote command location");
+ SAFE_FREE(quoted_location);
scp->state = SSH_SCP_ERROR;
return SSH_ERROR;
}
if (scp->mode == SSH_SCP_WRITE) {
snprintf(execbuffer, sizeof(execbuffer), "scp -t %s %s",
- scp->recursive ? "-r":"", scp->location);
+ scp->recursive ? "-r" : "", quoted_location);
} else {
snprintf(execbuffer, sizeof(execbuffer), "scp -f %s %s",
- scp->recursive ? "-r":"", scp->location);
+ scp->recursive ? "-r" : "", quoted_location);
}
- if (ssh_channel_request_exec(scp->channel, execbuffer) == SSH_ERROR) {
+ SAFE_FREE(quoted_location);
+
+ SSH_LOG(SSH_LOG_DEBUG, "Executing command: %s", execbuffer);
+
+ rc = ssh_channel_request_exec(scp->channel, execbuffer);
+ if (rc == SSH_ERROR){
+ ssh_set_error(scp->session, SSH_FATAL,
+ "Failed executing command: %s", execbuffer);
scp->state = SSH_SCP_ERROR;
return SSH_ERROR;
}
--
cgit v1.2.1

View File

@ -1,6 +1,6 @@
Name: libssh
Version: 0.8.3
Release: 5
Release: 6
Summary: A library implementing the SSH protocol
License: LGPLv2+
URL: https://www.libssh.org
@ -20,6 +20,11 @@ Patch6004: libssh-stable-0p8-CVE-2018-10933-part5.patch
Patch6005: libssh-stable-0p8-CVE-2018-10933-part6.patch
Patch6006: libssh-stable-0p8-CVE-2018-10933-part7.patch
Patch6007: libssh-stable-0p8-CVE-2018-10933-part8.patch
Patch6008: 0001-CVE-2019-14889.patch
Patch6009: 0002-CVE-2019-14889.patch
Patch6010: 0003-CVE-2019-14889.patch
Patch6011: 0004-CVE-2019-14889.patch
Patch6012: 0005-CVE-2019-14889.patch
BuildRequires: cmake libcmocka-devel krb5-devel zlib-devel pkgconfig
BuildRequires: doxygen gcc-c++ gnupg2 openssl-devel
@ -102,6 +107,12 @@ popd
%doc README ChangeLog obj/doc/html
%changelog
* Sun Jan 12 2020 openEuler Buildteam <buildteam@openeuler.org> - 0.8.3-6
- Type:bugfix
- Id:NA
- SUG:NA
- DESC: fixes cves
* Sat Dec 21 2019 openEuler Buildteam <buildteam@openeuler.org> - 0.8.3-5
- Type:bugfix
- Id:NA