diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2012-12-23 23:09:50 +0100 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2012-12-23 23:09:50 +0100 |
commit | 63c3f0e7368c7286a960c65422513850ce192124 (patch) | |
tree | 2267e176dac25d4c9e14512282a4723d94a063d6 /src | |
parent | e934ab0816e871253cd3d0538638f0b7cf98c375 (diff) | |
download | libssh-63c3f0e7368c7286a960c65422513850ce192124.tar.gz libssh-63c3f0e7368c7286a960c65422513850ce192124.tar.xz libssh-63c3f0e7368c7286a960c65422513850ce192124.zip |
Implement key re-exchange
Diffstat (limited to 'src')
-rw-r--r-- | src/auth.c | 2 | ||||
-rw-r--r-- | src/client.c | 5 | ||||
-rw-r--r-- | src/dh.c | 32 | ||||
-rw-r--r-- | src/kex.c | 5 | ||||
-rw-r--r-- | src/packet_cb.c | 9 | ||||
-rw-r--r-- | src/wrapper.c | 5 |
6 files changed, 44 insertions, 14 deletions
@@ -252,6 +252,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_success){ session->auth_state=SSH_AUTH_STATE_SUCCESS; session->session_state=SSH_SESSION_STATE_AUTHENTICATED; + session->flags |= SSH_SESSION_FLAG_AUTHENTICATED; + if(session->current_crypto && session->current_crypto->delayed_compress_out){ SSH_LOG(session, SSH_LOG_DEBUG, "Enabling delayed compression OUT"); session->current_crypto->do_compress_out=1; diff --git a/src/client.c b/src/client.c index f571b2d..ac1b83d 100644 --- a/src/client.c +++ b/src/client.c @@ -409,7 +409,10 @@ static void ssh_client_connection_callback(ssh_session session){ if(session->dh_handshake_state==DH_STATE_FINISHED){ set_status(session,1.0f); session->connected = 1; - session->session_state=SSH_SESSION_STATE_AUTHENTICATING; + if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) + session->session_state = SSH_SESSION_STATE_AUTHENTICATED; + else + session->session_state=SSH_SESSION_STATE_AUTHENTICATING; } break; case SSH_SESSION_STATE_AUTHENTICATING: @@ -788,31 +788,43 @@ int make_sessionid(ssh_session session) { case SSH_KEX_DH_GROUP14_SHA1: session->next_crypto->digest_len = SHA_DIGEST_LENGTH; session->next_crypto->mac_type = SSH_MAC_SHA1; - session->next_crypto->session_id = malloc(session->next_crypto->digest_len); - if(session->next_crypto->session_id == NULL){ + session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len); + if(session->next_crypto->secret_hash == NULL){ ssh_set_error_oom(session); goto error; } sha1(buffer_get_rest(buf), buffer_get_rest_len(buf), - session->next_crypto->session_id); + session->next_crypto->secret_hash); break; case SSH_KEX_ECDH_SHA2_NISTP256: session->next_crypto->digest_len = SHA256_DIGEST_LENGTH; session->next_crypto->mac_type = SSH_MAC_SHA256; - session->next_crypto->session_id = malloc(session->next_crypto->digest_len); - if(session->next_crypto->session_id == NULL){ + session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len); + if(session->next_crypto->secret_hash == NULL){ ssh_set_error_oom(session); goto error; } sha256(buffer_get_rest(buf), buffer_get_rest_len(buf), - session->next_crypto->session_id); + session->next_crypto->secret_hash); break; } - - + /* During the first kex, secret hash and session ID are equal. However, after + * a key re-exchange, a new secret hash is calculated. This hash will not replace + * but complement existing session id. + */ + if (!session->next_crypto->session_id){ + session->next_crypto->session_id = malloc(session->next_crypto->digest_len); + if (session->next_crypto->session_id == NULL){ + ssh_set_error_oom(session); + goto error; + } + memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash, + session->next_crypto->digest_len); + } #ifdef DEBUG_CRYPTO printf("Session hash: "); - ssh_print_hexa("session id", session->next_crypto->session_id, SHA_DIGEST_LEN); + ssh_print_hexa("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len); + ssh_print_hexa("session id", session->next_crypto->session_id, session->next_crypto->digest_len); #endif rc = SSH_OK; @@ -888,7 +900,7 @@ static int generate_one_key(ssh_string k, } ssh_mac_update(ctx, k, ssh_string_len(k) + 4); - ssh_mac_update(ctx, crypto->session_id, crypto->digest_len); + ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); ssh_mac_update(ctx, &letter, 1); ssh_mac_update(ctx, crypto->session_id, crypto->digest_len); ssh_mac_final(output, ctx); @@ -276,7 +276,9 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){ (void)type; (void)user; memset(strings, 0, sizeof(strings)); - if(session->session_state != SSH_SESSION_STATE_INITIAL_KEX){ + if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED){ + ssh_log(session,SSH_LOG_WARNING, "Other side initiating key re-exchange"); + } else if(session->session_state != SSH_SESSION_STATE_INITIAL_KEX){ ssh_set_error(session,SSH_FATAL,"SSH_KEXINIT received in wrong state"); goto error; } @@ -335,6 +337,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){ leave_function(); session->session_state=SSH_SESSION_STATE_KEXINIT_RECEIVED; + session->dh_handshake_state=DH_STATE_INIT; session->ssh_connection_callback(session); return SSH_PACKET_USED; error: diff --git a/src/packet_cb.c b/src/packet_cb.c index dd77dd7..41d0985 100644 --- a/src/packet_cb.c +++ b/src/packet_cb.c @@ -179,7 +179,7 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ rc = ssh_pki_signature_verify_blob(session, sig_blob, key, - session->next_crypto->session_id, + 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; @@ -210,6 +210,13 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ ssh_set_error_oom(session); goto error; } + session->next_crypto->session_id = malloc(session->current_crypto->digest_len); + if (session->next_crypto->session_id == NULL) { + ssh_set_error_oom(session); + goto error; + } + memcpy(session->next_crypto->session_id, session->current_crypto->session_id, + session->current_crypto->digest_len); } session->dh_handshake_state = DH_STATE_FINISHED; session->ssh_connection_callback(session); diff --git a/src/wrapper.c b/src/wrapper.c index e27579d..b8a489d 100644 --- a/src/wrapper.c +++ b/src/wrapper.c @@ -121,7 +121,10 @@ void crypto_free(struct ssh_crypto_struct *crypto){ memset(crypto->session_id, '\0', crypto->digest_len); SAFE_FREE(crypto->session_id); } - + if(crypto->secret_hash != NULL){ + memset(crypto->secret_hash, '\0', crypto->digest_len); + SAFE_FREE(crypto->secret_hash); + } #ifdef WITH_ZLIB if (crypto->compress_out_ctx && (deflateEnd(crypto->compress_out_ctx) != 0)) { |