mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
SSH2 can now use Pageant to obtain keys from
[originally from svn r977]
This commit is contained in:
parent
1f168926d7
commit
245cf9c8c9
28
pageant.c
28
pageant.c
@ -34,34 +34,6 @@
|
|||||||
|
|
||||||
#define APPNAME "Pageant"
|
#define APPNAME "Pageant"
|
||||||
|
|
||||||
/*
|
|
||||||
* SSH1 agent messages.
|
|
||||||
*/
|
|
||||||
#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_SUCCESS 6
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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[];
|
||||||
|
|
||||||
static HINSTANCE instance;
|
static HINSTANCE instance;
|
||||||
|
133
ssh.c
133
ssh.c
@ -68,15 +68,6 @@
|
|||||||
#define SSH1_AUTH_TIS 5 /* 0x5 */
|
#define SSH1_AUTH_TIS 5 /* 0x5 */
|
||||||
#define SSH1_AUTH_CCARD 16 /* 0x10 */
|
#define SSH1_AUTH_CCARD 16 /* 0x10 */
|
||||||
|
|
||||||
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 /* 0x1 */
|
|
||||||
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 /* 0x2 */
|
|
||||||
#define SSH_AGENTC_RSA_CHALLENGE 3 /* 0x3 */
|
|
||||||
#define SSH_AGENT_RSA_RESPONSE 4 /* 0x4 */
|
|
||||||
#define SSH_AGENT_FAILURE 5 /* 0x5 */
|
|
||||||
#define SSH_AGENT_SUCCESS 6 /* 0x6 */
|
|
||||||
#define SSH_AGENTC_ADD_RSA_IDENTITY 7 /* 0x7 */
|
|
||||||
#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8 /* 0x8 */
|
|
||||||
|
|
||||||
#define SSH2_MSG_DISCONNECT 1 /* 0x1 */
|
#define SSH2_MSG_DISCONNECT 1 /* 0x1 */
|
||||||
#define SSH2_MSG_IGNORE 2 /* 0x2 */
|
#define SSH2_MSG_IGNORE 2 /* 0x2 */
|
||||||
#define SSH2_MSG_UNIMPLEMENTED 3 /* 0x3 */
|
#define SSH2_MSG_UNIMPLEMENTED 3 /* 0x3 */
|
||||||
@ -1527,7 +1518,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
|
|||||||
|
|
||||||
/* Request the keys held by the agent. */
|
/* Request the keys held by the agent. */
|
||||||
PUT_32BIT(request, 1);
|
PUT_32BIT(request, 1);
|
||||||
request[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
|
request[4] = SSH1_AGENTC_REQUEST_RSA_IDENTITIES;
|
||||||
agent_query(request, 5, &r, &responselen);
|
agent_query(request, 5, &r, &responselen);
|
||||||
response = (unsigned char *)r;
|
response = (unsigned char *)r;
|
||||||
if (response) {
|
if (response) {
|
||||||
@ -1569,7 +1560,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
|
|||||||
agentreq = smalloc(4 + len);
|
agentreq = smalloc(4 + len);
|
||||||
PUT_32BIT(agentreq, len);
|
PUT_32BIT(agentreq, len);
|
||||||
q = agentreq + 4;
|
q = agentreq + 4;
|
||||||
*q++ = SSH_AGENTC_RSA_CHALLENGE;
|
*q++ = SSH1_AGENTC_RSA_CHALLENGE;
|
||||||
PUT_32BIT(q, ssh1_bignum_bitcount(key.modulus));
|
PUT_32BIT(q, ssh1_bignum_bitcount(key.modulus));
|
||||||
q += 4;
|
q += 4;
|
||||||
q += ssh1_write_bignum(q, key.exponent);
|
q += ssh1_write_bignum(q, key.exponent);
|
||||||
@ -1580,7 +1571,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
|
|||||||
agent_query(agentreq, len+4, &ret, &retlen);
|
agent_query(agentreq, len+4, &ret, &retlen);
|
||||||
sfree(agentreq);
|
sfree(agentreq);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (ret[4] == SSH_AGENT_RSA_RESPONSE) {
|
if (ret[4] == SSH1_AGENT_RSA_RESPONSE) {
|
||||||
logevent("Sending Pageant's response");
|
logevent("Sending Pageant's response");
|
||||||
send_packet(SSH1_CMSG_AUTH_RSA_RESPONSE,
|
send_packet(SSH1_CMSG_AUTH_RSA_RESPONSE,
|
||||||
PKT_DATA, ret+5, 16, PKT_END);
|
PKT_DATA, ret+5, 16, PKT_END);
|
||||||
@ -2638,7 +2629,8 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
|
|||||||
AUTH_TYPE_PUBLICKEY_OFFER_QUIET,
|
AUTH_TYPE_PUBLICKEY_OFFER_QUIET,
|
||||||
AUTH_TYPE_PASSWORD
|
AUTH_TYPE_PASSWORD
|
||||||
} type;
|
} type;
|
||||||
static int gotit, need_pw, can_pubkey, can_passwd, tried_pubkey_config;
|
static int gotit, need_pw, can_pubkey, can_passwd;
|
||||||
|
static int tried_pubkey_config, tried_agent;
|
||||||
static int we_are_in;
|
static int we_are_in;
|
||||||
static char username[100];
|
static char username[100];
|
||||||
static char pwprompt[200];
|
static char pwprompt[200];
|
||||||
@ -2752,6 +2744,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
|
|||||||
we_are_in = FALSE;
|
we_are_in = FALSE;
|
||||||
|
|
||||||
tried_pubkey_config = FALSE;
|
tried_pubkey_config = FALSE;
|
||||||
|
tried_agent = FALSE;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
/*
|
/*
|
||||||
@ -2833,6 +2826,119 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
|
|||||||
|
|
||||||
method = 0;
|
method = 0;
|
||||||
|
|
||||||
|
if (!method && can_pubkey && agent_exists && !tried_agent) {
|
||||||
|
/*
|
||||||
|
* Attempt public-key authentication using Pageant.
|
||||||
|
*/
|
||||||
|
static unsigned char request[5], *response, *p;
|
||||||
|
static int responselen;
|
||||||
|
static int i, nkeys;
|
||||||
|
static int authed = FALSE;
|
||||||
|
void *r;
|
||||||
|
|
||||||
|
tried_agent = TRUE;
|
||||||
|
|
||||||
|
logevent("Pageant is running. Requesting keys.");
|
||||||
|
|
||||||
|
/* Request the keys held by the agent. */
|
||||||
|
PUT_32BIT(request, 1);
|
||||||
|
request[4] = SSH2_AGENTC_REQUEST_IDENTITIES;
|
||||||
|
agent_query(request, 5, &r, &responselen);
|
||||||
|
response = (unsigned char *)r;
|
||||||
|
if (response) {
|
||||||
|
p = response + 5;
|
||||||
|
nkeys = GET_32BIT(p); p += 4;
|
||||||
|
{ char buf[64]; sprintf(buf, "Pageant has %d keys", nkeys);
|
||||||
|
logevent(buf); }
|
||||||
|
for (i = 0; i < nkeys; i++) {
|
||||||
|
static char *pkblob, *alg, *commentp;
|
||||||
|
static int pklen, alglen, commentlen;
|
||||||
|
static int siglen, retlen, len;
|
||||||
|
static char *q, *agentreq, *ret;
|
||||||
|
|
||||||
|
{ char buf[64]; sprintf(buf, "Trying Pageant key #%d", i);
|
||||||
|
logevent(buf); }
|
||||||
|
pklen = GET_32BIT(p); p += 4;
|
||||||
|
pkblob = p; p += pklen;
|
||||||
|
alglen = GET_32BIT(pkblob);
|
||||||
|
alg = pkblob + 4;
|
||||||
|
commentlen = GET_32BIT(p); p += 4;
|
||||||
|
commentp = p; p += commentlen;
|
||||||
|
ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
|
||||||
|
ssh2_pkt_addstring(username);
|
||||||
|
ssh2_pkt_addstring("ssh-connection");/* service requested */
|
||||||
|
ssh2_pkt_addstring("publickey");/* method */
|
||||||
|
ssh2_pkt_addbool(FALSE); /* no signature included */
|
||||||
|
ssh2_pkt_addstring_start();
|
||||||
|
ssh2_pkt_addstring_data(alg, alglen);
|
||||||
|
ssh2_pkt_addstring_start();
|
||||||
|
ssh2_pkt_addstring_data(pkblob, pklen);
|
||||||
|
ssh2_pkt_send();
|
||||||
|
|
||||||
|
crWaitUntilV(ispkt);
|
||||||
|
if (pktin.type != SSH2_MSG_USERAUTH_PK_OK) {
|
||||||
|
logevent("Key refused");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
c_write_str("Authenticating with public key \"");
|
||||||
|
c_write(commentp, commentlen);
|
||||||
|
c_write_str("\" from agent\r\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Server is willing to accept the key.
|
||||||
|
* Construct a SIGN_REQUEST.
|
||||||
|
*/
|
||||||
|
ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
|
||||||
|
ssh2_pkt_addstring(username);
|
||||||
|
ssh2_pkt_addstring("ssh-connection"); /* service requested */
|
||||||
|
ssh2_pkt_addstring("publickey"); /* method */
|
||||||
|
ssh2_pkt_addbool(TRUE);
|
||||||
|
ssh2_pkt_addstring_start();
|
||||||
|
ssh2_pkt_addstring_data(alg, alglen);
|
||||||
|
ssh2_pkt_addstring_start();
|
||||||
|
ssh2_pkt_addstring_data(pkblob, pklen);
|
||||||
|
|
||||||
|
siglen = pktout.length - 5 + 4 + 20;
|
||||||
|
len = 1; /* message type */
|
||||||
|
len += 4 + pklen; /* key blob */
|
||||||
|
len += 4 + siglen; /* data to sign */
|
||||||
|
len += 4; /* flags */
|
||||||
|
agentreq = smalloc(4 + len);
|
||||||
|
PUT_32BIT(agentreq, len);
|
||||||
|
q = agentreq + 4;
|
||||||
|
*q++ = SSH2_AGENTC_SIGN_REQUEST;
|
||||||
|
PUT_32BIT(q, pklen); q += 4;
|
||||||
|
memcpy(q, pkblob, pklen); q += pklen;
|
||||||
|
PUT_32BIT(q, siglen); q += 4;
|
||||||
|
/* Now the data to be signed... */
|
||||||
|
PUT_32BIT(q, 20); q += 4;
|
||||||
|
memcpy(q, ssh2_session_id, 20); q += 20;
|
||||||
|
memcpy(q, pktout.data+5, pktout.length-5);
|
||||||
|
q += pktout.length-5;
|
||||||
|
/* And finally the (zero) flags word. */
|
||||||
|
PUT_32BIT(q, 0);
|
||||||
|
agent_query(agentreq, len+4, &ret, &retlen);
|
||||||
|
sfree(agentreq);
|
||||||
|
if (ret) {
|
||||||
|
if (ret[4] == SSH2_AGENT_SIGN_RESPONSE) {
|
||||||
|
logevent("Sending Pageant's response");
|
||||||
|
ssh2_pkt_addstring_start();
|
||||||
|
ssh2_pkt_addstring_data(ret+9, GET_32BIT(ret+5));
|
||||||
|
ssh2_pkt_send();
|
||||||
|
authed = TRUE;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
logevent("Pageant failed to answer challenge");
|
||||||
|
sfree(ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (authed)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!method && can_pubkey && *cfg.keyfile && !tried_pubkey_config) {
|
if (!method && can_pubkey && *cfg.keyfile && !tried_pubkey_config) {
|
||||||
unsigned char *pub_blob;
|
unsigned char *pub_blob;
|
||||||
char *algorithm, *comment;
|
char *algorithm, *comment;
|
||||||
@ -3046,6 +3152,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
|
|||||||
ssh2_pkt_defer();
|
ssh2_pkt_defer();
|
||||||
}
|
}
|
||||||
ssh2_pkt_defersend();
|
ssh2_pkt_defersend();
|
||||||
|
logevent("Sent password\r\n");
|
||||||
type = AUTH_TYPE_PASSWORD;
|
type = AUTH_TYPE_PASSWORD;
|
||||||
} else {
|
} else {
|
||||||
c_write_str("No supported authentication methods left to try!\r\n");
|
c_write_str("No supported authentication methods left to try!\r\n");
|
||||||
|
28
ssh.h
28
ssh.h
@ -265,3 +265,31 @@ int zlib_compress_block(unsigned char *block, int len,
|
|||||||
unsigned char **outblock, int *outlen);
|
unsigned char **outblock, int *outlen);
|
||||||
int zlib_decompress_block(unsigned char *block, int len,
|
int zlib_decompress_block(unsigned char *block, int len,
|
||||||
unsigned char **outblock, int *outlen);
|
unsigned char **outblock, int *outlen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SSH1 agent messages.
|
||||||
|
*/
|
||||||
|
#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_SUCCESS 6
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
Loading…
Reference in New Issue
Block a user