From 3461196197fede8f9d1108136966a4f7d4d039ae Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 13 Mar 2021 10:59:47 +0000 Subject: [PATCH] Pass more information to interactive host key check. Now we pass the whole set of fingerprints, and also a displayable format for the full host public key. NFC: this commit doesn't modify any of the host key prompts to _use_ any of the new information. That's coming next. --- misc.c | 4 ++-- putty.h | 17 +++++++++-------- ssh1login.c | 7 ++++--- ssh2kex-client.c | 9 ++++++--- unix/gtkdlg.c | 14 ++++++++++---- unix/unix.h | 4 ++-- unix/uxcons.c | 9 ++++++--- windows/wincons.c | 9 ++++++--- windows/windlg.c | 7 ++++--- windows/winstuff.h | 4 ++-- 10 files changed, 51 insertions(+), 33 deletions(-) diff --git a/misc.c b/misc.c index 84de046d..56f2ba93 100644 --- a/misc.c +++ b/misc.c @@ -378,8 +378,8 @@ void nullseat_update_specials_menu(Seat *seat) {} char *nullseat_get_ttymode(Seat *seat, const char *mode) { return NULL; } void nullseat_set_busy_status(Seat *seat, BusyStatus status) {} int nullseat_verify_ssh_host_key( - Seat *seat, const char *host, int port, - const char *keytype, char *keystr, char *key_fingerprint, + Seat *seat, const char *host, int port, const char *keytype, + char *keystr, const char *keydisp, char **key_fingerprints, void (*callback)(void *ctx, int result), void *ctx) { return 0; } int nullseat_confirm_weak_crypto_primitive( Seat *seat, const char *algtype, const char *algname, diff --git a/putty.h b/putty.h index f89ffc09..206ee905 100644 --- a/putty.h +++ b/putty.h @@ -972,8 +972,8 @@ struct SeatVtable { * or +1'. */ int (*verify_ssh_host_key)( - Seat *seat, const char *host, int port, - const char *keytype, char *keystr, char *key_fingerprint, + Seat *seat, const char *host, int port, const char *keytype, + char *keystr, const char *keydisp, char **key_fingerprints, void (*callback)(void *ctx, int result), void *ctx); /* @@ -1095,8 +1095,9 @@ static inline void seat_set_busy_status(Seat *seat, BusyStatus status) { seat->vt->set_busy_status(seat, status); } static inline int seat_verify_ssh_host_key( Seat *seat, const char *h, int p, const char *ktyp, char *kstr, - char *fp, void (*cb)(void *ctx, int result), void *ctx) -{ return seat->vt->verify_ssh_host_key(seat, h, p, ktyp, kstr, fp, cb, ctx); } + const char *kdsp, char **fps, void (*cb)(void *ctx, int result), void *ctx) +{ return seat->vt->verify_ssh_host_key(seat, h, p, ktyp, kstr, kdsp, fps, + cb, ctx); } static inline int seat_confirm_weak_crypto_primitive( Seat *seat, const char *atyp, const char *aname, void (*cb)(void *ctx, int result), void *ctx) @@ -1159,8 +1160,8 @@ void nullseat_update_specials_menu(Seat *seat); char *nullseat_get_ttymode(Seat *seat, const char *mode); void nullseat_set_busy_status(Seat *seat, BusyStatus status); int nullseat_verify_ssh_host_key( - Seat *seat, const char *host, int port, - const char *keytype, char *keystr, char *key_fingerprint, + Seat *seat, const char *host, int port, const char *keytype, + char *keystr, const char *keydisp, char **key_fingerprints, void (*callback)(void *ctx, int result), void *ctx); int nullseat_confirm_weak_crypto_primitive( Seat *seat, const char *algtype, const char *algname, @@ -1191,8 +1192,8 @@ bool nullseat_get_cursor_position(Seat *seat, int *x, int *y); void console_connection_fatal(Seat *seat, const char *message); int console_verify_ssh_host_key( - Seat *seat, const char *host, int port, - const char *keytype, char *keystr, char *key_fingerprint, + Seat *seat, const char *host, int port, const char *keytype, + char *keystr, const char *keydisp, char **key_fingerprints, void (*callback)(void *ctx, int result), void *ctx); int console_confirm_weak_crypto_primitive( Seat *seat, const char *algtype, const char *algname, diff --git a/ssh1login.c b/ssh1login.c index 5556320b..8486cbf0 100644 --- a/ssh1login.c +++ b/ssh1login.c @@ -256,10 +256,11 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl) "configured list"); return; } else if (s->dlgret < 0) { /* none configured; use standard handling */ + char *keydisp = ssh1_pubkey_str(&s->hostkey); s->dlgret = seat_verify_ssh_host_key( - s->ppl.seat, s->savedhost, s->savedport, - "rsa", keystr, fingerprints[SSH_FPTYPE_DEFAULT], - ssh1_login_dialog_callback, s); + s->ppl.seat, s->savedhost, s->savedport, "rsa", keystr, + keydisp, fingerprints, ssh1_login_dialog_callback, s); + sfree(keydisp); ssh2_free_all_fingerprints(fingerprints); sfree(keystr); #ifdef FUZZING diff --git a/ssh2kex-client.c b/ssh2kex-client.c index 91452e55..1dd960c1 100644 --- a/ssh2kex-client.c +++ b/ssh2kex-client.c @@ -858,11 +858,13 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted) *aborted = true; return; } else if (s->dlgret < 0) { /* none configured; use standard handling */ + ssh2_userkey uk = { .key = s->hkey, .comment = NULL }; + char *keydisp = ssh2_pubkey_openssh_str(&uk); s->dlgret = seat_verify_ssh_host_key( s->ppl.seat, s->savedhost, s->savedport, - ssh_key_cache_id(s->hkey), s->keystr, - fingerprints[SSH_FPTYPE_DEFAULT], - ssh2_transport_dialog_callback, s); + ssh_key_cache_id(s->hkey), s->keystr, keydisp, + fingerprints, ssh2_transport_dialog_callback, s); + sfree(keydisp); ssh2_free_all_fingerprints(fingerprints); #ifdef FUZZING s->dlgret = 1; @@ -875,6 +877,7 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted) return; } } + /* * Save this host key, to check against the one presented in * subsequent rekeys. diff --git a/unix/gtkdlg.c b/unix/gtkdlg.c index 412c2f6c..ae5acaa7 100644 --- a/unix/gtkdlg.c +++ b/unix/gtkdlg.c @@ -31,6 +31,7 @@ #include "dialog.h" #include "tree234.h" #include "licence.h" +#include "ssh.h" #if GTK_CHECK_VERSION(2,0,0) /* Decide which of GtkFileChooserDialog and GtkFileSelection to use */ @@ -3461,8 +3462,8 @@ static void verify_ssh_host_key_result_callback(void *vctx, int result) } int gtk_seat_verify_ssh_host_key( - Seat *seat, const char *host, int port, - const char *keytype, char *keystr, char *fingerprint, + Seat *seat, const char *host, int port, const char *keytype, + char *keystr, const char *keydisp, char **fingerprints, void (*callback)(void *ctx, int result), void *ctx) { static const char absenttxt[] = @@ -3513,7 +3514,11 @@ int gtk_seat_verify_ssh_host_key( if (ret == 0) /* success - key matched OK */ return 1; - text = dupprintf((ret == 2 ? wrongtxt : absenttxt), keytype, fingerprint); + FingerprintType fptype_default = + ssh2_pick_default_fingerprint(fingerprints); + + text = dupprintf((ret == 2 ? wrongtxt : absenttxt), keytype, + fingerprints[fptype_default]); result_ctx = snew(struct verify_ssh_host_key_result_ctx); result_ctx->callback = callback; @@ -3526,7 +3531,8 @@ int gtk_seat_verify_ssh_host_key( mainwin = GTK_WIDGET(gtk_seat_get_window(seat)); msgbox = create_message_box( - mainwin, "PuTTY Security Alert", text, string_width(fingerprint), true, + mainwin, "PuTTY Security Alert", text, + string_width(fingerprints[fptype_default]), true, &buttons_hostkey, verify_ssh_host_key_result_callback, result_ctx); register_dialog(seat, DIALOG_SLOT_NETWORK_PROMPT, msgbox); diff --git a/unix/unix.h b/unix/unix.h index d050dccd..2c0664b2 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -218,8 +218,8 @@ void logevent_dlg(eventlog_stuff *estuff, const char *string); int gtkdlg_askappend(Seat *seat, Filename *filename, void (*callback)(void *ctx, int result), void *ctx); int gtk_seat_verify_ssh_host_key( - Seat *seat, const char *host, int port, - const char *keytype, char *keystr, char *fingerprint, + Seat *seat, const char *host, int port, const char *keytype, + char *keystr, const char *keydisp, char **fingerprints, void (*callback)(void *ctx, int result), void *ctx); int gtk_seat_confirm_weak_crypto_primitive( Seat *seat, const char *algtype, const char *algname, diff --git a/unix/uxcons.c b/unix/uxcons.c index fc741b06..7dd2b411 100644 --- a/unix/uxcons.c +++ b/unix/uxcons.c @@ -103,8 +103,8 @@ static int block_and_read(int fd, void *buf, size_t len) } int console_verify_ssh_host_key( - Seat *seat, const char *host, int port, - const char *keytype, char *keystr, char *fingerprint, + Seat *seat, const char *host, int port, const char *keytype, + char *keystr, const char *keydisp, char **fingerprints, void (*callback)(void *ctx, int result), void *ctx) { int ret; @@ -132,7 +132,10 @@ int console_verify_ssh_host_key( prompt = hk_absentmsg_interactive_prompt; } - fprintf(stderr, common_fmt, keytype, fingerprint); + FingerprintType fptype_default = + ssh2_pick_default_fingerprint(fingerprints); + + fprintf(stderr, common_fmt, keytype, fingerprints[fptype_default]); if (console_batch_mode) { fputs(console_abandoned_msg, stderr); return 0; diff --git a/windows/wincons.c b/windows/wincons.c index 2badf792..69cfe09a 100644 --- a/windows/wincons.c +++ b/windows/wincons.c @@ -33,8 +33,8 @@ void console_print_error_msg(const char *prefix, const char *msg) } int console_verify_ssh_host_key( - Seat *seat, const char *host, int port, - const char *keytype, char *keystr, char *fingerprint, + Seat *seat, const char *host, int port, const char *keytype, + char *keystr, const char *keydisp, char **fingerprints, void (*callback)(void *ctx, int result), void *ctx) { int ret; @@ -62,7 +62,10 @@ int console_verify_ssh_host_key( prompt = hk_absentmsg_interactive_prompt; } - fprintf(stderr, common_fmt, keytype, fingerprint); + FingerprintType fptype_default = + ssh2_pick_default_fingerprint(fingerprints); + + fprintf(stderr, common_fmt, keytype, fingerprints[fptype_default]); if (console_batch_mode) { fputs(console_abandoned_msg, stderr); return 0; diff --git a/windows/windlg.c b/windows/windlg.c index f862c5d8..45b5a217 100644 --- a/windows/windlg.c +++ b/windows/windlg.c @@ -939,8 +939,8 @@ static INT_PTR CALLBACK HostKeyDialogProc(HWND hwnd, UINT msg, } int win_seat_verify_ssh_host_key( - Seat *seat, const char *host, int port, - const char *keytype, char *keystr, char *fingerprint, + Seat *seat, const char *host, int port, const char *keytype, + char *keystr, const char *keydisp, char **fingerprints, void (*callback)(void *ctx, int result), void *ctx) { int ret; @@ -965,7 +965,8 @@ int win_seat_verify_ssh_host_key( struct hostkey_dialog_ctx ctx[1]; ctx->keywords = keywords; ctx->values = values; - ctx->fingerprint = fingerprint; + ctx->fingerprint = fingerprints[ + ssh2_pick_default_fingerprint(fingerprints)]; ctx->iconid = (ret == 2 ? IDI_WARNING : IDI_QUESTION); ctx->helpctx = (ret == 2 ? WINHELP_CTX_errors_hostkey_changed : WINHELP_CTX_errors_hostkey_absent); diff --git a/windows/winstuff.h b/windows/winstuff.h index f837a4b0..31012c6a 100644 --- a/windows/winstuff.h +++ b/windows/winstuff.h @@ -218,8 +218,8 @@ int has_embedded_chm(void); /* 1 = yes, 0 = no, -1 = N/A */ * window.c can refer to them. */ int win_seat_verify_ssh_host_key( - Seat *seat, const char *host, int port, - const char *keytype, char *keystr, char *key_fingerprint, + Seat *seat, const char *host, int port, const char *keytype, + char *keystr, const char *keydisp, char **key_fingerprints, void (*callback)(void *ctx, int result), void *ctx); int win_seat_confirm_weak_crypto_primitive( Seat *seat, const char *algtype, const char *algname,