mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 01:02:24 +00:00
Pageant client code: parse replies using BinarySource.
This affects both the client code used by Pageant itself, in pageant.c, and the client code in ssh.c used during SSH userauth.
This commit is contained in:
parent
392a8c00f6
commit
e2431c3ef8
118
pageant.c
118
pageant.c
@ -1307,145 +1307,91 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||||||
int pageant_enum_keys(pageant_key_enum_fn_t callback, void *callback_ctx,
|
int pageant_enum_keys(pageant_key_enum_fn_t callback, void *callback_ctx,
|
||||||
char **retstr)
|
char **retstr)
|
||||||
{
|
{
|
||||||
unsigned char *keylist, *p;
|
unsigned char *keylist;
|
||||||
int i, nkeys, keylistlen;
|
int i, nkeys, keylistlen;
|
||||||
char *comment;
|
ptrlen comment;
|
||||||
struct pageant_pubkey cbkey;
|
struct pageant_pubkey cbkey;
|
||||||
|
BinarySource src[1];
|
||||||
|
|
||||||
keylist = pageant_get_keylist1(&keylistlen);
|
keylist = pageant_get_keylist1(&keylistlen);
|
||||||
if (keylistlen < 4) {
|
if (!keylist) {
|
||||||
*retstr = dupstr("Received broken SSH-1 key list from agent");
|
*retstr = dupstr("Did not receive an SSH-1 key list from agent");
|
||||||
sfree(keylist);
|
|
||||||
return PAGEANT_ACTION_FAILURE;
|
return PAGEANT_ACTION_FAILURE;
|
||||||
}
|
}
|
||||||
nkeys = toint(GET_32BIT(keylist));
|
BinarySource_BARE_INIT(src, keylist, keylistlen);
|
||||||
if (nkeys < 0) {
|
|
||||||
*retstr = dupstr("Received broken SSH-1 key list from agent");
|
|
||||||
sfree(keylist);
|
|
||||||
return PAGEANT_ACTION_FAILURE;
|
|
||||||
}
|
|
||||||
p = keylist + 4;
|
|
||||||
keylistlen -= 4;
|
|
||||||
|
|
||||||
|
nkeys = toint(get_uint32(src));
|
||||||
for (i = 0; i < nkeys; i++) {
|
for (i = 0; i < nkeys; i++) {
|
||||||
struct RSAKey rkey;
|
struct RSAKey rkey;
|
||||||
char fingerprint[128];
|
char fingerprint[128];
|
||||||
int n;
|
|
||||||
|
|
||||||
/* public blob and fingerprint */
|
/* public blob and fingerprint */
|
||||||
memset(&rkey, 0, sizeof(rkey));
|
memset(&rkey, 0, sizeof(rkey));
|
||||||
n = rsa_ssh1_readpub(p, keylistlen, &rkey, NULL,
|
get_rsa_ssh1_pub(src, &rkey, NULL, RSA_SSH1_EXPONENT_FIRST);
|
||||||
RSA_SSH1_EXPONENT_FIRST);
|
comment = get_string(src);
|
||||||
if (n < 0 || n > keylistlen) {
|
|
||||||
freersakey(&rkey);
|
|
||||||
*retstr = dupstr("Received broken SSH-1 key list from agent");
|
|
||||||
sfree(keylist);
|
|
||||||
return PAGEANT_ACTION_FAILURE;
|
|
||||||
}
|
|
||||||
p += n, keylistlen -= n;
|
|
||||||
rsa_fingerprint(fingerprint, sizeof(fingerprint), &rkey);
|
|
||||||
|
|
||||||
/* comment */
|
if (get_err(src)) {
|
||||||
if (keylistlen < 4) {
|
|
||||||
*retstr = dupstr("Received broken SSH-1 key list from agent");
|
*retstr = dupstr("Received broken SSH-1 key list from agent");
|
||||||
freersakey(&rkey);
|
freersakey(&rkey);
|
||||||
sfree(keylist);
|
sfree(keylist);
|
||||||
return PAGEANT_ACTION_FAILURE;
|
return PAGEANT_ACTION_FAILURE;
|
||||||
}
|
}
|
||||||
n = toint(GET_32BIT(p));
|
|
||||||
p += 4, keylistlen -= 4;
|
rsa_fingerprint(fingerprint, sizeof(fingerprint), &rkey);
|
||||||
if (n < 0 || keylistlen < n) {
|
|
||||||
*retstr = dupstr("Received broken SSH-1 key list from agent");
|
|
||||||
freersakey(&rkey);
|
|
||||||
sfree(keylist);
|
|
||||||
return PAGEANT_ACTION_FAILURE;
|
|
||||||
}
|
|
||||||
comment = dupprintf("%.*s", (int)n, (const char *)p);
|
|
||||||
p += n, keylistlen -= n;
|
|
||||||
|
|
||||||
cbkey.blob = strbuf_new();
|
cbkey.blob = strbuf_new();
|
||||||
rsa_ssh1_public_blob(BinarySink_UPCAST(cbkey.blob), &rkey,
|
rsa_ssh1_public_blob(BinarySink_UPCAST(cbkey.blob), &rkey,
|
||||||
RSA_SSH1_EXPONENT_FIRST);
|
RSA_SSH1_EXPONENT_FIRST);
|
||||||
cbkey.comment = comment;
|
cbkey.comment = mkstr(comment);
|
||||||
cbkey.ssh_version = 1;
|
cbkey.ssh_version = 1;
|
||||||
callback(callback_ctx, fingerprint, comment, &cbkey);
|
callback(callback_ctx, fingerprint, cbkey.comment, &cbkey);
|
||||||
strbuf_free(cbkey.blob);
|
strbuf_free(cbkey.blob);
|
||||||
freersakey(&rkey);
|
freersakey(&rkey);
|
||||||
sfree(comment);
|
sfree(cbkey.comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
sfree(keylist);
|
sfree(keylist);
|
||||||
|
|
||||||
if (keylistlen != 0) {
|
if (get_err(src) || get_avail(src) != 0) {
|
||||||
*retstr = dupstr("Received broken SSH-1 key list from agent");
|
*retstr = dupstr("Received broken SSH-1 key list from agent");
|
||||||
return PAGEANT_ACTION_FAILURE;
|
return PAGEANT_ACTION_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
keylist = pageant_get_keylist2(&keylistlen);
|
keylist = pageant_get_keylist2(&keylistlen);
|
||||||
if (keylistlen < 4) {
|
if (!keylist) {
|
||||||
*retstr = dupstr("Received broken SSH-2 key list from agent");
|
*retstr = dupstr("Did not receive an SSH-2 key list from agent");
|
||||||
sfree(keylist);
|
|
||||||
return PAGEANT_ACTION_FAILURE;
|
return PAGEANT_ACTION_FAILURE;
|
||||||
}
|
}
|
||||||
nkeys = toint(GET_32BIT(keylist));
|
BinarySource_BARE_INIT(src, keylist, keylistlen);
|
||||||
if (nkeys < 0) {
|
|
||||||
*retstr = dupstr("Received broken SSH-2 key list from agent");
|
|
||||||
sfree(keylist);
|
|
||||||
return PAGEANT_ACTION_FAILURE;
|
|
||||||
}
|
|
||||||
p = keylist + 4;
|
|
||||||
keylistlen -= 4;
|
|
||||||
|
|
||||||
|
nkeys = toint(get_uint32(src));
|
||||||
for (i = 0; i < nkeys; i++) {
|
for (i = 0; i < nkeys; i++) {
|
||||||
|
ptrlen pubblob;
|
||||||
char *fingerprint;
|
char *fingerprint;
|
||||||
int n;
|
|
||||||
|
|
||||||
/* public blob */
|
pubblob = get_string(src);
|
||||||
if (keylistlen < 4) {
|
comment = get_string(src);
|
||||||
|
|
||||||
|
if (get_err(src)) {
|
||||||
*retstr = dupstr("Received broken SSH-2 key list from agent");
|
*retstr = dupstr("Received broken SSH-2 key list from agent");
|
||||||
sfree(keylist);
|
sfree(keylist);
|
||||||
return PAGEANT_ACTION_FAILURE;
|
return PAGEANT_ACTION_FAILURE;
|
||||||
}
|
}
|
||||||
n = toint(GET_32BIT(p));
|
|
||||||
p += 4, keylistlen -= 4;
|
fingerprint = ssh2_fingerprint_blob(pubblob.ptr, pubblob.len);
|
||||||
if (n < 0 || keylistlen < n) {
|
|
||||||
*retstr = dupstr("Received broken SSH-2 key list from agent");
|
|
||||||
sfree(keylist);
|
|
||||||
return PAGEANT_ACTION_FAILURE;
|
|
||||||
}
|
|
||||||
fingerprint = ssh2_fingerprint_blob(p, n);
|
|
||||||
cbkey.blob = strbuf_new();
|
cbkey.blob = strbuf_new();
|
||||||
put_data(cbkey.blob, p, n);
|
put_data(cbkey.blob, pubblob.ptr, pubblob.len);
|
||||||
p += n, keylistlen -= n;
|
|
||||||
|
|
||||||
/* comment */
|
|
||||||
if (keylistlen < 4) {
|
|
||||||
*retstr = dupstr("Received broken SSH-2 key list from agent");
|
|
||||||
sfree(fingerprint);
|
|
||||||
sfree(keylist);
|
|
||||||
return PAGEANT_ACTION_FAILURE;
|
|
||||||
}
|
|
||||||
n = toint(GET_32BIT(p));
|
|
||||||
p += 4, keylistlen -= 4;
|
|
||||||
if (n < 0 || keylistlen < n) {
|
|
||||||
*retstr = dupstr("Received broken SSH-2 key list from agent");
|
|
||||||
sfree(fingerprint);
|
|
||||||
sfree(keylist);
|
|
||||||
return PAGEANT_ACTION_FAILURE;
|
|
||||||
}
|
|
||||||
comment = dupprintf("%.*s", (int)n, (const char *)p);
|
|
||||||
p += n, keylistlen -= n;
|
|
||||||
|
|
||||||
cbkey.ssh_version = 2;
|
cbkey.ssh_version = 2;
|
||||||
cbkey.comment = comment;
|
cbkey.comment = mkstr(comment);
|
||||||
callback(callback_ctx, fingerprint, comment, &cbkey);
|
callback(callback_ctx, fingerprint, cbkey.comment, &cbkey);
|
||||||
sfree(fingerprint);
|
sfree(fingerprint);
|
||||||
sfree(comment);
|
sfree(cbkey.comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
sfree(keylist);
|
sfree(keylist);
|
||||||
|
|
||||||
if (keylistlen != 0) {
|
if (get_err(src) || get_avail(src) != 0) {
|
||||||
*retstr = dupstr("Received broken SSH-2 key list from agent");
|
*retstr = dupstr("Received broken SSH-2 key list from agent");
|
||||||
return PAGEANT_ACTION_FAILURE;
|
return PAGEANT_ACTION_FAILURE;
|
||||||
}
|
}
|
||||||
|
223
ssh.c
223
ssh.c
@ -4053,14 +4053,13 @@ 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 *response, *p;
|
unsigned char *agent_response;
|
||||||
int responselen;
|
BinarySource asrc[1]; /* response from SSH agent */
|
||||||
int keyi, nkeys;
|
int keyi, nkeys;
|
||||||
int authed;
|
int authed;
|
||||||
struct RSAKey key;
|
struct RSAKey key;
|
||||||
Bignum challenge;
|
Bignum challenge;
|
||||||
char *commentp;
|
ptrlen comment;
|
||||||
int commentlen;
|
|
||||||
int dlgret;
|
int dlgret;
|
||||||
Filename *keyfile;
|
Filename *keyfile;
|
||||||
struct RSAKey servkey, hostkey;
|
struct RSAKey servkey, hostkey;
|
||||||
@ -4425,6 +4424,7 @@ static void do_ssh1_login(void *vctx)
|
|||||||
* Attempt RSA authentication using Pageant.
|
* Attempt RSA authentication using Pageant.
|
||||||
*/
|
*/
|
||||||
void *r;
|
void *r;
|
||||||
|
int rlen;
|
||||||
strbuf *request;
|
strbuf *request;
|
||||||
|
|
||||||
s->authed = FALSE;
|
s->authed = FALSE;
|
||||||
@ -4435,63 +4435,37 @@ static void do_ssh1_login(void *vctx)
|
|||||||
request = strbuf_new_for_agent_query();
|
request = strbuf_new_for_agent_query();
|
||||||
put_byte(request, 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(
|
||||||
request, &r, &s->responselen, ssh_agent_callback, ssh);
|
request, &r, &rlen, ssh_agent_callback, ssh);
|
||||||
strbuf_free(request);
|
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);
|
||||||
r = ssh->agent_response;
|
r = ssh->agent_response;
|
||||||
s->responselen = ssh->agent_response_len;
|
rlen = ssh->agent_response_len;
|
||||||
}
|
}
|
||||||
s->response = (unsigned char *) r;
|
s->agent_response = r;
|
||||||
if (s->response && s->responselen >= 5 &&
|
BinarySource_BARE_INIT(s->asrc, r, rlen);
|
||||||
s->response[4] == SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
|
get_uint32(s->asrc); /* skip length field */
|
||||||
s->p = s->response + 5;
|
if (get_byte(s->asrc) == SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
|
||||||
s->nkeys = toint(GET_32BIT(s->p));
|
s->nkeys = toint(get_uint32(s->asrc));
|
||||||
if (s->nkeys < 0) {
|
if (s->nkeys < 0) {
|
||||||
logeventf(ssh, "Pageant reported negative key count %d",
|
logeventf(ssh, "Pageant reported negative key count %d",
|
||||||
s->nkeys);
|
s->nkeys);
|
||||||
s->nkeys = 0;
|
s->nkeys = 0;
|
||||||
}
|
}
|
||||||
s->p += 4;
|
|
||||||
logeventf(ssh, "Pageant has %d SSH-1 keys", s->nkeys);
|
logeventf(ssh, "Pageant has %d SSH-1 keys", s->nkeys);
|
||||||
for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
|
for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
|
||||||
unsigned char *pkblob = s->p;
|
ptrlen keystr;
|
||||||
s->p += 4;
|
get_rsa_ssh1_pub(s->asrc, &s->key, &keystr,
|
||||||
{
|
RSA_SSH1_EXPONENT_FIRST);
|
||||||
int n, ok = FALSE;
|
s->comment = get_string(s->asrc);
|
||||||
do { /* do while (0) to make breaking easy */
|
if (get_err(s->asrc)) {
|
||||||
n = ssh1_read_bignum
|
|
||||||
(s->p, toint(s->responselen-(s->p-s->response)),
|
|
||||||
&s->key.exponent);
|
|
||||||
if (n < 0)
|
|
||||||
break;
|
|
||||||
s->p += n;
|
|
||||||
n = ssh1_read_bignum
|
|
||||||
(s->p, toint(s->responselen-(s->p-s->response)),
|
|
||||||
&s->key.modulus);
|
|
||||||
if (n < 0)
|
|
||||||
break;
|
|
||||||
s->p += n;
|
|
||||||
if (s->responselen - (s->p-s->response) < 4)
|
|
||||||
break;
|
|
||||||
s->commentlen = toint(GET_32BIT(s->p));
|
|
||||||
s->p += 4;
|
|
||||||
if (s->commentlen < 0 ||
|
|
||||||
toint(s->responselen - (s->p-s->response)) <
|
|
||||||
s->commentlen)
|
|
||||||
break;
|
|
||||||
s->commentp = (char *)s->p;
|
|
||||||
s->p += s->commentlen;
|
|
||||||
ok = TRUE;
|
|
||||||
} while (0);
|
|
||||||
if (!ok) {
|
|
||||||
logevent("Pageant key list packet was truncated");
|
logevent("Pageant key list packet was truncated");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (s->publickey_blob) {
|
if (s->publickey_blob) {
|
||||||
if (!memcmp(pkblob, s->publickey_blob->s,
|
if (keystr.len == s->publickey_blob->len &&
|
||||||
|
!memcmp(keystr.ptr, s->publickey_blob->s,
|
||||||
s->publickey_blob->len)) {
|
s->publickey_blob->len)) {
|
||||||
logeventf(ssh, "Pageant key #%d matches "
|
logeventf(ssh, "Pageant key #%d matches "
|
||||||
"configured key file", s->keyi);
|
"configured key file", s->keyi);
|
||||||
@ -4560,8 +4534,8 @@ static void do_ssh1_login(void *vctx)
|
|||||||
if (flags & FLAG_VERBOSE) {
|
if (flags & FLAG_VERBOSE) {
|
||||||
c_write_str(ssh, "Authenticated using"
|
c_write_str(ssh, "Authenticated using"
|
||||||
" RSA key \"");
|
" RSA key \"");
|
||||||
c_write(ssh, s->commentp,
|
c_write(ssh, s->comment.ptr,
|
||||||
s->commentlen);
|
s->comment.len);
|
||||||
c_write_str(ssh, "\" from agent\r\n");
|
c_write_str(ssh, "\" from agent\r\n");
|
||||||
}
|
}
|
||||||
s->authed = TRUE;
|
s->authed = TRUE;
|
||||||
@ -4583,7 +4557,7 @@ static void do_ssh1_login(void *vctx)
|
|||||||
if (s->authed)
|
if (s->authed)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sfree(s->response);
|
sfree(s->agent_response);
|
||||||
if (s->publickey_blob && !s->tried_publickey)
|
if (s->publickey_blob && !s->tried_publickey)
|
||||||
logevent("Configured key file not in Pageant");
|
logevent("Configured key file not in Pageant");
|
||||||
} else {
|
} else {
|
||||||
@ -9730,14 +9704,12 @@ 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_response, *agentp;
|
unsigned char *agent_response;
|
||||||
int agent_responselen;
|
BinarySource asrc[1]; /* for reading SSH agent response */
|
||||||
unsigned char *pkblob_in_agent;
|
size_t pkblob_pos_in_agent;
|
||||||
int keyi, nkeys;
|
int keyi, nkeys;
|
||||||
char *pkblob, *alg, *commentp;
|
ptrlen pk, alg, comment;
|
||||||
int pklen, alglen, commentlen;
|
int len;
|
||||||
int retlen, len;
|
|
||||||
char *ret;
|
|
||||||
struct Packet *pktout;
|
struct Packet *pktout;
|
||||||
Filename *keyfile;
|
Filename *keyfile;
|
||||||
#ifndef NO_GSSAPI
|
#ifndef NO_GSSAPI
|
||||||
@ -9866,10 +9838,10 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
*/
|
*/
|
||||||
s->nkeys = 0;
|
s->nkeys = 0;
|
||||||
s->agent_response = NULL;
|
s->agent_response = NULL;
|
||||||
s->pkblob_in_agent = NULL;
|
s->pkblob_pos_in_agent = 0;
|
||||||
if (conf_get_int(ssh->conf, CONF_tryagent) && agent_exists()) {
|
if (conf_get_int(ssh->conf, CONF_tryagent) && agent_exists()) {
|
||||||
|
|
||||||
void *r;
|
void *r;
|
||||||
|
int rlen;
|
||||||
strbuf *agent_request;
|
strbuf *agent_request;
|
||||||
|
|
||||||
logevent("Pageant is running. Requesting keys.");
|
logevent("Pageant is running. Requesting keys.");
|
||||||
@ -9878,23 +9850,22 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
agent_request = strbuf_new_for_agent_query();
|
agent_request = strbuf_new_for_agent_query();
|
||||||
put_byte(agent_request, SSH2_AGENTC_REQUEST_IDENTITIES);
|
put_byte(agent_request, SSH2_AGENTC_REQUEST_IDENTITIES);
|
||||||
ssh->auth_agent_query = agent_query(
|
ssh->auth_agent_query = agent_query(
|
||||||
agent_request, &r, &s->agent_responselen,
|
agent_request, &r, &rlen, ssh_agent_callback, ssh);
|
||||||
ssh_agent_callback, ssh);
|
|
||||||
strbuf_free(agent_request);
|
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);
|
||||||
r = ssh->agent_response;
|
r = ssh->agent_response;
|
||||||
s->agent_responselen = ssh->agent_response_len;
|
rlen = ssh->agent_response_len;
|
||||||
}
|
}
|
||||||
s->agent_response = (unsigned char *) r;
|
s->agent_response = r;
|
||||||
if (s->agent_response && s->agent_responselen >= 5 &&
|
BinarySource_BARE_INIT(s->asrc, r, rlen);
|
||||||
s->agent_response[4] == SSH2_AGENT_IDENTITIES_ANSWER) {
|
get_uint32(s->asrc); /* skip length field */
|
||||||
|
if (get_byte(s->asrc) == SSH2_AGENT_IDENTITIES_ANSWER) {
|
||||||
int keyi;
|
int keyi;
|
||||||
unsigned char *p;
|
|
||||||
p = s->agent_response + 5;
|
s->nkeys = toint(get_uint32(s->asrc));
|
||||||
s->nkeys = toint(GET_32BIT(p));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Vet the Pageant response to ensure that the key
|
* Vet the Pageant response to ensure that the key
|
||||||
@ -9906,58 +9877,31 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
s->nkeys = 0;
|
s->nkeys = 0;
|
||||||
goto done_agent_query;
|
goto done_agent_query;
|
||||||
} else {
|
} else {
|
||||||
unsigned char *q = p + 4;
|
|
||||||
int lenleft = s->agent_responselen - 5 - 4;
|
|
||||||
|
|
||||||
for (keyi = 0; keyi < s->nkeys; keyi++) {
|
|
||||||
int bloblen, commentlen;
|
|
||||||
if (lenleft < 4) {
|
|
||||||
logeventf(ssh, "Pageant response was truncated");
|
|
||||||
s->nkeys = 0;
|
|
||||||
goto done_agent_query;
|
|
||||||
}
|
|
||||||
bloblen = toint(GET_32BIT(q));
|
|
||||||
lenleft -= 4;
|
|
||||||
q += 4;
|
|
||||||
if (bloblen < 0 || bloblen > lenleft) {
|
|
||||||
logeventf(ssh, "Pageant response was truncated");
|
|
||||||
s->nkeys = 0;
|
|
||||||
goto done_agent_query;
|
|
||||||
}
|
|
||||||
lenleft -= bloblen;
|
|
||||||
q += bloblen;
|
|
||||||
commentlen = toint(GET_32BIT(q));
|
|
||||||
lenleft -= 4;
|
|
||||||
q += 4;
|
|
||||||
if (commentlen < 0 || commentlen > lenleft) {
|
|
||||||
logeventf(ssh, "Pageant response was truncated");
|
|
||||||
s->nkeys = 0;
|
|
||||||
goto done_agent_query;
|
|
||||||
}
|
|
||||||
lenleft -= commentlen;
|
|
||||||
q += commentlen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p += 4;
|
|
||||||
logeventf(ssh, "Pageant has %d SSH-2 keys", s->nkeys);
|
logeventf(ssh, "Pageant has %d SSH-2 keys", s->nkeys);
|
||||||
if (s->publickey_blob) {
|
|
||||||
/* See if configured key is in agent. */
|
/* See if configured key is in agent. */
|
||||||
for (keyi = 0; keyi < s->nkeys; keyi++) {
|
for (keyi = 0; keyi < s->nkeys; keyi++) {
|
||||||
s->pklen = toint(GET_32BIT(p));
|
size_t pos = s->asrc->pos;
|
||||||
if (s->pklen == s->publickey_blob->len &&
|
ptrlen blob = get_string(s->asrc);
|
||||||
!memcmp(p+4, s->publickey_blob->s,
|
get_string(s->asrc); /* skip comment */
|
||||||
|
if (get_err(s->asrc)) {
|
||||||
|
logeventf(ssh, "Pageant response was truncated");
|
||||||
|
s->nkeys = 0;
|
||||||
|
goto done_agent_query;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->publickey_blob &&
|
||||||
|
blob.len == s->publickey_blob->len &&
|
||||||
|
!memcmp(blob.ptr, s->publickey_blob->s,
|
||||||
s->publickey_blob->len)) {
|
s->publickey_blob->len)) {
|
||||||
logeventf(ssh, "Pageant key #%d matches "
|
logeventf(ssh, "Pageant key #%d matches "
|
||||||
"configured key file", keyi);
|
"configured key file", keyi);
|
||||||
s->keyi = keyi;
|
s->keyi = keyi;
|
||||||
s->pkblob_in_agent = p;
|
s->pkblob_pos_in_agent = pos;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
p += 4 + s->pklen;
|
|
||||||
p += toint(GET_32BIT(p)) + 4; /* comment */
|
|
||||||
}
|
}
|
||||||
if (!s->pkblob_in_agent) {
|
if (s->publickey_blob && !s->pkblob_pos_in_agent) {
|
||||||
logevent("Configured key file not in Pageant");
|
logevent("Configured key file not in Pageant");
|
||||||
s->nkeys = 0;
|
s->nkeys = 0;
|
||||||
}
|
}
|
||||||
@ -10066,10 +10010,10 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
/* Reset agent request state. */
|
/* Reset agent request state. */
|
||||||
s->done_agent = FALSE;
|
s->done_agent = FALSE;
|
||||||
if (s->agent_response) {
|
if (s->agent_response) {
|
||||||
if (s->pkblob_in_agent) {
|
if (s->pkblob_pos_in_agent) {
|
||||||
s->agentp = s->pkblob_in_agent;
|
s->asrc->pos = s->pkblob_pos_in_agent;
|
||||||
} else {
|
} else {
|
||||||
s->agentp = s->agent_response + 5 + 4;
|
s->asrc->pos = 9; /* skip length + type + key count */
|
||||||
s->keyi = 0;
|
s->keyi = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10253,17 +10197,13 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
logeventf(ssh, "Trying Pageant key #%d", s->keyi);
|
logeventf(ssh, "Trying Pageant key #%d", s->keyi);
|
||||||
|
|
||||||
/* Unpack key from agent response */
|
/* Unpack key from agent response */
|
||||||
s->pklen = toint(GET_32BIT(s->agentp));
|
s->pk = get_string(s->asrc);
|
||||||
s->agentp += 4;
|
s->comment = get_string(s->asrc);
|
||||||
s->pkblob = (char *)s->agentp;
|
{
|
||||||
s->agentp += s->pklen;
|
BinarySource src[1];
|
||||||
s->alglen = toint(GET_32BIT(s->pkblob));
|
BinarySource_BARE_INIT(src, s->pk.ptr, s->pk.len);
|
||||||
s->alg = s->pkblob + 4;
|
s->alg = get_string(src);
|
||||||
s->commentlen = toint(GET_32BIT(s->agentp));
|
}
|
||||||
s->agentp += 4;
|
|
||||||
s->commentp = (char *)s->agentp;
|
|
||||||
s->agentp += s->commentlen;
|
|
||||||
/* s->agentp now points at next key, if any */
|
|
||||||
|
|
||||||
/* See if server will accept it */
|
/* See if server will accept it */
|
||||||
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
|
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
|
||||||
@ -10273,8 +10213,8 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
put_stringz(s->pktout, "publickey");
|
put_stringz(s->pktout, "publickey");
|
||||||
/* method */
|
/* method */
|
||||||
put_bool(s->pktout, FALSE); /* no signature included */
|
put_bool(s->pktout, FALSE); /* no signature included */
|
||||||
put_string(s->pktout, s->alg, s->alglen);
|
put_stringpl(s->pktout, s->alg);
|
||||||
put_string(s->pktout, s->pkblob, s->pklen);
|
put_stringpl(s->pktout, s->pk);
|
||||||
ssh2_pkt_send(ssh, s->pktout);
|
ssh2_pkt_send(ssh, s->pktout);
|
||||||
s->type = AUTH_TYPE_PUBLICKEY_OFFER_QUIET;
|
s->type = AUTH_TYPE_PUBLICKEY_OFFER_QUIET;
|
||||||
|
|
||||||
@ -10287,12 +10227,13 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
strbuf *agentreq, *sigdata;
|
strbuf *agentreq, *sigdata;
|
||||||
void *vret;
|
void *r;
|
||||||
|
int rlen;
|
||||||
|
|
||||||
if (flags & FLAG_VERBOSE) {
|
if (flags & FLAG_VERBOSE) {
|
||||||
c_write_str(ssh, "Authenticating with "
|
c_write_str(ssh, "Authenticating with "
|
||||||
"public key \"");
|
"public key \"");
|
||||||
c_write(ssh, s->commentp, s->commentlen);
|
c_write(ssh, s->comment.ptr, s->comment.len);
|
||||||
c_write_str(ssh, "\" from agent\r\n");
|
c_write_str(ssh, "\" from agent\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10307,13 +10248,13 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
put_stringz(s->pktout, "publickey");
|
put_stringz(s->pktout, "publickey");
|
||||||
/* method */
|
/* method */
|
||||||
put_bool(s->pktout, TRUE); /* signature included */
|
put_bool(s->pktout, TRUE); /* signature included */
|
||||||
put_string(s->pktout, s->alg, s->alglen);
|
put_stringpl(s->pktout, s->alg);
|
||||||
put_string(s->pktout, s->pkblob, s->pklen);
|
put_stringpl(s->pktout, s->pk);
|
||||||
|
|
||||||
/* Ask agent for signature. */
|
/* Ask agent for signature. */
|
||||||
agentreq = strbuf_new_for_agent_query();
|
agentreq = strbuf_new_for_agent_query();
|
||||||
put_byte(agentreq, SSH2_AGENTC_SIGN_REQUEST);
|
put_byte(agentreq, SSH2_AGENTC_SIGN_REQUEST);
|
||||||
put_string(agentreq, s->pkblob, s->pklen);
|
put_stringpl(agentreq, s->pk);
|
||||||
/* Now the data to be signed... */
|
/* Now the data to be signed... */
|
||||||
sigdata = strbuf_new();
|
sigdata = strbuf_new();
|
||||||
if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID) {
|
if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID) {
|
||||||
@ -10329,26 +10270,26 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
/* And finally the (zero) flags word. */
|
/* And finally the (zero) flags word. */
|
||||||
put_uint32(agentreq, 0);
|
put_uint32(agentreq, 0);
|
||||||
ssh->auth_agent_query = agent_query(
|
ssh->auth_agent_query = agent_query(
|
||||||
agentreq, &vret, &s->retlen,
|
agentreq, &r, &rlen, ssh_agent_callback, ssh);
|
||||||
ssh_agent_callback, ssh);
|
|
||||||
strbuf_free(agentreq);
|
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);
|
||||||
vret = ssh->agent_response;
|
r = ssh->agent_response;
|
||||||
s->retlen = ssh->agent_response_len;
|
rlen = ssh->agent_response_len;
|
||||||
}
|
}
|
||||||
s->ret = vret;
|
if (r) {
|
||||||
if (s->ret) {
|
ptrlen sigblob;
|
||||||
if (s->retlen >= 9 &&
|
BinarySource src[1];
|
||||||
s->ret[4] == SSH2_AGENT_SIGN_RESPONSE &&
|
BinarySource_BARE_INIT(src, r, rlen);
|
||||||
GET_32BIT(s->ret + 5) <= (unsigned)(s->retlen-9)) {
|
get_uint32(src); /* skip length field */
|
||||||
|
if (get_byte(src) == SSH2_AGENT_SIGN_RESPONSE &&
|
||||||
|
(sigblob = get_string(src), !get_err(src))) {
|
||||||
logevent("Sending Pageant's response");
|
logevent("Sending Pageant's response");
|
||||||
ssh2_add_sigblob(ssh, s->pktout,
|
ssh2_add_sigblob(ssh, s->pktout,
|
||||||
s->pkblob, s->pklen,
|
s->pk.ptr, s->pk.len,
|
||||||
s->ret + 9,
|
sigblob.ptr, sigblob.len);
|
||||||
GET_32BIT(s->ret + 5));
|
|
||||||
ssh2_pkt_send(ssh, s->pktout);
|
ssh2_pkt_send(ssh, s->pktout);
|
||||||
s->type = AUTH_TYPE_PUBLICKEY;
|
s->type = AUTH_TYPE_PUBLICKEY;
|
||||||
} else {
|
} else {
|
||||||
@ -10360,7 +10301,7 @@ static void do_ssh2_userauth(void *vctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do we have any keys left to try? */
|
/* Do we have any keys left to try? */
|
||||||
if (s->pkblob_in_agent) {
|
if (s->pkblob_pos_in_agent) {
|
||||||
s->done_agent = TRUE;
|
s->done_agent = TRUE;
|
||||||
s->tried_pubkey_config = TRUE;
|
s->tried_pubkey_config = TRUE;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user