mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-31 18:52:49 -05:00
Build outgoing SSH agent requests in a strbuf.
This simplifies the client code both in ssh.c and in the client side of Pageant. I've cheated a tiny bit by preparing agent requests in a strbuf that has space reserved at the front for the packet frame, which makes life easier for the code that sends them off.
This commit is contained in:
parent
8ce0a67028
commit
0c44fa85df
4
aqsync.c
4
aqsync.c
@ -11,11 +11,11 @@
|
|||||||
|
|
||||||
#include "putty.h"
|
#include "putty.h"
|
||||||
|
|
||||||
void agent_query_synchronous(void *in, int inlen, void **out, int *outlen)
|
void agent_query_synchronous(strbuf *query, void **out, int *outlen)
|
||||||
{
|
{
|
||||||
agent_pending_query *pending;
|
agent_pending_query *pending;
|
||||||
|
|
||||||
pending = agent_query(in, inlen, out, outlen, NULL, 0);
|
pending = agent_query(query, out, outlen, NULL, 0);
|
||||||
assert(!pending);
|
assert(!pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
misc.c
13
misc.c
@ -537,6 +537,19 @@ void strbuf_catf(strbuf *buf_o, const char *fmt, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strbuf *strbuf_new_for_agent_query(void)
|
||||||
|
{
|
||||||
|
strbuf *buf = strbuf_new();
|
||||||
|
put_uint32(buf, 0); /* reserve space for length field */
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
void strbuf_finalise_agent_query(strbuf *buf_o)
|
||||||
|
{
|
||||||
|
struct strbuf_impl *buf = FROMFIELD(buf_o, struct strbuf_impl, visible);
|
||||||
|
assert(buf->visible.len >= 5);
|
||||||
|
PUT_32BIT_MSB_FIRST(buf->visible.u, buf->visible.len - 4);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read an entire line of text from a file. Return a buffer
|
* Read an entire line of text from a file. Return a buffer
|
||||||
* malloced to be as big as necessary (caller must free).
|
* malloced to be as big as necessary (caller must free).
|
||||||
|
4
misc.h
4
misc.h
@ -47,10 +47,14 @@ struct strbuf {
|
|||||||
};
|
};
|
||||||
strbuf *strbuf_new(void);
|
strbuf *strbuf_new(void);
|
||||||
void strbuf_free(strbuf *buf);
|
void strbuf_free(strbuf *buf);
|
||||||
|
char *strbuf_append(strbuf *buf, size_t len);
|
||||||
char *strbuf_to_str(strbuf *buf); /* does free buf, but you must free result */
|
char *strbuf_to_str(strbuf *buf); /* does free buf, but you must free result */
|
||||||
void strbuf_catf(strbuf *buf, const char *fmt, ...);
|
void strbuf_catf(strbuf *buf, const char *fmt, ...);
|
||||||
void strbuf_catfv(strbuf *buf, const char *fmt, va_list ap);
|
void strbuf_catfv(strbuf *buf, const char *fmt, va_list ap);
|
||||||
|
|
||||||
|
strbuf *strbuf_new_for_agent_query(void);
|
||||||
|
void strbuf_finalise_agent_query(strbuf *buf);
|
||||||
|
|
||||||
/* String-to-Unicode converters that auto-allocate the destination and
|
/* String-to-Unicode converters that auto-allocate the destination and
|
||||||
* work around the rather deficient interface of mb_to_wc.
|
* work around the rather deficient interface of mb_to_wc.
|
||||||
*
|
*
|
||||||
|
159
pageant.c
159
pageant.c
@ -1118,14 +1118,16 @@ void *pageant_get_keylist1(int *length)
|
|||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
if (!pageant_local) {
|
if (!pageant_local) {
|
||||||
unsigned char request[5], *response;
|
strbuf *request;
|
||||||
|
unsigned char *response;
|
||||||
void *vresponse;
|
void *vresponse;
|
||||||
int resplen;
|
int resplen;
|
||||||
|
|
||||||
request[4] = SSH1_AGENTC_REQUEST_RSA_IDENTITIES;
|
request = strbuf_new_for_agent_query();
|
||||||
PUT_32BIT(request, 1);
|
put_byte(request, SSH1_AGENTC_REQUEST_RSA_IDENTITIES);
|
||||||
|
agent_query_synchronous(request, &vresponse, &resplen);
|
||||||
|
strbuf_free(request);
|
||||||
|
|
||||||
agent_query_synchronous(request, 5, &vresponse, &resplen);
|
|
||||||
response = vresponse;
|
response = vresponse;
|
||||||
if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
|
if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
|
||||||
sfree(response);
|
sfree(response);
|
||||||
@ -1149,14 +1151,16 @@ void *pageant_get_keylist2(int *length)
|
|||||||
void *ret;
|
void *ret;
|
||||||
|
|
||||||
if (!pageant_local) {
|
if (!pageant_local) {
|
||||||
unsigned char request[5], *response;
|
strbuf *request;
|
||||||
|
unsigned char *response;
|
||||||
void *vresponse;
|
void *vresponse;
|
||||||
int resplen;
|
int resplen;
|
||||||
|
|
||||||
request[4] = SSH2_AGENTC_REQUEST_IDENTITIES;
|
request = strbuf_new_for_agent_query();
|
||||||
PUT_32BIT(request, 1);
|
put_byte(request, SSH2_AGENTC_REQUEST_IDENTITIES);
|
||||||
|
agent_query_synchronous(request, &vresponse, &resplen);
|
||||||
|
strbuf_free(request);
|
||||||
|
|
||||||
agent_query_synchronous(request, 5, &vresponse, &resplen);
|
|
||||||
response = vresponse;
|
response = vresponse;
|
||||||
if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER) {
|
if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER) {
|
||||||
sfree(response);
|
sfree(response);
|
||||||
@ -1412,55 +1416,35 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||||||
|
|
||||||
if (type == SSH_KEYTYPE_SSH1) {
|
if (type == SSH_KEYTYPE_SSH1) {
|
||||||
if (!pageant_local) {
|
if (!pageant_local) {
|
||||||
unsigned char *request, *response;
|
strbuf *request;
|
||||||
|
unsigned char *response;
|
||||||
void *vresponse;
|
void *vresponse;
|
||||||
int reqlen, clen, resplen;
|
int resplen;
|
||||||
|
|
||||||
clen = strlen(rkey->comment);
|
request = strbuf_new_for_agent_query();
|
||||||
|
put_byte(request, SSH1_AGENTC_ADD_RSA_IDENTITY);
|
||||||
|
put_uint32(request, bignum_bitcount(rkey->modulus));
|
||||||
|
put_mp_ssh1(request, rkey->modulus);
|
||||||
|
put_mp_ssh1(request, rkey->exponent);
|
||||||
|
put_mp_ssh1(request, rkey->private_exponent);
|
||||||
|
put_mp_ssh1(request, rkey->iqmp);
|
||||||
|
put_mp_ssh1(request, rkey->q);
|
||||||
|
put_mp_ssh1(request, rkey->p);
|
||||||
|
put_stringz(request, rkey->comment);
|
||||||
|
agent_query_synchronous(request, &vresponse, &resplen);
|
||||||
|
strbuf_free(request);
|
||||||
|
|
||||||
reqlen = 4 + 1 + /* length, message type */
|
|
||||||
4 + /* bit count */
|
|
||||||
ssh1_bignum_length(rkey->modulus) +
|
|
||||||
ssh1_bignum_length(rkey->exponent) +
|
|
||||||
ssh1_bignum_length(rkey->private_exponent) +
|
|
||||||
ssh1_bignum_length(rkey->iqmp) +
|
|
||||||
ssh1_bignum_length(rkey->p) +
|
|
||||||
ssh1_bignum_length(rkey->q) + 4 + clen /* comment */
|
|
||||||
;
|
|
||||||
|
|
||||||
request = snewn(reqlen, unsigned char);
|
|
||||||
|
|
||||||
request[4] = SSH1_AGENTC_ADD_RSA_IDENTITY;
|
|
||||||
reqlen = 5;
|
|
||||||
PUT_32BIT(request + reqlen, bignum_bitcount(rkey->modulus));
|
|
||||||
reqlen += 4;
|
|
||||||
reqlen += ssh1_write_bignum(request + reqlen, rkey->modulus);
|
|
||||||
reqlen += ssh1_write_bignum(request + reqlen, rkey->exponent);
|
|
||||||
reqlen +=
|
|
||||||
ssh1_write_bignum(request + reqlen,
|
|
||||||
rkey->private_exponent);
|
|
||||||
reqlen += ssh1_write_bignum(request + reqlen, rkey->iqmp);
|
|
||||||
reqlen += ssh1_write_bignum(request + reqlen, rkey->q);
|
|
||||||
reqlen += ssh1_write_bignum(request + reqlen, rkey->p);
|
|
||||||
PUT_32BIT(request + reqlen, clen);
|
|
||||||
memcpy(request + reqlen + 4, rkey->comment, clen);
|
|
||||||
reqlen += 4 + clen;
|
|
||||||
PUT_32BIT(request, reqlen - 4);
|
|
||||||
|
|
||||||
agent_query_synchronous(request, reqlen, &vresponse, &resplen);
|
|
||||||
response = vresponse;
|
response = vresponse;
|
||||||
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
|
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
|
||||||
*retstr = dupstr("The already running Pageant "
|
*retstr = dupstr("The already running Pageant "
|
||||||
"refused to add the key.");
|
"refused to add the key.");
|
||||||
freersakey(rkey);
|
freersakey(rkey);
|
||||||
sfree(rkey);
|
sfree(rkey);
|
||||||
sfree(request);
|
|
||||||
sfree(response);
|
sfree(response);
|
||||||
return PAGEANT_ACTION_FAILURE;
|
return PAGEANT_ACTION_FAILURE;
|
||||||
}
|
}
|
||||||
freersakey(rkey);
|
freersakey(rkey);
|
||||||
sfree(rkey);
|
sfree(rkey);
|
||||||
sfree(request);
|
|
||||||
sfree(response);
|
sfree(response);
|
||||||
} else {
|
} else {
|
||||||
if (!pageant_add_ssh1_key(rkey)) {
|
if (!pageant_add_ssh1_key(rkey)) {
|
||||||
@ -1470,48 +1454,27 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!pageant_local) {
|
if (!pageant_local) {
|
||||||
unsigned char *request, *response;
|
strbuf *request;
|
||||||
|
unsigned char *response;
|
||||||
void *vresponse;
|
void *vresponse;
|
||||||
strbuf *keyblob;
|
int resplen;
|
||||||
int reqlen, alglen, clen, resplen;
|
|
||||||
alglen = strlen(skey->alg->name);
|
|
||||||
clen = strlen(skey->comment);
|
|
||||||
|
|
||||||
keyblob = strbuf_new();
|
request = strbuf_new_for_agent_query();
|
||||||
skey->alg->openssh_fmtkey(skey->data, BinarySink_UPCAST(keyblob));
|
put_byte(request, SSH2_AGENTC_ADD_IDENTITY);
|
||||||
|
put_stringz(request, skey->alg->name);
|
||||||
|
skey->alg->openssh_fmtkey(skey->data, BinarySink_UPCAST(request));
|
||||||
|
put_stringz(request, skey->comment);
|
||||||
|
agent_query_synchronous(request, &vresponse, &resplen);
|
||||||
|
strbuf_free(request);
|
||||||
|
|
||||||
reqlen = 4 + 1 + /* length, message type */
|
|
||||||
4 + alglen + /* algorithm name */
|
|
||||||
keyblob->len + /* key data */
|
|
||||||
4 + clen /* comment */
|
|
||||||
;
|
|
||||||
|
|
||||||
request = snewn(reqlen, unsigned char);
|
|
||||||
|
|
||||||
request[4] = SSH2_AGENTC_ADD_IDENTITY;
|
|
||||||
reqlen = 5;
|
|
||||||
PUT_32BIT(request + reqlen, alglen);
|
|
||||||
reqlen += 4;
|
|
||||||
memcpy(request + reqlen, skey->alg->name, alglen);
|
|
||||||
reqlen += alglen;
|
|
||||||
memcpy(request + reqlen, keyblob->s, keyblob->len);
|
|
||||||
reqlen += keyblob->len;
|
|
||||||
PUT_32BIT(request + reqlen, clen);
|
|
||||||
memcpy(request + reqlen + 4, skey->comment, clen);
|
|
||||||
reqlen += clen + 4;
|
|
||||||
PUT_32BIT(request, reqlen - 4);
|
|
||||||
|
|
||||||
agent_query_synchronous(request, reqlen, &vresponse, &resplen);
|
|
||||||
response = vresponse;
|
response = vresponse;
|
||||||
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
|
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
|
||||||
*retstr = dupstr("The already running Pageant "
|
*retstr = dupstr("The already running Pageant "
|
||||||
"refused to add the key.");
|
"refused to add the key.");
|
||||||
sfree(request);
|
|
||||||
sfree(response);
|
sfree(response);
|
||||||
return PAGEANT_ACTION_FAILURE;
|
return PAGEANT_ACTION_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sfree(request);
|
|
||||||
sfree(response);
|
sfree(response);
|
||||||
} else {
|
} else {
|
||||||
if (!pageant_add_ssh2_key(skey)) {
|
if (!pageant_add_ssh2_key(skey)) {
|
||||||
@ -1674,26 +1637,24 @@ int pageant_enum_keys(pageant_key_enum_fn_t callback, void *callback_ctx,
|
|||||||
|
|
||||||
int pageant_delete_key(struct pageant_pubkey *key, char **retstr)
|
int pageant_delete_key(struct pageant_pubkey *key, char **retstr)
|
||||||
{
|
{
|
||||||
unsigned char *request, *response;
|
strbuf *request;
|
||||||
int reqlen, resplen, ret;
|
unsigned char *response;
|
||||||
|
int resplen, ret;
|
||||||
void *vresponse;
|
void *vresponse;
|
||||||
|
|
||||||
|
request = strbuf_new_for_agent_query();
|
||||||
|
|
||||||
if (key->ssh_version == 1) {
|
if (key->ssh_version == 1) {
|
||||||
reqlen = 5 + key->blob->len;
|
put_byte(request, SSH1_AGENTC_REMOVE_RSA_IDENTITY);
|
||||||
request = snewn(reqlen, unsigned char);
|
put_data(request, key->blob->s, key->blob->len);
|
||||||
PUT_32BIT(request, reqlen - 4);
|
|
||||||
request[4] = SSH1_AGENTC_REMOVE_RSA_IDENTITY;
|
|
||||||
memcpy(request + 5, key->blob->s, key->blob->len);
|
|
||||||
} else {
|
} else {
|
||||||
reqlen = 9 + key->blob->len;
|
put_byte(request, SSH2_AGENTC_REMOVE_IDENTITY);
|
||||||
request = snewn(reqlen, unsigned char);
|
put_string(request, key->blob->s, key->blob->len);
|
||||||
PUT_32BIT(request, reqlen - 4);
|
|
||||||
request[4] = SSH2_AGENTC_REMOVE_IDENTITY;
|
|
||||||
PUT_32BIT(request + 5, key->blob->len);
|
|
||||||
memcpy(request + 9, key->blob->s, key->blob->len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
agent_query_synchronous(request, reqlen, &vresponse, &resplen);
|
agent_query_synchronous(request, &vresponse, &resplen);
|
||||||
|
strbuf_free(request);
|
||||||
|
|
||||||
response = vresponse;
|
response = vresponse;
|
||||||
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
|
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
|
||||||
*retstr = dupstr("Agent failed to delete key");
|
*retstr = dupstr("Agent failed to delete key");
|
||||||
@ -1702,21 +1663,21 @@ int pageant_delete_key(struct pageant_pubkey *key, char **retstr)
|
|||||||
*retstr = NULL;
|
*retstr = NULL;
|
||||||
ret = PAGEANT_ACTION_OK;
|
ret = PAGEANT_ACTION_OK;
|
||||||
}
|
}
|
||||||
sfree(request);
|
|
||||||
sfree(response);
|
sfree(response);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pageant_delete_all_keys(char **retstr)
|
int pageant_delete_all_keys(char **retstr)
|
||||||
{
|
{
|
||||||
unsigned char request[5], *response;
|
strbuf *request;
|
||||||
int reqlen, resplen, success;
|
unsigned char *response;
|
||||||
|
int resplen, success;
|
||||||
void *vresponse;
|
void *vresponse;
|
||||||
|
|
||||||
PUT_32BIT(request, 1);
|
request = strbuf_new_for_agent_query();
|
||||||
request[4] = SSH2_AGENTC_REMOVE_ALL_IDENTITIES;
|
put_byte(request, SSH2_AGENTC_REMOVE_ALL_IDENTITIES);
|
||||||
reqlen = 5;
|
agent_query_synchronous(request, &vresponse, &resplen);
|
||||||
agent_query_synchronous(request, reqlen, &vresponse, &resplen);
|
strbuf_free(request);
|
||||||
response = vresponse;
|
response = vresponse;
|
||||||
success = (resplen >= 4 && response[4] == SSH_AGENT_SUCCESS);
|
success = (resplen >= 4 && response[4] == SSH_AGENT_SUCCESS);
|
||||||
sfree(response);
|
sfree(response);
|
||||||
@ -1725,10 +1686,10 @@ int pageant_delete_all_keys(char **retstr)
|
|||||||
return PAGEANT_ACTION_FAILURE;
|
return PAGEANT_ACTION_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUT_32BIT(request, 1);
|
request = strbuf_new_for_agent_query();
|
||||||
request[4] = SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
|
put_byte(request, SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES);
|
||||||
reqlen = 5;
|
agent_query_synchronous(request, &vresponse, &resplen);
|
||||||
agent_query_synchronous(request, reqlen, &vresponse, &resplen);
|
strbuf_free(request);
|
||||||
response = vresponse;
|
response = vresponse;
|
||||||
success = (resplen >= 4 && response[4] == SSH_AGENT_SUCCESS);
|
success = (resplen >= 4 && response[4] == SSH_AGENT_SUCCESS);
|
||||||
sfree(response);
|
sfree(response);
|
||||||
|
4
putty.h
4
putty.h
@ -1292,10 +1292,10 @@ void crypto_wrapup();
|
|||||||
*/
|
*/
|
||||||
typedef struct agent_pending_query agent_pending_query;
|
typedef struct agent_pending_query agent_pending_query;
|
||||||
agent_pending_query *agent_query(
|
agent_pending_query *agent_query(
|
||||||
void *in, int inlen, void **out, int *outlen,
|
strbuf *in, void **out, int *outlen,
|
||||||
void (*callback)(void *, void *, int), void *callback_ctx);
|
void (*callback)(void *, void *, int), void *callback_ctx);
|
||||||
void agent_cancel_query(agent_pending_query *);
|
void agent_cancel_query(agent_pending_query *);
|
||||||
void agent_query_synchronous(void *in, int inlen, void **out, int *outlen);
|
void agent_query_synchronous(strbuf *in, void **out, int *outlen);
|
||||||
int agent_exists(void);
|
int agent_exists(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
138
ssh.c
138
ssh.c
@ -3938,8 +3938,8 @@ static void ssh_agentf_callback(void *cv, void *reply, int replylen);
|
|||||||
|
|
||||||
static void ssh_agentf_try_forward(struct ssh_channel *c)
|
static void ssh_agentf_try_forward(struct ssh_channel *c)
|
||||||
{
|
{
|
||||||
unsigned datalen, lengthfield, messagelen;
|
unsigned datalen, length;
|
||||||
unsigned char *message;
|
strbuf *message;
|
||||||
unsigned char msglen[4];
|
unsigned char msglen[4];
|
||||||
void *reply;
|
void *reply;
|
||||||
int replylen;
|
int replylen;
|
||||||
@ -3982,9 +3982,9 @@ static void ssh_agentf_try_forward(struct ssh_channel *c)
|
|||||||
break; /* not even a length field available yet */
|
break; /* not even a length field available yet */
|
||||||
|
|
||||||
bufchain_fetch(&c->u.a.inbuffer, msglen, 4);
|
bufchain_fetch(&c->u.a.inbuffer, msglen, 4);
|
||||||
lengthfield = GET_32BIT(msglen);
|
length = GET_32BIT(msglen);
|
||||||
|
|
||||||
if (lengthfield > AGENT_MAX_MSGLEN) {
|
if (length > AGENT_MAX_MSGLEN-4) {
|
||||||
/*
|
/*
|
||||||
* If the remote has sent a message that's just _too_
|
* If the remote has sent a message that's just _too_
|
||||||
* long, we should reject it in advance of seeing the rest
|
* long, we should reject it in advance of seeing the rest
|
||||||
@ -3998,16 +3998,17 @@ static void ssh_agentf_try_forward(struct ssh_channel *c)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lengthfield > datalen - 4)
|
if (length > datalen - 4)
|
||||||
break; /* a whole message is not yet available */
|
break; /* a whole message is not yet available */
|
||||||
|
|
||||||
messagelen = lengthfield + 4;
|
bufchain_consume(&c->u.a.inbuffer, 4);
|
||||||
|
|
||||||
message = snewn(messagelen, unsigned char);
|
message = strbuf_new_for_agent_query();
|
||||||
bufchain_fetch_consume(&c->u.a.inbuffer, message, messagelen);
|
bufchain_fetch_consume(
|
||||||
|
&c->u.a.inbuffer, strbuf_append(message, length), length);
|
||||||
c->u.a.pending = agent_query(
|
c->u.a.pending = agent_query(
|
||||||
message, messagelen, &reply, &replylen, ssh_agentf_callback, c);
|
message, &reply, &replylen, ssh_agentf_callback, c);
|
||||||
sfree(message);
|
strbuf_free(message);
|
||||||
|
|
||||||
if (c->u.a.pending)
|
if (c->u.a.pending)
|
||||||
return; /* agent_query promised to reply in due course */
|
return; /* agent_query promised to reply in due course */
|
||||||
@ -4172,7 +4173,7 @@ static void do_ssh1_login(void *vctx)
|
|||||||
int userpass_ret;
|
int userpass_ret;
|
||||||
char c;
|
char c;
|
||||||
int pwpkt_type;
|
int pwpkt_type;
|
||||||
unsigned char request[5], *response, *p;
|
unsigned char *response, *p;
|
||||||
int responselen;
|
int responselen;
|
||||||
int keyi, nkeys;
|
int keyi, nkeys;
|
||||||
int authed;
|
int authed;
|
||||||
@ -4545,16 +4546,18 @@ static void do_ssh1_login(void *vctx)
|
|||||||
* Attempt RSA authentication using Pageant.
|
* Attempt RSA authentication using Pageant.
|
||||||
*/
|
*/
|
||||||
void *r;
|
void *r;
|
||||||
|
strbuf *request;
|
||||||
|
|
||||||
s->authed = FALSE;
|
s->authed = FALSE;
|
||||||
s->tried_agent = 1;
|
s->tried_agent = 1;
|
||||||
logevent("Pageant is running. Requesting keys.");
|
logevent("Pageant is running. Requesting keys.");
|
||||||
|
|
||||||
/* Request the keys held by the agent. */
|
/* Request the keys held by the agent. */
|
||||||
PUT_32BIT(s->request, 1);
|
request = strbuf_new_for_agent_query();
|
||||||
s->request[4] = SSH1_AGENTC_REQUEST_RSA_IDENTITIES;
|
put_byte(request, SSH1_AGENTC_REQUEST_RSA_IDENTITIES);
|
||||||
ssh->auth_agent_query = agent_query(
|
ssh->auth_agent_query = agent_query(
|
||||||
s->request, 5, &r, &s->responselen, ssh_agent_callback, ssh);
|
request, &r, &s->responselen, ssh_agent_callback, ssh);
|
||||||
|
strbuf_free(request);
|
||||||
if (ssh->auth_agent_query) {
|
if (ssh->auth_agent_query) {
|
||||||
ssh->agent_response = NULL;
|
ssh->agent_response = NULL;
|
||||||
crWaitUntilV(ssh->agent_response);
|
crWaitUntilV(ssh->agent_response);
|
||||||
@ -4634,38 +4637,31 @@ static void do_ssh1_login(void *vctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
char *agentreq, *q, *ret;
|
strbuf *agentreq;
|
||||||
|
char *ret;
|
||||||
void *vret;
|
void *vret;
|
||||||
int len, retlen;
|
int retlen;
|
||||||
len = 1 + 4; /* message type, bit count */
|
|
||||||
len += ssh1_bignum_length(s->key.exponent);
|
agentreq = strbuf_new_for_agent_query();
|
||||||
len += ssh1_bignum_length(s->key.modulus);
|
put_byte(agentreq, SSH1_AGENTC_RSA_CHALLENGE);
|
||||||
len += ssh1_bignum_length(s->challenge);
|
put_uint32(agentreq, bignum_bitcount(s->key.modulus));
|
||||||
len += 16; /* session id */
|
put_mp_ssh1(agentreq, s->key.exponent);
|
||||||
len += 4; /* response format */
|
put_mp_ssh1(agentreq, s->key.modulus);
|
||||||
agentreq = snewn(4 + len, char);
|
put_mp_ssh1(agentreq, s->challenge);
|
||||||
PUT_32BIT(agentreq, len);
|
put_data(agentreq, s->session_id, 16);
|
||||||
q = agentreq + 4;
|
put_uint32(agentreq, 1); /* response format */
|
||||||
*q++ = SSH1_AGENTC_RSA_CHALLENGE;
|
|
||||||
PUT_32BIT(q, bignum_bitcount(s->key.modulus));
|
|
||||||
q += 4;
|
|
||||||
q += ssh1_write_bignum(q, s->key.exponent);
|
|
||||||
q += ssh1_write_bignum(q, s->key.modulus);
|
|
||||||
q += ssh1_write_bignum(q, s->challenge);
|
|
||||||
memcpy(q, s->session_id, 16);
|
|
||||||
q += 16;
|
|
||||||
PUT_32BIT(q, 1); /* response format */
|
|
||||||
ssh->auth_agent_query = agent_query(
|
ssh->auth_agent_query = agent_query(
|
||||||
agentreq, len + 4, &vret, &retlen,
|
agentreq, &vret, &retlen,
|
||||||
ssh_agent_callback, ssh);
|
ssh_agent_callback, ssh);
|
||||||
|
strbuf_free(agentreq);
|
||||||
|
|
||||||
if (ssh->auth_agent_query) {
|
if (ssh->auth_agent_query) {
|
||||||
sfree(agentreq);
|
|
||||||
ssh->agent_response = NULL;
|
ssh->agent_response = NULL;
|
||||||
crWaitUntilV(ssh->agent_response);
|
crWaitUntilV(ssh->agent_response);
|
||||||
vret = ssh->agent_response;
|
vret = ssh->agent_response;
|
||||||
retlen = ssh->agent_response_len;
|
retlen = ssh->agent_response_len;
|
||||||
} else
|
}
|
||||||
sfree(agentreq);
|
|
||||||
ret = vret;
|
ret = vret;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (ret[4] == SSH1_AGENT_RSA_RESPONSE) {
|
if (ret[4] == SSH1_AGENT_RSA_RESPONSE) {
|
||||||
@ -9921,14 +9917,14 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
int privatekey_available, privatekey_encrypted;
|
int privatekey_available, privatekey_encrypted;
|
||||||
char *publickey_algorithm;
|
char *publickey_algorithm;
|
||||||
char *publickey_comment;
|
char *publickey_comment;
|
||||||
unsigned char agent_request[5], *agent_response, *agentp;
|
unsigned char *agent_response, *agentp;
|
||||||
int agent_responselen;
|
int agent_responselen;
|
||||||
unsigned char *pkblob_in_agent;
|
unsigned char *pkblob_in_agent;
|
||||||
int keyi, nkeys;
|
int keyi, nkeys;
|
||||||
char *pkblob, *alg, *commentp;
|
char *pkblob, *alg, *commentp;
|
||||||
int pklen, alglen, commentlen;
|
int pklen, alglen, commentlen;
|
||||||
int siglen, retlen, len;
|
int retlen, len;
|
||||||
char *q, *agentreq, *ret;
|
char *ret;
|
||||||
struct Packet *pktout;
|
struct Packet *pktout;
|
||||||
Filename *keyfile;
|
Filename *keyfile;
|
||||||
#ifndef NO_GSSAPI
|
#ifndef NO_GSSAPI
|
||||||
@ -10061,15 +10057,18 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
if (conf_get_int(ssh->conf, CONF_tryagent) && agent_exists()) {
|
if (conf_get_int(ssh->conf, CONF_tryagent) && agent_exists()) {
|
||||||
|
|
||||||
void *r;
|
void *r;
|
||||||
|
strbuf *agent_request;
|
||||||
|
|
||||||
logevent("Pageant is running. Requesting keys.");
|
logevent("Pageant is running. Requesting keys.");
|
||||||
|
|
||||||
/* Request the keys held by the agent. */
|
/* Request the keys held by the agent. */
|
||||||
PUT_32BIT(s->agent_request, 1);
|
agent_request = strbuf_new_for_agent_query();
|
||||||
s->agent_request[4] = SSH2_AGENTC_REQUEST_IDENTITIES;
|
put_byte(agent_request, SSH2_AGENTC_REQUEST_IDENTITIES);
|
||||||
ssh->auth_agent_query = agent_query(
|
ssh->auth_agent_query = agent_query(
|
||||||
s->agent_request, 5, &r, &s->agent_responselen,
|
agent_request, &r, &s->agent_responselen,
|
||||||
ssh_agent_callback, ssh);
|
ssh_agent_callback, ssh);
|
||||||
|
strbuf_free(agent_request);
|
||||||
|
|
||||||
if (ssh->auth_agent_query) {
|
if (ssh->auth_agent_query) {
|
||||||
ssh->agent_response = NULL;
|
ssh->agent_response = NULL;
|
||||||
crWaitUntilV(ssh->agent_response);
|
crWaitUntilV(ssh->agent_response);
|
||||||
@ -10468,7 +10467,7 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
pq_push_front(&ssh->pq_ssh2_userauth, pktin);
|
pq_push_front(&ssh->pq_ssh2_userauth, pktin);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
strbuf *agentreq, *sigdata;
|
||||||
void *vret;
|
void *vret;
|
||||||
|
|
||||||
if (flags & FLAG_VERBOSE) {
|
if (flags & FLAG_VERBOSE) {
|
||||||
@ -10493,40 +10492,28 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
put_string(s->pktout, s->pkblob, s->pklen);
|
put_string(s->pktout, s->pkblob, s->pklen);
|
||||||
|
|
||||||
/* Ask agent for signature. */
|
/* Ask agent for signature. */
|
||||||
s->siglen = s->pktout->length - 5 + 4 +
|
agentreq = strbuf_new_for_agent_query();
|
||||||
ssh->v2_session_id_len;
|
put_byte(agentreq, SSH2_AGENTC_SIGN_REQUEST);
|
||||||
if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
|
put_string(agentreq, s->pkblob, s->pklen);
|
||||||
s->siglen -= 4;
|
|
||||||
s->len = 1; /* message type */
|
|
||||||
s->len += 4 + s->pklen; /* key blob */
|
|
||||||
s->len += 4 + s->siglen; /* data to sign */
|
|
||||||
s->len += 4; /* flags */
|
|
||||||
s->agentreq = snewn(4 + s->len, char);
|
|
||||||
PUT_32BIT(s->agentreq, s->len);
|
|
||||||
s->q = s->agentreq + 4;
|
|
||||||
*s->q++ = SSH2_AGENTC_SIGN_REQUEST;
|
|
||||||
PUT_32BIT(s->q, s->pklen);
|
|
||||||
s->q += 4;
|
|
||||||
memcpy(s->q, s->pkblob, s->pklen);
|
|
||||||
s->q += s->pklen;
|
|
||||||
PUT_32BIT(s->q, s->siglen);
|
|
||||||
s->q += 4;
|
|
||||||
/* Now the data to be signed... */
|
/* Now the data to be signed... */
|
||||||
if (!(ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)) {
|
sigdata = strbuf_new();
|
||||||
PUT_32BIT(s->q, ssh->v2_session_id_len);
|
if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID) {
|
||||||
s->q += 4;
|
put_data(sigdata, ssh->v2_session_id,
|
||||||
}
|
ssh->v2_session_id_len);
|
||||||
memcpy(s->q, ssh->v2_session_id,
|
} else {
|
||||||
ssh->v2_session_id_len);
|
put_string(sigdata, ssh->v2_session_id,
|
||||||
s->q += ssh->v2_session_id_len;
|
ssh->v2_session_id_len);
|
||||||
memcpy(s->q, s->pktout->data + 5,
|
}
|
||||||
s->pktout->length - 5);
|
put_data(sigdata, s->pktout->data + 5,
|
||||||
s->q += s->pktout->length - 5;
|
s->pktout->length - 5);
|
||||||
|
put_stringsb(agentreq, sigdata);
|
||||||
/* And finally the (zero) flags word. */
|
/* And finally the (zero) flags word. */
|
||||||
PUT_32BIT(s->q, 0);
|
put_uint32(agentreq, 0);
|
||||||
ssh->auth_agent_query = agent_query(
|
ssh->auth_agent_query = agent_query(
|
||||||
s->agentreq, s->len + 4, &vret, &s->retlen,
|
agentreq, &vret, &s->retlen,
|
||||||
ssh_agent_callback, ssh);
|
ssh_agent_callback, ssh);
|
||||||
|
strbuf_free(agentreq);
|
||||||
|
|
||||||
if (ssh->auth_agent_query) {
|
if (ssh->auth_agent_query) {
|
||||||
ssh->agent_response = NULL;
|
ssh->agent_response = NULL;
|
||||||
crWaitUntilV(ssh->agent_response);
|
crWaitUntilV(ssh->agent_response);
|
||||||
@ -10534,7 +10521,6 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
s->retlen = ssh->agent_response_len;
|
s->retlen = ssh->agent_response_len;
|
||||||
}
|
}
|
||||||
s->ret = vret;
|
s->ret = vret;
|
||||||
sfree(s->agentreq);
|
|
||||||
if (s->ret) {
|
if (s->ret) {
|
||||||
if (s->retlen >= 9 &&
|
if (s->retlen >= 9 &&
|
||||||
s->ret[4] == SSH2_AGENT_SIGN_RESPONSE &&
|
s->ret[4] == SSH2_AGENT_SIGN_RESPONSE &&
|
||||||
|
@ -126,7 +126,7 @@ static void agent_select_result(int fd, int event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
agent_pending_query *agent_query(
|
agent_pending_query *agent_query(
|
||||||
void *in, int inlen, void **out, int *outlen,
|
strbuf *query, void **out, int *outlen,
|
||||||
void (*callback)(void *, void *, int), void *callback_ctx)
|
void (*callback)(void *, void *, int), void *callback_ctx)
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
@ -154,8 +154,11 @@ agent_pending_query *agent_query(
|
|||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (done = 0; done < inlen ;) {
|
strbuf_finalise_agent_query(query);
|
||||||
int ret = write(sock, (char *)in + done, inlen - done);
|
|
||||||
|
for (done = 0; done < query->len ;) {
|
||||||
|
int ret = write(sock, query->s + done,
|
||||||
|
query->len - done);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
close(sock);
|
close(sock);
|
||||||
goto failure;
|
goto failure;
|
||||||
|
@ -31,7 +31,7 @@ void agent_cancel_query(agent_pending_query *q)
|
|||||||
}
|
}
|
||||||
|
|
||||||
agent_pending_query *agent_query(
|
agent_pending_query *agent_query(
|
||||||
void *in, int inlen, void **out, int *outlen,
|
strbuf *query, void **out, int *outlen,
|
||||||
void (*callback)(void *, void *, int), void *callback_ctx)
|
void (*callback)(void *, void *, int), void *callback_ctx)
|
||||||
{
|
{
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
@ -47,6 +47,9 @@ agent_pending_query *agent_query(
|
|||||||
*out = NULL;
|
*out = NULL;
|
||||||
*outlen = 0;
|
*outlen = 0;
|
||||||
|
|
||||||
|
if (query->len > AGENT_MAX_MSGLEN)
|
||||||
|
return NULL; /* query too large */
|
||||||
|
|
||||||
hwnd = FindWindow("Pageant", "Pageant");
|
hwnd = FindWindow("Pageant", "Pageant");
|
||||||
if (!hwnd)
|
if (!hwnd)
|
||||||
return NULL; /* *out == NULL, so failure */
|
return NULL; /* *out == NULL, so failure */
|
||||||
@ -93,7 +96,8 @@ agent_pending_query *agent_query(
|
|||||||
return NULL; /* *out == NULL, so failure */
|
return NULL; /* *out == NULL, so failure */
|
||||||
}
|
}
|
||||||
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
|
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
|
||||||
memcpy(p, in, inlen);
|
strbuf_finalise_agent_query(query);
|
||||||
|
memcpy(p, query->s, query->len);
|
||||||
cds.dwData = AGENT_COPYDATA_ID;
|
cds.dwData = AGENT_COPYDATA_ID;
|
||||||
cds.cbData = 1 + strlen(mapname);
|
cds.cbData = 1 + strlen(mapname);
|
||||||
cds.lpData = mapname;
|
cds.lpData = mapname;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user