diff options
author | Andreas Schneider <asn@cryptomilk.org> | 2017-11-10 17:35:38 +0100 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2018-03-21 20:40:02 +0100 |
commit | 16217454d576511f37f39c3169963629f9d5082f (patch) | |
tree | 231faa6d8e19eeec23e0d591b8a8af0e3f675055 /src | |
parent | 7e1e0e5098beeaf926dc53e35f9e9f35915d5515 (diff) | |
download | libssh-16217454d576511f37f39c3169963629f9d5082f.tar.gz libssh-16217454d576511f37f39c3169963629f9d5082f.tar.xz libssh-16217454d576511f37f39c3169963629f9d5082f.zip |
crypto: Change the type of server_pubkey to ssh_key
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/curve25519.c | 29 | ||||
-rw-r--r-- | src/dh.c | 98 | ||||
-rw-r--r-- | src/ecdh.c | 18 | ||||
-rw-r--r-- | src/known_hosts.c | 54 | ||||
-rw-r--r-- | src/legacy.c | 25 | ||||
-rw-r--r-- | src/packet_cb.c | 16 | ||||
-rw-r--r-- | src/server.c | 9 |
7 files changed, 179 insertions, 70 deletions
diff --git a/src/curve25519.c b/src/curve25519.c index 6d9a409c..8e08f512 100644 --- a/src/curve25519.c +++ b/src/curve25519.c @@ -118,17 +118,24 @@ static int ssh_curve25519_build_k(ssh_session session) { */ int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet){ ssh_string q_s_string = NULL; - ssh_string pubkey = NULL; + ssh_string pubkey_blob = NULL; ssh_string signature = NULL; int rc; - pubkey = ssh_buffer_get_ssh_string(packet); - if (pubkey == NULL){ + + pubkey_blob = ssh_buffer_get_ssh_string(packet); + if (pubkey_blob == NULL) { ssh_set_error(session,SSH_FATAL, "No public key in packet"); goto error; } - /* this is the server host key */ - session->next_crypto->server_pubkey = pubkey; - pubkey = NULL; + + rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); + ssh_string_free(pubkey_blob); + if (rc != 0) { + ssh_set_error(session, + SSH_FATAL, + "Failed to import next public key"); + goto error; + } q_s_string = ssh_buffer_get_ssh_string(packet); if (q_s_string == NULL) { @@ -178,6 +185,7 @@ int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet){ /* ECDH keys */ ssh_string q_c_string; ssh_string q_s_string; + ssh_string server_pubkey_blob = NULL; /* SSH host keys (rsa,dsa,ecdsa) */ ssh_key privkey; @@ -236,9 +244,16 @@ int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet){ goto error; } + rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob); + if (rc != 0) { + ssh_set_error(session, SSH_FATAL, "Could not export server public key"); + goto error; + } + /* add host's public key */ rc = ssh_buffer_add_ssh_string(session->out_buffer, - session->next_crypto->server_pubkey); + server_pubkey_blob); + ssh_string_free(server_pubkey_blob); if (rc < 0) { ssh_set_error_oom(session); goto error; @@ -387,8 +387,17 @@ ssh_string ssh_dh_get_f(ssh_session session) { return ssh_make_bignum_string(session->next_crypto->f); } -void ssh_dh_import_pubkey(ssh_session session, ssh_string pubkey_string) { - session->next_crypto->server_pubkey = pubkey_string; +int ssh_dh_import_pubkey_blob(ssh_session session, ssh_string pubkey_blob) +{ + return ssh_pki_import_pubkey_blob(pubkey_blob, + &session->current_crypto->server_pubkey); +} + +int ssh_dh_import_next_pubkey_blob(ssh_session session, ssh_string pubkey_blob) +{ + return ssh_pki_import_pubkey_blob(pubkey_blob, + &session->next_crypto->server_pubkey); + } int ssh_dh_import_f(ssh_session session, ssh_string f_string) { @@ -517,15 +526,21 @@ int ssh_client_dh_init(ssh_session session){ int ssh_client_dh_reply(ssh_session session, ssh_buffer packet){ ssh_string f; - ssh_string pubkey = NULL; + ssh_string pubkey_blob = NULL; ssh_string signature = NULL; int rc; - pubkey = ssh_buffer_get_ssh_string(packet); - if (pubkey == NULL){ + + pubkey_blob = ssh_buffer_get_ssh_string(packet); + if (pubkey_blob == NULL){ ssh_set_error(session,SSH_FATAL, "No public key in packet"); goto error; } - ssh_dh_import_pubkey(session, pubkey); + + rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); + ssh_string_free(pubkey_blob); + if (rc != 0) { + goto error; + } f = ssh_buffer_get_ssh_string(packet); if (f == NULL) { @@ -569,6 +584,7 @@ int ssh_make_sessionid(ssh_session session) { ssh_buffer server_hash = NULL; ssh_buffer client_hash = NULL; ssh_buffer buf = NULL; + ssh_string server_pubkey_blob = NULL; int rc = SSH_ERROR; buf = ssh_buffer_new(); @@ -619,6 +635,11 @@ int ssh_make_sessionid(ssh_session session) { } } + rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob); + if (rc != SSH_OK) { + goto error; + } + rc = ssh_buffer_pack(buf, "dPdPS", ssh_buffer_get_len(client_hash), @@ -627,8 +648,8 @@ int ssh_make_sessionid(ssh_session session) { ssh_buffer_get_len(server_hash), ssh_buffer_get_len(server_hash), ssh_buffer_get(server_hash), - session->next_crypto->server_pubkey); - + server_pubkey_blob); + ssh_string_free(server_pubkey_blob); if(rc != SSH_OK){ goto error; } @@ -959,9 +980,11 @@ error: * @deprecated Use ssh_get_publickey_hash() */ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) { - ssh_string pubkey; + ssh_key pubkey = NULL; + ssh_string pubkey_blob = NULL; MD5CTX ctx; unsigned char *h; + int rc; if (session == NULL || hash == NULL) { return SSH_ERROR; @@ -984,9 +1007,19 @@ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) { return SSH_ERROR; } - pubkey = session->current_crypto->server_pubkey; + rc = ssh_get_server_publickey(session, &pubkey); + if (rc != 0) { + SAFE_FREE(h); + return SSH_ERROR; + } - md5_update(ctx, ssh_string_data(pubkey), ssh_string_len(pubkey)); + rc = ssh_pki_export_pubkey_blob(pubkey, + &pubkey_blob); + ssh_key_free(pubkey); + if (rc != 0) { + } + md5_update(ctx, ssh_string_data(pubkey_blob), ssh_string_len(pubkey_blob)); + ssh_string_free(pubkey_blob); md5_final(h, ctx); *hash = h; @@ -1023,14 +1056,49 @@ void ssh_clean_pubkey_hash(unsigned char **hash) { */ int ssh_get_server_publickey(ssh_session session, ssh_key *key) { - if (session==NULL || - session->current_crypto ==NULL || + ssh_key pubkey = NULL; + + if (session == NULL || + session->current_crypto == NULL || session->current_crypto->server_pubkey == NULL) { return SSH_ERROR; } - return ssh_pki_import_pubkey_blob(session->current_crypto->server_pubkey, - key); + pubkey = ssh_key_dup(session->current_crypto->server_pubkey); + if (pubkey == NULL) { + return SSH_ERROR; + } + + *key = pubkey; + return SSH_OK; +} + +ssh_key ssh_dh_get_current_server_publickey(ssh_session session) +{ + return session->current_crypto->server_pubkey; +} + +/* Caller need to free the blob */ +int ssh_dh_get_current_server_publickey_blob(ssh_session session, + ssh_string *pubkey_blob) +{ + const ssh_key pubkey = ssh_dh_get_current_server_publickey(session); + + return ssh_pki_export_pubkey_blob(pubkey, pubkey_blob); +} + +ssh_key ssh_dh_get_next_server_publickey(ssh_session session) +{ + return session->next_crypto->server_pubkey; +} + +/* Caller need to free the blob */ +int ssh_dh_get_next_server_publickey_blob(ssh_session session, + ssh_string *pubkey_blob) +{ + const ssh_key pubkey = ssh_dh_get_next_server_publickey(session); + + return ssh_pki_export_pubkey_blob(pubkey, pubkey_blob); } /** @@ -30,25 +30,27 @@ #ifdef HAVE_ECDH -static void ecdh_import_pubkey(ssh_session session, ssh_string pubkey_string) { - session->next_crypto->server_pubkey = pubkey_string; -} - /** @internal * @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back * a SSH_MSG_NEWKEYS */ int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet){ ssh_string q_s_string = NULL; - ssh_string pubkey = NULL; + ssh_string pubkey_blob = NULL; ssh_string signature = NULL; int rc; - pubkey = ssh_buffer_get_ssh_string(packet); - if (pubkey == NULL){ + + pubkey_blob = ssh_buffer_get_ssh_string(packet); + if (pubkey_blob == NULL) { ssh_set_error(session,SSH_FATAL, "No public key in packet"); goto error; } - ecdh_import_pubkey(session, pubkey); + + rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); + ssh_string_free(pubkey_blob); + if (rc != 0) { + goto error; + } q_s_string = ssh_buffer_get_ssh_string(packet); if (q_s_string == NULL) { diff --git a/src/known_hosts.c b/src/known_hosts.c index 2f0584d8..d89aca19 100644 --- a/src/known_hosts.c +++ b/src/known_hosts.c @@ -32,6 +32,7 @@ #include "libssh/session.h" #include "libssh/buffer.h" #include "libssh/misc.h" +#include "libssh/dh.h" #include "libssh/pki.h" #include "libssh/options.h" #include "libssh/knownhosts.h" @@ -188,9 +189,10 @@ static char **ssh_get_knownhost_line(FILE **file, const char *filename, * on error. */ static int check_public_key(ssh_session session, char **tokens) { - ssh_string pubkey = session->current_crypto->server_pubkey; + ssh_string pubkey_blob = NULL; ssh_buffer pubkey_buffer; char *pubkey_64; + int rc; /* ok we found some public key in known hosts file. now un-base64it */ if (alldigits(tokens[1])) { @@ -270,18 +272,26 @@ static int check_public_key(ssh_session session, char **tokens) { return -1; } - if (ssh_buffer_get_len(pubkey_buffer) != ssh_string_len(pubkey)) { + rc = ssh_dh_get_current_server_publickey_blob(session, &pubkey_blob); + if (rc != 0) { + return -1; + } + + if (ssh_buffer_get_len(pubkey_buffer) != ssh_string_len(pubkey_blob)) { + ssh_string_free(pubkey_blob); ssh_buffer_free(pubkey_buffer); return 0; } /* now test that they are identical */ - if (memcmp(ssh_buffer_get(pubkey_buffer), ssh_string_data(pubkey), + if (memcmp(ssh_buffer_get(pubkey_buffer), ssh_string_data(pubkey_blob), ssh_buffer_get_len(pubkey_buffer)) != 0) { + ssh_string_free(pubkey_blob); ssh_buffer_free(pubkey_buffer); return 0; } + ssh_string_free(pubkey_blob); ssh_buffer_free(pubkey_buffer); return 1; } @@ -485,12 +495,21 @@ int ssh_is_server_known(ssh_session session) { match = match_hashed_host(hostport, tokens[0]); } if (match) { + ssh_key pubkey = ssh_dh_get_current_server_publickey(session); + const char *pubkey_type = NULL; + + if (ssh_key_type(pubkey) == SSH_KEYTYPE_ECDSA) { + pubkey_type = ssh_pki_key_ecdsa_name(pubkey); + } else { + pubkey_type = ssh_key_type_to_char(ssh_key_type(pubkey)); + } + /* We got a match. Now check the key type */ - if (strcmp(session->current_crypto->server_pubkey_type, type) != 0) { + if (strcmp(pubkey_type, type) != 0) { SSH_LOG(SSH_LOG_PACKET, "ssh_is_server_known: server type [%s] doesn't match the " "type [%s] in known_hosts file", - session->current_crypto->server_pubkey_type, + pubkey_type, type); /* Different type. We don't override the known_changed error which is * more important */ @@ -545,8 +564,7 @@ int ssh_is_server_known(ssh_session session) { * @return string on success, NULL on error. */ char * ssh_dump_knownhost(ssh_session session) { - ssh_string pubkey_s; - ssh_key key; + ssh_key server_pubkey = NULL; char *host; char *hostport; size_t len = 4096; @@ -578,40 +596,31 @@ char * ssh_dump_knownhost(ssh_session session) { return NULL; } - pubkey_s = session->current_crypto->server_pubkey; - if (pubkey_s == NULL){ + server_pubkey = ssh_dh_get_current_server_publickey(session); + if (server_pubkey == NULL){ ssh_set_error(session, SSH_FATAL, "No public key present"); SAFE_FREE(host); return NULL; } - rc = ssh_pki_import_pubkey_blob(pubkey_s, &key); - if (rc < 0) { - SAFE_FREE(host); - return NULL; - } - buffer = calloc (1, 4096); if (!buffer) { - ssh_key_free(key); SAFE_FREE(host); return NULL; } - if (strcmp(session->current_crypto->server_pubkey_type, "ssh-rsa1") == 0) { + if (ssh_key_type(server_pubkey) == SSH_KEYTYPE_RSA1) { /* openssh uses a different format for ssh-rsa1 keys. Be compatible --kv */ - rc = ssh_pki_export_pubkey_rsa1(key, host, buffer, len); - ssh_key_free(key); + rc = ssh_pki_export_pubkey_rsa1(server_pubkey, host, buffer, len); SAFE_FREE(host); if (rc < 0) { SAFE_FREE(buffer); return NULL; } } else { - rc = ssh_pki_export_pubkey_base64(key, &b64_key); + rc = ssh_pki_export_pubkey_base64(server_pubkey, &b64_key); if (rc < 0) { - ssh_key_free(key); SAFE_FREE(buffer); SAFE_FREE(host); return NULL; @@ -620,10 +629,9 @@ char * ssh_dump_knownhost(ssh_session session) { snprintf(buffer, len, "%s %s %s\n", host, - key->type_c, + server_pubkey->type_c, b64_key); - ssh_key_free(key); SAFE_FREE(host); SAFE_FREE(b64_key); } diff --git a/src/legacy.c b/src/legacy.c index 139f81b5..2be95099 100644 --- a/src/legacy.c +++ b/src/legacy.c @@ -33,6 +33,7 @@ #include <libssh/session.h> #include <libssh/server.h> #include <libssh/buffer.h> +#include <libssh/dh.h> #include <libssh/pki.h> #include "libssh/pki_priv.h" #include <libssh/misc.h> @@ -701,12 +702,24 @@ int ssh_try_publickey_from_file(ssh_session session, return 0; } -ssh_string ssh_get_pubkey(ssh_session session){ - if(session==NULL || session->current_crypto ==NULL || - session->current_crypto->server_pubkey==NULL) - return NULL; - else - return ssh_string_copy(session->current_crypto->server_pubkey); +ssh_string ssh_get_pubkey(ssh_session session) +{ + ssh_string pubkey_blob = NULL; + int rc; + + if (session == NULL || + session->current_crypto == NULL || + session->current_crypto->server_pubkey == NULL) { + return NULL; + } + + rc = ssh_dh_get_current_server_publickey_blob(session, + &pubkey_blob); + if (rc != 0) { + return NULL; + } + + return pubkey_blob; } /**************************************************************************** diff --git a/src/packet_cb.c b/src/packet_cb.c index 106c5d9b..2b407416 100644 --- a/src/packet_cb.c +++ b/src/packet_cb.c @@ -154,7 +154,8 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ /* server things are done in server.c */ session->dh_handshake_state=DH_STATE_FINISHED; } else { - ssh_key key; + ssh_key server_key; + /* client */ rc = ssh_make_sessionid(session); if (rc != SSH_OK) { @@ -178,7 +179,7 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ session->next_crypto->dh_server_signature = NULL; /* get the server public key */ - rc = ssh_pki_import_pubkey_blob(session->next_crypto->server_pubkey, &key); + server_key = ssh_dh_get_next_server_publickey(session); if (rc < 0) { return SSH_ERROR; } @@ -186,27 +187,22 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ /* check if public key from server matches user preferences */ if (session->opts.wanted_methods[SSH_HOSTKEYS]) { if(!ssh_match_group(session->opts.wanted_methods[SSH_HOSTKEYS], - key->type_c)) { + server_key->type_c)) { ssh_set_error(session, SSH_FATAL, "Public key from server (%s) doesn't match user " "preference (%s)", - key->type_c, + server_key->type_c, session->opts.wanted_methods[SSH_HOSTKEYS]); - ssh_key_free(key); return -1; } } rc = ssh_pki_signature_verify_blob(session, sig_blob, - key, + server_key, session->next_crypto->secret_hash, session->next_crypto->digest_len); - /* Set the server public key type for known host checking */ - session->next_crypto->server_pubkey_type = key->type_c; - - ssh_key_free(key); ssh_string_burn(sig_blob); ssh_string_free(sig_blob); sig_blob = NULL; diff --git a/src/server.c b/src/server.c index 7d807c3c..2ae87792 100644 --- a/src/server.c +++ b/src/server.c @@ -277,7 +277,14 @@ int ssh_get_key_params(ssh_session session, ssh_key *privkey){ return -1; } - ssh_dh_import_pubkey(session, pubkey_blob); + rc = ssh_dh_import_pubkey_blob(session, pubkey_blob); + if (rc != 0) { + ssh_set_error(session, + SSH_FATAL, + "Could not import server public key"); + return -1; + } + return SSH_OK; } |