1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-02 03:52:49 -05:00

Preliminary support for RSA user authentication in SSH2! Most of the

error messages are currently wrong, and Pageant doesn't yet support
the new key type, and I haven't thoroughly tested that falling back
to password authentication and trying invalid keys etc all work. But
what I have here has successfully performed a public key
authentication, so it's working to at least some extent.

[originally from svn r973]
This commit is contained in:
Simon Tatham
2001-03-03 11:54:34 +00:00
parent d894658913
commit 28b1fc766c
15 changed files with 1406 additions and 255 deletions

View File

@ -101,6 +101,21 @@ static int CALLBACK PassphraseProc(HWND hwnd, UINT msg,
SetForegroundWindow(hwnd);
SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
/*
* Centre the window.
*/
{ /* centre the window */
RECT rs, rd;
HWND hw;
hw = GetDesktopWindow();
if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
(rs.bottom + rs.top + rd.top - rd.bottom)/2,
rd.right-rd.left, rd.bottom-rd.top, TRUE);
}
p = (struct PassphraseProcStruct *)lParam;
passphrase = p->passphrase;
if (p->comment)
@ -176,6 +191,20 @@ static int CALLBACK LicenceProc (HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_INITDIALOG:
/*
* Centre the window.
*/
{ /* centre the window */
RECT rs, rd;
HWND hw;
hw = GetDesktopWindow();
if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
(rs.bottom + rs.top + rd.top - rd.bottom)/2,
rd.right-rd.left, rd.bottom-rd.top, TRUE);
}
return 1;
case WM_COMMAND:
switch (LOWORD(wParam)) {
@ -198,6 +227,20 @@ static int CALLBACK AboutProc (HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_INITDIALOG:
/*
* Centre the window.
*/
{ /* centre the window */
RECT rs, rd;
HWND hw;
hw = GetDesktopWindow();
if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
(rs.bottom + rs.top + rd.top - rd.bottom)/2,
rd.right-rd.left, rd.bottom-rd.top, TRUE);
}
SetDlgItemText (hwnd, 100, ver);
return 1;
case WM_COMMAND:
@ -228,7 +271,6 @@ struct rsa_key_thread_params {
HWND dialog; /* notify this on completion */
int keysize; /* bits in key */
struct RSAKey *key;
struct RSAAux *aux;
};
static DWORD WINAPI generate_rsa_key_thread(void *param) {
struct rsa_key_thread_params *params =
@ -236,8 +278,7 @@ static DWORD WINAPI generate_rsa_key_thread(void *param) {
struct progress prog;
prog.progbar = params->progressbar;
rsa_generate(params->key, params->aux,
params->keysize, progress_update, &prog);
rsa_generate(params->key, params->keysize, progress_update, &prog);
PostMessage(params->dialog, WM_DONEKEY, 0, 0);
@ -251,9 +292,11 @@ struct MainDlgState {
int key_exists;
int entropy_got, entropy_required, entropy_size;
int keysize;
int ssh2;
char **commentptr; /* points to key.comment or ssh2key.comment */
struct ssh2_userkey ssh2key;
unsigned *entropy;
struct RSAKey key;
struct RSAAux aux;
};
static void hidemany(HWND hwnd, const int *ids, int hideit) {
@ -262,7 +305,7 @@ static void hidemany(HWND hwnd, const int *ids, int hideit) {
}
}
static void setupbigedit(HWND hwnd, int id, struct RSAKey *key) {
static void setupbigedit1(HWND hwnd, int id, struct RSAKey *key) {
char *buffer;
char *dec1, *dec2;
@ -279,6 +322,32 @@ static void setupbigedit(HWND hwnd, int id, struct RSAKey *key) {
sfree(buffer);
}
static void setupbigedit2(HWND hwnd, int id, struct ssh2_userkey *key) {
unsigned char *pub_blob;
char *buffer, *p;
int pub_len, buflen;
int i;
pub_blob = key->alg->public_blob(key->data, &pub_len);
buffer = smalloc(strlen(key->alg->name) + 4*((pub_len+2)/3) +
strlen(key->comment) + 3);
strcpy(buffer, key->alg->name);
p = buffer + strlen(buffer);
*p++ = ' ';
i = 0;
while (i < pub_len) {
int n = (pub_len-i < 3 ? pub_len-i : 3);
base64_encode_atom(pub_blob+i, n, p);
i += n;
p += 4;
}
*p++ = ' ';
strcpy(p, key->comment);
SetDlgItemText(hwnd, id, buffer);
sfree(pub_blob);
sfree(buffer);
}
/*
* Dialog-box function for the main PuTTYgen dialog box.
*/
@ -301,6 +370,7 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
IDC_LOADSTATIC, IDC_LOAD,
IDC_SAVESTATIC, IDC_SAVE,
IDC_BOX_PARAMS,
IDC_TYPESTATIC, IDC_KEYSSH1, IDC_KEYSSH2RSA,
IDC_BITSSTATIC, IDC_BITS,
IDC_ABOUT,
};
@ -320,6 +390,20 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
switch (msg) {
case WM_INITDIALOG:
/*
* Centre the window.
*/
{ /* centre the window */
RECT rs, rd;
HWND hw;
hw = GetDesktopWindow();
if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd))
MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2,
(rs.bottom + rs.top + rd.top - rd.bottom)/2,
rd.right-rd.left, rd.bottom-rd.top, TRUE);
}
state = smalloc(sizeof(*state));
state->generation_thread_exists = FALSE;
state->collecting_entropy = FALSE;
@ -347,14 +431,14 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
IDC_PKSTATIC, IDC_KEYDISPLAY, 7);
SendDlgItemMessage(hwnd, IDC_KEYDISPLAY, EM_SETREADONLY, 1, 0);
staticedit(&cp, "Key fingerprint:", IDC_FPSTATIC,
IDC_FINGERPRINT, 70);
IDC_FINGERPRINT, 75);
SendDlgItemMessage(hwnd, IDC_FINGERPRINT, EM_SETREADONLY, 1, 0);
staticedit(&cp, "Key &comment:", IDC_COMMENTSTATIC,
IDC_COMMENTEDIT, 70);
IDC_COMMENTEDIT, 75);
staticpassedit(&cp, "Key p&assphrase:", IDC_PASSPHRASE1STATIC,
IDC_PASSPHRASE1EDIT, 70);
IDC_PASSPHRASE1EDIT, 75);
staticpassedit(&cp, "C&onfirm passphrase:", IDC_PASSPHRASE2STATIC,
IDC_PASSPHRASE2EDIT, 70);
IDC_PASSPHRASE2EDIT, 75);
endbox(&cp);
beginbox(&cp, "Actions",
IDC_BOX_ACTIONS);
@ -367,10 +451,14 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
endbox(&cp);
beginbox(&cp, "Parameters",
IDC_BOX_PARAMS);
radioline(&cp, "Type of key to generate:", IDC_TYPESTATIC, 2,
"SSH&1 (RSA)", IDC_KEYSSH1,
"SSH2 &RSA", IDC_KEYSSH2RSA, NULL);
staticedit(&cp, "Number of &bits in a generated key:",
IDC_BITSSTATIC, IDC_BITS, 20);
endbox(&cp);
}
CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2RSA, IDC_KEYSSH1);
SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEYSIZE, FALSE);
/*
@ -416,7 +504,6 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
params->dialog = hwnd;
params->keysize = state->keysize;
params->key = &state->key;
params->aux = &state->aux;
if (!CreateThread(NULL, 0, generate_rsa_key_thread,
params, 0, &threadid)) {
@ -439,10 +526,10 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
if (state->key_exists) {
HWND editctl = GetDlgItem(hwnd, IDC_COMMENTEDIT);
int len = GetWindowTextLength(editctl);
if (state->key.comment)
sfree(state->key.comment);
state->key.comment = smalloc(len+1);
GetWindowText(editctl, state->key.comment, len+1);
if (*state->commentptr)
sfree(*state->commentptr);
*state->commentptr = smalloc(len+1);
GetWindowText(editctl, *state->commentptr, len+1);
}
}
break;
@ -459,6 +546,8 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
state->keysize = GetDlgItemInt(hwnd, IDC_BITS,
&ok, FALSE);
if (!ok) state->keysize = DEFAULT_KEYSIZE;
/* If we ever introduce a new key type, check it here! */
state->ssh2 = !IsDlgButtonChecked(hwnd, IDC_KEYSSH1);
if (state->keysize < 256) {
int ret = MessageBox(hwnd,
"PuTTYgen will not generate a key"
@ -546,8 +635,13 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
if (ret != IDYES)
break;
}
ret = saversakey(filename, &state->key, &state->aux,
*passphrase ? passphrase : NULL);
if (state->ssh2) {
ret = ssh2_save_userkey(filename, &state->ssh2key,
*passphrase ? passphrase : NULL);
} else {
ret = saversakey(filename, &state->key,
*passphrase ? passphrase : NULL);
}
if (ret <= 0) {
MessageBox(hwnd, "Unable to save key file",
"PuTTYgen Error",
@ -564,13 +658,25 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
filename, 0)) {
char passphrase[PASSPHRASE_MAXLEN];
int needs_pass;
int ver;
int ret;
char *comment;
struct PassphraseProcStruct pps;
struct RSAKey newkey;
struct RSAAux newaux;
struct RSAKey newkey1;
struct ssh2_userkey *newkey2;
needs_pass = rsakey_encrypted(filename, &comment);
ver = keyfile_version(filename);
if (ver == 0) {
MessageBox(NULL, "Couldn't load private key.",
"PuTTYgen Error", MB_OK | MB_ICONERROR);
break;
}
comment = NULL;
if (ver == 1)
needs_pass = rsakey_encrypted(filename, &comment);
else
needs_pass = ssh2_userkey_encrypted(filename, &comment);
pps.passphrase = passphrase;
pps.comment = comment;
do {
@ -586,17 +692,23 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
}
} else
*passphrase = '\0';
ret = loadrsakey(filename, &newkey, &newaux,
passphrase);
if (ver == 1)
ret = loadrsakey(filename, &newkey1, passphrase);
else {
newkey2 = ssh2_load_userkey(filename, passphrase);
if (newkey2 == SSH2_WRONG_PASSPHRASE)
ret = -1;
else if (!newkey2)
ret = 0;
else
ret = 1;
}
} while (ret == -1);
if (comment) sfree(comment);
if (ret == 0) {
MessageBox(NULL, "Couldn't load private key.",
"PuTTYgen Error", MB_OK | MB_ICONERROR);
} else if (ret == 1) {
state->key = newkey;
state->aux = newaux;
EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1);
EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 1);
@ -605,29 +717,55 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
* key data.
*/
{
char buf[128];
SetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT,
passphrase);
SetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT,
passphrase);
SetDlgItemText(hwnd, IDC_COMMENTEDIT,
state->key.comment);
/*
* Set the key fingerprint.
*/
{
char *savecomment = state->key.comment;
if (ver == 1) {
char buf[128];
char *savecomment;
state->ssh2 = FALSE;
state->commentptr = &state->key.comment;
state->key = newkey1;
/*
* Set the key fingerprint.
*/
savecomment = state->key.comment;
state->key.comment = NULL;
rsa_fingerprint(buf, sizeof(buf), &state->key);
state->key.comment = savecomment;
}
SetDlgItemText(hwnd, IDC_FINGERPRINT, buf);
/*
* Construct a decimal representation
* of the key, for pasting into
* .ssh/authorized_keys on a Unix box.
*/
setupbigedit(hwnd, IDC_KEYDISPLAY, &state->key);
SetDlgItemText(hwnd, IDC_FINGERPRINT, buf);
/*
* Construct a decimal representation
* of the key, for pasting into
* .ssh/authorized_keys on a Unix box.
*/
setupbigedit1(hwnd, IDC_KEYDISPLAY, &state->key);
} else {
char *fp;
char *savecomment;
state->ssh2 = TRUE;
state->commentptr = &state->ssh2key.comment;
state->ssh2key = *newkey2; /* structure copy */
sfree(newkey2);
savecomment = state->ssh2key.comment;
state->ssh2key.comment = NULL;
fp = state->
ssh2key.alg->fingerprint(state->ssh2key.data);
state->ssh2key.comment = savecomment;
SetDlgItemText(hwnd, IDC_FINGERPRINT, fp);
sfree(fp);
setupbigedit2(hwnd, IDC_KEYDISPLAY, &state->ssh2key);
}
SetDlgItemText(hwnd, IDC_COMMENTEDIT,
*state->commentptr);
}
/*
* Finally, hide the progress bar and show
@ -651,26 +789,30 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
EnableWindow(GetDlgItem(hwnd, IDC_GENERATE), 1);
EnableWindow(GetDlgItem(hwnd, IDC_LOAD), 1);
EnableWindow(GetDlgItem(hwnd, IDC_SAVE), 1);
if (state->ssh2)
state->commentptr = &state->ssh2key.comment;
else
state->commentptr = &state->key.comment;
/*
* Invent a comment for the key. We'll do this by including
* the date in it. This will be so horrifyingly ugly that
* the user will immediately want to change it, which is
* what we want :-)
*/
state->key.comment = smalloc(30);
*state->commentptr = smalloc(30);
{
time_t t;
struct tm *tm;
time(&t);
tm = localtime(&t);
strftime(state->key.comment, 30, "rsa-key-%Y%m%d", tm);
strftime(*state->commentptr, 30, "rsa-key-%Y%m%d", tm);
}
/*
* Now update the key controls with all the key data.
*/
{
char buf[128];
char *savecomment;
/*
* Blank passphrase, initially. This isn't dangerous,
* because we will warn (Are You Sure?) before allowing
@ -681,22 +823,32 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
/*
* Set the comment.
*/
SetDlgItemText(hwnd, IDC_COMMENTEDIT, state->key.comment);
SetDlgItemText(hwnd, IDC_COMMENTEDIT, *state->commentptr);
/*
* Set the key fingerprint.
*/
{
char *savecomment = state->key.comment;
state->key.comment = NULL;
savecomment = *state->commentptr;
*state->commentptr = NULL;
if (state->ssh2) {
char *fp;
fp = state->ssh2key.alg->fingerprint(state->ssh2key.data);
SetDlgItemText(hwnd, IDC_FINGERPRINT, fp);
sfree(fp);
} else {
char buf[128];
rsa_fingerprint(buf, sizeof(buf), &state->key);
state->key.comment = savecomment;
SetDlgItemText(hwnd, IDC_FINGERPRINT, buf);
}
SetDlgItemText(hwnd, IDC_FINGERPRINT, buf);
*state->commentptr = savecomment;
/*
* Construct a decimal representation of the key, for
* pasting into .ssh/authorized_keys on a Unix box.
*/
setupbigedit(hwnd, IDC_KEYDISPLAY, &state->key);
if (state->ssh2) {
setupbigedit2(hwnd, IDC_KEYDISPLAY, &state->ssh2key);
} else {
setupbigedit1(hwnd, IDC_KEYDISPLAY, &state->key);
}
}
/*
* Finally, hide the progress bar and show the key data.