1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-04-18 03:28:07 -05:00

Replace PktOut body pointer with a prefix length.

The body pointer was used after encryption to mark the start of the
fully wire-ready packet by ssh2_pkt_construct, and before encryption
by the log_outgoing_packet functions. Now the former returns a nice
modern ptrlen (it never really needed to store the pointer _in_ the
packet structure anyway), and the latter uses an integer 'prefix'
field, which isn't very different in concept but saves effort on
reallocs.
This commit is contained in:
Simon Tatham 2018-06-06 07:17:32 +01:00
parent ea04bf3da9
commit 8c4680a972

75
ssh.c
View File

@ -366,7 +366,7 @@ static struct PktOut *ssh1_pkt_init(int pkt_type);
static struct PktOut *ssh2_pkt_init(int pkt_type); static struct PktOut *ssh2_pkt_init(int pkt_type);
static void ssh_pkt_ensure(struct PktOut *, int length); static void ssh_pkt_ensure(struct PktOut *, int length);
static void ssh_pkt_adddata(struct PktOut *, const void *data, int len); static void ssh_pkt_adddata(struct PktOut *, const void *data, int len);
static int ssh2_pkt_construct(Ssh, struct PktOut *); static ptrlen ssh2_pkt_construct(Ssh, struct PktOut *);
static void ssh2_pkt_send(Ssh, struct PktOut *); static void ssh2_pkt_send(Ssh, struct PktOut *);
static void ssh2_pkt_send_noqueue(Ssh, struct PktOut *); static void ssh2_pkt_send_noqueue(Ssh, struct PktOut *);
static void do_ssh1_login(void *vctx); static void do_ssh1_login(void *vctx);
@ -679,11 +679,11 @@ struct PktIn {
}; };
struct PktOut { struct PktOut {
long length; /* length relative to 'data' */ long prefix; /* bytes up to and including type field */
long length; /* total bytes, including prefix */
int type; int type;
long forcepad; /* SSH-2: force padding to at least this length */ long forcepad; /* SSH-2: force padding to at least this length */
unsigned char *data; /* allocated storage */ unsigned char *data; /* allocated storage */
unsigned char *body; /* offset of payload within `data' */
long maxlen; /* amount of storage allocated for `data' */ long maxlen; /* amount of storage allocated for `data' */
long encrypted_len; /* for SSH-2 total-size counting */ long encrypted_len; /* for SSH-2 total-size counting */
@ -1393,7 +1393,7 @@ static PktOut *ssh_new_packet(void)
PktOut *pkt = snew(PktOut); PktOut *pkt = snew(PktOut);
BinarySink_INIT(pkt, ssh_pkt_BinarySink_write); BinarySink_INIT(pkt, ssh_pkt_BinarySink_write);
pkt->body = pkt->data = NULL; pkt->data = NULL;
pkt->maxlen = 0; pkt->maxlen = 0;
return pkt; return pkt;
@ -1435,14 +1435,8 @@ static void ssh1_log_outgoing_packet(Ssh ssh, const PktOut *pkt)
ptrlen str; ptrlen str;
BinarySource src[1]; BinarySource src[1];
/* BinarySource_BARE_INIT(src, pkt->data + pkt->prefix,
* For outgoing packets, pkt->length represents the length of the pkt->length - pkt->prefix);
* whole packet starting at pkt->data (including some header), and
* pkt->body refers to the point within that where the log-worthy
* payload begins.
*/
BinarySource_BARE_INIT(src, pkt->body,
pkt->length - (pkt->body - pkt->data));
if (ssh->logomitdata && if (ssh->logomitdata &&
(pkt->type == SSH1_CMSG_STDIN_DATA || (pkt->type == SSH1_CMSG_STDIN_DATA ||
@ -1657,14 +1651,8 @@ static void ssh2_log_outgoing_packet(Ssh ssh, const PktOut *pkt)
ptrlen str; ptrlen str;
BinarySource src[1]; BinarySource src[1];
/* BinarySource_BARE_INIT(src, pkt->data + pkt->prefix,
* For outgoing packets, pkt->length represents the length of the pkt->length - pkt->prefix);
* whole packet starting at pkt->data (including some header), and
* pkt->body refers to the point within that where the log-worthy
* payload begins.
*/
BinarySource_BARE_INIT(src, pkt->body,
pkt->length - (pkt->body - pkt->data));
if (ssh->logomitdata && if (ssh->logomitdata &&
(pkt->type == SSH2_MSG_CHANNEL_DATA || (pkt->type == SSH2_MSG_CHANNEL_DATA ||
@ -2208,7 +2196,7 @@ static int s_wrpkt_prepare(Ssh ssh, PktOut *pkt, int *offset_p)
return biglen + 4; /* len(length+padding+type+data+CRC) */ return biglen + 4; /* len(length+padding+type+data+CRC) */
} }
static int s_write(Ssh ssh, void *data, int len) static int s_write(Ssh ssh, const void *data, int len)
{ {
if (len && ssh->logctx) if (len && ssh->logctx)
log_packet(ssh->logctx, PKT_OUTGOING, -1, NULL, data, len, log_packet(ssh->logctx, PKT_OUTGOING, -1, NULL, data, len,
@ -2337,11 +2325,8 @@ static int ssh_versioncmp(const char *a, const char *b)
static void ssh_pkt_ensure(PktOut *pkt, int length) static void ssh_pkt_ensure(PktOut *pkt, int length)
{ {
if (pkt->maxlen < length) { if (pkt->maxlen < length) {
unsigned char *body = pkt->body;
int offset = body ? body - pkt->data : 0;
pkt->maxlen = length + 256; pkt->maxlen = length + 256;
pkt->data = sresize(pkt->data, pkt->maxlen, unsigned char); pkt->data = sresize(pkt->data, pkt->maxlen, unsigned char);
if (body) pkt->body = pkt->data + offset;
} }
} }
static void ssh_pkt_adddata(PktOut *pkt, const void *data, int len) static void ssh_pkt_adddata(PktOut *pkt, const void *data, int len)
@ -2363,7 +2348,7 @@ static PktOut *ssh1_pkt_init(int pkt_type)
PktOut *pkt = ssh_new_packet(); PktOut *pkt = ssh_new_packet();
pkt->length = 4 + 8; /* space for length + max padding */ pkt->length = 4 + 8; /* space for length + max padding */
put_byte(pkt, pkt_type); put_byte(pkt, pkt_type);
pkt->body = pkt->data + pkt->length; pkt->prefix = pkt->length;
pkt->type = pkt_type; pkt->type = pkt_type;
pkt->downstream_id = 0; pkt->downstream_id = 0;
pkt->additional_log_text = NULL; pkt->additional_log_text = NULL;
@ -2377,18 +2362,18 @@ static PktOut *ssh2_pkt_init(int pkt_type)
pkt->forcepad = 0; pkt->forcepad = 0;
pkt->type = pkt_type; pkt->type = pkt_type;
put_byte(pkt, (unsigned char) pkt_type); put_byte(pkt, (unsigned char) pkt_type);
pkt->body = pkt->data + pkt->length; /* after packet type */ pkt->prefix = pkt->length;
pkt->downstream_id = 0; pkt->downstream_id = 0;
pkt->additional_log_text = NULL; pkt->additional_log_text = NULL;
return pkt; return pkt;
} }
/* /*
* Construct an SSH-2 final-form packet: compress it, encrypt it, * Construct an SSH-2 final-form packet: compress it, encrypt it, put
* put the MAC on it. Final packet, ready to be sent, is stored in * the MAC on it. Return a slice of pkt->data giving the final packet
* pkt->data. Total length is returned. * in ready-to-send form.
*/ */
static int ssh2_pkt_construct(Ssh ssh, PktOut *pkt) static ptrlen ssh2_pkt_construct(Ssh ssh, PktOut *pkt)
{ {
int cipherblk, maclen, padding, unencrypted_prefix, i; int cipherblk, maclen, padding, unencrypted_prefix, i;
@ -2400,10 +2385,12 @@ static int ssh2_pkt_construct(Ssh ssh, PktOut *pkt)
* Trivial packet construction for the bare connection * Trivial packet construction for the bare connection
* protocol. * protocol.
*/ */
PUT_32BIT(pkt->data + 1, pkt->length - 5); long start = pkt->prefix - 1;
pkt->body = pkt->data + 1; long length = pkt->length - start;
assert(start >= 4);
PUT_32BIT(pkt->data + start - 4, length);
ssh->v2_outgoing_sequence++; /* only for diagnostics, really */ ssh->v2_outgoing_sequence++; /* only for diagnostics, really */
return pkt->length - 1; return make_ptrlen(pkt->data + start - 4, length + 4);
} }
/* /*
@ -2477,9 +2464,7 @@ static int ssh2_pkt_construct(Ssh ssh, PktOut *pkt)
ssh->v2_outgoing_sequence++; /* whether or not we MACed */ ssh->v2_outgoing_sequence++; /* whether or not we MACed */
pkt->encrypted_len = pkt->length + padding; pkt->encrypted_len = pkt->length + padding;
/* Ready-to-send packet starts at pkt->data. We return length. */ return make_ptrlen(pkt->data, pkt->length + padding + maclen);
pkt->body = pkt->data;
return pkt->length + padding + maclen;
} }
/* /*
@ -2527,7 +2512,7 @@ static void ssh_pkt_defersend(Ssh);
*/ */
static void ssh2_pkt_send_noqueue(Ssh ssh, PktOut *pkt) static void ssh2_pkt_send_noqueue(Ssh ssh, PktOut *pkt)
{ {
int len; ptrlen data;
int backlog; int backlog;
if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC)) { if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC)) {
/* We need to send two packets, so use the deferral mechanism. */ /* We need to send two packets, so use the deferral mechanism. */
@ -2535,8 +2520,8 @@ static void ssh2_pkt_send_noqueue(Ssh ssh, PktOut *pkt)
ssh_pkt_defersend(ssh); ssh_pkt_defersend(ssh);
return; return;
} }
len = ssh2_pkt_construct(ssh, pkt); data = ssh2_pkt_construct(ssh, pkt);
backlog = s_write(ssh, pkt->body, len); backlog = s_write(ssh, data.ptr, data.len);
if (backlog > SSH_MAX_BACKLOG) if (backlog > SSH_MAX_BACKLOG)
ssh_throttle_all(ssh, 1, backlog); ssh_throttle_all(ssh, 1, backlog);
@ -2558,7 +2543,7 @@ static void ssh2_pkt_send_noqueue(Ssh ssh, PktOut *pkt)
*/ */
static void ssh2_pkt_defer_noqueue(Ssh ssh, PktOut *pkt, int noignore) static void ssh2_pkt_defer_noqueue(Ssh ssh, PktOut *pkt, int noignore)
{ {
int len; ptrlen data;
if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC) && if (ssh->cscipher != NULL && (ssh->cscipher->flags & SSH_CIPHER_IS_CBC) &&
ssh->deferred_len == 0 && !noignore && ssh->deferred_len == 0 && !noignore &&
!(ssh->remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE)) { !(ssh->remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE)) {
@ -2570,15 +2555,15 @@ static void ssh2_pkt_defer_noqueue(Ssh ssh, PktOut *pkt, int noignore)
put_stringz(ipkt, ""); put_stringz(ipkt, "");
ssh2_pkt_defer_noqueue(ssh, ipkt, TRUE); ssh2_pkt_defer_noqueue(ssh, ipkt, TRUE);
} }
len = ssh2_pkt_construct(ssh, pkt); data = ssh2_pkt_construct(ssh, pkt);
if (ssh->deferred_len + len > ssh->deferred_size) { if (ssh->deferred_len + data.len > ssh->deferred_size) {
ssh->deferred_size = ssh->deferred_len + len + 128; ssh->deferred_size = ssh->deferred_len + data.len + 128;
ssh->deferred_send_data = sresize(ssh->deferred_send_data, ssh->deferred_send_data = sresize(ssh->deferred_send_data,
ssh->deferred_size, ssh->deferred_size,
unsigned char); unsigned char);
} }
memcpy(ssh->deferred_send_data + ssh->deferred_len, pkt->body, len); memcpy(ssh->deferred_send_data + ssh->deferred_len, data.ptr, data.len);
ssh->deferred_len += len; ssh->deferred_len += data.len;
ssh->deferred_data_size += pkt->encrypted_len; ssh->deferred_data_size += pkt->encrypted_len;
ssh_free_pktout(pkt); ssh_free_pktout(pkt);
} }