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

Windows PuTTYgen: also display certificate info.

When PuTTYgen is holding a certified key, I don't think there's any
sensible use for pasting around the full public key in authorized_keys
format, because the whole point is that what you put in
authorized_keys is 'please trust this CA' rather than the specific
key. So instead I've reused the space in the dialog box to indicate
that it's a certificate, and provide a 'more info' sub-dialog.
This commit is contained in:
Simon Tatham 2022-07-30 14:41:08 +01:00
parent 2bd2560a60
commit b66c56f441
3 changed files with 214 additions and 26 deletions

View File

@ -444,6 +444,7 @@ void radioline(struct ctlpos *cp, const char *text, int id, int nacross, ...);
void bareradioline(struct ctlpos *cp, int nacross, ...);
void radiobig(struct ctlpos *cp, const char *text, int id, ...);
void checkbox(struct ctlpos *cp, const char *text, int id);
void button(struct ctlpos *cp, const char *btext, int bid, bool defbtn);
void statictext(struct ctlpos *cp, const char *text, int lines, int id);
void staticbtn(struct ctlpos *cp, const char *stext, int sid,
const char *btext, int bid);

View File

@ -696,6 +696,7 @@ enum {
IDC_GENERATING,
IDC_PROGRESS,
IDC_PKSTATIC, IDC_KEYDISPLAY,
IDC_CERTSTATIC, IDC_CERTMOREINFO,
IDC_FPSTATIC, IDC_FINGERPRINT,
IDC_COMMENTSTATIC, IDC_COMMENTEDIT,
IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT,
@ -723,23 +724,44 @@ enum {
IDC_ADDCERT, IDC_REMCERT,
};
static void setupbigedit1(HWND hwnd, int id, int idstatic, RSAKey *key)
static void setupbigedit1(HWND hwnd, RSAKey *key)
{
char *buffer = ssh1_pubkey_str(key);
SetDlgItemText(hwnd, id, buffer);
SetDlgItemText(hwnd, idstatic,
ShowWindow(GetDlgItem(hwnd, IDC_CERTSTATIC), SW_HIDE);
ShowWindow(GetDlgItem(hwnd, IDC_CERTMOREINFO), SW_HIDE);
ShowWindow(GetDlgItem(hwnd, IDC_PKSTATIC), SW_SHOW);
ShowWindow(GetDlgItem(hwnd, IDC_KEYDISPLAY), SW_SHOW);
SetDlgItemText(hwnd, IDC_PKSTATIC,
"&Public key for pasting into authorized_keys file:");
char *buffer = ssh1_pubkey_str(key);
SetDlgItemText(hwnd, IDC_KEYDISPLAY, buffer);
sfree(buffer);
}
static void setupbigedit2(HWND hwnd, int id, int idstatic,
ssh2_userkey *key)
static void setupbigedit2(HWND hwnd, ssh2_userkey *key)
{
char *buffer = ssh2_pubkey_openssh_str(key);
SetDlgItemText(hwnd, id, buffer);
SetDlgItemText(hwnd, idstatic, "&Public key for pasting into "
if (ssh_key_alg(key->key)->is_certificate) {
ShowWindow(GetDlgItem(hwnd, IDC_CERTSTATIC), SW_SHOW);
ShowWindow(GetDlgItem(hwnd, IDC_CERTMOREINFO), SW_SHOW);
ShowWindow(GetDlgItem(hwnd, IDC_PKSTATIC), SW_HIDE);
ShowWindow(GetDlgItem(hwnd, IDC_KEYDISPLAY), SW_HIDE);
SetDlgItemText(hwnd, IDC_CERTSTATIC,
"This public key contains an OpenSSH certificate.");
} else {
ShowWindow(GetDlgItem(hwnd, IDC_CERTSTATIC), SW_HIDE);
ShowWindow(GetDlgItem(hwnd, IDC_CERTMOREINFO), SW_HIDE);
ShowWindow(GetDlgItem(hwnd, IDC_PKSTATIC), SW_SHOW);
ShowWindow(GetDlgItem(hwnd, IDC_KEYDISPLAY), SW_SHOW);
SetDlgItemText(hwnd, IDC_PKSTATIC, "&Public key for pasting into "
"OpenSSH authorized_keys file:");
char *buffer = ssh2_pubkey_openssh_str(key);
SetDlgItemText(hwnd, IDC_KEYDISPLAY, buffer);
sfree(buffer);
}
}
/*
@ -764,13 +786,16 @@ void old_keyfile_warning(void)
static const int nokey_ids[] = { IDC_NOKEY, 0 };
static const int generating_ids[] = { IDC_GENERATING, IDC_PROGRESS, 0 };
static const int gotkey_ids[] = {
IDC_PKSTATIC, IDC_KEYDISPLAY,
static const int gotkey_ids_unconditional[] = {
IDC_FPSTATIC, IDC_FINGERPRINT,
IDC_COMMENTSTATIC, IDC_COMMENTEDIT,
IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT,
IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT, 0
};
static const int gotkey_ids_conditional[] = {
IDC_PKSTATIC, IDC_KEYDISPLAY,
IDC_CERTSTATIC, IDC_CERTMOREINFO,
};
/*
* Small UI helper function to switch the state of the main dialog
@ -784,7 +809,8 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
case 0: /* no key */
hidemany(hwnd, nokey_ids, false);
hidemany(hwnd, generating_ids, true);
hidemany(hwnd, gotkey_ids, true);
hidemany(hwnd, gotkey_ids_unconditional, true);
hidemany(hwnd, gotkey_ids_conditional, true);
EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1);
EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 0);
@ -819,7 +845,8 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
case 1: /* generating key */
hidemany(hwnd, nokey_ids, true);
hidemany(hwnd, generating_ids, false);
hidemany(hwnd, gotkey_ids, true);
hidemany(hwnd, gotkey_ids_unconditional, true);
hidemany(hwnd, gotkey_ids_conditional, true);
EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 0);
EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 0);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 0);
@ -854,7 +881,8 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
case 2:
hidemany(hwnd, nokey_ids, true);
hidemany(hwnd, generating_ids, true);
hidemany(hwnd, gotkey_ids, false);
hidemany(hwnd, gotkey_ids_unconditional, false);
// gotkey_ids_conditional will be unhidden by setupbigedit2
EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1);
EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 1);
@ -1042,7 +1070,7 @@ static void update_ui_after_ssh2_pubkey_change(
SetDlgItemText(hwnd, IDC_FINGERPRINT, fp);
sfree(fp);
setupbigedit2(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC, &state->ssh2key);
setupbigedit2(hwnd, &state->ssh2key);
}
static void update_ui_after_load(HWND hwnd, struct MainDlgState *state,
@ -1073,7 +1101,7 @@ static void update_ui_after_load(HWND hwnd, struct MainDlgState *state,
* Construct a decimal representation of the key, for pasting
* into .ssh/authorized_keys on a Unix box.
*/
setupbigedit1(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC, &state->key);
setupbigedit1(hwnd, &state->key);
} else {
state->ssh2 = true;
state->commentptr = &state->ssh2key.comment;
@ -1340,6 +1368,130 @@ static void start_generating_key(HWND hwnd, struct MainDlgState *state)
}
}
/*
* Dialog-box function and context structure for the 'Certificate
* info' button.
*/
struct certinfo_dialog_ctx {
SeatDialogText *text;
};
static INT_PTR CertInfoProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam, void *vctx)
{
struct certinfo_dialog_ctx *ctx = (struct certinfo_dialog_ctx *)vctx;
switch (msg) {
case WM_INITDIALOG: {
int index = 100, y = 12;
WPARAM font = SendMessage(hwnd, WM_GETFONT, 0, 0);
const char *key = NULL;
for (SeatDialogTextItem *item = ctx->text->items,
*end = item + ctx->text->nitems; item < end; item++) {
switch (item->type) {
case SDT_MORE_INFO_KEY:
key = item->text;
break;
case SDT_MORE_INFO_VALUE_SHORT:
case SDT_MORE_INFO_VALUE_BLOB: {
RECT rk, rv;
DWORD editstyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP |
ES_AUTOHSCROLL | ES_READONLY;
if (item->type == SDT_MORE_INFO_VALUE_BLOB) {
rk.left = 12;
rk.right = 426;
rk.top = y;
rk.bottom = 8;
y += 10;
editstyle |= ES_MULTILINE;
rv.left = 12;
rv.right = 426;
rv.top = y;
rv.bottom = 64;
y += 68;
} else {
rk.left = 12;
rk.right = 130;
rk.top = y+2;
rk.bottom = 8;
rv.left = 150;
rv.right = 438;
rv.top = y;
rv.bottom = 12;
y += 16;
}
MapDialogRect(hwnd, &rk);
HWND ctl = CreateWindowEx(
0, "STATIC", key, WS_CHILD | WS_VISIBLE,
rk.left, rk.top, rk.right, rk.bottom,
hwnd, (HMENU)(ULONG_PTR)index++, hinst, NULL);
SendMessage(ctl, WM_SETFONT, font, MAKELPARAM(true, 0));
MapDialogRect(hwnd, &rv);
ctl = CreateWindowEx(
WS_EX_CLIENTEDGE, "EDIT", item->text, editstyle,
rv.left, rv.top, rv.right, rv.bottom,
hwnd, (HMENU)(ULONG_PTR)index++, hinst, NULL);
SendMessage(ctl, WM_SETFONT, font, MAKELPARAM(true, 0));
break;
}
default:
break;
}
}
/*
* Now resize the overall window, and move the Close button at
* the bottom.
*/
RECT r;
r.left = 176;
r.top = y + 10;
r.right = r.bottom = 0;
MapDialogRect(hwnd, &r);
HWND ctl = GetDlgItem(hwnd, IDOK);
SetWindowPos(ctl, NULL, r.left, r.top, 0, 0,
SWP_NOSIZE | SWP_NOREDRAW | SWP_NOZORDER);
r.left = r.top = r.right = 0;
r.bottom = 300;
MapDialogRect(hwnd, &r);
int oldheight = r.bottom;
r.left = r.top = r.right = 0;
r.bottom = y + 30;
MapDialogRect(hwnd, &r);
int newheight = r.bottom;
GetWindowRect(hwnd, &r);
SetWindowPos(hwnd, NULL, 0, 0, r.right - r.left,
r.bottom - r.top + newheight - oldheight,
SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER);
ShowWindow(hwnd, SW_SHOWNORMAL);
return 1;
}
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
ShinyEndDialog(hwnd, 0);
return 0;
}
return 0;
case WM_CLOSE:
ShinyEndDialog(hwnd, 0);
return 0;
}
return 0;
}
/*
* Dialog-box function for the main PuTTYgen dialog box.
*/
@ -1469,6 +1621,18 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
cp2 = cp;
statictext(&cp2, "", 1, IDC_GENERATING);
progressbar(&cp2, IDC_PROGRESS);
cp2 = cp;
bigeditctrl(&cp2, NULL, -1, IDC_CERTSTATIC, 3);
{
HWND child = GetDlgItem(hwnd, IDC_CERTSTATIC);
LONG_PTR style = GetWindowLongPtr(child, GWL_STYLE);
style &= ~WS_VSCROLL;
SetWindowLongPtr(child, GWL_STYLE, style);
SendMessage(child, EM_SETREADONLY, true, 0);
}
MakeDlgItemBorderless(hwnd, IDC_CERTSTATIC);
cp2.xoff = cp2.width = cp2.width / 3;
button(&cp2, "Certificate info...", IDC_CERTMOREINFO, false);
bigeditctrl(&cp,
"&Public key for pasting into authorized_keys file:",
IDC_PKSTATIC, IDC_KEYDISPLAY, 5);
@ -1695,11 +1859,9 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
*state->commentptr = snewn(len + 1, char);
GetWindowText(editctl, *state->commentptr, len + 1);
if (state->ssh2) {
setupbigedit2(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC,
&state->ssh2key);
setupbigedit2(hwnd, &state->ssh2key);
} else {
setupbigedit1(hwnd, IDC_KEYDISPLAY, IDC_PKSTATIC,
&state->key);
setupbigedit1(hwnd, &state->key);
}
}
}
@ -2039,6 +2201,23 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
remove_certificate(hwnd, state);
}
break;
case IDC_CERTMOREINFO: {
if (HIWORD(wParam) != BN_CLICKED)
break;
state =
(struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (!state->key_exists || !state->ssh2 || !state->ssh2key.key)
break;
if (!ssh_key_alg(state->ssh2key.key)->is_certificate)
break;
struct certinfo_dialog_ctx ctx[1];
ctx->text = ssh_key_cert_info(state->ssh2key.key);
ShinyDialogBox(hinst, MAKEINTRESOURCE(216),
"PuTTYgenCertInfo", hwnd, CertInfoProc, ctx);
seat_dialog_text_free(ctx->text);
break;
}
}
return 0;
case WM_DONEKEY:
@ -2116,11 +2295,9 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
* .ssh/authorized_keys2 on a Unix box.
*/
if (state->ssh2) {
setupbigedit2(hwnd, IDC_KEYDISPLAY,
IDC_PKSTATIC, &state->ssh2key);
setupbigedit2(hwnd, &state->ssh2key);
} else {
setupbigedit1(hwnd, IDC_KEYDISPLAY,
IDC_PKSTATIC, &state->key);
setupbigedit1(hwnd, &state->key);
}
}
/*

View File

@ -82,6 +82,16 @@ BEGIN
PUSHBUTTON "&Cancel", IDCANCEL, 134, 80, 40, 14
END
/* Accelerators used: clw */
216 DIALOG DISCARDABLE 140, 40, 450, 300
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "PuTTYgen: certificate information"
FONT 8, "MS Shell Dlg"
CLASS "PuTTYgenCertInfo"
BEGIN
DEFPUSHBUTTON "&Close", IDOK, 201, 130, 48, 14
END
#include "version.rc2"
#ifndef NO_MANIFESTS