aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client.c143
-rw-r--r--src/config.c54
-rw-r--r--src/kex.c76
-rw-r--r--src/misc.c23
-rw-r--r--src/pki_gcrypt.c5
5 files changed, 195 insertions, 106 deletions
diff --git a/src/client.c b/src/client.c
index 4610b787..3984b3f4 100644
--- a/src/client.c
+++ b/src/client.c
@@ -689,84 +689,89 @@ int ssh_get_openssh_version(ssh_session session) {
*
* @param[in] session The SSH session to use.
*/
-void ssh_disconnect(ssh_session session) {
- struct ssh_iterator *it;
- int rc;
+void
+ssh_disconnect(ssh_session session)
+{
+ struct ssh_iterator *it;
+ int rc;
- if (session == NULL) {
- return;
- }
+ if (session == NULL) {
+ return;
+ }
- if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
- rc = ssh_buffer_pack(session->out_buffer,
- "bdss",
- SSH2_MSG_DISCONNECT,
- SSH2_DISCONNECT_BY_APPLICATION,
- "Bye Bye",
- ""); /* language tag */
- if (rc != SSH_OK){
- ssh_set_error_oom(session);
- goto error;
+ if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
+ rc = ssh_buffer_pack(session->out_buffer,
+ "bdss",
+ SSH2_MSG_DISCONNECT,
+ SSH2_DISCONNECT_BY_APPLICATION,
+ "Bye Bye",
+ ""); /* language tag */
+ if (rc != SSH_OK) {
+ ssh_set_error_oom(session);
+ goto error;
+ }
+
+ ssh_packet_send(session);
+ ssh_socket_close(session->socket);
}
- ssh_packet_send(session);
- ssh_socket_close(session->socket);
- }
error:
- session->recv_seq = 0;
- session->send_seq = 0;
- session->alive = 0;
- if (session->socket != NULL){
- ssh_socket_reset(session->socket);
- }
- session->opts.fd = SSH_INVALID_SOCKET;
- session->session_state=SSH_SESSION_STATE_DISCONNECTED;
+ session->recv_seq = 0;
+ session->send_seq = 0;
+ session->alive = 0;
+ if (session->socket != NULL){
+ ssh_socket_reset(session->socket);
+ }
+ session->opts.fd = SSH_INVALID_SOCKET;
+ session->session_state = SSH_SESSION_STATE_DISCONNECTED;
+ session->pending_call_state = SSH_PENDING_CALL_NONE;
- while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
- ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
- ssh_list_remove(session->channels, it);
- }
- if(session->current_crypto){
- crypto_free(session->current_crypto);
- session->current_crypto=NULL;
- }
- if (session->next_crypto) {
- crypto_free(session->next_crypto);
- session->next_crypto = crypto_new();
- if (session->next_crypto == NULL) {
- ssh_set_error_oom(session);
+ while ((it = ssh_list_get_iterator(session->channels)) != NULL) {
+ ssh_channel_do_free(ssh_iterator_value(ssh_channel, it));
+ ssh_list_remove(session->channels, it);
}
- }
- if (session->in_buffer) {
- ssh_buffer_reinit(session->in_buffer);
- }
- if (session->out_buffer) {
- ssh_buffer_reinit(session->out_buffer);
- }
- if (session->in_hashbuf) {
- ssh_buffer_reinit(session->in_hashbuf);
- }
- if (session->out_hashbuf) {
- ssh_buffer_reinit(session->out_hashbuf);
- }
- session->auth.supported_methods = 0;
- SAFE_FREE(session->serverbanner);
- SAFE_FREE(session->clientbanner);
-
- if(session->ssh_message_list){
- ssh_message msg;
- while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
- != NULL){
- ssh_message_free(msg);
+ if (session->current_crypto) {
+ crypto_free(session->current_crypto);
+ session->current_crypto = NULL;
}
- ssh_list_free(session->ssh_message_list);
- session->ssh_message_list=NULL;
- }
+ if (session->next_crypto) {
+ crypto_free(session->next_crypto);
+ session->next_crypto = crypto_new();
+ if (session->next_crypto == NULL) {
+ ssh_set_error_oom(session);
+ }
+ }
+ if (session->in_buffer) {
+ ssh_buffer_reinit(session->in_buffer);
+ }
+ if (session->out_buffer) {
+ ssh_buffer_reinit(session->out_buffer);
+ }
+ if (session->in_hashbuf) {
+ ssh_buffer_reinit(session->in_hashbuf);
+ }
+ if (session->out_hashbuf) {
+ ssh_buffer_reinit(session->out_hashbuf);
+ }
+ session->auth.supported_methods = 0;
+ SAFE_FREE(session->serverbanner);
+ SAFE_FREE(session->clientbanner);
- if (session->packet_callbacks){
- ssh_list_free(session->packet_callbacks);
- session->packet_callbacks=NULL;
- }
+ if (session->ssh_message_list) {
+ ssh_message msg = NULL;
+
+ while ((msg = ssh_list_pop_head(ssh_message,
+ session->ssh_message_list)) != NULL) {
+ ssh_message_free(msg);
+ }
+ ssh_list_free(session->ssh_message_list);
+ session->ssh_message_list = NULL;
+ }
+
+ if (session->packet_callbacks) {
+ ssh_list_free(session->packet_callbacks);
+ session->packet_callbacks = NULL;
+ }
}
const char *ssh_copyright(void) {
diff --git a/src/config.c b/src/config.c
index 79a64339..198a4726 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1170,3 +1170,57 @@ int ssh_config_parse_file(ssh_session session, const char *filename)
fclose(f);
return 0;
}
+
+/* @brief Parse configuration string and set the options to the given session
+ *
+ * @params[in] session The ssh session
+ * @params[in] input Null terminated string containing the configuration
+ *
+ * @returns SSH_OK on successful parsing the configuration string,
+ * SSH_ERROR on error
+ */
+int ssh_config_parse_string(ssh_session session, const char *input)
+{
+ char line[MAX_LINE_SIZE] = {0};
+ const char *c = input, *line_start = input;
+ unsigned int line_num = 0, line_len;
+ int parsing, rv;
+
+ SSH_LOG(SSH_LOG_DEBUG, "Reading configuration data from string:");
+ SSH_LOG(SSH_LOG_DEBUG, "START\n%s\nEND", input);
+
+ parsing = 1;
+ while (1) {
+ line_num++;
+ line_start = c;
+ c = strchr(line_start, '\n');
+ if (c == NULL) {
+ /* if there is no newline in the end of the string */
+ c = strchr(line_start, '\0');
+ }
+ if (c == NULL) {
+ /* should not happen, would mean a string without trailing '\0' */
+ SSH_LOG(SSH_LOG_WARN, "No trailing '\\0' in config string");
+ return SSH_ERROR;
+ }
+ line_len = c - line_start;
+ if (line_len > MAX_LINE_SIZE - 1) {
+ SSH_LOG(SSH_LOG_WARN, "Line %u too long: %u characters",
+ line_num, line_len);
+ return SSH_ERROR;
+ }
+ memcpy(line, line_start, line_len);
+ line[line_len] = '\0';
+ SSH_LOG(SSH_LOG_DEBUG, "Line %u: %s", line_num, line);
+ rv = ssh_config_parse_line(session, line, line_num, &parsing);
+ if (rv < 0) {
+ return SSH_ERROR;
+ }
+ if (*c == '\0') {
+ break;
+ }
+ c++;
+ }
+
+ return SSH_OK;
+}
diff --git a/src/kex.c b/src/kex.c
index c2c59de2..95948136 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -168,16 +168,17 @@
#define CHACHA20 "chacha20-poly1305@openssh.com,"
-#define KEY_EXCHANGE \
+#define DEFAULT_KEY_EXCHANGE \
CURVE25519 \
ECDH \
"diffie-hellman-group18-sha512,diffie-hellman-group16-sha512," \
GEX_SHA256 \
- "diffie-hellman-group14-sha256," \
- "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
+ "diffie-hellman-group14-sha256" \
+
#define KEY_EXCHANGE_SUPPORTED \
GEX_SHA1 \
- KEY_EXCHANGE
+ DEFAULT_KEY_EXCHANGE \
+ ",diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
/* RFC 8308 */
#define KEX_EXTENSION_CLIENT "ext-info-c"
@@ -231,12 +232,12 @@ static const char *fips_methods[] = {
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
static const char *default_methods[] = {
- KEY_EXCHANGE,
+ DEFAULT_KEY_EXCHANGE,
DEFAULT_PUBLIC_KEY_ALGORITHMS,
- CHACHA20 AES DES,
- CHACHA20 AES DES,
- "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1",
- "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1",
+ CHACHA20 AES,
+ CHACHA20 AES,
+ "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512",
+ "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512",
"none",
"none",
"",
@@ -754,13 +755,29 @@ int ssh_set_client_kex(ssh_session session)
return SSH_OK;
}
+static const char *ssh_find_aead_hmac(const char *cipher)
+{
+ if (cipher == NULL) {
+ return NULL;
+ } else if (strcmp(cipher, "chacha20-poly1305@openssh.com") == 0) {
+ return "aead-poly1305";
+ } else if (strcmp(cipher, "aes256-gcm@openssh.com") == 0) {
+ return "aead-gcm";
+ } else if (strcmp(cipher, "aes128-gcm@openssh.com") == 0) {
+ return "aead-gcm";
+ }
+ return NULL;
+}
+
/** @brief Select the different methods on basis of client's and
* server's kex messages, and watches out if a match is possible.
*/
-int ssh_kex_select_methods (ssh_session session){
+int ssh_kex_select_methods (ssh_session session)
+{
struct ssh_kex_struct *server = &session->next_crypto->server_kex;
struct ssh_kex_struct *client = &session->next_crypto->client_kex;
char *ext_start = NULL;
+ const char *aead_hmac = NULL;
int i;
/* Here we should drop the ext-info-c from the list so we avoid matching.
@@ -772,7 +789,15 @@ int ssh_kex_select_methods (ssh_session session){
for (i = 0; i < SSH_KEX_METHODS; i++) {
session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]);
- if(session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){
+
+ if (i == SSH_MAC_C_S || i == SSH_MAC_S_C) {
+ aead_hmac = ssh_find_aead_hmac(session->next_crypto->kex_methods[i-2]);
+ if (aead_hmac) {
+ free(session->next_crypto->kex_methods[i]);
+ session->next_crypto->kex_methods[i] = strdup(aead_hmac);
+ }
+ }
+ if (session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){
ssh_set_error(session,SSH_FATAL,"kex error : no match for method %s: server [%s], client [%s]",
ssh_kex_descriptions[i],server->methods[i],client->methods[i]);
return SSH_ERROR;
@@ -781,31 +806,31 @@ int ssh_kex_select_methods (ssh_session session){
session->next_crypto->kex_methods[i] = strdup("");
}
}
- if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group1-sha1") == 0){
+ if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group1-sha1") == 0){
session->next_crypto->kex_type=SSH_KEX_DH_GROUP1_SHA1;
- } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){
+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){
session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1;
- } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha256") == 0){
+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha256") == 0){
session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA256;
- } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group16-sha512") == 0){
+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group16-sha512") == 0){
session->next_crypto->kex_type=SSH_KEX_DH_GROUP16_SHA512;
- } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group18-sha512") == 0){
+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group18-sha512") == 0){
session->next_crypto->kex_type=SSH_KEX_DH_GROUP18_SHA512;
#ifdef WITH_GEX
- } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha1") == 0){
+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha1") == 0){
session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA1;
- } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha256") == 0){
+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha256") == 0){
session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA256;
#endif /* WITH_GEX */
- } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){
+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){
session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256;
- } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp384") == 0){
+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp384") == 0){
session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP384;
- } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp521") == 0){
+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp521") == 0){
session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP521;
- } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256@libssh.org") == 0){
+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256@libssh.org") == 0){
session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG;
- } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256") == 0){
+ } else if (strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256") == 0){
session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256;
}
SSH_LOG(SSH_LOG_INFO, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
@@ -825,7 +850,8 @@ int ssh_kex_select_methods (ssh_session session){
/* this function only sends the predefined set of kex methods */
-int ssh_send_kex(ssh_session session, int server_kex) {
+int ssh_send_kex(ssh_session session, int server_kex)
+{
struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex :
&session->next_crypto->client_kex);
ssh_string str = NULL;
@@ -1042,7 +1068,7 @@ int ssh_make_sessionid(ssh_session session)
ssh_buffer_get(server_hash),
server_pubkey_blob);
SSH_STRING_FREE(server_pubkey_blob);
- if(rc != SSH_OK){
+ if (rc != SSH_OK){
goto error;
}
diff --git a/src/misc.c b/src/misc.c
index 955ceed6..167beaf1 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1749,6 +1749,8 @@ int ssh_tmpname(char *template)
{
char *tmp = NULL;
size_t i = 0;
+ int rc = 0;
+ uint8_t random[6];
if (template == NULL) {
goto err;
@@ -1767,17 +1769,18 @@ int ssh_tmpname(char *template)
}
}
- srand(time(NULL));
+ rc = ssh_get_random(random, 6, 0);
+ if (!rc) {
+ SSH_LOG(SSH_LOG_WARNING,
+ "Could not generate random data\n");
+ goto err;
+ }
- for (i = 0; i < 6; ++i) {
-#ifdef _WIN32
- /* in win32 MAX_RAND is 32767, thus we can not shift that far,
- * otherwise the last three chars are 0 */
- int hexdigit = (rand() >> (i * 2)) & 0x1f;
-#else
- int hexdigit = (rand() >> (i * 5)) & 0x1f;
-#endif
- tmp[i] = hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0';
+ for (i = 0; i < 6; i++) {
+ /* Limit the random[i] < 32 */
+ random[i] &= 0x1f;
+ /* For values from 0 to 9 use numbers, otherwise use letters */
+ tmp[i] = random[i] > 9 ? random[i] + 'a' - 10 : random[i] + '0';
}
return 0;
diff --git a/src/pki_gcrypt.c b/src/pki_gcrypt.c
index 62ec8ea7..0373cdae 100644
--- a/src/pki_gcrypt.c
+++ b/src/pki_gcrypt.c
@@ -1983,8 +1983,9 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
if (len > rsalen) {
SSH_LOG(SSH_LOG_WARN,
- "Signature is to big size: %lu",
- (unsigned long)len);
+ "Signature is too big: %lu > %lu",
+ (unsigned long)len,
+ (unsigned long)rsalen);
ssh_signature_free(sig);
return NULL;
}