mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-24 16:52:24 +00:00
Tighten up a lot of casts from unsigned to int which are read by one
of the GET_32BIT macros and then used as length fields. Missing bounds checks against zero have been added, and also I've introduced a helper function toint() which casts from unsigned to int in such a way as to avoid C undefined behaviour, since I'm not sure I trust compilers any more to do the obviously sensible thing. [originally from svn r9918]
This commit is contained in:
parent
1662a2f6cf
commit
896bb7c74d
9
conf.c
9
conf.c
@ -522,14 +522,15 @@ int conf_deserialise(Conf *conf, void *vdata, int maxsize)
|
|||||||
unsigned char *data = (unsigned char *)vdata;
|
unsigned char *data = (unsigned char *)vdata;
|
||||||
unsigned char *start = data;
|
unsigned char *start = data;
|
||||||
struct conf_entry *entry;
|
struct conf_entry *entry;
|
||||||
int primary, used;
|
unsigned primary;
|
||||||
|
int used;
|
||||||
unsigned char *zero;
|
unsigned char *zero;
|
||||||
|
|
||||||
while (maxsize >= 4) {
|
while (maxsize >= 4) {
|
||||||
primary = GET_32BIT_MSB_FIRST(data);
|
primary = GET_32BIT_MSB_FIRST(data);
|
||||||
data += 4, maxsize -= 4;
|
data += 4, maxsize -= 4;
|
||||||
|
|
||||||
if ((unsigned)primary >= N_CONFIG_OPTIONS)
|
if (primary >= N_CONFIG_OPTIONS)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
entry = snew(struct conf_entry);
|
entry = snew(struct conf_entry);
|
||||||
@ -541,7 +542,7 @@ int conf_deserialise(Conf *conf, void *vdata, int maxsize)
|
|||||||
sfree(entry);
|
sfree(entry);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
entry->key.secondary.i = GET_32BIT_MSB_FIRST(data);
|
entry->key.secondary.i = toint(GET_32BIT_MSB_FIRST(data));
|
||||||
data += 4, maxsize -= 4;
|
data += 4, maxsize -= 4;
|
||||||
break;
|
break;
|
||||||
case TYPE_STR:
|
case TYPE_STR:
|
||||||
@ -564,7 +565,7 @@ int conf_deserialise(Conf *conf, void *vdata, int maxsize)
|
|||||||
sfree(entry);
|
sfree(entry);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
entry->value.u.intval = GET_32BIT_MSB_FIRST(data);
|
entry->value.u.intval = toint(GET_32BIT_MSB_FIRST(data));
|
||||||
data += 4, maxsize -= 4;
|
data += 4, maxsize -= 4;
|
||||||
break;
|
break;
|
||||||
case TYPE_STR:
|
case TYPE_STR:
|
||||||
|
41
import.c
41
import.c
@ -289,7 +289,7 @@ static int ssh2_read_mpint(void *data, int len, struct mpint_pos *ret)
|
|||||||
|
|
||||||
if (len < 4)
|
if (len < 4)
|
||||||
goto error;
|
goto error;
|
||||||
bytes = GET_32BIT(d);
|
bytes = toint(GET_32BIT(d));
|
||||||
if (bytes < 0 || len-4 < bytes)
|
if (bytes < 0 || len-4 < bytes)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -745,6 +745,10 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
|
|||||||
struct mpint_pos n, e, d, p, q, iqmp, dmp1, dmq1;
|
struct mpint_pos n, e, d, p, q, iqmp, dmp1, dmq1;
|
||||||
Bignum bd, bp, bq, bdmp1, bdmq1;
|
Bignum bd, bp, bq, bdmp1, bdmq1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These blobs were generated from inside PuTTY, so we needn't
|
||||||
|
* treat them as untrusted.
|
||||||
|
*/
|
||||||
pos = 4 + GET_32BIT(pubblob);
|
pos = 4 + GET_32BIT(pubblob);
|
||||||
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);
|
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);
|
||||||
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);
|
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);
|
||||||
@ -798,6 +802,10 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
|
|||||||
int pos;
|
int pos;
|
||||||
struct mpint_pos p, q, g, y, x;
|
struct mpint_pos p, q, g, y, x;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These blobs were generated from inside PuTTY, so we needn't
|
||||||
|
* treat them as untrusted.
|
||||||
|
*/
|
||||||
pos = 4 + GET_32BIT(pubblob);
|
pos = 4 + GET_32BIT(pubblob);
|
||||||
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);
|
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);
|
||||||
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);
|
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);
|
||||||
@ -1216,11 +1224,12 @@ int sshcom_encrypted(const Filename *filename, char **comment)
|
|||||||
pos = 8;
|
pos = 8;
|
||||||
if (key->keyblob_len < pos+4)
|
if (key->keyblob_len < pos+4)
|
||||||
goto done; /* key is far too short */
|
goto done; /* key is far too short */
|
||||||
pos += 4 + GET_32BIT(key->keyblob + pos); /* skip key type */
|
len = toint(GET_32BIT(key->keyblob + pos));
|
||||||
if (key->keyblob_len < pos+4)
|
if (len < 0 || len > key->keyblob_len - pos - 4)
|
||||||
goto done; /* key is far too short */
|
goto done; /* key is far too short */
|
||||||
len = GET_32BIT(key->keyblob + pos); /* find cipher-type length */
|
pos += 4 + len; /* skip key type */
|
||||||
if (key->keyblob_len < pos+4+len)
|
len = toint(GET_32BIT(key->keyblob + pos)); /* find cipher-type length */
|
||||||
|
if (len < 0 || len > key->keyblob_len - pos - 4)
|
||||||
goto done; /* cipher type string is incomplete */
|
goto done; /* cipher type string is incomplete */
|
||||||
if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4))
|
if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4))
|
||||||
answer = 1;
|
answer = 1;
|
||||||
@ -1236,8 +1245,7 @@ int sshcom_encrypted(const Filename *filename, char **comment)
|
|||||||
|
|
||||||
static int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret)
|
static int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret)
|
||||||
{
|
{
|
||||||
int bits;
|
unsigned bits, bytes;
|
||||||
int bytes;
|
|
||||||
unsigned char *d = (unsigned char *) data;
|
unsigned char *d = (unsigned char *) data;
|
||||||
|
|
||||||
if (len < 4)
|
if (len < 4)
|
||||||
@ -1309,7 +1317,8 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
|
|||||||
*/
|
*/
|
||||||
pos = 8;
|
pos = 8;
|
||||||
if (key->keyblob_len < pos+4 ||
|
if (key->keyblob_len < pos+4 ||
|
||||||
(len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
|
(len = toint(GET_32BIT(key->keyblob + pos))) < 0 ||
|
||||||
|
len > key->keyblob_len - pos - 4) {
|
||||||
errmsg = "key blob does not contain a key type string";
|
errmsg = "key blob does not contain a key type string";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -1329,7 +1338,8 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
|
|||||||
* Determine the cipher type.
|
* Determine the cipher type.
|
||||||
*/
|
*/
|
||||||
if (key->keyblob_len < pos+4 ||
|
if (key->keyblob_len < pos+4 ||
|
||||||
(len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
|
(len = toint(GET_32BIT(key->keyblob + pos))) < 0 ||
|
||||||
|
len > key->keyblob_len - pos - 4) {
|
||||||
errmsg = "key blob does not contain a cipher type string";
|
errmsg = "key blob does not contain a cipher type string";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -1347,7 +1357,8 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
|
|||||||
* Get hold of the encrypted part of the key.
|
* Get hold of the encrypted part of the key.
|
||||||
*/
|
*/
|
||||||
if (key->keyblob_len < pos+4 ||
|
if (key->keyblob_len < pos+4 ||
|
||||||
(len = GET_32BIT(key->keyblob + pos)) > key->keyblob_len - pos - 4) {
|
(len = toint(GET_32BIT(key->keyblob + pos))) < 0 ||
|
||||||
|
len > key->keyblob_len - pos - 4) {
|
||||||
errmsg = "key blob does not contain actual key data";
|
errmsg = "key blob does not contain actual key data";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -1411,7 +1422,7 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
|
|||||||
/*
|
/*
|
||||||
* Strip away the containing string to get to the real meat.
|
* Strip away the containing string to get to the real meat.
|
||||||
*/
|
*/
|
||||||
len = GET_32BIT(ciphertext);
|
len = toint(GET_32BIT(ciphertext));
|
||||||
if (len < 0 || len > cipherlen-4) {
|
if (len < 0 || len > cipherlen-4) {
|
||||||
errmsg = "containing string was ill-formed";
|
errmsg = "containing string was ill-formed";
|
||||||
goto error;
|
goto error;
|
||||||
@ -1540,6 +1551,10 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key,
|
|||||||
int pos;
|
int pos;
|
||||||
struct mpint_pos n, e, d, p, q, iqmp;
|
struct mpint_pos n, e, d, p, q, iqmp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These blobs were generated from inside PuTTY, so we needn't
|
||||||
|
* treat them as untrusted.
|
||||||
|
*/
|
||||||
pos = 4 + GET_32BIT(pubblob);
|
pos = 4 + GET_32BIT(pubblob);
|
||||||
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);
|
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);
|
||||||
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);
|
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);
|
||||||
@ -1565,6 +1580,10 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key,
|
|||||||
int pos;
|
int pos;
|
||||||
struct mpint_pos p, q, g, y, x;
|
struct mpint_pos p, q, g, y, x;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These blobs were generated from inside PuTTY, so we needn't
|
||||||
|
* treat them as untrusted.
|
||||||
|
*/
|
||||||
pos = 4 + GET_32BIT(pubblob);
|
pos = 4 + GET_32BIT(pubblob);
|
||||||
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);
|
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);
|
||||||
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);
|
pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);
|
||||||
|
23
misc.c
23
misc.c
@ -208,6 +208,29 @@ void burnstr(char *string) /* sfree(str), only clear it first */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int toint(unsigned u)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Convert an unsigned to an int, without running into the
|
||||||
|
* undefined behaviour which happens by the strict C standard if
|
||||||
|
* the value overflows. You'd hope that sensible compilers would
|
||||||
|
* do the sensible thing in response to a cast, but actually I
|
||||||
|
* don't trust modern compilers not to do silly things like
|
||||||
|
* assuming that _obviously_ you wouldn't have caused an overflow
|
||||||
|
* and so they can elide an 'if (i < 0)' test immediately after
|
||||||
|
* the cast.
|
||||||
|
*
|
||||||
|
* Sensible compilers ought of course to optimise this entire
|
||||||
|
* function into 'just return the input value'!
|
||||||
|
*/
|
||||||
|
if (u <= (unsigned)INT_MAX)
|
||||||
|
return (int)u;
|
||||||
|
else if (u >= (unsigned)INT_MIN) /* wrap in cast _to_ unsigned is OK */
|
||||||
|
return INT_MIN + (int)(u - (unsigned)INT_MIN);
|
||||||
|
else
|
||||||
|
return INT_MIN; /* fallback; should never occur on binary machines */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do an sprintf(), but into a custom-allocated buffer.
|
* Do an sprintf(), but into a custom-allocated buffer.
|
||||||
*
|
*
|
||||||
|
2
misc.h
2
misc.h
@ -30,6 +30,8 @@ char *dupprintf(const char *fmt, ...);
|
|||||||
char *dupvprintf(const char *fmt, va_list ap);
|
char *dupvprintf(const char *fmt, va_list ap);
|
||||||
void burnstr(char *string);
|
void burnstr(char *string);
|
||||||
|
|
||||||
|
int toint(unsigned);
|
||||||
|
|
||||||
char *fgetline(FILE *fp);
|
char *fgetline(FILE *fp);
|
||||||
|
|
||||||
void base64_encode_atom(unsigned char *data, int n, char *out);
|
void base64_encode_atom(unsigned char *data, int n, char *out);
|
||||||
|
2
sftp.c
2
sftp.c
@ -150,7 +150,7 @@ static int sftp_pkt_getstring(struct sftp_packet *pkt,
|
|||||||
*p = NULL;
|
*p = NULL;
|
||||||
if (pkt->length - pkt->savedpos < 4)
|
if (pkt->length - pkt->savedpos < 4)
|
||||||
return 0;
|
return 0;
|
||||||
*length = GET_32BIT(pkt->data + pkt->savedpos);
|
*length = toint(GET_32BIT(pkt->data + pkt->savedpos));
|
||||||
pkt->savedpos += 4;
|
pkt->savedpos += 4;
|
||||||
if ((int)(pkt->length - pkt->savedpos) < *length || *length < 0) {
|
if ((int)(pkt->length - pkt->savedpos) < *length || *length < 0) {
|
||||||
*length = 0;
|
*length = 0;
|
||||||
|
128
ssh.c
128
ssh.c
@ -1449,7 +1449,8 @@ static struct Packet *ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
|
|||||||
/* See if that gives us a valid packet. */
|
/* See if that gives us a valid packet. */
|
||||||
if (ssh->scmac->verresult(ssh->sc_mac_ctx,
|
if (ssh->scmac->verresult(ssh->sc_mac_ctx,
|
||||||
st->pktin->data + st->packetlen) &&
|
st->pktin->data + st->packetlen) &&
|
||||||
(st->len = GET_32BIT(st->pktin->data)) + 4 == st->packetlen)
|
((st->len = toint(GET_32BIT(st->pktin->data))) ==
|
||||||
|
st->packetlen-4))
|
||||||
break;
|
break;
|
||||||
if (st->packetlen >= OUR_V2_PACKETLIMIT) {
|
if (st->packetlen >= OUR_V2_PACKETLIMIT) {
|
||||||
bombout(("No valid incoming packet found"));
|
bombout(("No valid incoming packet found"));
|
||||||
@ -1482,7 +1483,7 @@ static struct Packet *ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
|
|||||||
/*
|
/*
|
||||||
* Now get the length figure.
|
* Now get the length figure.
|
||||||
*/
|
*/
|
||||||
st->len = GET_32BIT(st->pktin->data);
|
st->len = toint(GET_32BIT(st->pktin->data));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _Completely_ silly lengths should be stomped on before they
|
* _Completely_ silly lengths should be stomped on before they
|
||||||
@ -2313,7 +2314,7 @@ static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length)
|
|||||||
*length = 0;
|
*length = 0;
|
||||||
if (pkt->length - pkt->savedpos < 4)
|
if (pkt->length - pkt->savedpos < 4)
|
||||||
return;
|
return;
|
||||||
len = GET_32BIT(pkt->body + pkt->savedpos);
|
len = toint(GET_32BIT(pkt->body + pkt->savedpos));
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
return;
|
return;
|
||||||
*length = len;
|
*length = len;
|
||||||
@ -2397,7 +2398,7 @@ static void ssh2_add_sigblob(Ssh ssh, struct Packet *pkt,
|
|||||||
* See if this is in fact an ssh-rsa signature and a buggy
|
* See if this is in fact an ssh-rsa signature and a buggy
|
||||||
* server; otherwise we can just do this the easy way.
|
* server; otherwise we can just do this the easy way.
|
||||||
*/
|
*/
|
||||||
if ((ssh->remote_bugs & BUG_SSH2_RSA_PADDING) &&
|
if ((ssh->remote_bugs & BUG_SSH2_RSA_PADDING) && pkblob_len > 4+7+4 &&
|
||||||
(GET_32BIT(pkblob) == 7 && !memcmp(pkblob+4, "ssh-rsa", 7))) {
|
(GET_32BIT(pkblob) == 7 && !memcmp(pkblob+4, "ssh-rsa", 7))) {
|
||||||
int pos, len, siglen;
|
int pos, len, siglen;
|
||||||
|
|
||||||
@ -2406,8 +2407,15 @@ static void ssh2_add_sigblob(Ssh ssh, struct Packet *pkt,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
pos = 4+7; /* skip over "ssh-rsa" */
|
pos = 4+7; /* skip over "ssh-rsa" */
|
||||||
pos += 4 + GET_32BIT(pkblob+pos); /* skip over exponent */
|
len = toint(GET_32BIT(pkblob+pos)); /* get length of exponent */
|
||||||
len = GET_32BIT(pkblob+pos); /* find length of modulus */
|
if (len < 0 || len > pkblob_len - pos - 4)
|
||||||
|
goto give_up;
|
||||||
|
pos += 4 + len; /* skip over exponent */
|
||||||
|
if (pkblob_len - pos < 4)
|
||||||
|
goto give_up;
|
||||||
|
len = toint(GET_32BIT(pkblob+pos)); /* find length of modulus */
|
||||||
|
if (len < 0 || len > pkblob_len - pos - 4)
|
||||||
|
goto give_up;
|
||||||
pos += 4; /* find modulus itself */
|
pos += 4; /* find modulus itself */
|
||||||
while (len > 0 && pkblob[pos] == 0)
|
while (len > 0 && pkblob[pos] == 0)
|
||||||
len--, pos++;
|
len--, pos++;
|
||||||
@ -2417,7 +2425,11 @@ static void ssh2_add_sigblob(Ssh ssh, struct Packet *pkt,
|
|||||||
* Now find the signature integer.
|
* Now find the signature integer.
|
||||||
*/
|
*/
|
||||||
pos = 4+7; /* skip over "ssh-rsa" */
|
pos = 4+7; /* skip over "ssh-rsa" */
|
||||||
siglen = GET_32BIT(sigblob+pos);
|
if (sigblob_len < pos+4)
|
||||||
|
goto give_up;
|
||||||
|
siglen = toint(GET_32BIT(sigblob+pos));
|
||||||
|
if (siglen != sigblob_len - pos - 4)
|
||||||
|
goto give_up;
|
||||||
/* debug(("signature length is %d\n", siglen)); */
|
/* debug(("signature length is %d\n", siglen)); */
|
||||||
|
|
||||||
if (len != siglen) {
|
if (len != siglen) {
|
||||||
@ -2439,7 +2451,10 @@ static void ssh2_add_sigblob(Ssh ssh, struct Packet *pkt,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise fall through and do it the easy way. */
|
/* Otherwise fall through and do it the easy way. We also come
|
||||||
|
* here as a fallback if we discover above that the key blob
|
||||||
|
* is misformatted in some way. */
|
||||||
|
give_up:;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh2_pkt_addstring_start(pkt);
|
ssh2_pkt_addstring_start(pkt);
|
||||||
@ -3677,7 +3692,12 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,
|
|||||||
if (s->response && s->responselen >= 5 &&
|
if (s->response && s->responselen >= 5 &&
|
||||||
s->response[4] == SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
|
s->response[4] == SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
|
||||||
s->p = s->response + 5;
|
s->p = s->response + 5;
|
||||||
s->nkeys = GET_32BIT(s->p);
|
s->nkeys = toint(GET_32BIT(s->p));
|
||||||
|
if (s->nkeys < 0) {
|
||||||
|
logeventf(ssh, "Pageant reported negative key count %d",
|
||||||
|
s->nkeys);
|
||||||
|
s->nkeys = 0;
|
||||||
|
}
|
||||||
s->p += 4;
|
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++) {
|
||||||
@ -3687,22 +3707,23 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,
|
|||||||
int n, ok = FALSE;
|
int n, ok = FALSE;
|
||||||
do { /* do while (0) to make breaking easy */
|
do { /* do while (0) to make breaking easy */
|
||||||
n = ssh1_read_bignum
|
n = ssh1_read_bignum
|
||||||
(s->p, s->responselen-(s->p-s->response),
|
(s->p, toint(s->responselen-(s->p-s->response)),
|
||||||
&s->key.exponent);
|
&s->key.exponent);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
break;
|
break;
|
||||||
s->p += n;
|
s->p += n;
|
||||||
n = ssh1_read_bignum
|
n = ssh1_read_bignum
|
||||||
(s->p, s->responselen-(s->p-s->response),
|
(s->p, toint(s->responselen-(s->p-s->response)),
|
||||||
&s->key.modulus);
|
&s->key.modulus);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
break;
|
break;
|
||||||
s->p += n;
|
s->p += n;
|
||||||
if (s->responselen - (s->p-s->response) < 4)
|
if (s->responselen - (s->p-s->response) < 4)
|
||||||
break;
|
break;
|
||||||
s->commentlen = GET_32BIT(s->p);
|
s->commentlen = toint(GET_32BIT(s->p));
|
||||||
s->p += 4;
|
s->p += 4;
|
||||||
if (s->responselen - (s->p-s->response) <
|
if (s->commentlen < 0 ||
|
||||||
|
toint(s->responselen - (s->p-s->response)) <
|
||||||
s->commentlen)
|
s->commentlen)
|
||||||
break;
|
break;
|
||||||
s->commentp = (char *)s->p;
|
s->commentp = (char *)s->p;
|
||||||
@ -7193,16 +7214,18 @@ static void ssh2_msg_channel_request(Ssh ssh, struct Packet *pktin)
|
|||||||
is_int = FALSE;
|
is_int = FALSE;
|
||||||
} else {
|
} else {
|
||||||
int maybe_int = FALSE, maybe_str = FALSE;
|
int maybe_int = FALSE, maybe_str = FALSE;
|
||||||
#define CHECK_HYPOTHESIS(offset, result) \
|
#define CHECK_HYPOTHESIS(offset, result) \
|
||||||
do { \
|
do \
|
||||||
long q = offset; \
|
{ \
|
||||||
if (q >= 0 && q+4 <= len) { \
|
int q = toint(offset); \
|
||||||
q = q + 4 + GET_32BIT(p+q); \
|
if (q >= 0 && q+4 <= len) { \
|
||||||
if (q >= 0 && q+4 <= len && \
|
q = toint(q + 4 + GET_32BIT(p+q)); \
|
||||||
((q = q + 4 + GET_32BIT(p+q))!= 0) && q == len) \
|
if (q >= 0 && q+4 <= len && \
|
||||||
result = TRUE; \
|
((q = toint(q + 4 + GET_32BIT(p+q))) != 0) && \
|
||||||
} \
|
q == len) \
|
||||||
} while(0)
|
result = TRUE; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
CHECK_HYPOTHESIS(4+1, maybe_int);
|
CHECK_HYPOTHESIS(4+1, maybe_int);
|
||||||
CHECK_HYPOTHESIS(4+num+1, maybe_str);
|
CHECK_HYPOTHESIS(4+num+1, maybe_str);
|
||||||
#undef CHECK_HYPOTHESIS
|
#undef CHECK_HYPOTHESIS
|
||||||
@ -7896,13 +7919,53 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
|
|||||||
int keyi;
|
int keyi;
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
p = s->agent_response + 5;
|
p = s->agent_response + 5;
|
||||||
s->nkeys = GET_32BIT(p);
|
s->nkeys = toint(GET_32BIT(p));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Vet the Pageant response to ensure that the key
|
||||||
|
* count and blob lengths make sense.
|
||||||
|
*/
|
||||||
|
if (s->nkeys < 0) {
|
||||||
|
logeventf(ssh, "Pageant response contained a negative"
|
||||||
|
" key count %d", s->nkeys);
|
||||||
|
s->nkeys = 0;
|
||||||
|
goto done_agent_query;
|
||||||
|
} 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));
|
||||||
|
if (bloblen < 0 || bloblen > lenleft) {
|
||||||
|
logeventf(ssh, "Pageant response was truncated");
|
||||||
|
s->nkeys = 0;
|
||||||
|
goto done_agent_query;
|
||||||
|
}
|
||||||
|
lenleft -= 4 + bloblen;
|
||||||
|
q += 4 + bloblen;
|
||||||
|
commentlen = toint(GET_32BIT(q));
|
||||||
|
if (commentlen < 0 || commentlen > lenleft) {
|
||||||
|
logeventf(ssh, "Pageant response was truncated");
|
||||||
|
s->nkeys = 0;
|
||||||
|
goto done_agent_query;
|
||||||
|
}
|
||||||
|
lenleft -= 4 + commentlen;
|
||||||
|
q += 4 + commentlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p += 4;
|
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) {
|
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 = GET_32BIT(p);
|
s->pklen = toint(GET_32BIT(p));
|
||||||
if (s->pklen == s->publickey_bloblen &&
|
if (s->pklen == s->publickey_bloblen &&
|
||||||
!memcmp(p+4, s->publickey_blob,
|
!memcmp(p+4, s->publickey_blob,
|
||||||
s->publickey_bloblen)) {
|
s->publickey_bloblen)) {
|
||||||
@ -7913,7 +7976,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
p += 4 + s->pklen;
|
p += 4 + s->pklen;
|
||||||
p += GET_32BIT(p) + 4; /* comment */
|
p += toint(GET_32BIT(p)) + 4; /* comment */
|
||||||
}
|
}
|
||||||
if (!s->pkblob_in_agent) {
|
if (!s->pkblob_in_agent) {
|
||||||
logevent("Configured key file not in Pageant");
|
logevent("Configured key file not in Pageant");
|
||||||
@ -7923,6 +7986,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
|
|||||||
} else {
|
} else {
|
||||||
logevent("Failed to get reply from Pageant");
|
logevent("Failed to get reply from Pageant");
|
||||||
}
|
}
|
||||||
|
done_agent_query:;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -8174,13 +8238,13 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
|
|||||||
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 = GET_32BIT(s->agentp);
|
s->pklen = toint(GET_32BIT(s->agentp));
|
||||||
s->agentp += 4;
|
s->agentp += 4;
|
||||||
s->pkblob = (char *)s->agentp;
|
s->pkblob = (char *)s->agentp;
|
||||||
s->agentp += s->pklen;
|
s->agentp += s->pklen;
|
||||||
s->alglen = GET_32BIT(s->pkblob);
|
s->alglen = toint(GET_32BIT(s->pkblob));
|
||||||
s->alg = s->pkblob + 4;
|
s->alg = s->pkblob + 4;
|
||||||
s->commentlen = GET_32BIT(s->agentp);
|
s->commentlen = toint(GET_32BIT(s->agentp));
|
||||||
s->agentp += 4;
|
s->agentp += 4;
|
||||||
s->commentp = (char *)s->agentp;
|
s->commentp = (char *)s->agentp;
|
||||||
s->agentp += s->commentlen;
|
s->agentp += s->commentlen;
|
||||||
@ -8284,7 +8348,9 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
|
|||||||
s->ret = vret;
|
s->ret = vret;
|
||||||
sfree(s->agentreq);
|
sfree(s->agentreq);
|
||||||
if (s->ret) {
|
if (s->ret) {
|
||||||
if (s->ret[4] == SSH2_AGENT_SIGN_RESPONSE) {
|
if (s->retlen >= 9 &&
|
||||||
|
s->ret[4] == SSH2_AGENT_SIGN_RESPONSE &&
|
||||||
|
GET_32BIT(s->ret + 5) <= (unsigned)(s->retlen-9)) {
|
||||||
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->pkblob, s->pklen,
|
||||||
|
2
sshdss.c
2
sshdss.c
@ -42,7 +42,7 @@ static void getstring(char **data, int *datalen, char **p, int *length)
|
|||||||
*p = NULL;
|
*p = NULL;
|
||||||
if (*datalen < 4)
|
if (*datalen < 4)
|
||||||
return;
|
return;
|
||||||
*length = GET_32BIT(*data);
|
*length = toint(GET_32BIT(*data));
|
||||||
if (*length < 0)
|
if (*length < 0)
|
||||||
return;
|
return;
|
||||||
*datalen -= 4;
|
*datalen -= 4;
|
||||||
|
@ -73,7 +73,7 @@ static int loadrsakey_main(FILE * fp, struct RSAKey *key, int pub_only,
|
|||||||
i += j;
|
i += j;
|
||||||
|
|
||||||
/* Next, the comment field. */
|
/* Next, the comment field. */
|
||||||
j = GET_32BIT(buf + i);
|
j = toint(GET_32BIT(buf + i));
|
||||||
i += 4;
|
i += 4;
|
||||||
if (j < 0 || len - i < j)
|
if (j < 0 || len - i < j)
|
||||||
goto end;
|
goto end;
|
||||||
|
2
sshrsa.c
2
sshrsa.c
@ -525,7 +525,7 @@ static void getstring(char **data, int *datalen, char **p, int *length)
|
|||||||
*p = NULL;
|
*p = NULL;
|
||||||
if (*datalen < 4)
|
if (*datalen < 4)
|
||||||
return;
|
return;
|
||||||
*length = GET_32BIT(*data);
|
*length = toint(GET_32BIT(*data));
|
||||||
if (*length < 0)
|
if (*length < 0)
|
||||||
return;
|
return;
|
||||||
*datalen -= 4;
|
*datalen -= 4;
|
||||||
|
@ -75,13 +75,12 @@ static int agent_select_result(int fd, int event)
|
|||||||
}
|
}
|
||||||
conn->retlen += ret;
|
conn->retlen += ret;
|
||||||
if (conn->retsize == 4 && conn->retlen == 4) {
|
if (conn->retsize == 4 && conn->retlen == 4) {
|
||||||
conn->retsize = GET_32BIT(conn->retbuf);
|
conn->retsize = toint(GET_32BIT(conn->retbuf) + 4);
|
||||||
if (conn->retsize <= 0) {
|
if (conn->retsize <= 0) {
|
||||||
conn->retbuf = NULL;
|
conn->retbuf = NULL;
|
||||||
conn->retlen = 0;
|
conn->retlen = 0;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
conn->retsize += 4;
|
|
||||||
assert(conn->retbuf == conn->sizebuf);
|
assert(conn->retbuf == conn->sizebuf);
|
||||||
conn->retbuf = snewn(conn->retsize, char);
|
conn->retbuf = snewn(conn->retsize, char);
|
||||||
memcpy(conn->retbuf, conn->sizebuf, 4);
|
memcpy(conn->retbuf, conn->sizebuf, 4);
|
||||||
|
@ -450,7 +450,12 @@ static void add_keyfile(Filename *filename)
|
|||||||
MB_OK | MB_ICONERROR);
|
MB_OK | MB_ICONERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nkeys = GET_32BIT(keylist);
|
nkeys = toint(GET_32BIT(keylist));
|
||||||
|
if (nkeys < 0) {
|
||||||
|
MessageBox(NULL, "Received broken key list?!", APPNAME,
|
||||||
|
MB_OK | MB_ICONERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
p = keylist + 4;
|
p = keylist + 4;
|
||||||
keylistlen -= 4;
|
keylistlen -= 4;
|
||||||
|
|
||||||
@ -478,8 +483,8 @@ static void add_keyfile(Filename *filename)
|
|||||||
MB_OK | MB_ICONERROR);
|
MB_OK | MB_ICONERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
n = 4 + GET_32BIT(p);
|
n = toint(4 + GET_32BIT(p));
|
||||||
if (keylistlen < n) {
|
if (n < 0 || keylistlen < n) {
|
||||||
MessageBox(NULL, "Received broken key list?!", APPNAME,
|
MessageBox(NULL, "Received broken key list?!", APPNAME,
|
||||||
MB_OK | MB_ICONERROR);
|
MB_OK | MB_ICONERROR);
|
||||||
return;
|
return;
|
||||||
@ -495,8 +500,8 @@ static void add_keyfile(Filename *filename)
|
|||||||
MB_OK | MB_ICONERROR);
|
MB_OK | MB_ICONERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
n = 4 + GET_32BIT(p);
|
n = toint(4 + GET_32BIT(p));
|
||||||
if (keylistlen < n) {
|
if (n < 0 || keylistlen < n) {
|
||||||
MessageBox(NULL, "Received broken key list?!", APPNAME,
|
MessageBox(NULL, "Received broken key list?!", APPNAME,
|
||||||
MB_OK | MB_ICONERROR);
|
MB_OK | MB_ICONERROR);
|
||||||
return;
|
return;
|
||||||
@ -998,17 +1003,17 @@ static void answer_msg(void *msg)
|
|||||||
|
|
||||||
if (msgend < p+4)
|
if (msgend < p+4)
|
||||||
goto failure;
|
goto failure;
|
||||||
b.len = GET_32BIT(p);
|
b.len = toint(GET_32BIT(p));
|
||||||
|
if (b.len < 0 || b.len > msgend - (p+4))
|
||||||
|
goto failure;
|
||||||
p += 4;
|
p += 4;
|
||||||
if (msgend < p+b.len)
|
|
||||||
goto failure;
|
|
||||||
b.blob = p;
|
b.blob = p;
|
||||||
p += b.len;
|
p += b.len;
|
||||||
if (msgend < p+4)
|
if (msgend < p+4)
|
||||||
goto failure;
|
goto failure;
|
||||||
datalen = GET_32BIT(p);
|
datalen = toint(GET_32BIT(p));
|
||||||
p += 4;
|
p += 4;
|
||||||
if (msgend < p+datalen)
|
if (datalen < 0 || datalen > msgend - p)
|
||||||
goto failure;
|
goto failure;
|
||||||
data = p;
|
data = p;
|
||||||
key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
|
key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
|
||||||
@ -1081,9 +1086,9 @@ static void answer_msg(void *msg)
|
|||||||
sfree(key);
|
sfree(key);
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
commentlen = GET_32BIT(p);
|
commentlen = toint(GET_32BIT(p));
|
||||||
|
|
||||||
if (msgend < p+commentlen) {
|
if (commentlen < 0 || commentlen > msgend - p) {
|
||||||
freersakey(key);
|
freersakey(key);
|
||||||
sfree(key);
|
sfree(key);
|
||||||
goto failure;
|
goto failure;
|
||||||
@ -1120,9 +1125,9 @@ static void answer_msg(void *msg)
|
|||||||
|
|
||||||
if (msgend < p+4)
|
if (msgend < p+4)
|
||||||
goto failure;
|
goto failure;
|
||||||
alglen = GET_32BIT(p);
|
alglen = toint(GET_32BIT(p));
|
||||||
p += 4;
|
p += 4;
|
||||||
if (msgend < p+alglen)
|
if (alglen < 0 || alglen > msgend - p)
|
||||||
goto failure;
|
goto failure;
|
||||||
alg = p;
|
alg = p;
|
||||||
p += alglen;
|
p += alglen;
|
||||||
@ -1156,10 +1161,10 @@ static void answer_msg(void *msg)
|
|||||||
sfree(key);
|
sfree(key);
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
commlen = GET_32BIT(p);
|
commlen = toint(GET_32BIT(p));
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|
||||||
if (msgend < p+commlen) {
|
if (commlen < 0 || commlen > msgend - p) {
|
||||||
key->alg->freekey(key->data);
|
key->alg->freekey(key->data);
|
||||||
sfree(key);
|
sfree(key);
|
||||||
goto failure;
|
goto failure;
|
||||||
@ -1223,10 +1228,10 @@ static void answer_msg(void *msg)
|
|||||||
|
|
||||||
if (msgend < p+4)
|
if (msgend < p+4)
|
||||||
goto failure;
|
goto failure;
|
||||||
b.len = GET_32BIT(p);
|
b.len = toint(GET_32BIT(p));
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|
||||||
if (msgend < p+b.len)
|
if (b.len < 0 || b.len > msgend - p)
|
||||||
goto failure;
|
goto failure;
|
||||||
b.blob = p;
|
b.blob = p;
|
||||||
p += b.len;
|
p += b.len;
|
||||||
|
Loading…
Reference in New Issue
Block a user