Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>2022-07-30 16:41:08 +0300
committerSimon Tatham <anakin@pobox.com>2022-07-30 19:16:55 +0300
commitb66c56f44129817540086c1c64e4d3e6631c31f4 (patch)
treefd319d411cb9d91f540731d122f7a8e925bec1de /windows/puttygen.c
parent2bd2560a60f5f6c4a03bb645bfcf283f8cf47c83 (diff)
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.
Diffstat (limited to 'windows/puttygen.c')
-rw-r--r--windows/puttygen.c229
1 files changed, 203 insertions, 26 deletions
diff --git a/windows/puttygen.c b/windows/puttygen.c
index db7c5c87..c7b39c97 100644
--- a/windows/puttygen.c
+++ b/windows/puttygen.c
@@ -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 "
- "OpenSSH authorized_keys file:");
- sfree(buffer);
+ 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;
@@ -1341,6 +1369,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.
*/
static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
@@ -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);
}
}
/*