From c195ff2b4f0e7cae40232ae71fe3100027a29061 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 25 Feb 2016 20:22:23 +0000 Subject: [PATCH] Fix a segfault in parsing OpenSSH private key files. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The initial test for a line ending with "PRIVATE KEY-----" failed to take into account the possibility that the line might be shorter than that. Fixed by introducing a new library function strendswith(), and strstartswith() for good measure, and using that. Thanks to Hanno Böck for spotting this, with the aid of AFL. (cherry picked from commit fa7b23ce9025daba08e86bb934fc430099792b9a) Conflicts: misc.c misc.h (cherry-picker's note: the conflicts were only due to other functions introduced on trunk just next to the ones introduced by this commit) --- import.c | 8 ++++---- misc.c | 11 +++++++++++ misc.h | 2 ++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/import.c b/import.c index bc35a4ab..466326f6 100644 --- a/import.c +++ b/import.c @@ -345,8 +345,8 @@ static struct openssh_key *load_openssh_key(const Filename *filename, goto error; } strip_crlf(line); - if (0 != strncmp(line, "-----BEGIN ", 11) || - 0 != strcmp(line+strlen(line)-16, "PRIVATE KEY-----")) { + if (!strstartswith(line, "-----BEGIN ") || + !strendswith(line, "PRIVATE KEY-----")) { errmsg = "file does not begin with OpenSSH key header"; goto error; } @@ -369,8 +369,8 @@ static struct openssh_key *load_openssh_key(const Filename *filename, goto error; } strip_crlf(line); - if (0 == strncmp(line, "-----END ", 9) && - 0 == strcmp(line+strlen(line)-16, "PRIVATE KEY-----")) { + if (strstartswith(line, "-----END ") && + strendswith(line, "PRIVATE KEY-----")) { sfree(line); line = NULL; break; /* done */ diff --git a/misc.c b/misc.c index 507837f9..d3a67f66 100644 --- a/misc.c +++ b/misc.c @@ -1035,3 +1035,14 @@ int smemeq(const void *av, const void *bv, size_t len) * we want to return 1, so then we can just shift down. */ return (0x100 - val) >> 8; } + +int strstartswith(const char *s, const char *t) +{ + return !memcmp(s, t, strlen(t)); +} + +int strendswith(const char *s, const char *t) +{ + size_t slen = strlen(s), tlen = strlen(t); + return slen >= tlen && !strcmp(s + (slen - tlen), t); +} diff --git a/misc.h b/misc.h index a16a2fa0..e53f8929 100644 --- a/misc.h +++ b/misc.h @@ -51,6 +51,8 @@ wchar_t *dup_mb_to_wc(int codepage, int flags, const char *string); int toint(unsigned); char *fgetline(FILE *fp); +int strstartswith(const char *s, const char *t); +int strendswith(const char *s, const char *t); void base64_encode_atom(unsigned char *data, int n, char *out); int base64_decode_atom(char *atom, unsigned char *out); -- 2.45.2