]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Fix a segfault in parsing OpenSSH private key files.
authorSimon Tatham <anakin@pobox.com>
Thu, 25 Feb 2016 20:22:23 +0000 (20:22 +0000)
committerSimon Tatham <anakin@pobox.com>
Mon, 29 Feb 2016 19:59:32 +0000 (19:59 +0000)
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
misc.c
misc.h

index bc35a4ab7d08b5aebb64332e7d0b84dad2f50bb2..466326f69da3a0e5586a0705cb9f0b2752457a8a 100644 (file)
--- 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 507837f941fd375c40d74fbd2f80132b76965342..d3a67f66ff8c8f55214e6af531fa5a2c1b700175 100644 (file)
--- 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 a16a2fa0f5896c7f19d009fbd10e2c9f84da3122..e53f89299cd70b15b4668dfcff4b29eed27496ef 100644 (file)
--- 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);