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:
parent
2bd2560a60
commit
b66c56f441
@ -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);
|
||||
|
@ -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,24 +724,45 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Warn about the obsolescent key file format.
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user