aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/libssh.h2
-rw-r--r--include/libssh/session.h2
-rw-r--r--src/ecdh_crypto.c6
-rw-r--r--src/options.c50
-rw-r--r--src/pki.c2
-rw-r--r--src/socket.c64
6 files changed, 115 insertions, 11 deletions
diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h
index e80214c9..711f5c1e 100644
--- a/include/libssh/libssh.h
+++ b/include/libssh/libssh.h
@@ -415,6 +415,8 @@ enum ssh_options_e {
SSH_OPTIONS_PROCESS_CONFIG,
SSH_OPTIONS_REKEY_DATA,
SSH_OPTIONS_REKEY_TIME,
+ SSH_OPTIONS_CLIENT_TRACE,
+ SSH_OPTIONS_SERVER_TRACE,
};
enum {
diff --git a/include/libssh/session.h b/include/libssh/session.h
index 944213c9..7e0298b8 100644
--- a/include/libssh/session.h
+++ b/include/libssh/session.h
@@ -231,6 +231,8 @@ struct ssh_session_struct {
uint8_t options_seen[SOC_MAX];
uint64_t rekey_data;
uint32_t rekey_time;
+ char *client_trace;
+ char *server_trace;
} opts;
/* counters */
ssh_counter socket_counter;
diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c
index 23654d02..91d3624f 100644
--- a/src/ecdh_crypto.c
+++ b/src/ecdh_crypto.c
@@ -119,9 +119,9 @@ int ssh_client_ecdh_init(ssh_session session){
int ecdh_build_k(ssh_session session) {
const EC_GROUP *group = EC_KEY_get0_group(session->next_crypto->ecdh_privkey);
- EC_POINT *pubkey;
- void *buffer;
- int rc;
+ EC_POINT *pubkey = NULL;
+ void *buffer = NULL;
+ int rc = -1;
int len = (EC_GROUP_get_degree(group) + 7) / 8;
bignum_CTX ctx = bignum_ctx_new();
if (ctx == NULL) {
diff --git a/src/options.c b/src/options.c
index 672735a4..2b491336 100644
--- a/src/options.c
+++ b/src/options.c
@@ -465,6 +465,16 @@ int ssh_options_set_algo(ssh_session session,
* in seconds. RFC 4253 Section 9 recommends one hour.
* (uint32_t, 0=off)
*
+ * - SSH_OPTIONS_CLIENT_TRACE
+ * Set the path to a file to dump all packets a client sends.
+ * This is only working on a SSH client implementation. It is
+ * useful to create traces for fuzzing.
+ *
+ * - SSH_OPTIONS_SERVER_TRACE
+ * Set the path to a file to dump all packets a client receives.
+ * This is only working on a SSH client implementation. It is
+ * useful to create traces for fuzzing.
+ *
* @param value The value to set. This is a generic pointer and the
* datatype which is used should be set according to the
* type set.
@@ -1030,6 +1040,46 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
session->opts.rekey_time = (*x) * 1000;
}
break;
+ case SSH_OPTIONS_CLIENT_TRACE:
+ if (value == NULL) {
+ ssh_set_error_invalid(session);
+ return -1;
+ } else {
+ switch(session->type) {
+ case SSH_SESSION_TYPE_CLIENT:
+ break;
+ case SSH_SESSION_TYPE_SERVER:
+ return -1;
+ }
+ q = strdup(value);
+ if (q == NULL) {
+ ssh_set_error_oom(session);
+ return -1;
+ }
+ SAFE_FREE(session->opts.client_trace);
+ session->opts.client_trace = q;
+ }
+ break;
+ case SSH_OPTIONS_SERVER_TRACE:
+ if (value == NULL) {
+ ssh_set_error_invalid(session);
+ return -1;
+ } else {
+ switch(session->type) {
+ case SSH_SESSION_TYPE_CLIENT:
+ break;
+ case SSH_SESSION_TYPE_SERVER:
+ return -1;
+ }
+ q = strdup(value);
+ if (q == NULL) {
+ ssh_set_error_oom(session);
+ return -1;
+ }
+ SAFE_FREE(session->opts.server_trace);
+ session->opts.server_trace = q;
+ }
+ break;
default:
ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
return -1;
diff --git a/src/pki.c b/src/pki.c
index 1d99ee56..c07b186f 100644
--- a/src/pki.c
+++ b/src/pki.c
@@ -339,7 +339,7 @@ static enum ssh_digest_e ssh_key_hash_from_name(const char *name)
*/
int ssh_key_algorithm_allowed(ssh_session session, const char *type)
{
- const char *allowed_list;
+ const char *allowed_list = NULL;
switch(session->type) {
case SSH_SESSION_TYPE_CLIENT:
diff --git a/src/socket.c b/src/socket.c
index 974e712a..e862584c 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -81,6 +81,8 @@ struct ssh_socket_struct {
not block */
int write_wontblock;
int data_except;
+ FILE *client_fp;
+ FILE *server_fp;
enum ssh_socket_states_e state;
ssh_buffer out_buffer;
ssh_buffer in_buffer;
@@ -156,15 +158,26 @@ ssh_socket ssh_socket_new(ssh_session session)
s->in_buffer = ssh_buffer_new();
if (s->in_buffer == NULL) {
ssh_set_error_oom(session);
- SAFE_FREE(s);
- return NULL;
+ goto error;
}
s->out_buffer=ssh_buffer_new();
if (s->out_buffer == NULL) {
ssh_set_error_oom(session);
- ssh_buffer_free(s->in_buffer);
- SAFE_FREE(s);
- return NULL;
+ goto error;
+ }
+
+ if (session->opts.client_trace != NULL) {
+ s->client_fp = fopen(session->opts.client_trace, "wb");
+ if (s->client_fp == NULL) {
+ goto error;
+ };
+ }
+
+ if (session->opts.server_trace != NULL) {
+ s->server_fp = fopen(session->opts.server_trace, "wb");
+ if (s->server_fp == NULL) {
+ goto error;
+ };
}
s->read_wontblock = 0;
s->write_wontblock = 0;
@@ -172,6 +185,10 @@ ssh_socket ssh_socket_new(ssh_session session)
s->poll_handle = NULL;
s->state=SSH_SOCKET_NONE;
return s;
+error:
+ ssh_socket_free(s);
+
+ return NULL;
}
/**
@@ -393,8 +410,16 @@ void ssh_socket_free(ssh_socket s)
return;
}
ssh_socket_close(s);
- ssh_buffer_free(s->in_buffer);
- ssh_buffer_free(s->out_buffer);
+
+ if (s->client_fp != NULL) {
+ fclose(s->client_fp);
+ }
+ if (s->server_fp != NULL) {
+ fclose(s->server_fp);
+ }
+ SSH_BUFFER_FREE(s->in_buffer);
+ SSH_BUFFER_FREE(s->out_buffer);
+
SAFE_FREE(s);
}
@@ -525,6 +550,18 @@ static ssize_t ssh_socket_unbuffered_read(ssh_socket s,
s->data_except = 1;
}
+ if (rc > 0) {
+ switch(s->session->type) {
+ case SSH_SESSION_TYPE_CLIENT:
+ if (s->server_fp != NULL) {
+ fwrite(buffer, rc, 1, s->server_fp);
+ }
+ break;
+ case SSH_SESSION_TYPE_SERVER:
+ break;
+ }
+ }
+
return rc;
}
@@ -557,6 +594,19 @@ static ssize_t ssh_socket_unbuffered_write(ssh_socket s,
s->last_errno = errno;
#endif
s->write_wontblock = 0;
+
+ if (w > 0) {
+ switch(s->session->type) {
+ case SSH_SESSION_TYPE_CLIENT:
+ if (s->client_fp != NULL) {
+ fwrite(buffer, w, 1, s->client_fp);
+ }
+ break;
+ case SSH_SESSION_TYPE_SERVER:
+ break;
+ }
+ }
+
/* Reactive the POLLOUT detector in the poll multiplexer system */
if (s->poll_handle) {
SSH_LOG(SSH_LOG_PACKET, "Enabling POLLOUT for socket");