mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
Build SSH agent reply messages in a BinarySink.
This gets rid of yet another huge pile of beating around the bush with length-counting. Also, this time, the BinarySink in question is a little more interesting than just being a strbuf every time: on Windows, where the shared-memory Pageant IPC system imposes a hard limit on the size of message we can return, I've written a custom BinarySink implementation that collects up to that much data and then gives up and sets an overflow flag rather than continue to allocate memory. So the main Pageant code no longer has to worry about checking AGENT_MAX_MSGLEN all the time - and better still, the Unix version of Pageant is no longer _limited_ by AGENT_MAX_MSGLEN in its outgoing messages, i.e. it could store a really extra large number of keys if it needed to. That limitation is now a local feature of Windows Pageant rather than intrinsic to the whole code base. (AGENT_MAX_MSGLEN is still used to check incoming agent messages for sanity, however. Mostly that's because I feel I ought to check them against _some_ limit, and this one seems sensible enough. Incoming agent messages are more bounded anyway - they generally don't hold more than _one_ private key.)
This commit is contained in:
parent
0c44fa85df
commit
b6cbad89fc
409
pageant.c
409
pageant.c
@ -127,14 +127,8 @@ static int cmpkeys_ssh2(void *av, void *bv)
|
|||||||
return toret;
|
return toret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void pageant_make_keylist1(BinarySink *bs)
|
||||||
* Create an SSH-1 key list in a malloc'ed buffer; return its
|
|
||||||
* length.
|
|
||||||
*/
|
|
||||||
void *pageant_make_keylist1(int *length)
|
|
||||||
{
|
{
|
||||||
strbuf *buf = strbuf_new();
|
|
||||||
BinarySink *bs = BinarySink_UPCAST(buf);
|
|
||||||
int i;
|
int i;
|
||||||
struct RSAKey *key;
|
struct RSAKey *key;
|
||||||
|
|
||||||
@ -143,18 +137,10 @@ void *pageant_make_keylist1(int *length)
|
|||||||
rsa_ssh1_public_blob(bs, key, RSA_SSH1_EXPONENT_FIRST);
|
rsa_ssh1_public_blob(bs, key, RSA_SSH1_EXPONENT_FIRST);
|
||||||
put_stringz(bs, key->comment);
|
put_stringz(bs, key->comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
return strbuf_to_str(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void pageant_make_keylist2(BinarySink *bs)
|
||||||
* Create an SSH-2 key list in a malloc'ed buffer; return its
|
|
||||||
* length.
|
|
||||||
*/
|
|
||||||
void *pageant_make_keylist2(int *length)
|
|
||||||
{
|
{
|
||||||
strbuf *buf = strbuf_new();
|
|
||||||
BinarySink *bs = BinarySink_UPCAST(buf);
|
|
||||||
int i;
|
int i;
|
||||||
struct ssh2_userkey *key;
|
struct ssh2_userkey *key;
|
||||||
|
|
||||||
@ -165,8 +151,6 @@ void *pageant_make_keylist2(int *length)
|
|||||||
put_stringsb(bs, blob);
|
put_stringsb(bs, blob);
|
||||||
put_stringz(bs, key->comment);
|
put_stringz(bs, key->comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
return strbuf_to_str(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plog(void *logctx, pageant_logfn_t logfn, const char *fmt, ...)
|
static void plog(void *logctx, pageant_logfn_t logfn, const char *fmt, ...)
|
||||||
@ -193,14 +177,13 @@ static void plog(void *logctx, pageant_logfn_t logfn, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
void pageant_handle_msg(BinarySink *bs,
|
||||||
void *logctx, pageant_logfn_t logfn)
|
const void *msg, int msglen,
|
||||||
|
void *logctx, pageant_logfn_t logfn)
|
||||||
{
|
{
|
||||||
const unsigned char *p = msg;
|
const unsigned char *p = msg;
|
||||||
const unsigned char *msgend;
|
const unsigned char *msgend;
|
||||||
unsigned char *ret = snewn(AGENT_MAX_MSGLEN, unsigned char);
|
|
||||||
int type;
|
int type;
|
||||||
const char *fail_reason;
|
|
||||||
|
|
||||||
msgend = p + msglen;
|
msgend = p + msglen;
|
||||||
|
|
||||||
@ -208,8 +191,9 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
* Get the message type.
|
* Get the message type.
|
||||||
*/
|
*/
|
||||||
if (msgend < p+1) {
|
if (msgend < p+1) {
|
||||||
fail_reason = "message contained no type code";
|
pageant_failure_msg(bs, "message contained no type code",
|
||||||
goto failure;
|
logctx, logfn);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
type = *p++;
|
type = *p++;
|
||||||
|
|
||||||
@ -219,20 +203,10 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
* Reply with SSH1_AGENT_RSA_IDENTITIES_ANSWER.
|
* Reply with SSH1_AGENT_RSA_IDENTITIES_ANSWER.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
int len;
|
|
||||||
void *keylist;
|
|
||||||
|
|
||||||
plog(logctx, logfn, "request: SSH1_AGENTC_REQUEST_RSA_IDENTITIES");
|
plog(logctx, logfn, "request: SSH1_AGENTC_REQUEST_RSA_IDENTITIES");
|
||||||
|
|
||||||
ret[4] = SSH1_AGENT_RSA_IDENTITIES_ANSWER;
|
put_byte(bs, SSH1_AGENT_RSA_IDENTITIES_ANSWER);
|
||||||
keylist = pageant_make_keylist1(&len);
|
pageant_make_keylist1(bs);
|
||||||
if (len + 5 > AGENT_MAX_MSGLEN) {
|
|
||||||
sfree(keylist);
|
|
||||||
fail_reason = "output would exceed max msglen";
|
|
||||||
goto failure;
|
|
||||||
}
|
|
||||||
PUT_32BIT(ret, len + 1);
|
|
||||||
memcpy(ret + 5, keylist, len);
|
|
||||||
|
|
||||||
plog(logctx, logfn, "reply: SSH1_AGENT_RSA_IDENTITIES_ANSWER");
|
plog(logctx, logfn, "reply: SSH1_AGENT_RSA_IDENTITIES_ANSWER");
|
||||||
if (logfn) { /* skip this loop if not logging */
|
if (logfn) { /* skip this loop if not logging */
|
||||||
@ -244,7 +218,6 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
plog(logctx, logfn, "returned key: %s", fingerprint);
|
plog(logctx, logfn, "returned key: %s", fingerprint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sfree(keylist);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSH2_AGENTC_REQUEST_IDENTITIES:
|
case SSH2_AGENTC_REQUEST_IDENTITIES:
|
||||||
@ -252,20 +225,10 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
* Reply with SSH2_AGENT_IDENTITIES_ANSWER.
|
* Reply with SSH2_AGENT_IDENTITIES_ANSWER.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
int len;
|
|
||||||
void *keylist;
|
|
||||||
|
|
||||||
plog(logctx, logfn, "request: SSH2_AGENTC_REQUEST_IDENTITIES");
|
plog(logctx, logfn, "request: SSH2_AGENTC_REQUEST_IDENTITIES");
|
||||||
|
|
||||||
ret[4] = SSH2_AGENT_IDENTITIES_ANSWER;
|
put_byte(bs, SSH2_AGENT_IDENTITIES_ANSWER);
|
||||||
keylist = pageant_make_keylist2(&len);
|
pageant_make_keylist2(bs);
|
||||||
if (len + 5 > AGENT_MAX_MSGLEN) {
|
|
||||||
sfree(keylist);
|
|
||||||
fail_reason = "output would exceed max msglen";
|
|
||||||
goto failure;
|
|
||||||
}
|
|
||||||
PUT_32BIT(ret, len + 1);
|
|
||||||
memcpy(ret + 5, keylist, len);
|
|
||||||
|
|
||||||
plog(logctx, logfn, "reply: SSH2_AGENT_IDENTITIES_ANSWER");
|
plog(logctx, logfn, "reply: SSH2_AGENT_IDENTITIES_ANSWER");
|
||||||
if (logfn) { /* skip this loop if not logging */
|
if (logfn) { /* skip this loop if not logging */
|
||||||
@ -279,8 +242,6 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
sfree(fingerprint);
|
sfree(fingerprint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sfree(keylist);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSH1_AGENTC_RSA_CHALLENGE:
|
case SSH1_AGENTC_RSA_CHALLENGE:
|
||||||
@ -294,55 +255,56 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
Bignum challenge, response;
|
Bignum challenge, response;
|
||||||
unsigned char response_source[48], response_md5[16];
|
unsigned char response_source[48], response_md5[16];
|
||||||
struct MD5Context md5c;
|
struct MD5Context md5c;
|
||||||
int i, len;
|
int i;
|
||||||
|
|
||||||
plog(logctx, logfn, "request: SSH1_AGENTC_RSA_CHALLENGE");
|
plog(logctx, logfn, "request: SSH1_AGENTC_RSA_CHALLENGE");
|
||||||
|
|
||||||
|
reqkey.exponent = reqkey.modulus = challenge = response = NULL;
|
||||||
|
|
||||||
p += 4;
|
p += 4;
|
||||||
i = ssh1_read_bignum(p, msgend - p, &reqkey.exponent);
|
i = ssh1_read_bignum(p, msgend - p, &reqkey.exponent);
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
fail_reason = "request truncated before key exponent";
|
pageant_failure_msg(
|
||||||
goto failure;
|
bs, "request truncated before key exponent",
|
||||||
|
logctx, logfn);
|
||||||
|
goto challenge1_cleanup;
|
||||||
}
|
}
|
||||||
p += i;
|
p += i;
|
||||||
i = ssh1_read_bignum(p, msgend - p, &reqkey.modulus);
|
i = ssh1_read_bignum(p, msgend - p, &reqkey.modulus);
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
freebn(reqkey.exponent);
|
pageant_failure_msg(
|
||||||
fail_reason = "request truncated before key modulus";
|
bs, "request truncated before key modulus",
|
||||||
goto failure;
|
logctx, logfn);
|
||||||
|
goto challenge1_cleanup;
|
||||||
}
|
}
|
||||||
p += i;
|
p += i;
|
||||||
i = ssh1_read_bignum(p, msgend - p, &challenge);
|
i = ssh1_read_bignum(p, msgend - p, &challenge);
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
freebn(reqkey.exponent);
|
pageant_failure_msg(
|
||||||
freebn(reqkey.modulus);
|
bs, "request truncated before challenge",
|
||||||
freebn(challenge);
|
logctx, logfn);
|
||||||
fail_reason = "request truncated before challenge";
|
goto challenge1_cleanup;
|
||||||
goto failure;
|
|
||||||
}
|
}
|
||||||
p += i;
|
p += i;
|
||||||
if (msgend < p+16) {
|
if (msgend < p+16) {
|
||||||
freebn(reqkey.exponent);
|
pageant_failure_msg(
|
||||||
freebn(reqkey.modulus);
|
bs, "request truncated before session id",
|
||||||
freebn(challenge);
|
logctx, logfn);
|
||||||
fail_reason = "request truncated before session id";
|
goto challenge1_cleanup;
|
||||||
goto failure;
|
|
||||||
}
|
}
|
||||||
memcpy(response_source + 32, p, 16);
|
memcpy(response_source + 32, p, 16);
|
||||||
p += 16;
|
p += 16;
|
||||||
if (msgend < p+4) {
|
if (msgend < p+4) {
|
||||||
freebn(reqkey.exponent);
|
pageant_failure_msg(
|
||||||
freebn(reqkey.modulus);
|
bs, "request truncated before response type",
|
||||||
freebn(challenge);
|
logctx, logfn);
|
||||||
fail_reason = "request truncated before response type";
|
goto challenge1_cleanup;
|
||||||
goto failure;
|
|
||||||
}
|
}
|
||||||
if (GET_32BIT(p) != 1) {
|
if (GET_32BIT(p) != 1) {
|
||||||
freebn(reqkey.exponent);
|
pageant_failure_msg(
|
||||||
freebn(reqkey.modulus);
|
bs, "response type other than 1 not supported",
|
||||||
freebn(challenge);
|
logctx, logfn);
|
||||||
fail_reason = "response type other than 1 not supported";
|
goto challenge1_cleanup;
|
||||||
goto failure;
|
|
||||||
}
|
}
|
||||||
if (logfn) {
|
if (logfn) {
|
||||||
char fingerprint[128];
|
char fingerprint[128];
|
||||||
@ -351,11 +313,8 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
plog(logctx, logfn, "requested key: %s", fingerprint);
|
plog(logctx, logfn, "requested key: %s", fingerprint);
|
||||||
}
|
}
|
||||||
if ((key = find234(rsakeys, &reqkey, NULL)) == NULL) {
|
if ((key = find234(rsakeys, &reqkey, NULL)) == NULL) {
|
||||||
freebn(reqkey.exponent);
|
pageant_failure_msg(bs, "key not found", logctx, logfn);
|
||||||
freebn(reqkey.modulus);
|
goto challenge1_cleanup;
|
||||||
freebn(challenge);
|
|
||||||
fail_reason = "key not found";
|
|
||||||
goto failure;
|
|
||||||
}
|
}
|
||||||
response = rsa_ssh1_decrypt(challenge, key);
|
response = rsa_ssh1_decrypt(challenge, key);
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++)
|
||||||
@ -365,21 +324,17 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
put_data(&md5c, response_source, 48);
|
put_data(&md5c, response_source, 48);
|
||||||
MD5Final(response_md5, &md5c);
|
MD5Final(response_md5, &md5c);
|
||||||
smemclr(response_source, 48); /* burn the evidence */
|
smemclr(response_source, 48); /* burn the evidence */
|
||||||
freebn(response); /* and that evidence */
|
|
||||||
freebn(challenge); /* yes, and that evidence */
|
|
||||||
freebn(reqkey.exponent); /* and free some memory ... */
|
|
||||||
freebn(reqkey.modulus); /* ... while we're at it. */
|
|
||||||
|
|
||||||
/*
|
put_byte(bs, SSH1_AGENT_RSA_RESPONSE);
|
||||||
* Packet is the obvious five byte header, plus sixteen
|
put_data(bs, response_md5, 16);
|
||||||
* bytes of MD5.
|
|
||||||
*/
|
|
||||||
len = 5 + 16;
|
|
||||||
PUT_32BIT(ret, len - 4);
|
|
||||||
ret[4] = SSH1_AGENT_RSA_RESPONSE;
|
|
||||||
memcpy(ret + 5, response_md5, 16);
|
|
||||||
|
|
||||||
plog(logctx, logfn, "reply: SSH1_AGENT_RSA_RESPONSE");
|
plog(logctx, logfn, "reply: SSH1_AGENT_RSA_RESPONSE");
|
||||||
|
|
||||||
|
challenge1_cleanup:
|
||||||
|
if (response) freebn(response);
|
||||||
|
if (challenge) freebn(challenge);
|
||||||
|
if (reqkey.exponent) freebn(reqkey.exponent);
|
||||||
|
if (reqkey.modulus) freebn(reqkey.modulus);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSH2_AGENTC_SIGN_REQUEST:
|
case SSH2_AGENTC_SIGN_REQUEST:
|
||||||
@ -394,31 +349,39 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
int bloblen;
|
int bloblen;
|
||||||
const unsigned char *data;
|
const unsigned char *data;
|
||||||
strbuf *signature;
|
strbuf *signature;
|
||||||
int datalen, len;
|
int datalen;
|
||||||
|
|
||||||
plog(logctx, logfn, "request: SSH2_AGENTC_SIGN_REQUEST");
|
plog(logctx, logfn, "request: SSH2_AGENTC_SIGN_REQUEST");
|
||||||
|
|
||||||
if (msgend < p+4) {
|
if (msgend < p+4) {
|
||||||
fail_reason = "request truncated before public key";
|
pageant_failure_msg(
|
||||||
goto failure;
|
bs, "request truncated before public key",
|
||||||
|
logctx, logfn);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
bloblen = toint(GET_32BIT(p));
|
bloblen = toint(GET_32BIT(p));
|
||||||
if (bloblen < 0 || bloblen > msgend - (p+4)) {
|
if (bloblen < 0 || bloblen > msgend - (p+4)) {
|
||||||
fail_reason = "request truncated before public key";
|
pageant_failure_msg(
|
||||||
goto failure;
|
bs, "request truncated before public key",
|
||||||
|
logctx, logfn);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
p += 4;
|
p += 4;
|
||||||
blobp = p;
|
blobp = p;
|
||||||
p += bloblen;
|
p += bloblen;
|
||||||
if (msgend < p+4) {
|
if (msgend < p+4) {
|
||||||
fail_reason = "request truncated before string to sign";
|
pageant_failure_msg(
|
||||||
goto failure;
|
bs, "request truncated before string to sign",
|
||||||
|
logctx, logfn);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
datalen = toint(GET_32BIT(p));
|
datalen = toint(GET_32BIT(p));
|
||||||
p += 4;
|
p += 4;
|
||||||
if (datalen < 0 || datalen > msgend - p) {
|
if (datalen < 0 || datalen > msgend - p) {
|
||||||
fail_reason = "request truncated before string to sign";
|
pageant_failure_msg(
|
||||||
goto failure;
|
bs, "request truncated before string to sign",
|
||||||
|
logctx, logfn);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
data = p;
|
data = p;
|
||||||
if (logfn) {
|
if (logfn) {
|
||||||
@ -433,18 +396,16 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
strbuf_free(blob);
|
strbuf_free(blob);
|
||||||
}
|
}
|
||||||
if (!key) {
|
if (!key) {
|
||||||
fail_reason = "key not found";
|
pageant_failure_msg(bs, "key not found", logctx, logfn);
|
||||||
goto failure;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
put_byte(bs, SSH2_AGENT_SIGN_RESPONSE);
|
||||||
|
|
||||||
signature = strbuf_new();
|
signature = strbuf_new();
|
||||||
key->alg->sign(key->data, (const char *)data, datalen,
|
key->alg->sign(key->data, (const char *)data, datalen,
|
||||||
BinarySink_UPCAST(signature));
|
BinarySink_UPCAST(signature));
|
||||||
len = 5 + 4 + signature->len;
|
put_stringsb(bs, signature);
|
||||||
PUT_32BIT(ret, len - 4);
|
|
||||||
ret[4] = SSH2_AGENT_SIGN_RESPONSE;
|
|
||||||
PUT_32BIT(ret + 5, signature->len);
|
|
||||||
memcpy(ret + 5 + 4, signature->s, signature->len);
|
|
||||||
strbuf_free(signature);
|
|
||||||
|
|
||||||
plog(logctx, logfn, "reply: SSH2_AGENT_SIGN_RESPONSE");
|
plog(logctx, logfn, "reply: SSH2_AGENT_SIGN_RESPONSE");
|
||||||
}
|
}
|
||||||
@ -467,19 +428,19 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
n = rsa_ssh1_readpub(p, msgend - p, key, NULL,
|
n = rsa_ssh1_readpub(p, msgend - p, key, NULL,
|
||||||
RSA_SSH1_MODULUS_FIRST);
|
RSA_SSH1_MODULUS_FIRST);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
freersakey(key);
|
pageant_failure_msg(
|
||||||
sfree(key);
|
bs, "request truncated before public key",
|
||||||
fail_reason = "request truncated before public key";
|
logctx, logfn);
|
||||||
goto failure;
|
goto add1_cleanup;
|
||||||
}
|
}
|
||||||
p += n;
|
p += n;
|
||||||
|
|
||||||
n = rsa_ssh1_readpriv(p, msgend - p, key);
|
n = rsa_ssh1_readpriv(p, msgend - p, key);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
freersakey(key);
|
pageant_failure_msg(
|
||||||
sfree(key);
|
bs, "request truncated before private key",
|
||||||
fail_reason = "request truncated before private key";
|
logctx, logfn);
|
||||||
goto failure;
|
goto add1_cleanup;
|
||||||
}
|
}
|
||||||
p += n;
|
p += n;
|
||||||
|
|
||||||
@ -489,44 +450,41 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
|
|
||||||
n = ssh1_read_bignum(p, msgend - p, &key->iqmp); /* p^-1 mod q */
|
n = ssh1_read_bignum(p, msgend - p, &key->iqmp); /* p^-1 mod q */
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
freersakey(key);
|
pageant_failure_msg(bs, "request truncated before iqmp",
|
||||||
sfree(key);
|
logctx, logfn);
|
||||||
fail_reason = "request truncated before iqmp";
|
goto add1_cleanup;
|
||||||
goto failure;
|
|
||||||
}
|
}
|
||||||
p += n;
|
p += n;
|
||||||
|
|
||||||
n = ssh1_read_bignum(p, msgend - p, &key->q); /* p */
|
n = ssh1_read_bignum(p, msgend - p, &key->q); /* p */
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
freersakey(key);
|
pageant_failure_msg(bs, "request truncated before p",
|
||||||
sfree(key);
|
logctx, logfn);
|
||||||
fail_reason = "request truncated before p";
|
goto add1_cleanup;
|
||||||
goto failure;
|
|
||||||
}
|
}
|
||||||
p += n;
|
p += n;
|
||||||
|
|
||||||
n = ssh1_read_bignum(p, msgend - p, &key->p); /* q */
|
n = ssh1_read_bignum(p, msgend - p, &key->p); /* q */
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
freersakey(key);
|
pageant_failure_msg(
|
||||||
sfree(key);
|
bs, "request truncated before q", logctx, logfn);
|
||||||
fail_reason = "request truncated before q";
|
goto add1_cleanup;
|
||||||
goto failure;
|
|
||||||
}
|
}
|
||||||
p += n;
|
p += n;
|
||||||
|
|
||||||
if (msgend < p+4) {
|
if (msgend < p+4) {
|
||||||
freersakey(key);
|
pageant_failure_msg(
|
||||||
sfree(key);
|
bs, "request truncated before key comment",
|
||||||
fail_reason = "request truncated before key comment";
|
logctx, logfn);
|
||||||
goto failure;
|
goto add1_cleanup;
|
||||||
}
|
}
|
||||||
commentlen = toint(GET_32BIT(p));
|
commentlen = toint(GET_32BIT(p));
|
||||||
|
|
||||||
if (commentlen < 0 || commentlen > msgend - p) {
|
if (commentlen < 0 || commentlen > msgend - p) {
|
||||||
freersakey(key);
|
pageant_failure_msg(
|
||||||
sfree(key);
|
bs, "request truncated before key comment",
|
||||||
fail_reason = "request truncated before key comment";
|
logctx, logfn);
|
||||||
goto failure;
|
goto add1_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
comment = snewn(commentlen+1, char);
|
comment = snewn(commentlen+1, char);
|
||||||
@ -544,17 +502,19 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
|
|
||||||
if (add234(rsakeys, key) == key) {
|
if (add234(rsakeys, key) == key) {
|
||||||
keylist_update();
|
keylist_update();
|
||||||
PUT_32BIT(ret, 1);
|
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||||
ret[4] = SSH_AGENT_SUCCESS;
|
|
||||||
|
|
||||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||||
|
key = NULL; /* don't free it in cleanup */
|
||||||
} else {
|
} else {
|
||||||
|
pageant_failure_msg(bs, "key already present",
|
||||||
|
logctx, logfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
add1_cleanup:
|
||||||
|
if (key) {
|
||||||
freersakey(key);
|
freersakey(key);
|
||||||
sfree(key);
|
sfree(key);
|
||||||
|
}
|
||||||
fail_reason = "key already present";
|
|
||||||
goto failure;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSH2_AGENTC_ADD_IDENTITY:
|
case SSH2_AGENTC_ADD_IDENTITY:
|
||||||
@ -563,7 +523,7 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
* SSH_AGENT_FAILURE if the key was malformed.
|
* SSH_AGENT_FAILURE if the key was malformed.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
struct ssh2_userkey *key;
|
struct ssh2_userkey *key = NULL;
|
||||||
char *comment;
|
char *comment;
|
||||||
const char *alg;
|
const char *alg;
|
||||||
int alglen, commlen;
|
int alglen, commlen;
|
||||||
@ -572,32 +532,36 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
plog(logctx, logfn, "request: SSH2_AGENTC_ADD_IDENTITY");
|
plog(logctx, logfn, "request: SSH2_AGENTC_ADD_IDENTITY");
|
||||||
|
|
||||||
if (msgend < p+4) {
|
if (msgend < p+4) {
|
||||||
fail_reason = "request truncated before key algorithm";
|
pageant_failure_msg(
|
||||||
goto failure;
|
bs, "request truncated before key algorithm",
|
||||||
|
logctx, logfn);
|
||||||
|
goto add2_cleanup;
|
||||||
}
|
}
|
||||||
alglen = toint(GET_32BIT(p));
|
alglen = toint(GET_32BIT(p));
|
||||||
p += 4;
|
p += 4;
|
||||||
if (alglen < 0 || alglen > msgend - p) {
|
if (alglen < 0 || alglen > msgend - p) {
|
||||||
fail_reason = "request truncated before key algorithm";
|
pageant_failure_msg(
|
||||||
goto failure;
|
bs, "request truncated before key algorithm",
|
||||||
|
logctx, logfn);
|
||||||
|
goto add2_cleanup;
|
||||||
}
|
}
|
||||||
alg = (const char *)p;
|
alg = (const char *)p;
|
||||||
p += alglen;
|
p += alglen;
|
||||||
|
|
||||||
key = snew(struct ssh2_userkey);
|
key = snew(struct ssh2_userkey);
|
||||||
|
key->data = NULL;
|
||||||
|
key->comment = NULL;
|
||||||
key->alg = find_pubkey_alg_len(alglen, alg);
|
key->alg = find_pubkey_alg_len(alglen, alg);
|
||||||
if (!key->alg) {
|
if (!key->alg) {
|
||||||
sfree(key);
|
pageant_failure_msg(bs, "algorithm unknown", logctx, logfn);
|
||||||
fail_reason = "algorithm unknown";
|
goto add2_cleanup;
|
||||||
goto failure;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bloblen = msgend - p;
|
bloblen = msgend - p;
|
||||||
key->data = key->alg->openssh_createkey(key->alg, &p, &bloblen);
|
key->data = key->alg->openssh_createkey(key->alg, &p, &bloblen);
|
||||||
if (!key->data) {
|
if (!key->data) {
|
||||||
sfree(key);
|
pageant_failure_msg(bs, "key setup failed", logctx, logfn);
|
||||||
fail_reason = "key setup failed";
|
goto add2_cleanup;
|
||||||
goto failure;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -607,19 +571,19 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
assert(p <= msgend);
|
assert(p <= msgend);
|
||||||
|
|
||||||
if (msgend < p+4) {
|
if (msgend < p+4) {
|
||||||
key->alg->freekey(key->data);
|
pageant_failure_msg(
|
||||||
sfree(key);
|
bs, "request truncated before key comment",
|
||||||
fail_reason = "request truncated before key comment";
|
logctx, logfn);
|
||||||
goto failure;
|
goto add2_cleanup;
|
||||||
}
|
}
|
||||||
commlen = toint(GET_32BIT(p));
|
commlen = toint(GET_32BIT(p));
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|
||||||
if (commlen < 0 || commlen > msgend - p) {
|
if (commlen < 0 || commlen > msgend - p) {
|
||||||
key->alg->freekey(key->data);
|
pageant_failure_msg(
|
||||||
sfree(key);
|
bs, "request truncated before key comment",
|
||||||
fail_reason = "request truncated before key comment";
|
logctx, logfn);
|
||||||
goto failure;
|
goto add2_cleanup;
|
||||||
}
|
}
|
||||||
comment = snewn(commlen + 1, char);
|
comment = snewn(commlen + 1, char);
|
||||||
if (comment) {
|
if (comment) {
|
||||||
@ -637,18 +601,24 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
|
|
||||||
if (add234(ssh2keys, key) == key) {
|
if (add234(ssh2keys, key) == key) {
|
||||||
keylist_update();
|
keylist_update();
|
||||||
PUT_32BIT(ret, 1);
|
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||||
ret[4] = SSH_AGENT_SUCCESS;
|
|
||||||
|
|
||||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||||
} else {
|
|
||||||
key->alg->freekey(key->data);
|
|
||||||
sfree(key->comment);
|
|
||||||
sfree(key);
|
|
||||||
|
|
||||||
fail_reason = "key already present";
|
key = NULL; /* don't clean it up */
|
||||||
goto failure;
|
} else {
|
||||||
|
pageant_failure_msg(bs, "key already present",
|
||||||
|
logctx, logfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add2_cleanup:
|
||||||
|
if (key) {
|
||||||
|
if (key->data)
|
||||||
|
key->alg->freekey(key->data);
|
||||||
|
if (key->comment)
|
||||||
|
sfree(key->comment);
|
||||||
|
sfree(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSH1_AGENTC_REMOVE_RSA_IDENTITY:
|
case SSH1_AGENTC_REMOVE_RSA_IDENTITY:
|
||||||
@ -666,8 +636,10 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
n = rsa_ssh1_readpub(p, msgend - p, &reqkey, NULL,
|
n = rsa_ssh1_readpub(p, msgend - p, &reqkey, NULL,
|
||||||
RSA_SSH1_EXPONENT_FIRST);
|
RSA_SSH1_EXPONENT_FIRST);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
fail_reason = "request truncated before public key";
|
pageant_failure_msg(
|
||||||
goto failure;
|
bs, "request truncated before public key",
|
||||||
|
logctx, logfn);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logfn) {
|
if (logfn) {
|
||||||
@ -680,7 +652,6 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
key = find234(rsakeys, &reqkey, NULL);
|
key = find234(rsakeys, &reqkey, NULL);
|
||||||
freebn(reqkey.exponent);
|
freebn(reqkey.exponent);
|
||||||
freebn(reqkey.modulus);
|
freebn(reqkey.modulus);
|
||||||
PUT_32BIT(ret, 1);
|
|
||||||
if (key) {
|
if (key) {
|
||||||
plog(logctx, logfn, "found with comment: %s", key->comment);
|
plog(logctx, logfn, "found with comment: %s", key->comment);
|
||||||
|
|
||||||
@ -688,12 +659,11 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
keylist_update();
|
keylist_update();
|
||||||
freersakey(key);
|
freersakey(key);
|
||||||
sfree(key);
|
sfree(key);
|
||||||
ret[4] = SSH_AGENT_SUCCESS;
|
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||||
|
|
||||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||||
} else {
|
} else {
|
||||||
fail_reason = "key not found";
|
pageant_failure_msg(bs, "key not found", logctx, logfn);
|
||||||
goto failure;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -711,15 +681,19 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
plog(logctx, logfn, "request: SSH2_AGENTC_REMOVE_IDENTITY");
|
plog(logctx, logfn, "request: SSH2_AGENTC_REMOVE_IDENTITY");
|
||||||
|
|
||||||
if (msgend < p+4) {
|
if (msgend < p+4) {
|
||||||
fail_reason = "request truncated before public key";
|
pageant_failure_msg(
|
||||||
goto failure;
|
bs, "request truncated before public key",
|
||||||
|
logctx, logfn);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
bloblen = toint(GET_32BIT(p));
|
bloblen = toint(GET_32BIT(p));
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|
||||||
if (bloblen < 0 || bloblen > msgend - p) {
|
if (bloblen < 0 || bloblen > msgend - p) {
|
||||||
fail_reason = "request truncated before public key";
|
pageant_failure_msg(
|
||||||
goto failure;
|
bs, "request truncated before public key",
|
||||||
|
logctx, logfn);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
blobp = p;
|
blobp = p;
|
||||||
p += bloblen;
|
p += bloblen;
|
||||||
@ -737,8 +711,8 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
strbuf_free(blob);
|
strbuf_free(blob);
|
||||||
}
|
}
|
||||||
if (!key) {
|
if (!key) {
|
||||||
fail_reason = "key not found";
|
pageant_failure_msg(bs, "key not found", logctx, logfn);
|
||||||
goto failure;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
plog(logctx, logfn, "found with comment: %s", key->comment);
|
plog(logctx, logfn, "found with comment: %s", key->comment);
|
||||||
@ -747,8 +721,7 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
keylist_update();
|
keylist_update();
|
||||||
key->alg->freekey(key->data);
|
key->alg->freekey(key->data);
|
||||||
sfree(key);
|
sfree(key);
|
||||||
PUT_32BIT(ret, 1);
|
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||||
ret[4] = SSH_AGENT_SUCCESS;
|
|
||||||
|
|
||||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||||
}
|
}
|
||||||
@ -770,8 +743,7 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
}
|
}
|
||||||
keylist_update();
|
keylist_update();
|
||||||
|
|
||||||
PUT_32BIT(ret, 1);
|
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||||
ret[4] = SSH_AGENT_SUCCESS;
|
|
||||||
|
|
||||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||||
}
|
}
|
||||||
@ -792,38 +764,24 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
|||||||
}
|
}
|
||||||
keylist_update();
|
keylist_update();
|
||||||
|
|
||||||
PUT_32BIT(ret, 1);
|
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||||
ret[4] = SSH_AGENT_SUCCESS;
|
|
||||||
|
|
||||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
plog(logctx, logfn, "request: unknown message type %d", type);
|
plog(logctx, logfn, "request: unknown message type %d", type);
|
||||||
|
pageant_failure_msg(bs, "unrecognised message", logctx, logfn);
|
||||||
fail_reason = "unrecognised message";
|
|
||||||
/* fall through */
|
|
||||||
failure:
|
|
||||||
/*
|
|
||||||
* Unrecognised message. Return SSH_AGENT_FAILURE.
|
|
||||||
*/
|
|
||||||
PUT_32BIT(ret, 1);
|
|
||||||
ret[4] = SSH_AGENT_FAILURE;
|
|
||||||
plog(logctx, logfn, "reply: SSH_AGENT_FAILURE (%s)", fail_reason);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*outlen = 4 + GET_32BIT(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *pageant_failure_msg(int *outlen)
|
void pageant_failure_msg(BinarySink *bs,
|
||||||
|
const char *log_reason,
|
||||||
|
void *logctx, pageant_logfn_t logfn)
|
||||||
{
|
{
|
||||||
unsigned char *ret = snewn(5, unsigned char);
|
put_byte(bs, SSH_AGENT_FAILURE);
|
||||||
PUT_32BIT(ret, 1);
|
plog(logctx, logfn, "reply: SSH_AGENT_FAILURE (%s)", log_reason);
|
||||||
ret[4] = SSH_AGENT_FAILURE;
|
|
||||||
*outlen = 5;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pageant_init(void)
|
void pageant_init(void)
|
||||||
@ -971,21 +929,24 @@ static void pageant_conn_receive(Plug plug, int urgent, char *data, int len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
void *reply;
|
strbuf *reply = strbuf_new();
|
||||||
int replylen;
|
|
||||||
|
put_uint32(reply, 0); /* length field to fill in later */
|
||||||
|
|
||||||
if (pc->real_packet) {
|
if (pc->real_packet) {
|
||||||
reply = pageant_handle_msg(pc->pktbuf, pc->len, &replylen, pc,
|
pageant_handle_msg(BinarySink_UPCAST(reply), pc->pktbuf, pc->len, pc,
|
||||||
pc->logfn?pageant_conn_log:NULL);
|
pc->logfn ? pageant_conn_log : NULL);
|
||||||
} else {
|
} else {
|
||||||
plog(pc->logctx, pc->logfn, "%p: overlong message (%u)",
|
plog(pc->logctx, pc->logfn, "%p: overlong message (%u)",
|
||||||
pc, pc->len);
|
pc, pc->len);
|
||||||
plog(pc->logctx, pc->logfn, "%p: reply: SSH_AGENT_FAILURE "
|
pageant_failure_msg(BinarySink_UPCAST(reply), "message too long", pc,
|
||||||
"(message too long)", pc);
|
pc->logfn ? pageant_conn_log : NULL);
|
||||||
reply = pageant_failure_msg(&replylen);
|
|
||||||
}
|
}
|
||||||
sk_write(pc->connsock, reply, replylen);
|
|
||||||
smemclr(reply, replylen);
|
PUT_32BIT(reply->s, reply->len - 4);
|
||||||
|
sk_write(pc->connsock, reply->s, reply->len);
|
||||||
|
|
||||||
|
strbuf_free(reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1141,7 +1102,10 @@ void *pageant_get_keylist1(int *length)
|
|||||||
if (length)
|
if (length)
|
||||||
*length = resplen-5;
|
*length = resplen-5;
|
||||||
} else {
|
} else {
|
||||||
ret = pageant_make_keylist1(length);
|
strbuf *buf = strbuf_new();
|
||||||
|
pageant_make_keylist1(BinarySink_UPCAST(buf));
|
||||||
|
*length = buf->len;
|
||||||
|
ret = strbuf_to_str(buf);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1174,7 +1138,10 @@ void *pageant_get_keylist2(int *length)
|
|||||||
if (length)
|
if (length)
|
||||||
*length = resplen-5;
|
*length = resplen-5;
|
||||||
} else {
|
} else {
|
||||||
ret = pageant_make_keylist2(length);
|
strbuf *buf = strbuf_new();
|
||||||
|
pageant_make_keylist2(BinarySink_UPCAST(buf));
|
||||||
|
*length = buf->len;
|
||||||
|
ret = strbuf_to_str(buf);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
15
pageant.h
15
pageant.h
@ -28,21 +28,26 @@ void pageant_init(void);
|
|||||||
* Returns a fully formatted message as output, *with* its initial
|
* Returns a fully formatted message as output, *with* its initial
|
||||||
* length field, and sets *outlen to the full size of that message.
|
* length field, and sets *outlen to the full size of that message.
|
||||||
*/
|
*/
|
||||||
void *pageant_handle_msg(const void *msg, int msglen, int *outlen,
|
void pageant_handle_msg(BinarySink *bs,
|
||||||
void *logctx, pageant_logfn_t logfn);
|
const void *msg, int msglen,
|
||||||
|
void *logctx, pageant_logfn_t logfn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct a failure response. Useful for agent front ends which
|
* Construct a failure response. Useful for agent front ends which
|
||||||
* suffer a problem before they even get to pageant_handle_msg.
|
* suffer a problem before they even get to pageant_handle_msg.
|
||||||
|
*
|
||||||
|
* 'log_reason' is only used if logfn is not NULL.
|
||||||
*/
|
*/
|
||||||
void *pageant_failure_msg(int *outlen);
|
void pageant_failure_msg(BinarySink *bs,
|
||||||
|
const char *log_reason,
|
||||||
|
void *logctx, pageant_logfn_t logfn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct a list of public keys, just as the two LIST_IDENTITIES
|
* Construct a list of public keys, just as the two LIST_IDENTITIES
|
||||||
* requests would have returned them.
|
* requests would have returned them.
|
||||||
*/
|
*/
|
||||||
void *pageant_make_keylist1(int *length);
|
void pageant_make_keylist1(BinarySink *);
|
||||||
void *pageant_make_keylist2(int *length);
|
void pageant_make_keylist2(BinarySink *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Accessor functions for Pageant's internal key lists. Fetch the nth
|
* Accessor functions for Pageant's internal key lists. Fetch the nth
|
||||||
|
@ -376,22 +376,46 @@ void keylist_update(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PageantReply {
|
||||||
|
char buf[AGENT_MAX_MSGLEN - 4];
|
||||||
|
int len, overflowed;
|
||||||
|
BinarySink_IMPLEMENTATION;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void pageant_reply_BinarySink_write(
|
||||||
|
BinarySink *bs, const void *data, size_t len)
|
||||||
|
{
|
||||||
|
struct PageantReply *rep = BinarySink_DOWNCAST(bs, struct PageantReply);
|
||||||
|
if (!rep->overflowed && len <= sizeof(rep->buf) - rep->len) {
|
||||||
|
memcpy(rep->buf + rep->len, data, len);
|
||||||
|
rep->len += len;
|
||||||
|
} else {
|
||||||
|
rep->overflowed = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void answer_msg(void *msgv)
|
static void answer_msg(void *msgv)
|
||||||
{
|
{
|
||||||
unsigned char *msg = (unsigned char *)msgv;
|
unsigned char *msg = (unsigned char *)msgv;
|
||||||
unsigned msglen;
|
unsigned msglen;
|
||||||
void *reply;
|
struct PageantReply reply;
|
||||||
int replylen;
|
|
||||||
|
reply.len = 0;
|
||||||
|
reply.overflowed = FALSE;
|
||||||
|
BinarySink_INIT(&reply, pageant_reply_BinarySink_write);
|
||||||
|
|
||||||
msglen = GET_32BIT(msg);
|
msglen = GET_32BIT(msg);
|
||||||
if (msglen > AGENT_MAX_MSGLEN) {
|
if (msglen > AGENT_MAX_MSGLEN) {
|
||||||
reply = pageant_failure_msg(&replylen);
|
pageant_failure_msg(BinarySink_UPCAST(&reply),
|
||||||
|
"incoming length field too large", NULL, NULL);
|
||||||
} else {
|
} else {
|
||||||
reply = pageant_handle_msg(msg + 4, msglen, &replylen, NULL, NULL);
|
pageant_handle_msg(BinarySink_UPCAST(&reply),
|
||||||
if (replylen > AGENT_MAX_MSGLEN) {
|
msg + 4, msglen, NULL, NULL);
|
||||||
smemclr(reply, replylen);
|
if (reply.len > AGENT_MAX_MSGLEN) {
|
||||||
sfree(reply);
|
reply.len = 0;
|
||||||
reply = pageant_failure_msg(&replylen);
|
reply.overflowed = FALSE;
|
||||||
|
pageant_failure_msg(BinarySink_UPCAST(&reply),
|
||||||
|
"output would exceed max msglen", NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,9 +423,10 @@ static void answer_msg(void *msgv)
|
|||||||
* Windows Pageant answers messages in place, by overwriting the
|
* Windows Pageant answers messages in place, by overwriting the
|
||||||
* input message buffer.
|
* input message buffer.
|
||||||
*/
|
*/
|
||||||
memcpy(msg, reply, replylen);
|
assert(4 + reply.len <= AGENT_MAX_MSGLEN);
|
||||||
smemclr(reply, replylen);
|
PUT_32BIT(msg, reply.len);
|
||||||
sfree(reply);
|
memcpy(msg + 4, reply.buf, reply.len);
|
||||||
|
smemclr(reply.buf, sizeof(reply.buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_add_keyfile(Filename *filename)
|
static void win_add_keyfile(Filename *filename)
|
||||||
|
Loading…
Reference in New Issue
Block a user