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

Add support for the OpenSSH SSH2 agent protocol.

[originally from svn r976]
This commit is contained in:
Simon Tatham 2001-03-03 15:31:35 +00:00
parent deccfaa3ef
commit 1f168926d7
5 changed files with 480 additions and 48 deletions

477
pageant.c
View File

@ -9,6 +9,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include "putty.h" // FIXME
#include "ssh.h" #include "ssh.h"
#include "tree234.h" #include "tree234.h"
@ -33,14 +34,33 @@
#define APPNAME "Pageant" #define APPNAME "Pageant"
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 /*
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 * SSH1 agent messages.
#define SSH_AGENTC_RSA_CHALLENGE 3 */
#define SSH_AGENT_RSA_RESPONSE 4 #define SSH1_AGENTC_REQUEST_RSA_IDENTITIES 1
#define SSH1_AGENT_RSA_IDENTITIES_ANSWER 2
#define SSH1_AGENTC_RSA_CHALLENGE 3
#define SSH1_AGENT_RSA_RESPONSE 4
#define SSH1_AGENTC_ADD_RSA_IDENTITY 7
#define SSH1_AGENTC_REMOVE_RSA_IDENTITY 8
#define SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 /* openssh private? */
/*
* Messages common to SSH1 and OpenSSH's SSH2.
*/
#define SSH_AGENT_FAILURE 5 #define SSH_AGENT_FAILURE 5
#define SSH_AGENT_SUCCESS 6 #define SSH_AGENT_SUCCESS 6
#define SSH_AGENTC_ADD_RSA_IDENTITY 7
#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8 /*
* OpenSSH's SSH2 agent messages.
*/
#define SSH2_AGENTC_REQUEST_IDENTITIES 11
#define SSH2_AGENT_IDENTITIES_ANSWER 12
#define SSH2_AGENTC_SIGN_REQUEST 13
#define SSH2_AGENT_SIGN_RESPONSE 14
#define SSH2_AGENTC_ADD_IDENTITY 17
#define SSH2_AGENTC_REMOVE_IDENTITY 18
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
extern char ver[]; extern char ver[];
@ -50,7 +70,7 @@ static HWND keylist;
static HWND aboutbox; static HWND aboutbox;
static HMENU systray_menu; static HMENU systray_menu;
static tree234 *rsakeys; static tree234 *rsakeys, *ssh2keys;
static int has_security; static int has_security;
#ifndef NO_SECURITY #ifndef NO_SECURITY
@ -63,9 +83,10 @@ static gsi_fn_t getsecurityinfo;
/* /*
* We need this to link with the RSA code, because rsaencrypt() * We need this to link with the RSA code, because rsaencrypt()
* pads its data with random bytes. Since we only use rsadecrypt(), * pads its data with random bytes. Since we only use rsadecrypt()
* which is deterministic, this should never be called. * and the signing functions, which are deterministic, this should
* * never be called.
*
* If it _is_ called, there is a _serious_ problem, because it * If it _is_ called, there is a _serious_ problem, because it
* won't generate true random numbers. So we must scream, panic, * won't generate true random numbers. So we must scream, panic,
* and exit immediately if that should happen. * and exit immediately if that should happen.
@ -75,6 +96,16 @@ int random_byte(void) {
exit(0); exit(0);
} }
/*
* Blob structure for passing to the asymmetric SSH2 key compare
* function, prototyped here.
*/
struct blob {
unsigned char *blob;
int len;
};
static int cmpkeys_ssh2_asymm(void *av, void *bv);
/* /*
* This function is needed to link with the DES code. We need not * This function is needed to link with the DES code. We need not
* have it do anything at all. * have it do anything at all.
@ -164,6 +195,20 @@ static int CALLBACK PassphraseProc(HWND hwnd, UINT msg,
switch (msg) { switch (msg) {
case WM_INITDIALOG: 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);
}
SetForegroundWindow(hwnd); SetForegroundWindow(hwnd);
SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
@ -203,23 +248,45 @@ static int CALLBACK PassphraseProc(HWND hwnd, UINT msg,
* Update the visible key list. * Update the visible key list.
*/ */
static void keylist_update(void) { static void keylist_update(void) {
struct RSAKey *key; struct RSAKey *rkey;
struct ssh2_userkey *skey;
enum234 e; enum234 e;
if (keylist) { if (keylist) {
SendDlgItemMessage(keylist, 100, LB_RESETCONTENT, 0, 0); SendDlgItemMessage(keylist, 100, LB_RESETCONTENT, 0, 0);
for (key = first234(rsakeys, &e); key; key = next234(&e)) { for (rkey = first234(rsakeys, &e); rkey; rkey = next234(&e)) {
char listentry[512], *p; char listentry[512], *p;
/* /*
* Replace two spaces in the fingerprint with tabs, for * Replace two spaces in the fingerprint with tabs, for
* nice alignment in the box. * nice alignment in the box.
*/ */
rsa_fingerprint(listentry, sizeof(listentry), key); strcpy(listentry, "ssh1\t");
p = listentry+strlen(listentry);
rsa_fingerprint(p, sizeof(listentry)-(p-listentry), rkey);
p = strchr(listentry, ' '); if (p) *p = '\t'; p = strchr(listentry, ' '); if (p) *p = '\t';
p = strchr(listentry, ' '); if (p) *p = '\t'; p = strchr(listentry, ' '); if (p) *p = '\t';
SendDlgItemMessage (keylist, 100, LB_ADDSTRING, SendDlgItemMessage (keylist, 100, LB_ADDSTRING,
0, (LPARAM)listentry); 0, (LPARAM)listentry);
} }
for (skey = first234(ssh2keys, &e); skey; skey = next234(&e)) {
char listentry[512], *p;
int len;
/*
* Replace two spaces in the fingerprint with tabs, for
* nice alignment in the box.
*/
p = skey->alg->fingerprint(skey->data);
strncpy(listentry, p, sizeof(listentry));
p = strchr(listentry, ' '); if (p) *p = '\t';
p = strchr(listentry, ' '); if (p) *p = '\t';
len = strlen(listentry);
if (len < sizeof(listentry)-2) {
listentry[len] = '\t';
strncpy(listentry+len+1, skey->comment, sizeof(listentry)-len-1);
}
SendDlgItemMessage (keylist, 100, LB_ADDSTRING,
0, (LPARAM)listentry);
}
SendDlgItemMessage (keylist, 100, LB_SETCURSEL, (WPARAM) -1, 0); SendDlgItemMessage (keylist, 100, LB_SETCURSEL, (WPARAM) -1, 0);
} }
} }
@ -229,16 +296,29 @@ static void keylist_update(void) {
*/ */
static void add_keyfile(char *filename) { static void add_keyfile(char *filename) {
char passphrase[PASSPHRASE_MAXLEN]; char passphrase[PASSPHRASE_MAXLEN];
struct RSAKey *key; struct RSAKey *rkey;
struct ssh2_userkey *skey;
int needs_pass; int needs_pass;
int ret; int ret;
int attempts; int attempts;
char *comment; char *comment;
struct PassphraseProcStruct pps; struct PassphraseProcStruct pps;
int ver;
needs_pass = rsakey_encrypted(filename, &comment); ver = keyfile_version(filename);
if (ver == 0) {
MessageBox(NULL, "Couldn't load private key.", APPNAME,
MB_OK | MB_ICONERROR);
return;
}
if (ver == 1)
needs_pass = rsakey_encrypted(filename, &comment);
else
needs_pass = ssh2_userkey_encrypted(filename, &comment);
attempts = 0; attempts = 0;
key = smalloc(sizeof(*key)); if (ver == 1)
rkey = smalloc(sizeof(*rkey));
pps.passphrase = passphrase; pps.passphrase = passphrase;
pps.comment = comment; pps.comment = comment;
do { do {
@ -249,23 +329,42 @@ static void add_keyfile(char *filename) {
(LPARAM)&pps); (LPARAM)&pps);
if (!dlgret) { if (!dlgret) {
if (comment) sfree(comment); if (comment) sfree(comment);
sfree(key); if (ver == 1)
sfree(rkey);
return; /* operation cancelled */ return; /* operation cancelled */
} }
} else } else
*passphrase = '\0'; *passphrase = '\0';
ret = loadrsakey(filename, key, passphrase); if (ver == 1)
ret = loadrsakey(filename, rkey, passphrase);
else {
skey = ssh2_load_userkey(filename, passphrase);
if (skey == SSH2_WRONG_PASSPHRASE)
ret = -1;
else if (!skey)
ret = 0;
else
ret = 1;
}
attempts++; attempts++;
} while (ret == -1); } while (ret == -1);
if (comment) sfree(comment); if (comment) sfree(comment);
if (ret == 0) { if (ret == 0) {
MessageBox(NULL, "Couldn't load private key.", APPNAME, MessageBox(NULL, "Couldn't load private key.", APPNAME,
MB_OK | MB_ICONERROR); MB_OK | MB_ICONERROR);
sfree(key); if (ver == 1)
sfree(rkey);
return; return;
} }
if (add234(rsakeys, key) != key) if (ver == 1) {
sfree(key); /* already present, don't waste RAM */ if (add234(rsakeys, rkey) != rkey)
sfree(rkey); /* already present, don't waste RAM */
} else {
if (add234(ssh2keys, skey) != skey) {
skey->alg->freekey(skey->data);
sfree(skey); /* already present, don't waste RAM */
}
}
} }
/* /*
@ -283,9 +382,9 @@ static void answer_msg(void *msg) {
p += 5; p += 5;
switch (type) { switch (type) {
case SSH_AGENTC_REQUEST_RSA_IDENTITIES: case SSH1_AGENTC_REQUEST_RSA_IDENTITIES:
/* /*
* Reply with SSH_AGENT_RSA_IDENTITIES_ANSWER. * Reply with SSH1_AGENT_RSA_IDENTITIES_ANSWER.
*/ */
{ {
enum234 e; enum234 e;
@ -312,7 +411,7 @@ static void answer_msg(void *msg) {
if (len > AGENT_MAX_MSGLEN) if (len > AGENT_MAX_MSGLEN)
goto failure; /* aaargh! too much stuff! */ goto failure; /* aaargh! too much stuff! */
PUT_32BIT(ret, len-4); PUT_32BIT(ret, len-4);
ret[4] = SSH_AGENT_RSA_IDENTITIES_ANSWER; ret[4] = SSH1_AGENT_RSA_IDENTITIES_ANSWER;
PUT_32BIT(ret+5, nkeys); PUT_32BIT(ret+5, nkeys);
p = ret + 5 + 4; p = ret + 5 + 4;
for (key = first234(rsakeys, &e); key; key = next234(&e)) { for (key = first234(rsakeys, &e); key; key = next234(&e)) {
@ -326,9 +425,57 @@ static void answer_msg(void *msg) {
} }
} }
break; break;
case SSH_AGENTC_RSA_CHALLENGE: case SSH2_AGENTC_REQUEST_IDENTITIES:
/* /*
* Reply with either SSH_AGENT_RSA_RESPONSE or * Reply with SSH2_AGENT_IDENTITIES_ANSWER.
*/
{
enum234 e;
struct ssh2_userkey *key;
int len, nkeys;
unsigned char *blob;
int bloblen;
/*
* Count up the number and length of keys we hold.
*/
len = nkeys = 0;
for (key = first234(ssh2keys, &e); key; key = next234(&e)) {
nkeys++;
len += 4; /* length field */
blob = key->alg->public_blob(key->data, &bloblen);
len += bloblen;
sfree(blob);
len += 4 + strlen(key->comment);
}
/*
* Packet header is the obvious five bytes, plus four
* bytes for the key count.
*/
len += 5 + 4;
if (len > AGENT_MAX_MSGLEN)
goto failure; /* aaargh! too much stuff! */
PUT_32BIT(ret, len-4);
ret[4] = SSH2_AGENT_IDENTITIES_ANSWER;
PUT_32BIT(ret+5, nkeys);
p = ret + 5 + 4;
for (key = first234(ssh2keys, &e); key; key = next234(&e)) {
blob = key->alg->public_blob(key->data, &bloblen);
PUT_32BIT(p, bloblen);
p += 4;
memcpy(p, blob, bloblen);
p += bloblen;
sfree(blob);
PUT_32BIT(p, strlen(key->comment));
memcpy(p+4, key->comment, strlen(key->comment));
p += 4 + strlen(key->comment);
}
}
break;
case SSH1_AGENTC_RSA_CHALLENGE:
/*
* Reply with either SSH1_AGENT_RSA_RESPONSE or
* SSH_AGENT_FAILURE, depending on whether we have that key * SSH_AGENT_FAILURE, depending on whether we have that key
* or not. * or not.
*/ */
@ -370,11 +517,42 @@ static void answer_msg(void *msg) {
*/ */
len = 5 + 16; len = 5 + 16;
PUT_32BIT(ret, len-4); PUT_32BIT(ret, len-4);
ret[4] = SSH_AGENT_RSA_RESPONSE; ret[4] = SSH1_AGENT_RSA_RESPONSE;
memcpy(ret+5, response_md5, 16); memcpy(ret+5, response_md5, 16);
} }
break; break;
case SSH_AGENTC_ADD_RSA_IDENTITY: case SSH2_AGENTC_SIGN_REQUEST:
/*
* Reply with either SSH2_AGENT_RSA_RESPONSE or
* SSH_AGENT_FAILURE, depending on whether we have that key
* or not.
*/
{
struct ssh2_userkey *key;
struct blob b;
unsigned char *data, *signature;
int datalen, siglen, len;
b.len = GET_32BIT(p);
p += 4;
b.blob = p;
p += b.len;
datalen = GET_32BIT(p);
p += 4;
data = p;
key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
if (!key)
goto failure;
signature = key->alg->sign(key->data, data, datalen, &siglen);
len = 5+4+siglen;
PUT_32BIT(ret, len-4);
ret[4] = SSH2_AGENT_SIGN_RESPONSE;
PUT_32BIT(ret+5, siglen);
memcpy(ret+5+4, signature, siglen);
sfree(signature);
}
break;
case SSH1_AGENTC_ADD_RSA_IDENTITY:
/* /*
* Add to the list and return SSH_AGENT_SUCCESS, or * Add to the list and return SSH_AGENT_SUCCESS, or
* SSH_AGENT_FAILURE if the key was malformed. * SSH_AGENT_FAILURE if the key was malformed.
@ -386,9 +564,9 @@ static void answer_msg(void *msg) {
memset(key, 0, sizeof(key)); memset(key, 0, sizeof(key));
p += makekey(p, key, NULL, 1); p += makekey(p, key, NULL, 1);
p += makeprivate(p, key); p += makeprivate(p, key);
p += ssh1_read_bignum(p, NULL); /* p^-1 mod q */ p += ssh1_read_bignum(p, key->iqmp); /* p^-1 mod q */
p += ssh1_read_bignum(p, NULL); /* p */ p += ssh1_read_bignum(p, key->p); /* p */
p += ssh1_read_bignum(p, NULL); /* q */ p += ssh1_read_bignum(p, key->q); /* q */
comment = smalloc(GET_32BIT(p)); comment = smalloc(GET_32BIT(p));
if (comment) { if (comment) {
memcpy(comment, p+4, GET_32BIT(p)); memcpy(comment, p+4, GET_32BIT(p));
@ -405,7 +583,57 @@ static void answer_msg(void *msg) {
} }
} }
break; break;
case SSH_AGENTC_REMOVE_RSA_IDENTITY: case SSH2_AGENTC_ADD_IDENTITY:
/*
* Add to the list and return SSH_AGENT_SUCCESS, or
* SSH_AGENT_FAILURE if the key was malformed.
*/
{
struct ssh2_userkey *key;
char *comment, *alg;
int alglen, commlen;
int bloblen;
key = smalloc(sizeof(struct ssh2_userkey));
alglen = GET_32BIT(p); p += 4;
alg = p; p += alglen;
/* Add further algorithm names here. */
if (alglen == 7 && !memcmp(alg, "ssh-rsa", 7))
key->alg = &ssh_rsa;
else {
sfree(key);
goto failure;
}
bloblen = GET_32BIT((unsigned char *)msg) - (p-(unsigned char *)msg-4);
key->data = key->alg->openssh_createkey(&p, &bloblen);
if (!key->data) {
sfree(key);
goto failure;
}
commlen = GET_32BIT(p); p += 4;
comment = smalloc(commlen+1);
if (comment) {
memcpy(comment, p, commlen);
comment[commlen] = '\0';
}
key->comment = comment;
PUT_32BIT(ret, 1);
ret[4] = SSH_AGENT_FAILURE;
if (add234(ssh2keys, key) == key) {
keylist_update();
ret[4] = SSH_AGENT_SUCCESS;
} else {
key->alg->freekey(key->data);
sfree(key->comment);
sfree(key);
}
}
break;
case SSH1_AGENTC_REMOVE_RSA_IDENTITY:
/* /*
* Remove from the list and return SSH_AGENT_SUCCESS, or * Remove from the list and return SSH_AGENT_SUCCESS, or
* perhaps SSH_AGENT_FAILURE if it wasn't in the list to * perhaps SSH_AGENT_FAILURE if it wasn't in the list to
@ -424,10 +652,78 @@ static void answer_msg(void *msg) {
del234(rsakeys, key); del234(rsakeys, key);
keylist_update(); keylist_update();
freersakey(key); freersakey(key);
sfree(key);
ret[4] = SSH_AGENT_SUCCESS; ret[4] = SSH_AGENT_SUCCESS;
} }
} }
break; break;
case SSH2_AGENTC_REMOVE_IDENTITY:
/*
* Remove from the list and return SSH_AGENT_SUCCESS, or
* perhaps SSH_AGENT_FAILURE if it wasn't in the list to
* start with.
*/
{
struct ssh2_userkey *key;
struct blob b;
b.len = GET_32BIT(p);
p += 4;
b.blob = p;
p += b.len;
key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
if (!key)
goto failure;
PUT_32BIT(ret, 1);
ret[4] = SSH_AGENT_FAILURE;
if (key) {
del234(ssh2keys, key);
keylist_update();
key->alg->freekey(key->data);
sfree(key);
ret[4] = SSH_AGENT_SUCCESS;
}
}
break;
case SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
/*
* Remove all SSH1 keys. Always returns success.
*/
{
struct RSAKey *rkey;
enum234 e;
while ( (rkey = first234(rsakeys, &e)) != NULL ) {
del234(rsakeys, rkey);
freersakey(rkey);
sfree(rkey);
}
keylist_update();
PUT_32BIT(ret, 1);
ret[4] = SSH_AGENT_SUCCESS;
}
break;
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
/*
* Remove all SSH2 keys. Always returns success.
*/
{
struct ssh2_userkey *skey;
enum234 e;
while ( (skey = first234(ssh2keys, &e)) != NULL ) {
del234(ssh2keys, skey);
skey->alg->freekey(skey->data);
sfree(skey);
}
keylist_update();
PUT_32BIT(ret, 1);
ret[4] = SSH_AGENT_SUCCESS;
}
break;
default: default:
failure: failure:
/* /*
@ -442,7 +738,7 @@ static void answer_msg(void *msg) {
/* /*
* Key comparison function for the 2-3-4 tree of RSA keys. * Key comparison function for the 2-3-4 tree of RSA keys.
*/ */
static int cmpkeys(void *av, void *bv) { static int cmpkeys_rsa(void *av, void *bv) {
struct RSAKey *a = (struct RSAKey *)av; struct RSAKey *a = (struct RSAKey *)av;
struct RSAKey *b = (struct RSAKey *)bv; struct RSAKey *b = (struct RSAKey *)bv;
Bignum am, bm; Bignum am, bm;
@ -472,6 +768,75 @@ static int cmpkeys(void *av, void *bv) {
return 0; return 0;
} }
/*
* Key comparison function for the 2-3-4 tree of SSH2 keys.
*/
static int cmpkeys_ssh2(void *av, void *bv) {
struct ssh2_userkey *a = (struct ssh2_userkey *)av;
struct ssh2_userkey *b = (struct ssh2_userkey *)bv;
int i;
int alen, blen;
unsigned char *ablob, *bblob;
int c;
/*
* Compare purely by public blob.
*/
ablob = a->alg->public_blob(a->data, &alen);
bblob = b->alg->public_blob(b->data, &blen);
c = 0;
for (i = 0; i < alen && i < blen; i++) {
if (ablob[i] < bblob[i]) {
c = -1; break;
} else if (ablob[i] > bblob[i]) {
c = +1; break;
}
}
if (c == 0 && i < alen) c = +1; /* a is longer */
if (c == 0 && i < blen) c = -1; /* a is longer */
sfree(ablob);
sfree(bblob);
return c;
}
/*
* Key comparison function for looking up a blob in the 2-3-4 tree
* of SSH2 keys.
*/
static int cmpkeys_ssh2_asymm(void *av, void *bv) {
struct blob *a = (struct blob *)av;
struct ssh2_userkey *b = (struct ssh2_userkey *)bv;
int i;
int alen, blen;
unsigned char *ablob, *bblob;
int c;
/*
* Compare purely by public blob.
*/
ablob = a->blob;
alen = a->len;
bblob = b->alg->public_blob(b->data, &blen);
c = 0;
for (i = 0; i < alen && i < blen; i++) {
if (ablob[i] < bblob[i]) {
c = -1; break;
} else if (ablob[i] > bblob[i]) {
c = +1; break;
}
}
if (c == 0 && i < alen) c = +1; /* a is longer */
if (c == 0 && i < blen) c = -1; /* a is longer */
sfree(bblob);
return c;
}
static void error(char *s) { static void error(char *s) {
MessageBox(hwnd, s, APPNAME, MB_OK | MB_ICONERROR); MessageBox(hwnd, s, APPNAME, MB_OK | MB_ICONERROR);
} }
@ -510,15 +875,30 @@ static void prompt_add_keyfile(void) {
static int CALLBACK KeyListProc(HWND hwnd, UINT msg, static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) { WPARAM wParam, LPARAM lParam) {
enum234 e; enum234 e;
struct RSAKey *key; struct RSAKey *rkey;
struct ssh2_userkey *skey;
switch (msg) { switch (msg) {
case WM_INITDIALOG: 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);
}
keylist = hwnd; keylist = hwnd;
{ {
static int tabs[2] = {25, 175}; static int tabs[] = {35, 60, 210};
SendDlgItemMessage (hwnd, 100, LB_SETTABSTOPS, 2, SendDlgItemMessage (hwnd, 100, LB_SETTABSTOPS,
(LPARAM) tabs); sizeof(tabs)/sizeof(*tabs), (LPARAM) tabs);
} }
keylist_update(); keylist_update();
return 0; return 0;
@ -543,11 +923,23 @@ static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
MessageBeep(0); MessageBeep(0);
break; break;
} }
for (key = first234(rsakeys, &e); key; key = next234(&e)) for (rkey = first234(rsakeys, &e); rkey; rkey = next234(&e))
if (n-- == 0) if (n-- == 0)
break; break;
del234(rsakeys, key); if (rkey) {
freersakey(key); free(key); del234(rsakeys, rkey);
freersakey(rkey);
sfree(rkey);
} else {
for (skey = first234(ssh2keys, &e); skey; skey = next234(&e))
if (n-- == 0)
break;
if (skey) {
del234(ssh2keys, skey);
skey->alg->freekey(skey->data);
sfree(skey);
}
}
keylist_update(); keylist_update();
} }
return 0; return 0;
@ -830,10 +1222,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
/* /*
* Initialise storage for RSA keys. * Initialise storage for RSA keys.
*/ */
rsakeys = newtree234(cmpkeys); rsakeys = newtree234(cmpkeys_rsa);
ssh2keys = newtree234(cmpkeys_ssh2);
/* /*
* Process the command line and add RSA keys as listed on it. * Process the command line and add keys as listed on it.
*/ */
{ {
char *p; char *p;

View File

@ -18,16 +18,16 @@ BEGIN
PUSHBUTTON "&Cancel", IDCANCEL, 80, 42, 40, 14 PUSHBUTTON "&Cancel", IDCANCEL, 80, 42, 40, 14
END END
211 DIALOG DISCARDABLE 0, 0, 300, 200 211 DIALOG DISCARDABLE 0, 0, 330, 200
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Pageant Key List" CAPTION "Pageant Key List"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
BEGIN BEGIN
LISTBOX 100, 10, 10, 280, 155, LISTBOX 100, 10, 10, 310, 155,
LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | WS_TABSTOP LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "&Add Key", 101, 60, 162, 60, 14 PUSHBUTTON "&Add Key", 101, 75, 162, 60, 14
PUSHBUTTON "&Remove Key", 102, 180, 162, 60, 14 PUSHBUTTON "&Remove Key", 102, 195, 162, 60, 14
DEFPUSHBUTTON "&Close", IDOK, 240, 182, 50, 14 DEFPUSHBUTTON "&Close", IDOK, 270, 182, 50, 14
END END
/* Accelerators used: cl */ /* Accelerators used: cl */

1
ssh.h
View File

@ -142,6 +142,7 @@ struct ssh_signkey {
unsigned char *(*private_blob)(void *key, int *len); unsigned char *(*private_blob)(void *key, int *len);
void *(*createkey)(unsigned char *pub_blob, int pub_len, void *(*createkey)(unsigned char *pub_blob, int pub_len,
unsigned char *priv_blob, int priv_len); unsigned char *priv_blob, int priv_len);
void *(*openssh_createkey)(unsigned char **blob, int *len);
char *(*fingerprint)(void *key); char *(*fingerprint)(void *key);
int (*verifysig)(void *key, char *sig, int siglen, int (*verifysig)(void *key, char *sig, int siglen,
char *data, int datalen); char *data, int datalen);

View File

@ -315,6 +315,10 @@ static void *dss_createkey(unsigned char *pub_blob, int pub_len,
return NULL; /* can't handle DSS private keys */ return NULL; /* can't handle DSS private keys */
} }
static void *dss_openssh_createkey(unsigned char **blob, int *len) {
return NULL; /* can't handle DSS private keys */
}
unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen) { unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen) {
return NULL; /* can't handle DSS private keys */ return NULL; /* can't handle DSS private keys */
} }
@ -326,6 +330,7 @@ const struct ssh_signkey ssh_dss = {
dss_public_blob, dss_public_blob,
dss_private_blob, dss_private_blob,
dss_createkey, dss_createkey,
dss_openssh_createkey,
dss_fingerprint, dss_fingerprint,
dss_verifysig, dss_verifysig,
dss_sign, dss_sign,

View File

@ -208,7 +208,7 @@ static void *rsa2_newkey(char *data, int len) {
if (!rsa) return NULL; if (!rsa) return NULL;
getstring(&data, &len, &p, &slen); getstring(&data, &len, &p, &slen);
if (!p || memcmp(p, "ssh-rsa", 7)) { if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
sfree(rsa); sfree(rsa);
return NULL; return NULL;
} }
@ -309,6 +309,38 @@ static void *rsa2_createkey(unsigned char *pub_blob, int pub_len,
return rsa; return rsa;
} }
static void *rsa2_openssh_createkey(unsigned char **blob, int *len) {
char **b = (char **)blob;
struct RSAKey *rsa;
char *p;
int slen;
rsa = smalloc(sizeof(struct RSAKey));
if (!rsa) return NULL;
rsa->comment = NULL;
rsa->modulus = getmp(b, len);
rsa->exponent = getmp(b, len);
rsa->private_exponent = getmp(b, len);
rsa->iqmp = getmp(b, len);
rsa->p = getmp(b, len);
rsa->q = getmp(b, len);
if (!rsa->modulus || !rsa->exponent || !rsa->private_exponent ||
!rsa->iqmp || !rsa->p || !rsa->q) {
sfree(rsa->modulus);
sfree(rsa->exponent);
sfree(rsa->private_exponent);
sfree(rsa->iqmp);
sfree(rsa->p);
sfree(rsa->q);
sfree(rsa);
return NULL;
}
return rsa;
}
static char *rsa2_fingerprint(void *key) { static char *rsa2_fingerprint(void *key) {
struct RSAKey *rsa = (struct RSAKey *)key; struct RSAKey *rsa = (struct RSAKey *)key;
struct MD5Context md5c; struct MD5Context md5c;
@ -455,6 +487,7 @@ const struct ssh_signkey ssh_rsa = {
rsa2_public_blob, rsa2_public_blob,
rsa2_private_blob, rsa2_private_blob,
rsa2_createkey, rsa2_createkey,
rsa2_openssh_createkey,
rsa2_fingerprint, rsa2_fingerprint,
rsa2_verifysig, rsa2_verifysig,
rsa2_sign, rsa2_sign,