diff --git a/sshpubk.c b/sshpubk.c index fc999eb9..b9f67eb5 100644 --- a/sshpubk.c +++ b/sshpubk.c @@ -24,6 +24,18 @@ static int key_type_fp(FILE *fp); +/* + * Fairly arbitrary size limit on any public or private key blob. + * Chosen to match AGENT_MAX_MSGLEN, on the basis that any key too + * large to transfer over the ssh-agent protocol is probably too large + * to be useful in general. + * + * MAX_KEY_BLOB_LINES is the corresponding limit on the Public-Lines + * or Private-Lines header field in a key file. + */ +#define MAX_KEY_BLOB_SIZE 262144 +#define MAX_KEY_BLOB_LINES (MAX_KEY_BLOB_SIZE / 48) + static int rsa_ssh1_load_main(FILE * fp, RSAKey *key, bool pub_only, char **commentptr, const char *passphrase, const char **error) @@ -514,7 +526,9 @@ static bool read_blob(FILE *fp, int nlines, BinarySink *bs) int i, j, k; /* We expect at most 64 base64 characters, ie 48 real bytes, per line. */ + assert(nlines < MAX_KEY_BLOB_LINES); blob = snewn(48 * nlines, unsigned char); + for (i = 0; i < nlines; i++) { line = read_body(fp); if (!line) { @@ -584,6 +598,16 @@ static void ssh2_ppk_derivekey(ptrlen passphrase, uint8_t *key) ssh_hash_final(h, key + 20); } +static int userkey_parse_line_counter(const char *text) +{ + char *endptr; + unsigned long ul = strtoul(text, &endptr, 10); + if (*text && !*endptr && ul < MAX_KEY_BLOB_LINES) + return ul; + else + return -1; +} + ssh2_userkey *ssh2_load_userkey( const Filename *filename, const char *passphrase, const char **errorstr) { @@ -665,8 +689,10 @@ ssh2_userkey *ssh2_load_userkey( goto error; if ((b = read_body(fp)) == NULL) goto error; - i = atoi(b); + i = userkey_parse_line_counter(b); sfree(b); + if (i < 0) + goto error; public_blob = strbuf_new(); if (!read_blob(fp, i, BinarySink_UPCAST(public_blob))) goto error; @@ -676,8 +702,10 @@ ssh2_userkey *ssh2_load_userkey( goto error; if ((b = read_body(fp)) == NULL) goto error; - i = atoi(b); + i = userkey_parse_line_counter(b); sfree(b); + if (i < 0) + goto error; private_blob = strbuf_new_nm(); if (!read_blob(fp, i, BinarySink_UPCAST(private_blob))) goto error; @@ -1106,8 +1134,10 @@ bool ssh2_userkey_loadpub(const Filename *filename, char **algorithm, goto error; if ((b = read_body(fp)) == NULL) goto error; - i = atoi(b); + i = userkey_parse_line_counter(b); sfree(b); + if (i < 0) + goto error; if (!read_blob(fp, i, bs)) goto error;