1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 09:58:01 +00:00

GUI host key prompts: add 'More info' subdialog.

This behaves like the 'i' keystroke I just added to the console host
key prompts: it shows you all fingerprints and the full public key.
This commit is contained in:
Simon Tatham 2021-03-13 11:06:32 +00:00
parent 5612dfe419
commit 99a3b0c380
4 changed files with 182 additions and 41 deletions

View File

@ -3426,20 +3426,24 @@ GtkWidget *create_message_box(
NULL /* action_postproc */, NULL /* postproc_ctx */); NULL /* action_postproc */, NULL /* postproc_ctx */);
} }
struct verify_ssh_host_key_result_ctx { struct verify_ssh_host_key_dialog_ctx {
char *host; char *host;
int port; int port;
char *keytype; char *keytype;
char *keystr; char *keystr;
char *more_info;
void (*callback)(void *callback_ctx, int result); void (*callback)(void *callback_ctx, int result);
void *callback_ctx; void *callback_ctx;
Seat *seat; Seat *seat;
GtkWidget *main_dialog;
GtkWidget *more_info_dialog;
}; };
static void verify_ssh_host_key_result_callback(void *vctx, int result) static void verify_ssh_host_key_result_callback(void *vctx, int result)
{ {
struct verify_ssh_host_key_result_ctx *ctx = struct verify_ssh_host_key_dialog_ctx *ctx =
(struct verify_ssh_host_key_result_ctx *)vctx; (struct verify_ssh_host_key_dialog_ctx *)vctx;
if (result >= 0) { if (result >= 0) {
int logical_result; int logical_result;
@ -3468,12 +3472,51 @@ static void verify_ssh_host_key_result_callback(void *vctx, int result)
*/ */
unregister_dialog(ctx->seat, DIALOG_SLOT_NETWORK_PROMPT); unregister_dialog(ctx->seat, DIALOG_SLOT_NETWORK_PROMPT);
if (ctx->more_info_dialog)
gtk_widget_destroy(ctx->more_info_dialog);
sfree(ctx->host); sfree(ctx->host);
sfree(ctx->keytype); sfree(ctx->keytype);
sfree(ctx->keystr); sfree(ctx->keystr);
sfree(ctx->more_info);
sfree(ctx); sfree(ctx);
} }
static GtkWidget *add_more_info_button(GtkWidget *w, void *vctx)
{
GtkWidget *box = gtk_hbox_new(false, 10);
gtk_widget_show(box);
gtk_box_pack_end(GTK_BOX(box), w, false, true, 0);
GtkWidget *button = gtk_button_new_with_label("More info...");
gtk_widget_show(button);
gtk_box_pack_start(GTK_BOX(box), button, false, true, 0);
*(GtkWidget **)vctx = button;
return box;
}
static void more_info_closed(void *vctx, int result)
{
struct verify_ssh_host_key_dialog_ctx *ctx =
(struct verify_ssh_host_key_dialog_ctx *)vctx;
ctx->more_info_dialog = NULL;
}
static void more_info_button_clicked(GtkButton *button, gpointer vctx)
{
struct verify_ssh_host_key_dialog_ctx *ctx =
(struct verify_ssh_host_key_dialog_ctx *)vctx;
if (ctx->more_info_dialog)
return;
ctx->more_info_dialog = create_message_box(
ctx->main_dialog, "Host key information", ctx->more_info,
string_width("SHA256 fingerprint: ecdsa-sha2-nistp521 521 "
"abcdefghkmnopqrsuvwxyzABCDEFGHJKLMNOPQRSTUW"), true,
&buttons_ok, more_info_closed, ctx);
}
int gtk_seat_verify_ssh_host_key( int gtk_seat_verify_ssh_host_key(
Seat *seat, const char *host, int port, const char *keytype, Seat *seat, const char *host, int port, const char *keytype,
char *keystr, const char *keydisp, char **fingerprints, char *keystr, const char *keydisp, char **fingerprints,
@ -3516,7 +3559,7 @@ int gtk_seat_verify_ssh_host_key(
char *text; char *text;
int ret; int ret;
struct verify_ssh_host_key_result_ctx *result_ctx; struct verify_ssh_host_key_dialog_ctx *result_ctx;
GtkWidget *mainwin, *msgbox; GtkWidget *mainwin, *msgbox;
/* /*
@ -3533,7 +3576,7 @@ int gtk_seat_verify_ssh_host_key(
text = dupprintf((ret == 2 ? wrongtxt : absenttxt), keytype, text = dupprintf((ret == 2 ? wrongtxt : absenttxt), keytype,
fingerprints[fptype_default]); fingerprints[fptype_default]);
result_ctx = snew(struct verify_ssh_host_key_result_ctx); result_ctx = snew(struct verify_ssh_host_key_dialog_ctx);
result_ctx->callback = callback; result_ctx->callback = callback;
result_ctx->callback_ctx = ctx; result_ctx->callback_ctx = ctx;
result_ctx->host = dupstr(host); result_ctx->host = dupstr(host);
@ -3543,10 +3586,40 @@ int gtk_seat_verify_ssh_host_key(
result_ctx->seat = seat; result_ctx->seat = seat;
mainwin = GTK_WIDGET(gtk_seat_get_window(seat)); mainwin = GTK_WIDGET(gtk_seat_get_window(seat));
msgbox = create_message_box( GtkWidget *more_info_button = NULL;
msgbox = create_message_box_general(
mainwin, "PuTTY Security Alert", text, mainwin, "PuTTY Security Alert", text,
string_width(fingerprints[fptype_default]), true, string_width(fingerprints[fptype_default]), true,
&buttons_hostkey, verify_ssh_host_key_result_callback, result_ctx); &buttons_hostkey, verify_ssh_host_key_result_callback, result_ctx,
add_more_info_button, &more_info_button);
result_ctx->main_dialog = msgbox;
result_ctx->more_info_dialog = NULL;
strbuf *sb = strbuf_new();
if (fingerprints[SSH_FPTYPE_SHA256])
strbuf_catf(sb, "SHA256 fingerprint: %s\n",
fingerprints[SSH_FPTYPE_SHA256]);
if (fingerprints[SSH_FPTYPE_MD5])
strbuf_catf(sb, "MD5 fingerprint: %s\n",
fingerprints[SSH_FPTYPE_MD5]);
strbuf_catf(sb, "Full text of host's public key:");
/* We have to manually wrap the public key, or else the GtkLabel
* will resize itself to accommodate the longest word, which will
* lead to a hilariously wide message box. */
for (const char *p = keydisp, *q = p + strlen(p); p < q ;) {
size_t linelen = q-p;
if (linelen > 72)
linelen = 72;
put_byte(sb, '\n');
put_data(sb, p, linelen);
p += linelen;
}
result_ctx->more_info = strbuf_to_str(sb);
g_signal_connect(G_OBJECT(more_info_button), "clicked",
G_CALLBACK(more_info_button_clicked), result_ctx);
register_dialog(seat, DIALOG_SLOT_NETWORK_PROMPT, msgbox); register_dialog(seat, DIALOG_SLOT_NETWORK_PROMPT, msgbox);
sfree(text); sfree(text);

View File

@ -15,6 +15,7 @@
#define IDD_LICENCEBOX 113 #define IDD_LICENCEBOX 113
#define IDD_HK_ABSENT 114 #define IDD_HK_ABSENT 114
#define IDD_HK_WRONG 115 #define IDD_HK_WRONG 115
#define IDD_HK_MOREINFO 116
#define IDN_LIST 1001 #define IDN_LIST 1001
#define IDN_COPY 1002 #define IDN_COPY 1002
@ -36,6 +37,11 @@
#define IDC_HK_ACCEPT 1001 #define IDC_HK_ACCEPT 1001
#define IDC_HK_ONCE 1000 #define IDC_HK_ONCE 1000
#define IDC_HK_FINGERPRINT 1002 #define IDC_HK_FINGERPRINT 1002
#define IDC_HK_MOREINFO 1003
#define IDC_HKI_SHA256 1000
#define IDC_HKI_MD5 1001
#define IDC_HKI_PUBKEY 1002
#define ID_CUSTOM_CHMFILE 2000 #define ID_CUSTOM_CHMFILE 2000
#define TYPE_CUSTOM_CHMFILE 2000 #define TYPE_CUSTOM_CHMFILE 2000

View File

@ -63,58 +63,75 @@ BEGIN
END END
/* No accelerators used */ /* No accelerators used */
IDD_HK_ABSENT DIALOG DISCARDABLE 50, 50, 300, 148 IDD_HK_ABSENT DIALOG DISCARDABLE 50, 50, 340, 148
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "PuTTY Security Alert" CAPTION "PuTTY Security Alert"
FONT 8, "MS Shell Dlg" FONT 8, "MS Shell Dlg"
BEGIN BEGIN
LTEXT "The server's host key is not cached in the registry. You have no", 100, 40, 20, 260, 8 LTEXT "The server's host key is not cached in the registry. You have no", 100, 40, 20, 300, 8
LTEXT "guarantee that the server is the computer you think it is.", 101, 40, 28, 260, 8 LTEXT "guarantee that the server is the computer you think it is.", 101, 40, 28, 300, 8
LTEXT "The server's {KEYTYPE} key fingerprint is:", 102, 40, 40, 260, 8 LTEXT "The server's {KEYTYPE} key fingerprint is:", 102, 40, 40, 300, 8
LTEXT "If you trust this host, press ""Accept"" to add the key to {APPNAME}'s", 103, 40, 60, 260, 8 LTEXT "If you trust this host, press ""Accept"" to add the key to {APPNAME}'s", 103, 40, 60, 300, 8
LTEXT "cache and carry on connecting.", 104, 40, 68, 260, 8 LTEXT "cache and carry on connecting.", 104, 40, 68, 300, 8
LTEXT "If you want to carry on connecting just once, without adding the key", 105, 40, 80, 260, 8 LTEXT "If you want to carry on connecting just once, without adding the key", 105, 40, 80, 300, 8
LTEXT "to the cache, press ""Connect Once"".", 106, 40, 88, 260, 8 LTEXT "to the cache, press ""Connect Once"".", 106, 40, 88, 300, 8
LTEXT "If you do not trust this host, press ""Cancel"" to abandon the connection.", 107, 40, 100, 260, 8 LTEXT "If you do not trust this host, press ""Cancel"" to abandon the connection.", 107, 40, 100, 300, 8
ICON "", IDC_HK_ICON, 10, 18, 0, 0 ICON "", IDC_HK_ICON, 10, 18, 0, 0
PUSHBUTTON "Cancel", IDCANCEL, 248, 128, 40, 14 PUSHBUTTON "Cancel", IDCANCEL, 288, 128, 40, 14
PUSHBUTTON "Accept", IDC_HK_ACCEPT, 128, 128, 40, 14 PUSHBUTTON "Accept", IDC_HK_ACCEPT, 168, 128, 40, 14
PUSHBUTTON "Connect Once", IDC_HK_ONCE, 176, 128, 64, 14 PUSHBUTTON "Connect Once", IDC_HK_ONCE, 216, 128, 64, 14
PUSHBUTTON "More info...", IDC_HK_MOREINFO, 60, 128, 64, 14
PUSHBUTTON "Help", IDHELP, 12, 128, 40, 14 PUSHBUTTON "Help", IDHELP, 12, 128, 40, 14
EDITTEXT IDC_HK_FINGERPRINT, 40, 48, 260, 12, ES_READONLY | ES_LEFT, 0 EDITTEXT IDC_HK_FINGERPRINT, 40, 48, 300, 12, ES_READONLY | ES_LEFT, 0
END END
/* No accelerators used */ /* No accelerators used */
IDD_HK_WRONG DIALOG DISCARDABLE 50, 50, 300, 188 IDD_HK_WRONG DIALOG DISCARDABLE 50, 50, 340, 188
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "PuTTY Security Alert" CAPTION "PuTTY Security Alert"
FONT 8, "MS Shell Dlg" FONT 8, "MS Shell Dlg"
BEGIN BEGIN
LTEXT "WARNING - POTENTIAL SECURITY BREACH!", IDC_HK_TITLE, 40, 20, 260, 12 LTEXT "WARNING - POTENTIAL SECURITY BREACH!", IDC_HK_TITLE, 40, 20, 300, 12
LTEXT "The server's host key does not match the one {APPNAME} has cached in", 100, 40, 36, 260, 8 LTEXT "The server's host key does not match the one {APPNAME} has cached in", 100, 40, 36, 300, 8
LTEXT "the registry. This means that either the server administrator has", 101, 40, 44, 260, 8 LTEXT "the registry. This means that either the server administrator has", 101, 40, 44, 300, 8
LTEXT "changed the host key, or you have actually connected to another", 102, 40, 52, 260, 8 LTEXT "changed the host key, or you have actually connected to another", 102, 40, 52, 300, 8
LTEXT "computer pretending to be the server.", 103, 40, 60, 260, 8 LTEXT "computer pretending to be the server.", 103, 40, 60, 300, 8
LTEXT "The new {KEYTYPE} key fingerprint is:", 104, 40, 72, 260, 8 LTEXT "The new {KEYTYPE} key fingerprint is:", 104, 40, 72, 300, 8
LTEXT "If you were expecting this change and trust the new key, press", 105, 40, 92, 260, 8 LTEXT "If you were expecting this change and trust the new key, press", 105, 40, 92, 300, 8
LTEXT """Accept"" to update {APPNAME}'s cache and continue connecting.", 106, 40, 100, 260, 8 LTEXT """Accept"" to update {APPNAME}'s cache and continue connecting.", 106, 40, 100, 300, 8
LTEXT "If you want to carry on connecting but without updating the cache,", 107, 40, 112, 260, 8 LTEXT "If you want to carry on connecting but without updating the cache,", 107, 40, 112, 300, 8
LTEXT "press ""Connect Once"".", 108, 40, 120, 260, 8 LTEXT "press ""Connect Once"".", 108, 40, 120, 300, 8
LTEXT "If you want to abandon the connection completely, press ""Cancel"".", 109, 40, 132, 260, 8 LTEXT "If you want to abandon the connection completely, press ""Cancel"".", 109, 40, 132, 300, 8
LTEXT "Pressing ""Cancel"" is the ONLY guaranteed safe choice.", 110, 40, 140, 260, 8 LTEXT "Pressing ""Cancel"" is the ONLY guaranteed safe choice.", 110, 40, 140, 300, 8
ICON "", IDC_HK_ICON, 10, 16, 0, 0 ICON "", IDC_HK_ICON, 10, 16, 0, 0
PUSHBUTTON "Cancel", IDCANCEL, 248, 168, 40, 14 PUSHBUTTON "Cancel", IDCANCEL, 288, 168, 40, 14
PUSHBUTTON "Accept", IDC_HK_ACCEPT, 128, 168, 40, 14 PUSHBUTTON "Accept", IDC_HK_ACCEPT, 168, 168, 40, 14
PUSHBUTTON "Connect Once", IDC_HK_ONCE, 176, 168, 64, 14 PUSHBUTTON "Connect Once", IDC_HK_ONCE, 216, 168, 64, 14
PUSHBUTTON "More info...", IDC_HK_MOREINFO, 60, 168, 64, 14
PUSHBUTTON "Help", IDHELP, 12, 168, 40, 14 PUSHBUTTON "Help", IDHELP, 12, 168, 40, 14
EDITTEXT IDC_HK_FINGERPRINT, 40, 80, 260, 12, ES_READONLY | ES_LEFT, 0 EDITTEXT IDC_HK_FINGERPRINT, 40, 80, 300, 12, ES_READONLY | ES_LEFT, 0
END
/* Accelerators used: clw */
IDD_HK_MOREINFO DIALOG DISCARDABLE 140, 40, 400, 156
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "PuTTY: information about the server's host key"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "SHA256 fingerprint:", 100, 12, 12, 80, 8
EDITTEXT IDC_HKI_SHA256, 100, 10, 288, 12, ES_READONLY
LTEXT "MD5 fingerprint:", 101, 12, 28, 80, 8
EDITTEXT IDC_HKI_MD5, 100, 26, 288, 12, ES_READONLY
LTEXT "Full public key:", 102, 12, 44, 376, 8
EDITTEXT IDC_HKI_PUBKEY, 12, 54, 376, 64, ES_READONLY | ES_MULTILINE | ES_LEFT | ES_AUTOVSCROLL, WS_EX_STATICEDGE
DEFPUSHBUTTON "&Close", IDOK, 176, 130, 48, 14
END END
#include "version.rc2" #include "version.rc2"

View File

@ -838,11 +838,47 @@ void showabout(HWND hwnd)
struct hostkey_dialog_ctx { struct hostkey_dialog_ctx {
const char *const *keywords; const char *const *keywords;
const char *const *values; const char *const *values;
const char *fingerprint; FingerprintType fptype_default;
char **fingerprints;
const char *keydisp;
LPCTSTR iconid; LPCTSTR iconid;
const char *helpctx; const char *helpctx;
}; };
static INT_PTR CALLBACK HostKeyMoreInfoProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_INITDIALOG: {
const struct hostkey_dialog_ctx *ctx =
(const struct hostkey_dialog_ctx *)lParam;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (INT_PTR)ctx);
if (ctx->fingerprints[SSH_FPTYPE_SHA256])
SetDlgItemText(hwnd, IDC_HKI_SHA256,
ctx->fingerprints[SSH_FPTYPE_SHA256]);
if (ctx->fingerprints[SSH_FPTYPE_MD5])
SetDlgItemText(hwnd, IDC_HKI_MD5,
ctx->fingerprints[SSH_FPTYPE_MD5]);
SetDlgItemText(hwnd, IDA_TEXT, ctx->keydisp);
return 1;
}
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
EndDialog(hwnd, 0);
return 0;
}
return 0;
case WM_CLOSE:
EndDialog(hwnd, 0);
return 0;
}
return 0;
}
static INT_PTR CALLBACK HostKeyDialogProc(HWND hwnd, UINT msg, static INT_PTR CALLBACK HostKeyDialogProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) WPARAM wParam, LPARAM lParam)
{ {
@ -878,7 +914,8 @@ static INT_PTR CALLBACK HostKeyDialogProc(HWND hwnd, UINT msg,
} }
strbuf_free(sb); strbuf_free(sb);
SetDlgItemText(hwnd, IDC_HK_FINGERPRINT, ctx->fingerprint); SetDlgItemText(hwnd, IDC_HK_FINGERPRINT,
ctx->fingerprints[ctx->fptype_default]);
MakeDlgItemBorderless(hwnd, IDC_HK_FINGERPRINT); MakeDlgItemBorderless(hwnd, IDC_HK_FINGERPRINT);
HANDLE icon = LoadImage( HANDLE icon = LoadImage(
@ -929,6 +966,13 @@ static INT_PTR CALLBACK HostKeyDialogProc(HWND hwnd, UINT msg,
launch_help(hwnd, ctx->helpctx); launch_help(hwnd, ctx->helpctx);
return 0; return 0;
} }
case IDC_HK_MOREINFO: {
const struct hostkey_dialog_ctx *ctx =
(const struct hostkey_dialog_ctx *)
GetWindowLongPtr(hwnd, GWLP_USERDATA);
DialogBoxParam(hinst, MAKEINTRESOURCE(IDD_HK_MOREINFO),
hwnd, HostKeyMoreInfoProc, (LPARAM)ctx);
}
} }
return 0; return 0;
case WM_CLOSE: case WM_CLOSE:
@ -965,8 +1009,9 @@ int win_seat_verify_ssh_host_key(
struct hostkey_dialog_ctx ctx[1]; struct hostkey_dialog_ctx ctx[1];
ctx->keywords = keywords; ctx->keywords = keywords;
ctx->values = values; ctx->values = values;
ctx->fingerprint = fingerprints[ ctx->fingerprints = fingerprints;
ssh2_pick_default_fingerprint(fingerprints)]; ctx->fptype_default = ssh2_pick_default_fingerprint(fingerprints);
ctx->keydisp = keydisp;
ctx->iconid = (ret == 2 ? IDI_WARNING : IDI_QUESTION); ctx->iconid = (ret == 2 ? IDI_WARNING : IDI_QUESTION);
ctx->helpctx = (ret == 2 ? WINHELP_CTX_errors_hostkey_changed : ctx->helpctx = (ret == 2 ? WINHELP_CTX_errors_hostkey_changed :
WINHELP_CTX_errors_hostkey_absent); WINHELP_CTX_errors_hostkey_absent);