commit
85b575cc88
File diff suppressed because it is too large
Load Diff
@ -1,169 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,238 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
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
|
||||
|
||||
|
||||
@ -1,128 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
From 26a8b6535159e3f7fb4a6204373b195f09e3bc20 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Schneider <asn@cryptomilk.org>
|
||||
Date: Tue, 11 Feb 2020 11:52:33 +0100
|
||||
Subject: [PATCH] CVE-2020-1730: Fix a possible segfault when zeroing AES-CTR
|
||||
key
|
||||
|
||||
Fixes T213
|
||||
|
||||
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
|
||||
Reviewed-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
---
|
||||
src/libcrypto.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/libcrypto.c b/src/libcrypto.c
|
||||
index b24a18f..2d692cd 100644
|
||||
--- a/src/libcrypto.c
|
||||
+++ b/src/libcrypto.c
|
||||
@@ -638,8 +638,12 @@ static void aes_ctr_encrypt(struct ssh_cipher_struct *cipher, void *in, void *ou
|
||||
}
|
||||
|
||||
static void aes_ctr_cleanup(struct ssh_cipher_struct *cipher){
|
||||
- explicit_bzero(cipher->aes_key, sizeof(*cipher->aes_key));
|
||||
- SAFE_FREE(cipher->aes_key);
|
||||
+ if (cipher != NULL) {
|
||||
+ if (cipher->aes_key != NULL) {
|
||||
+ explicit_bzero(cipher->aes_key, sizeof(*cipher->aes_key));
|
||||
+ }
|
||||
+ SAFE_FREE(cipher->aes_key);
|
||||
+ }
|
||||
}
|
||||
|
||||
#endif /* HAVE_OPENSSL_EVP_AES_CTR */
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,58 +0,0 @@
|
||||
From 6ae097069ad8e4658f14870c4d23409b88139810 Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Jelen <jjelen@redhat.com>
|
||||
Date: Tue, 10 Dec 2019 18:09:51 +0800
|
||||
Subject: [PATCH] backport-fixes-the-oss-fuzz-bug
|
||||
|
||||
---
|
||||
src/buffer.c | 19 +++++++++++++------
|
||||
1 file changed, 13 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/buffer.c b/src/buffer.c
|
||||
index da6e587..08529ee 100644
|
||||
--- a/src/buffer.c
|
||||
+++ b/src/buffer.c
|
||||
@@ -1112,6 +1112,7 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
+ rc = SSH_ERROR;
|
||||
switch (*p) {
|
||||
case 'b':
|
||||
o.byte = va_arg(ap, uint8_t *);
|
||||
@@ -1121,20 +1122,26 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
case 'w':
|
||||
o.word = va_arg(ap, uint16_t *);
|
||||
rlen = ssh_buffer_get_data(buffer, o.word, sizeof(uint16_t));
|
||||
- *o.word = ntohs(*o.word);
|
||||
- rc = rlen==2 ? SSH_OK : SSH_ERROR;
|
||||
+ if (rlen == 2) {
|
||||
+ *o.word = ntohs(*o.word);
|
||||
+ rc = SSH_OK;
|
||||
+ }
|
||||
break;
|
||||
case 'd':
|
||||
o.dword = va_arg(ap, uint32_t *);
|
||||
rlen = ssh_buffer_get_u32(buffer, o.dword);
|
||||
- *o.dword = ntohl(*o.dword);
|
||||
- rc = rlen==4 ? SSH_OK : SSH_ERROR;
|
||||
+ if (rlen == 4) {
|
||||
+ *o.dword = ntohl(*o.dword);
|
||||
+ rc = SSH_OK;
|
||||
+ }
|
||||
break;
|
||||
case 'q':
|
||||
o.qword = va_arg(ap, uint64_t*);
|
||||
rlen = ssh_buffer_get_u64(buffer, o.qword);
|
||||
- *o.qword = ntohll(*o.qword);
|
||||
- rc = rlen==8 ? SSH_OK : SSH_ERROR;
|
||||
+ if (rlen == 8) {
|
||||
+ *o.qword = ntohll(*o.qword);
|
||||
+ rc = SSH_OK;
|
||||
+ }
|
||||
break;
|
||||
case 'S':
|
||||
o.string = va_arg(ap, ssh_string *);
|
||||
--
|
||||
2.19.1
|
||||
|
||||
|
||||
Binary file not shown.
@ -1,16 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCAAdFiEEjf9T4Y8qvI2PPJIjfuD8TcwBTj0FAlukpGkACgkQfuD8TcwB
|
||||
Tj3qsA//bPS3hYBbKIChg1+o2s/lAbkjV6mv5LR9gyTljjUAikFNf/AN/yrNLD/H
|
||||
0sAAD8S2Mj5t4+daUronpX9IJPZtimFB3WoBl+S9J9ybyzpgsspTNv0KZt/O9Vt+
|
||||
QamOYkMXDtDcqUCHxIzURKiIc6ATsobiUx6EhWOSa8fFsnW6golCJtHzHi5fKsPF
|
||||
x92J5gZ4jUehZJEiX/LmqFCblLK5qV8g/F+TauWg9jL5m0SNuR0gfDxi3VNV+yeG
|
||||
gCtneHNrg/Jq9PwI71dIAQ+EDxYARBrLRe7zNSJgZHNuHttyVZaObgO/tFGzAwfj
|
||||
g+9cuBTHvkKbgM0CodT9ftmdXU8Gt2/3yugfP/FSHUKCy9YgOM5Yo+T8lhAw3Pnt
|
||||
5ZienZztJwBabui7rWeebhaBSFNuaFUhp1V5HOBT1YjKWlr3yqSGs2PmYYA7Ioeq
|
||||
ulcyUsNZFXj7hALCxhyBfcwz+USWBpjuxZz5gK5uXbwWcxZUkiRTCXprKiN8jUn/
|
||||
1/wteO4inm3dpKM3oMuxsk6c64JZnbXkD9vPEP7Fv48nPVVcqs+jk5RPK7iOBUgd
|
||||
bglc6F05cnUzFz78Lj/FIgEqdYV/vGtxxpwOCRPBDhDWvjbDltN7GkcKQ7ItNd9L
|
||||
UpMir12LL1Lo32IWxH457dKSCut2/+wGGLcXjUMMhhs/6UDqerg=
|
||||
=uDol
|
||||
-----END PGP SIGNATURE-----
|
||||
11
libssh-0.9.4-fix-version.patch
Normal file
11
libssh-0.9.4-fix-version.patch
Normal file
@ -0,0 +1,11 @@
|
||||
--- a/include/libssh/libssh.h 2020-04-15 13:38:32.899177005 +0200
|
||||
+++ b/include/libssh/libssh.h 2020-04-15 13:38:57.406454427 +0200
|
||||
@@ -79,7 +79,7 @@
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR 0
|
||||
#define LIBSSH_VERSION_MINOR 9
|
||||
-#define LIBSSH_VERSION_MICRO 3
|
||||
+#define LIBSSH_VERSION_MICRO 4
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
BIN
libssh-0.9.4.tar.xz
Normal file
BIN
libssh-0.9.4.tar.xz
Normal file
Binary file not shown.
16
libssh-0.9.4.tar.xz.asc
Normal file
16
libssh-0.9.4.tar.xz.asc
Normal file
@ -0,0 +1,16 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCgAdFiEEjf9T4Y8qvI2PPJIjfuD8TcwBTj0FAl6O0BgACgkQfuD8TcwB
|
||||
Tj0dCQ/+J0pjZU6uu7h6gkc4BbRciCpYDIv66Lw9iCc2bQmLLhPrukWjz6/PDV+U
|
||||
iL/1dlwxG8rOlXdtCEFGyDvm0y4E8NaQCcgjU9jA8nsXo+SyyJAeWT7BeI3m2hPi
|
||||
tjbLAjQVHCW1jIite1dJeoPIPg15LChc08t+HWVI3pwQviwlJWTPmHgMaT3uwa1X
|
||||
fD66hjgB2UFo5eYnbION3L/jpA0vsI4o4F5CFPEhgbz3H6KmrgQbKLPM3H/103zU
|
||||
XjtHEw7gy/85OmjpcskMrUVAMbw9EZ5ESFOrKyuQaFBY57L//tAdUaEloxsMKt+5
|
||||
nmYunmlGmDLT6rHfjSg5X1S+NsQaXhGelc0TLVgvlzs4kR+QbApR1ewKTcsYlVwr
|
||||
jYG+PuAiROqc18xM/fQYh8UqohluDBmUpEDmVOEKT2tg/S7R5RJtOxdmcZPsLO+W
|
||||
EOoP+OeUvQqNlzqu6kBRI4v2lwVU4QwDzKCNRzwQHJOH+azH/3FRJBDF1ZAQvgxy
|
||||
w/NqlpFO6P76e0SLzBjHCDyqwbAzfq4WK3f5oE0RAA5RlndWusovTAWaYrAbVaoz
|
||||
emkt/guiHHsbLy6S2ELJu4BI9TGGtDMJoo1ScMMQzFqijUISCBgK/+6mUVUlMli0
|
||||
lTH6VE+MvpElADE+IYSXWOLHrspTxVa/jVun3iYE8Nexn6G0XE0=
|
||||
=xSu8
|
||||
-----END PGP SIGNATURE-----
|
||||
@ -1,130 +0,0 @@
|
||||
From b166ac4749c78f475b1708f0345e6ca2749c5d6d Mon Sep 17 00:00:00 2001
|
||||
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Date: Mon, 10 Sep 2018 17:37:42 +0200
|
||||
Subject: CVE-2018-10933: Introduced new auth states
|
||||
|
||||
Introduced the states SSH_AUTH_STATE_PUBKEY_OFFER_SENT and
|
||||
SSH_AUTH_STATE_PUBKEY_AUTH_SENT to know when SSH2_MSG_USERAUTH_PK_OK and
|
||||
SSH2_MSG_USERAUTH_SUCCESS should be expected.
|
||||
|
||||
Fixes T101
|
||||
|
||||
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
|
||||
---
|
||||
include/libssh/auth.h | 4 ++++
|
||||
src/auth.c | 44 +++++++++++++++++++++++++++-----------------
|
||||
2 files changed, 31 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/include/libssh/auth.h b/include/libssh/auth.h
|
||||
index 3913f219..8daab47d 100644
|
||||
--- a/include/libssh/auth.h
|
||||
+++ b/include/libssh/auth.h
|
||||
@@ -76,6 +76,10 @@ enum ssh_auth_state_e {
|
||||
SSH_AUTH_STATE_GSSAPI_TOKEN,
|
||||
/** We have sent the MIC and expecting to be authenticated */
|
||||
SSH_AUTH_STATE_GSSAPI_MIC_SENT,
|
||||
+ /** We have offered a pubkey to check if it is supported */
|
||||
+ SSH_AUTH_STATE_PUBKEY_OFFER_SENT,
|
||||
+ /** We have sent pubkey and signature expecting to be authenticated */
|
||||
+ SSH_AUTH_STATE_PUBKEY_AUTH_SENT,
|
||||
};
|
||||
|
||||
/** @internal
|
||||
diff --git a/src/auth.c b/src/auth.c
|
||||
index 97b6a6e1..41b76aa6 100644
|
||||
--- a/src/auth.c
|
||||
+++ b/src/auth.c
|
||||
@@ -85,6 +85,8 @@ static int ssh_auth_response_termination(void *user) {
|
||||
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
|
||||
case SSH_AUTH_STATE_GSSAPI_TOKEN:
|
||||
case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
|
||||
+ case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
|
||||
+ case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
@@ -167,6 +169,8 @@ static int ssh_userauth_get_response(ssh_session session) {
|
||||
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
|
||||
case SSH_AUTH_STATE_GSSAPI_TOKEN:
|
||||
case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
|
||||
+ case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
|
||||
+ case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
|
||||
case SSH_AUTH_STATE_NONE:
|
||||
/* not reached */
|
||||
rc = SSH_AUTH_ERROR;
|
||||
@@ -312,24 +316,30 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_success) {
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok) {
|
||||
int rc;
|
||||
|
||||
- SSH_LOG(SSH_LOG_TRACE, "Received SSH_USERAUTH_PK_OK/INFO_REQUEST/GSSAPI_RESPONSE");
|
||||
-
|
||||
- if (session->auth.state == SSH_AUTH_STATE_KBDINT_SENT) {
|
||||
- /* Assuming we are in keyboard-interactive context */
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
- "keyboard-interactive context, assuming SSH_USERAUTH_INFO_REQUEST");
|
||||
- rc = ssh_packet_userauth_info_request(session,type,packet,user);
|
||||
+ "Received SSH_USERAUTH_PK_OK/INFO_REQUEST/GSSAPI_RESPONSE");
|
||||
+
|
||||
+ if (session->auth.state == SSH_AUTH_STATE_KBDINT_SENT) {
|
||||
+ /* Assuming we are in keyboard-interactive context */
|
||||
+ SSH_LOG(SSH_LOG_TRACE,
|
||||
+ "keyboard-interactive context, "
|
||||
+ "assuming SSH_USERAUTH_INFO_REQUEST");
|
||||
+ rc = ssh_packet_userauth_info_request(session,type,packet,user);
|
||||
#ifdef WITH_GSSAPI
|
||||
- } else if (session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT) {
|
||||
- rc = ssh_packet_userauth_gssapi_response(session, type, packet, user);
|
||||
+ } else if (session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT) {
|
||||
+ rc = ssh_packet_userauth_gssapi_response(session, type, packet, user);
|
||||
#endif
|
||||
- } else {
|
||||
- session->auth.state = SSH_AUTH_STATE_PK_OK;
|
||||
- SSH_LOG(SSH_LOG_TRACE, "Assuming SSH_USERAUTH_PK_OK");
|
||||
- rc = SSH_PACKET_USED;
|
||||
- }
|
||||
+ } else if (session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT) {
|
||||
+ session->auth.state = SSH_AUTH_STATE_PK_OK;
|
||||
+ SSH_LOG(SSH_LOG_TRACE, "Assuming SSH_USERAUTH_PK_OK");
|
||||
+ rc = SSH_PACKET_USED;
|
||||
+ } else {
|
||||
+ session->auth.state = SSH_AUTH_STATE_ERROR;
|
||||
+ SSH_LOG(SSH_LOG_TRACE, "SSH_USERAUTH_PK_OK received in wrong state");
|
||||
+ rc = SSH_PACKET_USED;
|
||||
+ }
|
||||
|
||||
- return rc;
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -553,7 +563,7 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
ssh_string_free(pubkey_s);
|
||||
|
||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||
- session->auth.state = SSH_AUTH_STATE_NONE;
|
||||
+ session->auth.state = SSH_AUTH_STATE_PUBKEY_OFFER_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY;
|
||||
rc = ssh_packet_send(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
@@ -701,7 +711,7 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
}
|
||||
|
||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||
- session->auth.state = SSH_AUTH_STATE_NONE;
|
||||
+ session->auth.state = SSH_AUTH_STATE_PUBKEY_AUTH_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_PUBKEY;
|
||||
rc = ssh_packet_send(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
@@ -797,7 +807,7 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
}
|
||||
|
||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||
- session->auth.state = SSH_AUTH_STATE_NONE;
|
||||
+ session->auth.state = SSH_AUTH_STATE_PUBKEY_AUTH_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_AGENT;
|
||||
rc = ssh_packet_send(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
--
|
||||
cgit v1.2.1
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
From fcfba0d8aa15a0142e57513f271eb7fa4bbabc9a Mon Sep 17 00:00:00 2001
|
||||
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Date: Mon, 10 Sep 2018 17:38:22 +0200
|
||||
Subject: CVE-2018-10933: Introduce SSH_AUTH_STATE_PASSWORD_AUTH_SENT
|
||||
|
||||
The introduced auth state allows to identify when authentication using
|
||||
password was tried.
|
||||
|
||||
Fixes T101
|
||||
|
||||
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
|
||||
---
|
||||
include/libssh/auth.h | 2 ++
|
||||
src/auth.c | 4 +++-
|
||||
2 files changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/libssh/auth.h b/include/libssh/auth.h
|
||||
index 8daab47d..899282c1 100644
|
||||
--- a/include/libssh/auth.h
|
||||
+++ b/include/libssh/auth.h
|
||||
@@ -80,6 +80,8 @@ enum ssh_auth_state_e {
|
||||
SSH_AUTH_STATE_PUBKEY_OFFER_SENT,
|
||||
/** We have sent pubkey and signature expecting to be authenticated */
|
||||
SSH_AUTH_STATE_PUBKEY_AUTH_SENT,
|
||||
+ /** We have sent a password expecting to be authenticated */
|
||||
+ SSH_AUTH_STATE_PASSWORD_AUTH_SENT,
|
||||
};
|
||||
|
||||
/** @internal
|
||||
diff --git a/src/auth.c b/src/auth.c
|
||||
index 41b76aa6..2b06d2e1 100644
|
||||
--- a/src/auth.c
|
||||
+++ b/src/auth.c
|
||||
@@ -87,6 +87,7 @@ static int ssh_auth_response_termination(void *user) {
|
||||
case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
|
||||
case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
|
||||
case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
|
||||
+ case SSH_AUTH_STATE_PASSWORD_AUTH_SENT:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
@@ -171,6 +172,7 @@ static int ssh_userauth_get_response(ssh_session session) {
|
||||
case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
|
||||
case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
|
||||
case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
|
||||
+ case SSH_AUTH_STATE_PASSWORD_AUTH_SENT:
|
||||
case SSH_AUTH_STATE_NONE:
|
||||
/* not reached */
|
||||
rc = SSH_AUTH_ERROR;
|
||||
@@ -1268,7 +1270,7 @@ int ssh_userauth_password(ssh_session session,
|
||||
}
|
||||
|
||||
session->auth.current_method = SSH_AUTH_METHOD_PASSWORD;
|
||||
- session->auth.state = SSH_AUTH_STATE_NONE;
|
||||
+ session->auth.state = SSH_AUTH_STATE_PASSWORD_AUTH_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_PASSWORD;
|
||||
rc = ssh_packet_send(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
--
|
||||
cgit v1.2.1
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
From 7819621fc2a07d2d4649b36ca77850610741cfec Mon Sep 17 00:00:00 2001
|
||||
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Date: Wed, 19 Sep 2018 17:01:15 +0200
|
||||
Subject: CVE-2018-10933: Introduce SSH_AUTH_STATE_AUTH_NONE_SENT
|
||||
|
||||
The introduced auth state allows to identify when a request without
|
||||
authentication information was sent.
|
||||
|
||||
Fixes T101
|
||||
|
||||
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
|
||||
---
|
||||
include/libssh/auth.h | 2 ++
|
||||
src/auth.c | 4 +++-
|
||||
2 files changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/libssh/auth.h b/include/libssh/auth.h
|
||||
index 899282c1..90b377d4 100644
|
||||
--- a/include/libssh/auth.h
|
||||
+++ b/include/libssh/auth.h
|
||||
@@ -82,6 +82,8 @@ enum ssh_auth_state_e {
|
||||
SSH_AUTH_STATE_PUBKEY_AUTH_SENT,
|
||||
/** We have sent a password expecting to be authenticated */
|
||||
SSH_AUTH_STATE_PASSWORD_AUTH_SENT,
|
||||
+ /** We have sent a request without auth information (method 'none') */
|
||||
+ SSH_AUTH_STATE_AUTH_NONE_SENT,
|
||||
};
|
||||
|
||||
/** @internal
|
||||
diff --git a/src/auth.c b/src/auth.c
|
||||
index 2b06d2e1..993e6dfe 100644
|
||||
--- a/src/auth.c
|
||||
+++ b/src/auth.c
|
||||
@@ -88,6 +88,7 @@ static int ssh_auth_response_termination(void *user) {
|
||||
case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
|
||||
case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
|
||||
case SSH_AUTH_STATE_PASSWORD_AUTH_SENT:
|
||||
+ case SSH_AUTH_STATE_AUTH_NONE_SENT:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
@@ -173,6 +174,7 @@ static int ssh_userauth_get_response(ssh_session session) {
|
||||
case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
|
||||
case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
|
||||
case SSH_AUTH_STATE_PASSWORD_AUTH_SENT:
|
||||
+ case SSH_AUTH_STATE_AUTH_NONE_SENT:
|
||||
case SSH_AUTH_STATE_NONE:
|
||||
/* not reached */
|
||||
rc = SSH_AUTH_ERROR;
|
||||
@@ -428,7 +430,7 @@ int ssh_userauth_none(ssh_session session, const char *username) {
|
||||
}
|
||||
|
||||
session->auth.current_method = SSH_AUTH_METHOD_NONE;
|
||||
- session->auth.state = SSH_AUTH_STATE_NONE;
|
||||
+ session->auth.state = SSH_AUTH_STATE_AUTH_NONE_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_NONE;
|
||||
rc = ssh_packet_send(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
--
|
||||
cgit v1.2.1
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
From 72bce5ece7edc2fd8023185f9d47b9fc86ef4663 Mon Sep 17 00:00:00 2001
|
||||
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Date: Wed, 5 Sep 2018 12:14:07 +0200
|
||||
Subject: CVE-2018-10933: Set correct state after sending MIC
|
||||
|
||||
After sending the client token, the auth state is set as
|
||||
SSH_AUTH_STATE_GSSAPI_MIC_SENT. Then this can be expected to be the
|
||||
state when a USERAUTH_FAILURE or USERAUTH_SUCCESS arrives.
|
||||
|
||||
Fixes T101
|
||||
|
||||
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
|
||||
---
|
||||
src/gssapi.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/gssapi.c b/src/gssapi.c
|
||||
index 51b69e7a..77df0b59 100644
|
||||
--- a/src/gssapi.c
|
||||
+++ b/src/gssapi.c
|
||||
@@ -960,8 +960,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){
|
||||
}
|
||||
|
||||
if (maj_stat == GSS_S_COMPLETE) {
|
||||
- session->auth.state = SSH_AUTH_STATE_NONE;
|
||||
ssh_gssapi_send_mic(session);
|
||||
+ session->auth.state = SSH_AUTH_STATE_GSSAPI_MIC_SENT;
|
||||
}
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
--
|
||||
cgit v1.2.1
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
From adeaa69cc535827ec8acfbaf3ff91224b5a595a7 Mon Sep 17 00:00:00 2001
|
||||
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Date: Fri, 7 Sep 2018 17:00:40 +0200
|
||||
Subject: CVE-2018-10933: Check channel state when OPEN_CONFIRMATION arrives
|
||||
|
||||
When a SSH2_MSG_OPEN_CONFIRMATION arrives, the channel state is checked
|
||||
to be in SSH_CHANNEL_STATE_OPENING.
|
||||
|
||||
Fixes T101
|
||||
|
||||
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
|
||||
---
|
||||
src/channels.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/src/channels.c b/src/channels.c
|
||||
index 103009a8..b26f6bd4 100644
|
||||
--- a/src/channels.c
|
||||
+++ b/src/channels.c
|
||||
@@ -171,6 +171,15 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf){
|
||||
"Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d",
|
||||
channel->local_channel,
|
||||
channel->remote_channel);
|
||||
+
|
||||
+ if (channel->state != SSH_CHANNEL_STATE_OPENING) {
|
||||
+ SSH_LOG(SSH_LOG_RARE,
|
||||
+ "SSH2_MSG_CHANNEL_OPEN_CONFIRMATION received in incorrect "
|
||||
+ "channel state %d",
|
||||
+ channel->state);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"Remote window : %lu, maxpacket : %lu",
|
||||
(long unsigned int) channel->remote_window,
|
||||
--
|
||||
cgit v1.2.1
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
From f8c452cbef228b105dcb757d7554c3388a4dbea5 Mon Sep 17 00:00:00 2001
|
||||
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Date: Fri, 7 Sep 2018 17:12:01 +0200
|
||||
Subject: CVE-2018-10933: Check channel state when OPEN_FAILURE arrives
|
||||
|
||||
When a SSH2_MSG_OPEN_FAILURE arrives, the channel state is checked
|
||||
to be in SSH_CHANNEL_STATE_OPENING.
|
||||
|
||||
Fixes T101
|
||||
|
||||
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
|
||||
---
|
||||
src/channels.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/src/channels.c b/src/channels.c
|
||||
index b26f6bd4..0e61e5cd 100644
|
||||
--- a/src/channels.c
|
||||
+++ b/src/channels.c
|
||||
@@ -220,6 +220,14 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail){
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
+ if (channel->state != SSH_CHANNEL_STATE_OPENING) {
|
||||
+ SSH_LOG(SSH_LOG_RARE,
|
||||
+ "SSH2_MSG_CHANNEL_OPEN_FAILURE received in incorrect channel "
|
||||
+ "state %d",
|
||||
+ channel->state);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Channel opening failure: channel %u error (%lu) %s",
|
||||
channel->local_channel,
|
||||
@@ -228,6 +236,10 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail){
|
||||
SAFE_FREE(error);
|
||||
channel->state=SSH_CHANNEL_STATE_OPEN_DENIED;
|
||||
return SSH_PACKET_USED;
|
||||
+
|
||||
+error:
|
||||
+ ssh_set_error(session, SSH_FATAL, "Invalid packet");
|
||||
+ return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
static int ssh_channel_open_termination(void *c){
|
||||
--
|
||||
cgit v1.2.1
|
||||
|
||||
@ -1,871 +0,0 @@
|
||||
From 203818608ac8a83d68098f008306c3a568ac4cac Mon Sep 17 00:00:00 2001
|
||||
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Date: Tue, 28 Aug 2018 18:13:03 +0200
|
||||
Subject: CVE-2018-10933: Introduced packet filtering
|
||||
|
||||
The packet filter checks required states for the incoming packets and
|
||||
reject them if they arrived in the wrong state.
|
||||
|
||||
Fixes T101
|
||||
|
||||
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
|
||||
---
|
||||
include/libssh/packet.h | 6 +
|
||||
src/packet.c | 809 +++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 813 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/include/libssh/packet.h b/include/libssh/packet.h
|
||||
index a3bcb9a8..fbe09700 100644
|
||||
--- a/include/libssh/packet.h
|
||||
+++ b/include/libssh/packet.h
|
||||
@@ -43,6 +43,12 @@ enum ssh_packet_state_e {
|
||||
PACKET_STATE_PROCESSING
|
||||
};
|
||||
|
||||
+enum ssh_packet_filter_result_e {
|
||||
+ SSH_PACKET_UNKNOWN,
|
||||
+ SSH_PACKET_ALLOWED,
|
||||
+ SSH_PACKET_DENIED
|
||||
+};
|
||||
+
|
||||
int ssh_packet_send(ssh_session session);
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_unimplemented);
|
||||
diff --git a/src/packet.c b/src/packet.c
|
||||
index aa2f17f0..0b070fd4 100644
|
||||
--- a/src/packet.c
|
||||
+++ b/src/packet.c
|
||||
@@ -128,6 +128,797 @@ static ssh_packet_callback default_packet_handlers[]= {
|
||||
ssh_packet_channel_failure, // SSH2_MSG_CHANNEL_FAILURE 100
|
||||
};
|
||||
|
||||
+/** @internal
|
||||
+ * @brief check if the received packet is allowed for the current session state
|
||||
+ * @param session current ssh_session
|
||||
+ * @returns SSH_PACKET_ALLOWED if the packet is allowed; SSH_PACKET_DENIED
|
||||
+ * if the packet arrived in wrong state; SSH_PACKET_UNKNOWN if the packet type
|
||||
+ * is unknown
|
||||
+ */
|
||||
+static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session session)
|
||||
+{
|
||||
+ enum ssh_packet_filter_result_e rc;
|
||||
+
|
||||
+#ifdef DEBUG_PACKET
|
||||
+ SSH_LOG(SSH_LOG_PACKET, "Filtering packet type %d",
|
||||
+ session->in_packet.type);
|
||||
+#endif
|
||||
+
|
||||
+ switch(session->in_packet.type) {
|
||||
+ case SSH2_MSG_DISCONNECT: // 1
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - None
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - session->socket->state = SSH_SOCKET_CLOSED
|
||||
+ * - session->session_state = SSH_SESSION_STATE_ERROR
|
||||
+ * */
|
||||
+
|
||||
+ /* Always allowed */
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_IGNORE: // 2
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - None
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ /* Always allowed */
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_UNIMPLEMENTED: // 3
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - None
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ /* Always allowed */
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_DEBUG: // 4
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - None
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ /* Always allowed */
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_SERVICE_REQUEST: // 5
|
||||
+ /* Server only */
|
||||
+
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session->session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
+ * or session->session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ * - session->dh_handshake_state == DH_STATE_FINISHED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ /* If this is a client, reject the message */
|
||||
+ if (session->client) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATING) &&
|
||||
+ (session->session_state != SSH_SESSION_STATE_AUTHENTICATED))
|
||||
+ {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_SERVICE_ACCEPT: // 6
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session->session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
+ * or session->session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ * - session->dh_handshake_state == DH_STATE_FINISHED
|
||||
+ * - session->auth.service_state == SSH_AUTH_SERVICE_SENT
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - auth.service_state = SSH_AUTH_SERVICE_ACCEPTED
|
||||
+ * */
|
||||
+
|
||||
+ if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATING) &&
|
||||
+ (session->session_state != SSH_SESSION_STATE_AUTHENTICATED))
|
||||
+ {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* TODO check if only auth service can be requested */
|
||||
+ if (session->auth.service_state != SSH_AUTH_SERVICE_SENT) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_EXT_INFO: // 7
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
+ * - dh_handshake_state == DH_STATE_FINISHED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_KEXINIT: // 20
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ * or session_state == SSH_SESSION_STATE_INITIAL_KEX
|
||||
+ * - dh_handshake_state == DH_STATE_INIT
|
||||
+ * or dh_handshake_state == DH_STATE_FINISHED (re-exchange)
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - session->dh_handshake_state = DH_STATE_INIT
|
||||
+ * - session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED
|
||||
+ *
|
||||
+ * On server:
|
||||
+ * - session->session_state = SSH_SESSION_STATE_DH
|
||||
+ * */
|
||||
+
|
||||
+ if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATED) &&
|
||||
+ (session->session_state != SSH_SESSION_STATE_INITIAL_KEX))
|
||||
+ {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if ((session->dh_handshake_state != DH_STATE_INIT) &&
|
||||
+ (session->dh_handshake_state != DH_STATE_FINISHED))
|
||||
+ {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_NEWKEYS: // 21
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_DH
|
||||
+ * - dh_handshake_state == DH_STATE_NEWKEYS_SENT
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - session->dh_handshake_state = DH_STATE_FINISHED
|
||||
+ * - session->session_state = SSH_SESSION_STATE_AUTHENTICATING
|
||||
+ * if session->flags & SSH_SESSION_FLAG_AUTHENTICATED
|
||||
+ * - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ * */
|
||||
+
|
||||
+ /* If DH has not been started, reject message */
|
||||
+ if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Only allowed if dh_handshake_state is in NEWKEYS_SENT state */
|
||||
+ if (session->dh_handshake_state != DH_STATE_NEWKEYS_SENT) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_KEXDH_INIT: // 30
|
||||
+ // SSH2_MSG_KEX_ECDH_INIT: // 30
|
||||
+ // SSH2_MSG_ECMQV_INIT: // 30
|
||||
+ // SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: // 30
|
||||
+
|
||||
+ /* Server only */
|
||||
+
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_DH
|
||||
+ * - dh_handshake_state == DH_STATE_INIT
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - session->dh_handshake_state = DH_STATE_INIT_SENT
|
||||
+ * then calls dh_handshake_server which triggers:
|
||||
+ * - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Only allowed if dh_handshake_state is in initial state */
|
||||
+ if (session->dh_handshake_state != DH_STATE_INIT) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_KEXDH_REPLY: // 31
|
||||
+ // SSH2_MSG_KEX_ECDH_REPLY: // 31
|
||||
+ // SSH2_MSG_ECMQV_REPLY: // 31
|
||||
+ // SSH2_MSG_KEX_DH_GEX_GROUP: // 31
|
||||
+
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_DH
|
||||
+ * - dh_handshake_state == DH_STATE_INIT_SENT
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->dh_handshake_state != DH_STATE_INIT_SENT) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_KEX_DH_GEX_INIT: // 32
|
||||
+ /* TODO Not filtered */
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_KEX_DH_GEX_REPLY: // 33
|
||||
+ /* TODO Not filtered */
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_KEX_DH_GEX_REQUEST: // 34
|
||||
+ /* TODO Not filtered */
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_USERAUTH_REQUEST: // 50
|
||||
+ /* Server only */
|
||||
+
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
+ * - dh_hanshake_state == DH_STATE_FINISHED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - if authentication was successful:
|
||||
+ * - session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ * */
|
||||
+
|
||||
+ /* If this is a client, reject the message */
|
||||
+ if (session->client) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_USERAUTH_FAILURE: // 51
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
+ * - dh_hanshake_state == DH_STATE_FINISHED
|
||||
+ * - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||
+ * or session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
|
||||
+ * or session->auth.state == SSH_AUTH_STATE_PUBKEY_AUTH_SENT
|
||||
+ * or session->auth.state == SSH_AUTH_STATE_PASSWORD_AUTH_SENT
|
||||
+ * or session->auth.state == SSH_AUTH_STATE_GSSAPI_MIC_SENT
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - if unpacking failed:
|
||||
+ * - session->auth.state = SSH_AUTH_ERROR
|
||||
+ * - if failure was partial:
|
||||
+ * - session->auth.state = SSH_AUTH_PARTIAL
|
||||
+ * - else:
|
||||
+ * - session->auth.state = SSH_AUTH_STATE_FAILED
|
||||
+ * */
|
||||
+
|
||||
+ /* If this is a server, reject the message */
|
||||
+ if (session->server) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_USERAUTH_SUCCESS: // 52
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
+ * - dh_hanshake_state == DH_STATE_FINISHED
|
||||
+ * - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||
+ * or session->auth.state == SSH_AUTH_STATE_PUBKEY_AUTH_SENT
|
||||
+ * or session->auth.state == SSH_AUTH_STATE_PASSWORD_AUTH_SENT
|
||||
+ * or session->auth.state == SSH_AUTH_STATE_GSSAPI_MIC_SENT
|
||||
+ * or session->auth.state == SSH_AUTH_STATE_AUTH_NONE_SENT
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - session->auth.state = SSH_AUTH_STATE_SUCCESS
|
||||
+ * - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ * - session->flags |= SSH_SESSION_FLAG_AUTHENTICATED
|
||||
+ * - sessions->auth.current_method = SSH_AUTH_METHOD_UNKNOWN
|
||||
+ * */
|
||||
+
|
||||
+ /* If this is a server, reject the message */
|
||||
+ if (session->server) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if ((session->auth.state != SSH_AUTH_STATE_KBDINT_SENT) &&
|
||||
+ (session->auth.state != SSH_AUTH_STATE_PUBKEY_AUTH_SENT) &&
|
||||
+ (session->auth.state != SSH_AUTH_STATE_PASSWORD_AUTH_SENT) &&
|
||||
+ (session->auth.state != SSH_AUTH_STATE_GSSAPI_MIC_SENT) &&
|
||||
+ (session->auth.state != SSH_AUTH_STATE_AUTH_NONE_SENT))
|
||||
+ {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_USERAUTH_BANNER: // 53
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_USERAUTH_PK_OK: // 60
|
||||
+ // SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: // 60
|
||||
+ // SSH2_MSG_USERAUTH_INFO_REQUEST: // 60
|
||||
+ // SSH2_MSG_USERAUTH_GSSAPI_RESPONSE: // 60
|
||||
+
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
+ * - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||
+ * or
|
||||
+ * session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT
|
||||
+ * or
|
||||
+ * session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * Depending on the current state, the message is treated
|
||||
+ * differently:
|
||||
+ * - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||
+ * - session->auth.state = SSH_AUTH_STATE_INFO
|
||||
+ * - session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT
|
||||
+ * - session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN
|
||||
+ * - session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
|
||||
+ * - session->auth.state = SSH_AUTH_STATE_PK_OK
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if ((session->auth.state != SSH_AUTH_STATE_KBDINT_SENT) &&
|
||||
+ (session->auth.state != SSH_AUTH_STATE_PUBKEY_OFFER_SENT) &&
|
||||
+ (session->auth.state != SSH_AUTH_STATE_GSSAPI_REQUEST_SENT))
|
||||
+ {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_USERAUTH_INFO_RESPONSE: // 61
|
||||
+ // SSH2_MSG_USERAUTH_GSSAPI_TOKEN: // 61
|
||||
+
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
+ * - session_state->auth.state == SSH_SESSION_STATE_GSSAPI_TOKEN
|
||||
+ * or
|
||||
+ * session_state->auth.state == SSH_SESSION_STATE_INFO
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if ((session->auth.state != SSH_AUTH_STATE_INFO) &&
|
||||
+ (session->auth.state != SSH_AUTH_STATE_GSSAPI_TOKEN))
|
||||
+ {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE: // 63
|
||||
+ /* TODO Not filtered */
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_USERAUTH_GSSAPI_ERROR: // 64
|
||||
+ /* TODO Not filtered */
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_USERAUTH_GSSAPI_ERRTOK: // 65
|
||||
+ /* TODO Not filtered */
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_USERAUTH_GSSAPI_MIC: // 66
|
||||
+ /* Server only */
|
||||
+
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
+ * - session->gssapi->state == SSH_GSSAPI_STATE_RCV_MIC
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * Depending on the result of the verification, the states are
|
||||
+ * changed:
|
||||
+ * - SSH_AUTH_SUCCESS:
|
||||
+ * - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ * - session->flags != SSH_SESSION_FLAG_AUTHENTICATED
|
||||
+ * - SSH_AUTH_PARTIAL:
|
||||
+ * - None
|
||||
+ * - any other case:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ /* If this is a client, reject the message */
|
||||
+ if (session->client) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_GLOBAL_REQUEST: // 80
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_REQUEST_SUCCESS: // 81
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ * - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - session->global_req_state == SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_REQUEST_FAILURE: // 82
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ * - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - session->global_req_state == SSH_CHANNEL_REQ_STATE_DENIED
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_CHANNEL_OPEN: // 90
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: // 91
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - channel->state = SSH_CHANNEL_STATE_OPEN
|
||||
+ * - channel->flags &= ~SSH_CHANNEL_FLAG_NOT_BOUND
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_CHANNEL_OPEN_FAILURE: // 92
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - channel->state = SSH_CHANNEL_STATE_OPEN_DENIED
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_CHANNEL_WINDOW_ADJUST: // 93
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_CHANNEL_DATA: // 94
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_CHANNEL_EXTENDED_DATA: // 95
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_CHANNEL_EOF: // 96
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - None
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_CHANNEL_CLOSE: // 97
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - channel->state = SSH_CHANNEL_STATE_CLOSED
|
||||
+ * - channel->flags |= SSH_CHANNEL_FLAG_CLOSED_REMOTE
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_CHANNEL_REQUEST: // 98
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - Depends on the request
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_CHANNEL_SUCCESS: // 99
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ * - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ case SSH2_MSG_CHANNEL_FAILURE: // 100
|
||||
+ /*
|
||||
+ * States required:
|
||||
+ * - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
+ * - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
+ *
|
||||
+ * Transitions:
|
||||
+ * - channel->request_state = SSH_CHANNEL_REQ_STATE_DENIED
|
||||
+ * */
|
||||
+
|
||||
+ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
+ rc = SSH_PACKET_DENIED;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ rc = SSH_PACKET_ALLOWED;
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* Unknown message, do not filter */
|
||||
+ rc = SSH_PACKET_UNKNOWN;
|
||||
+ goto end;
|
||||
+ }
|
||||
+
|
||||
+end:
|
||||
+#ifdef DEBUG_PACKET
|
||||
+ if (rc == SSH_PACKET_DENIED) {
|
||||
+ SSH_LOG(SSH_LOG_PACKET, "REJECTED packet type %d: ",
|
||||
+ session->in_packet.type);
|
||||
+ }
|
||||
+
|
||||
+ if (rc == SSH_PACKET_UNKNOWN) {
|
||||
+ SSH_LOG(SSH_LOG_PACKET, "UNKNOWN packet type %d",
|
||||
+ session->in_packet.type);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
/* in nonblocking mode, socket_read will read as much as it can, and return */
|
||||
/* SSH_OK if it has read at least len bytes, otherwise, SSH_AGAIN. */
|
||||
/* in blocking mode, it will read at least len bytes and will block until it's ok. */
|
||||
@@ -158,6 +949,7 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
uint32_t packet_len, compsize, payloadsize;
|
||||
uint8_t padding;
|
||||
size_t processed = 0; /* number of byte processed from the callback */
|
||||
+ enum ssh_packet_filter_result_e filter_result;
|
||||
|
||||
if(session->current_crypto != NULL) {
|
||||
current_macsize = hmac_digest_len(session->current_crypto->in_hmac);
|
||||
@@ -345,8 +1137,21 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
"packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]",
|
||||
session->in_packet.type, packet_len, padding, compsize, payloadsize);
|
||||
|
||||
- /* Execute callbacks */
|
||||
- ssh_packet_process(session, session->in_packet.type);
|
||||
+ /* Check if the packet is expected */
|
||||
+ filter_result = ssh_packet_incoming_filter(session);
|
||||
+
|
||||
+ switch(filter_result) {
|
||||
+ case SSH_PACKET_ALLOWED:
|
||||
+ /* Execute callbacks */
|
||||
+ ssh_packet_process(session, session->in_packet.type);
|
||||
+ break;
|
||||
+ case SSH_PACKET_DENIED:
|
||||
+ goto error;
|
||||
+ case SSH_PACKET_UNKNOWN:
|
||||
+ ssh_packet_send_unimplemented(session, session->recv_seq - 1);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
session->packet_state = PACKET_STATE_INIT;
|
||||
if (processed < receivedlen) {
|
||||
/* Handle a potential packet left in socket buffer */
|
||||
--
|
||||
cgit v1.2.1
|
||||
|
||||
@ -1,543 +0,0 @@
|
||||
From 09a7638575b3c07ad227763e1f03f7553b045e79 Mon Sep 17 00:00:00 2001
|
||||
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Date: Fri, 7 Sep 2018 15:26:49 +0200
|
||||
Subject: CVE-2018-10933: Add tests for packet filtering
|
||||
|
||||
Created the test torture_packet_filter.c which tests if packets are
|
||||
being correctly filtered.
|
||||
|
||||
Fixes T101
|
||||
|
||||
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
|
||||
---
|
||||
tests/unittests/CMakeLists.txt | 3 +
|
||||
tests/unittests/torture_packet_filter.c | 502 ++++++++++++++++++++++++++++++++
|
||||
2 files changed, 505 insertions(+)
|
||||
create mode 100644 tests/unittests/torture_packet_filter.c
|
||||
|
||||
diff --git a/tests/unittests/CMakeLists.txt b/tests/unittests/CMakeLists.txt
|
||||
index 397ebd05..13887ff1 100644
|
||||
--- a/tests/unittests/CMakeLists.txt
|
||||
+++ b/tests/unittests/CMakeLists.txt
|
||||
@@ -35,6 +35,9 @@ target_compile_options(torture_knownhosts_parsing PRIVATE ${DEFAULT_C_COMPILE_FL
|
||||
add_cmocka_test(torture_hashes torture_hashes.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_hashes PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
+add_cmocka_test(torture_packet_filter torture_packet_filter.c ${TORTURE_LIBRARY})
|
||||
+target_compile_options(torture_packet_filter PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
+
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
add_cmocka_test(torture_rand torture_rand.c ${TEST_TARGET_LIBRARIES})
|
||||
target_compile_options(torture_rand PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
diff --git a/tests/unittests/torture_packet_filter.c b/tests/unittests/torture_packet_filter.c
|
||||
new file mode 100644
|
||||
index 00000000..72cbc4cd
|
||||
--- /dev/null
|
||||
+++ b/tests/unittests/torture_packet_filter.c
|
||||
@@ -0,0 +1,502 @@
|
||||
+/*
|
||||
+ * This file is part of the SSH Library
|
||||
+ *
|
||||
+ * Copyright (c) 2018 by Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
+ *
|
||||
+ * The SSH Library is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU Lesser General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
+ * option) any later version.
|
||||
+ *
|
||||
+ * The SSH Library is distributed in the hope that it will be useful, but
|
||||
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
+ * License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Lesser General Public License
|
||||
+ * along with the SSH Library; see the file COPYING. If not, write to
|
||||
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
+ * MA 02111-1307, USA.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * This test checks if the messages accepted by the packet filter were intented
|
||||
+ * to be accepted.
|
||||
+ *
|
||||
+ * The process consists in 2 steps:
|
||||
+ * - Try the filter with a message type in an arbitrary state
|
||||
+ * - If the message is accepted by the filter, check if the message is in the
|
||||
+ * set of accepted states.
|
||||
+ *
|
||||
+ * Only the values selected by the flag (COMPARE_*) are considered.
|
||||
+ * */
|
||||
+
|
||||
+#include "config.h"
|
||||
+
|
||||
+#define LIBSSH_STATIC
|
||||
+
|
||||
+#include "torture.h"
|
||||
+#include "libssh/priv.h"
|
||||
+#include "libssh/libssh.h"
|
||||
+#include "libssh/session.h"
|
||||
+#include "libssh/auth.h"
|
||||
+#include "libssh/ssh2.h"
|
||||
+#include "libssh/packet.h"
|
||||
+
|
||||
+#include "packet.c"
|
||||
+
|
||||
+#define COMPARE_SESSION_STATE 1
|
||||
+#define COMPARE_ROLE (1 << 1)
|
||||
+#define COMPARE_DH_STATE (1 << 2)
|
||||
+#define COMPARE_AUTH_STATE (1 << 3)
|
||||
+#define COMPARE_GLOBAL_REQ_STATE (1 << 4)
|
||||
+#define COMPARE_CURRENT_METHOD (1 << 5)
|
||||
+
|
||||
+#define SESSION_STATE_COUNT 11
|
||||
+#define DH_STATE_COUNT 4
|
||||
+#define AUTH_STATE_COUNT 15
|
||||
+#define GLOBAL_REQ_STATE_COUNT 5
|
||||
+#define MESSAGE_COUNT 100 // from 1 to 100
|
||||
+
|
||||
+#define ROLE_CLIENT 0
|
||||
+#define ROLE_SERVER 1
|
||||
+
|
||||
+/*
|
||||
+ * This is the list of currently unfiltered message types.
|
||||
+ * Only unrecognized types should be in this list.
|
||||
+ * */
|
||||
+static uint8_t unfiltered[] = {
|
||||
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||
+ 22, 23, 24, 25, 26, 27, 28, 29,
|
||||
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
|
||||
+ 54, 55, 56, 57, 58, 59,
|
||||
+ 62,
|
||||
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
+ 83, 84, 85, 86, 87, 88, 89,
|
||||
+};
|
||||
+
|
||||
+typedef struct global_state_st {
|
||||
+ /* If the bit in this flag is zero, the corresponding state is not
|
||||
+ * considered, working as a wildcard (meaning any value is accepted) */
|
||||
+ uint32_t flags;
|
||||
+ uint8_t role;
|
||||
+ enum ssh_session_state_e session;
|
||||
+ enum ssh_dh_state_e dh;
|
||||
+ enum ssh_auth_state_e auth;
|
||||
+ enum ssh_channel_request_state_e global_req;
|
||||
+} global_state;
|
||||
+
|
||||
+static int cmp_state(const void *e1, const void *e2)
|
||||
+{
|
||||
+ global_state *s1 = (global_state *) e1;
|
||||
+ global_state *s2 = (global_state *) e2;
|
||||
+
|
||||
+ /* Compare role (client == 0 or server == 1)*/
|
||||
+ if (s1->role < s2->role) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ else if (s1->role > s2->role) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Compare session state */
|
||||
+ if (s1->session < s2->session) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ else if (s1->session > s2->session) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Compare DH state */
|
||||
+ if (s1->dh < s2->dh) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ else if (s1->dh > s2->dh) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Compare auth */
|
||||
+ if (s1->auth < s2->auth) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ else if (s1->auth > s2->auth) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Compare global_req */
|
||||
+ if (s1->global_req < s2->global_req) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ else if (s1->global_req > s2->global_req) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ /* If all equal, they are equal */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cmp_state_search(const void *key, const void *array_element)
|
||||
+{
|
||||
+ global_state *s1 = (global_state *) key;
|
||||
+ global_state *s2 = (global_state *) array_element;
|
||||
+
|
||||
+ int result = 0;
|
||||
+
|
||||
+ if (s2->flags & COMPARE_ROLE) {
|
||||
+ /* Compare role (client == 0 or server == 1)*/
|
||||
+ if (s1->role < s2->role) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ else if (s1->role > s2->role) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (s2->flags & COMPARE_SESSION_STATE) {
|
||||
+ /* Compare session state */
|
||||
+ if (s1->session < s2->session) {
|
||||
+ result = -1;
|
||||
+ goto end;
|
||||
+ }
|
||||
+ else if (s1->session > s2->session) {
|
||||
+ result = 1;
|
||||
+ goto end;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (s2->flags & COMPARE_DH_STATE) {
|
||||
+ /* Compare DH state */
|
||||
+ if (s1->dh < s2->dh) {
|
||||
+ result = -1;
|
||||
+ goto end;
|
||||
+ }
|
||||
+ else if (s1->dh > s2->dh) {
|
||||
+ result = 1;
|
||||
+ goto end;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (s2->flags & COMPARE_AUTH_STATE) {
|
||||
+ /* Compare auth */
|
||||
+ if (s1->auth < s2->auth) {
|
||||
+ result = -1;
|
||||
+ goto end;
|
||||
+ }
|
||||
+ else if (s1->auth > s2->auth) {
|
||||
+ result = 1;
|
||||
+ goto end;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (s2->flags & COMPARE_GLOBAL_REQ_STATE) {
|
||||
+ /* Compare global_req */
|
||||
+ if (s1->global_req < s2->global_req) {
|
||||
+ result = -1;
|
||||
+ goto end;
|
||||
+ }
|
||||
+ else if (s1->global_req > s2->global_req) {
|
||||
+ result = 1;
|
||||
+ goto end;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+end:
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+static int is_state_accepted(global_state *tested, global_state *accepted,
|
||||
+ int accepted_len)
|
||||
+{
|
||||
+ global_state *found = NULL;
|
||||
+
|
||||
+ found = bsearch(tested, accepted, accepted_len, sizeof(global_state),
|
||||
+ cmp_state_search);
|
||||
+
|
||||
+ if (found != NULL) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cmp_uint8(const void *i, const void *j)
|
||||
+{
|
||||
+ uint8_t e1 = *((uint8_t *)i);
|
||||
+ uint8_t e2 = *((uint8_t *)j);
|
||||
+
|
||||
+ if (e1 < e2) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ else if (e1 > e2) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int check_unfiltered(uint8_t msg_type)
|
||||
+{
|
||||
+ uint8_t *found;
|
||||
+
|
||||
+ found = bsearch(&msg_type, unfiltered, sizeof(unfiltered)/sizeof(uint8_t),
|
||||
+ sizeof(uint8_t), cmp_uint8);
|
||||
+
|
||||
+ if (found != NULL) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void torture_packet_filter_check_unfiltered(void **state)
|
||||
+{
|
||||
+ ssh_session session;
|
||||
+
|
||||
+ int role_c;
|
||||
+ int auth_c;
|
||||
+ int session_c;
|
||||
+ int dh_c;
|
||||
+ int global_req_c;
|
||||
+
|
||||
+ uint8_t msg_type;
|
||||
+
|
||||
+ enum ssh_packet_filter_result_e rc;
|
||||
+ int in_unfiltered;
|
||||
+
|
||||
+ session = ssh_new();
|
||||
+
|
||||
+ for (msg_type = 1; msg_type <= MESSAGE_COUNT; msg_type++) {
|
||||
+ session->in_packet.type = msg_type;
|
||||
+ for (role_c = 0; role_c < 2; role_c++) {
|
||||
+ session->server = role_c;
|
||||
+ for (session_c = 0; session_c < SESSION_STATE_COUNT; session_c++) {
|
||||
+ session->session_state = session_c;
|
||||
+ for (dh_c = 0; dh_c < DH_STATE_COUNT; dh_c++) {
|
||||
+ session->dh_handshake_state = dh_c;
|
||||
+ for (auth_c = 0; auth_c < AUTH_STATE_COUNT; auth_c++) {
|
||||
+ session->auth.state = auth_c;
|
||||
+ for (global_req_c = 0;
|
||||
+ global_req_c < GLOBAL_REQ_STATE_COUNT;
|
||||
+ global_req_c++)
|
||||
+ {
|
||||
+ session->global_req_state = global_req_c;
|
||||
+
|
||||
+ rc = ssh_packet_incoming_filter(session);
|
||||
+
|
||||
+ if (rc == SSH_PACKET_UNKNOWN) {
|
||||
+ in_unfiltered = check_unfiltered(msg_type);
|
||||
+
|
||||
+ if (!in_unfiltered) {
|
||||
+ fprintf(stderr, "Message type %d UNFILTERED "
|
||||
+ "in state: role %d, session %d, dh %d, auth %d\n",
|
||||
+ msg_type, role_c, session_c, dh_c, auth_c);
|
||||
+ }
|
||||
+ assert_int_equal(in_unfiltered, 1);
|
||||
+ }
|
||||
+ else {
|
||||
+ in_unfiltered = check_unfiltered(msg_type);
|
||||
+
|
||||
+ if (in_unfiltered) {
|
||||
+ fprintf(stderr, "Message type %d NOT UNFILTERED "
|
||||
+ "in state: role %d, session %d, dh %d, auth %d\n",
|
||||
+ msg_type, role_c, session_c, dh_c, auth_c);
|
||||
+ }
|
||||
+ assert_int_equal(in_unfiltered, 0);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ ssh_free(session);
|
||||
+}
|
||||
+
|
||||
+static int check_message_in_all_states(global_state accepted[],
|
||||
+ int accepted_count, uint8_t msg_type)
|
||||
+{
|
||||
+ ssh_session session;
|
||||
+
|
||||
+ int role_c;
|
||||
+ int auth_c;
|
||||
+ int session_c;
|
||||
+ int dh_c;
|
||||
+ int global_req_c;
|
||||
+
|
||||
+ enum ssh_packet_filter_result_e rc;
|
||||
+ int in_accepted;
|
||||
+
|
||||
+ global_state key;
|
||||
+
|
||||
+ session = ssh_new();
|
||||
+
|
||||
+ /* Sort the accepted array so that the elements can be searched using
|
||||
+ * bsearch */
|
||||
+ qsort(accepted, accepted_count, sizeof(global_state), cmp_state);
|
||||
+
|
||||
+ session->in_packet.type = msg_type;
|
||||
+
|
||||
+ for (role_c = 0; role_c < 2; role_c++) {
|
||||
+ session->server = role_c;
|
||||
+ key.role = role_c;
|
||||
+ for (session_c = 0; session_c < SESSION_STATE_COUNT; session_c++) {
|
||||
+ session->session_state = session_c;
|
||||
+ key.session = session_c;
|
||||
+ for (dh_c = 0; dh_c < DH_STATE_COUNT; dh_c++) {
|
||||
+ session->dh_handshake_state = dh_c;
|
||||
+ key.dh = dh_c;
|
||||
+ for (auth_c = 0; auth_c < AUTH_STATE_COUNT; auth_c++) {
|
||||
+ session->auth.state = auth_c;
|
||||
+ key.auth = auth_c;
|
||||
+ for (global_req_c = 0;
|
||||
+ global_req_c < GLOBAL_REQ_STATE_COUNT;
|
||||
+ global_req_c++)
|
||||
+ {
|
||||
+ session->global_req_state = global_req_c;
|
||||
+ key.global_req = global_req_c;
|
||||
+
|
||||
+ rc = ssh_packet_incoming_filter(session);
|
||||
+
|
||||
+ if (rc == SSH_PACKET_ALLOWED) {
|
||||
+ in_accepted = is_state_accepted(&key, accepted,
|
||||
+ accepted_count);
|
||||
+
|
||||
+ if (!in_accepted) {
|
||||
+ fprintf(stderr, "Message type %d ALLOWED "
|
||||
+ "in state: role %d, session %d, dh %d, auth %d\n",
|
||||
+ msg_type, role_c, session_c, dh_c, auth_c);
|
||||
+ }
|
||||
+ assert_int_equal(in_accepted, 1);
|
||||
+ }
|
||||
+ else if (rc == SSH_PACKET_DENIED) {
|
||||
+ in_accepted = is_state_accepted(&key, accepted, accepted_count);
|
||||
+
|
||||
+ if (in_accepted) {
|
||||
+ fprintf(stderr, "Message type %d DENIED "
|
||||
+ "in state: role %d, session %d, dh %d, auth %d\n",
|
||||
+ msg_type, role_c, session_c, dh_c, auth_c);
|
||||
+ }
|
||||
+ assert_int_equal(in_accepted, 0);
|
||||
+ }
|
||||
+ else {
|
||||
+ fprintf(stderr, "Message type %d UNFILTERED "
|
||||
+ "in state: role %d, session %d, dh %d, auth %d\n",
|
||||
+ msg_type, role_c, session_c, dh_c, auth_c);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ssh_free(session);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void torture_packet_filter_check_auth_success(void **state)
|
||||
+{
|
||||
+ int rc;
|
||||
+
|
||||
+ global_state accepted[] = {
|
||||
+ {
|
||||
+ .flags = (COMPARE_SESSION_STATE |
|
||||
+ COMPARE_ROLE |
|
||||
+ COMPARE_AUTH_STATE |
|
||||
+ COMPARE_DH_STATE),
|
||||
+ .role = ROLE_CLIENT,
|
||||
+ .session = SSH_SESSION_STATE_AUTHENTICATING,
|
||||
+ .dh = DH_STATE_FINISHED,
|
||||
+ .auth = SSH_AUTH_STATE_PUBKEY_AUTH_SENT,
|
||||
+ },
|
||||
+ {
|
||||
+ .flags = (COMPARE_SESSION_STATE |
|
||||
+ COMPARE_ROLE |
|
||||
+ COMPARE_AUTH_STATE |
|
||||
+ COMPARE_DH_STATE),
|
||||
+ .role = ROLE_CLIENT,
|
||||
+ .session = SSH_SESSION_STATE_AUTHENTICATING,
|
||||
+ .dh = DH_STATE_FINISHED,
|
||||
+ .auth = SSH_AUTH_STATE_PASSWORD_AUTH_SENT,
|
||||
+ },
|
||||
+ {
|
||||
+ .flags = (COMPARE_SESSION_STATE |
|
||||
+ COMPARE_ROLE |
|
||||
+ COMPARE_AUTH_STATE |
|
||||
+ COMPARE_DH_STATE),
|
||||
+ .role = ROLE_CLIENT,
|
||||
+ .session = SSH_SESSION_STATE_AUTHENTICATING,
|
||||
+ .dh = DH_STATE_FINISHED,
|
||||
+ .auth = SSH_AUTH_STATE_GSSAPI_MIC_SENT,
|
||||
+ },
|
||||
+ {
|
||||
+ .flags = (COMPARE_SESSION_STATE |
|
||||
+ COMPARE_ROLE |
|
||||
+ COMPARE_AUTH_STATE |
|
||||
+ COMPARE_DH_STATE),
|
||||
+ .role = ROLE_CLIENT,
|
||||
+ .session = SSH_SESSION_STATE_AUTHENTICATING,
|
||||
+ .dh = DH_STATE_FINISHED,
|
||||
+ .auth = SSH_AUTH_STATE_KBDINT_SENT,
|
||||
+ },
|
||||
+ {
|
||||
+ .flags = (COMPARE_SESSION_STATE |
|
||||
+ COMPARE_ROLE |
|
||||
+ COMPARE_AUTH_STATE |
|
||||
+ COMPARE_DH_STATE |
|
||||
+ COMPARE_CURRENT_METHOD),
|
||||
+ .role = ROLE_CLIENT,
|
||||
+ .session = SSH_SESSION_STATE_AUTHENTICATING,
|
||||
+ .dh = DH_STATE_FINISHED,
|
||||
+ .auth = SSH_AUTH_STATE_AUTH_NONE_SENT,
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ int accepted_count = 5;
|
||||
+
|
||||
+ /* Unused */
|
||||
+ (void) state;
|
||||
+
|
||||
+ rc = check_message_in_all_states(accepted, accepted_count,
|
||||
+ SSH2_MSG_USERAUTH_SUCCESS);
|
||||
+
|
||||
+ assert_int_equal(rc, 0);
|
||||
+}
|
||||
+
|
||||
+static void torture_packet_filter_check_channel_open(void **state)
|
||||
+{
|
||||
+ int rc;
|
||||
+
|
||||
+ /* The only condition to accept a CHANNEL_OPEN is to be authenticated */
|
||||
+ global_state accepted[] = {
|
||||
+ {
|
||||
+ .flags = COMPARE_SESSION_STATE,
|
||||
+ .session = SSH_SESSION_STATE_AUTHENTICATED,
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ int accepted_count = 1;
|
||||
+
|
||||
+ /* Unused */
|
||||
+ (void) state;
|
||||
+
|
||||
+ rc = check_message_in_all_states(accepted, accepted_count,
|
||||
+ SSH2_MSG_CHANNEL_OPEN);
|
||||
+
|
||||
+ assert_int_equal(rc, 0);
|
||||
+}
|
||||
+
|
||||
+int torture_run_tests(void)
|
||||
+{
|
||||
+ int rc;
|
||||
+ struct CMUnitTest tests[] = {
|
||||
+ cmocka_unit_test(torture_packet_filter_check_auth_success),
|
||||
+ cmocka_unit_test(torture_packet_filter_check_channel_open),
|
||||
+ cmocka_unit_test(torture_packet_filter_check_unfiltered),
|
||||
+ };
|
||||
+
|
||||
+ ssh_init();
|
||||
+ torture_filter_tests(tests);
|
||||
+ rc = cmocka_run_group_tests(tests, NULL, NULL);
|
||||
+ ssh_finalize();
|
||||
+ return rc;
|
||||
+}
|
||||
--
|
||||
cgit v1.2.1
|
||||
|
||||
54
libssh.spec
54
libssh.spec
@ -1,34 +1,21 @@
|
||||
Name: libssh
|
||||
Version: 0.8.3
|
||||
Release: 8
|
||||
Version: 0.9.4
|
||||
Release: 1
|
||||
Summary: A library implementing the SSH protocol
|
||||
License: LGPLv2+
|
||||
URL: https://www.libssh.org
|
||||
Source0: https://www.libssh.org/files/0.8/%{name}-%{version}.tar.xz
|
||||
Source1: https://www.libssh.org/files/0.8/%{name}-%{version}.tar.xz.asc
|
||||
Source2: https://cryptomilk.org/gpgkey-8DFF53E18F2ABC8D8F3C92237EE0FC4DCC014E3D.gpg#/%{name}.keyring
|
||||
URL: http://www.libssh.org
|
||||
|
||||
Patch1: libssh-0.8.3-fix-covscan-errors.patch
|
||||
Patch2: libssh-0.8.3-fixes-the-oss-fuzz-bug.patch
|
||||
Source0: https://www.libssh.org/files/0.9/%{name}-%{version}.tar.xz
|
||||
Source1: https://www.libssh.org/files/0.9/%{name}-%{version}.tar.xz.asc
|
||||
Source2: https://cryptomilk.org/gpgkey-8DFF53E18F2ABC8D8F3C92237EE0FC4DCC014E3D.gpg#/%{name}.keyring
|
||||
|
||||
#patches6000-patches6007 come from https://git.libssh.org/
|
||||
Patch6000: libssh-stable-0p8-CVE-2018-10933-part1.patch
|
||||
Patch6001: libssh-stable-0p8-CVE-2018-10933-part2.patch
|
||||
Patch6002: libssh-stable-0p8-CVE-2018-10933-part3.patch
|
||||
Patch6003: libssh-stable-0p8-CVE-2018-10933-part4.patch
|
||||
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
|
||||
Patch6013: CVE-2020-1730.patch
|
||||
Patch1: libssh-0.9.4-fix-version.patch
|
||||
|
||||
BuildRequires: cmake libcmocka-devel krb5-devel zlib-devel pkgconfig
|
||||
BuildRequires: doxygen gcc-c++ gnupg2 openssl-devel
|
||||
BuildRequires: cmake gcc-c++ gnupg2 openssl-devel pkgconfig zlib-devel
|
||||
BuildRequires: krb5-devel libcmocka-devel openssh-clients openssh-server
|
||||
BuildRequires: nmap-ncat libssh
|
||||
|
||||
Recommends: crypto-policies
|
||||
|
||||
Provides: libssh_threads.so.4()(64bit)
|
||||
|
||||
@ -61,15 +48,15 @@ fi
|
||||
pushd obj
|
||||
|
||||
%cmake .. \
|
||||
-DUNIT_TESTING=ON
|
||||
-DUNIT_TESTING=ON \
|
||||
|
||||
%make_build VERBOSE=1
|
||||
make docs
|
||||
|
||||
popd
|
||||
|
||||
%install
|
||||
make DESTDIR=%{buildroot} install/fast -C obj
|
||||
install -d -m755 %{buildroot}%{_sysconfdir}/libssh
|
||||
|
||||
pushd %{buildroot}%{_libdir}
|
||||
for i in libssh.so*;
|
||||
@ -82,6 +69,7 @@ do
|
||||
ln -s "${_target}" "${_link_name}"
|
||||
done;
|
||||
popd
|
||||
cp -p %{_libdir}/{libssh,libssh_threads}.so.4.7.0 %{buildroot}%{_libdir}/
|
||||
|
||||
%ldconfig_scriptlets
|
||||
|
||||
@ -100,19 +88,19 @@ popd
|
||||
%defattr(-,root,root)
|
||||
%{_includedir}/libssh/
|
||||
%{_libdir}/cmake/libssh/
|
||||
%{_libdir}/pkgconfig/*.pc
|
||||
%{_libdir}/pkgconfig/libssh.pc
|
||||
%{_libdir}/*.so
|
||||
|
||||
%files help
|
||||
%defattr(-,root,root)
|
||||
%doc README ChangeLog obj/doc/html
|
||||
%doc ChangeLog README
|
||||
|
||||
%changelog
|
||||
* Fri Apr 17 2020 openEuler Buildteam <buildteam@openeuler.org> - 0.8.3-8
|
||||
- Type:cves
|
||||
- ID:CVE-2020-1730
|
||||
* Mon Apr 20 2020 openEuler Buildteam <buildteam@openeuler.org> - 0.9.4-1
|
||||
- Type:bugfix
|
||||
- Id:NA
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2020-1730
|
||||
- DESC:update to 0.9.4
|
||||
|
||||
* Sun Jan 12 2020 openEuler Buildteam <buildteam@openeuler.org> - 0.8.3-7
|
||||
- Type:bugfix
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user