mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-01 03:22:48 -05: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:
@ -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)
|
||||
{
|
||||
unsigned char *msg = (unsigned char *)msgv;
|
||||
unsigned msglen;
|
||||
void *reply;
|
||||
int replylen;
|
||||
struct PageantReply reply;
|
||||
|
||||
reply.len = 0;
|
||||
reply.overflowed = FALSE;
|
||||
BinarySink_INIT(&reply, pageant_reply_BinarySink_write);
|
||||
|
||||
msglen = GET_32BIT(msg);
|
||||
if (msglen > AGENT_MAX_MSGLEN) {
|
||||
reply = pageant_failure_msg(&replylen);
|
||||
pageant_failure_msg(BinarySink_UPCAST(&reply),
|
||||
"incoming length field too large", NULL, NULL);
|
||||
} else {
|
||||
reply = pageant_handle_msg(msg + 4, msglen, &replylen, NULL, NULL);
|
||||
if (replylen > AGENT_MAX_MSGLEN) {
|
||||
smemclr(reply, replylen);
|
||||
sfree(reply);
|
||||
reply = pageant_failure_msg(&replylen);
|
||||
pageant_handle_msg(BinarySink_UPCAST(&reply),
|
||||
msg + 4, msglen, NULL, NULL);
|
||||
if (reply.len > AGENT_MAX_MSGLEN) {
|
||||
reply.len = 0;
|
||||
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
|
||||
* input message buffer.
|
||||
*/
|
||||
memcpy(msg, reply, replylen);
|
||||
smemclr(reply, replylen);
|
||||
sfree(reply);
|
||||
assert(4 + reply.len <= AGENT_MAX_MSGLEN);
|
||||
PUT_32BIT(msg, reply.len);
|
||||
memcpy(msg + 4, reply.buf, reply.len);
|
||||
smemclr(reply.buf, sizeof(reply.buf));
|
||||
}
|
||||
|
||||
static void win_add_keyfile(Filename *filename)
|
||||
|
Reference in New Issue
Block a user