mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-12 19:20:27 +09:00
feat: add gssapi key exchange
feat: add generic functions for importing name and initializing ctx feat: add suffix to gsskex algs dynamically feat: move gssapi key exchange to another file feat: add gssapi key exchange for server refactor: remove unnecessary fields in gssapi struct refactor: add some documentation and improve logging fix: remove gss_dh callbacks feat: add a check to see if GSSAPI is configured correctly fix: memory leaks feat: add client side "gssapi-keyex" auth feat: add gssapi_key_exchange_algs for server fix: some memory issues feat: add gssapi kex options to config feat: add check to see if GSSAPI key exchange was performed feat: add more tests for gssapi key exchange fix: add valgrind supp Signed-off-by: Gauravsingh Sisodia <xaerru@gmail.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
committed by
Jakub Jelen
parent
701a2155a7
commit
bc5211d055
108
src/packet_cb.c
108
src/packet_cb.c
@@ -27,6 +27,10 @@
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef WITH_GSSAPI
|
||||
#include <gssapi/gssapi.h>
|
||||
#include "libssh/gssapi.h"
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/buffer.h"
|
||||
@@ -173,53 +177,79 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys)
|
||||
/* server things are done in server.c */
|
||||
session->dh_handshake_state=DH_STATE_FINISHED;
|
||||
} else {
|
||||
ssh_key server_key = NULL;
|
||||
if (session->opts.gssapi_key_exchange) {
|
||||
#ifdef WITH_GSSAPI
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
gss_buffer_desc mic = GSS_C_EMPTY_BUFFER, msg = GSS_C_EMPTY_BUFFER;
|
||||
|
||||
/* client */
|
||||
mic.length = ssh_string_len(session->gssapi_key_exchange_mic);
|
||||
mic.value = ssh_string_data(session->gssapi_key_exchange_mic);
|
||||
|
||||
/* Verify the host's signature. FIXME do it sooner */
|
||||
sig_blob = session->next_crypto->dh_server_signature;
|
||||
session->next_crypto->dh_server_signature = NULL;
|
||||
msg.length = session->next_crypto->digest_len;
|
||||
msg.value = session->next_crypto->secret_hash;
|
||||
|
||||
/* get the server public key */
|
||||
server_key = ssh_dh_get_next_server_publickey(session);
|
||||
if (server_key == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_signature_blob(sig_blob, server_key, &sig);
|
||||
ssh_string_burn(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Check if signature from server matches user preferences */
|
||||
if (session->opts.wanted_methods[SSH_HOSTKEYS]) {
|
||||
rc = match_group(session->opts.wanted_methods[SSH_HOSTKEYS],
|
||||
sig->type_c);
|
||||
if (rc == 0) {
|
||||
maj_stat = gss_verify_mic(&min_stat,
|
||||
session->gssapi->ctx,
|
||||
&msg,
|
||||
&mic,
|
||||
NULL);
|
||||
if (maj_stat != GSS_S_COMPLETE) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Public key from server (%s) doesn't match user "
|
||||
"preference (%s)",
|
||||
sig->type_c,
|
||||
session->opts.wanted_methods[SSH_HOSTKEYS]);
|
||||
"Failed to verify mic after GSSAPI Key Exchange");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
SSH_STRING_FREE(session->gssapi_key_exchange_mic);
|
||||
#endif
|
||||
} else {
|
||||
ssh_key server_key = NULL;
|
||||
|
||||
rc = ssh_pki_signature_verify(session,
|
||||
sig,
|
||||
server_key,
|
||||
session->next_crypto->secret_hash,
|
||||
session->next_crypto->digest_len);
|
||||
SSH_SIGNATURE_FREE(sig);
|
||||
if (rc == SSH_ERROR) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to verify server hostkey signature");
|
||||
goto error;
|
||||
/* client */
|
||||
|
||||
/* Verify the host's signature. FIXME do it sooner */
|
||||
sig_blob = session->next_crypto->dh_server_signature;
|
||||
session->next_crypto->dh_server_signature = NULL;
|
||||
|
||||
/* get the server public key */
|
||||
server_key = ssh_dh_get_next_server_publickey(session);
|
||||
if (server_key == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_signature_blob(sig_blob, server_key, &sig);
|
||||
ssh_string_burn(sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Check if signature from server matches user preferences */
|
||||
if (session->opts.wanted_methods[SSH_HOSTKEYS]) {
|
||||
rc = match_group(session->opts.wanted_methods[SSH_HOSTKEYS],
|
||||
sig->type_c);
|
||||
if (rc == 0) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Public key from server (%s) doesn't match user "
|
||||
"preference (%s)",
|
||||
sig->type_c,
|
||||
session->opts.wanted_methods[SSH_HOSTKEYS]);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_pki_signature_verify(session,
|
||||
sig,
|
||||
server_key,
|
||||
session->next_crypto->secret_hash,
|
||||
session->next_crypto->digest_len);
|
||||
SSH_SIGNATURE_FREE(sig);
|
||||
if (rc == SSH_ERROR) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to verify server hostkey signature");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Signature verified and valid");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user