]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - import.c
first pass
[PuTTY.git] / import.c
index ed57add09fc85186bc331b5aab2bdd3255d9b70b..adf68777dcd96de71faef9e3de49f5a0aed0ddf1 100644 (file)
--- a/import.c
+++ b/import.c
@@ -195,14 +195,16 @@ static int ber_read_id_len(void *source, int sourcelen,
        return -1;
 
     if (*p & 0x80) {
+        unsigned len;
        int n = *p & 0x7F;
        p++, sourcelen--;
        if (sourcelen < n)
            return -1;
-       *length = 0;
+       len = 0;
        while (n--)
-           *length = (*length << 8) | (*p++);
+           len = (len << 8) | (*p++);
        sourcelen -= n;
+        *length = toint(len);
     } else {
        *length = *p;
        p++, sourcelen--;
@@ -362,7 +364,8 @@ static struct openssh_pem_key *load_openssh_pem_key(const Filename *filename,
     struct openssh_pem_key *ret;
     FILE *fp = NULL;
     char *line = NULL;
-    char *errmsg, *p;
+    const char *errmsg;
+    char *p;
     int headers_done;
     char base64_bit[4];
     int base64_chars = 0;
@@ -382,8 +385,8 @@ static struct openssh_pem_key *load_openssh_pem_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;
     }
@@ -420,8 +423,8 @@ static struct openssh_pem_key *load_openssh_pem_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 */
@@ -570,7 +573,7 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
     int ret, id, len, flags;
     int i, num_integers;
     struct ssh2_userkey *retval = NULL;
-    char *errmsg;
+    const char *errmsg;
     unsigned char *blob;
     int blobsize = 0, blobptr, privptr;
     char *modptr = NULL;
@@ -656,7 +659,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
      * decrypt, if the key was encrypted. */
     ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags);
     p += ret;
-    if (ret < 0 || id != 16) {
+    if (ret < 0 || id != 16 || len < 0 ||
+        key->keyblob+key->keyblob_len-p < len) {
         errmsg = "ASN.1 decoding failure";
         retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
         goto error;
@@ -682,8 +686,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
         ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
                               &id, &len, &flags);
         p += ret;
-        if (ret < 0 || id != 2 || key->keyblob+key->keyblob_len-p < len ||
-            len != 1 || p[0] != 1) {
+        if (ret < 0 || id != 2 || len != 1 ||
+            key->keyblob+key->keyblob_len-p < len || p[0] != 1) {
             errmsg = "ASN.1 decoding failure";
             retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
             goto error;
@@ -693,7 +697,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
         ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
                               &id, &len, &flags);
         p += ret;
-        if (ret < 0 || id != 4 || key->keyblob+key->keyblob_len-p < len) {
+        if (ret < 0 || id != 4 || len < 0 ||
+            key->keyblob+key->keyblob_len-p < len) {
             errmsg = "ASN.1 decoding failure";
             retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
             goto error;
@@ -705,7 +710,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
         ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
                               &id, &len, &flags);
         p += ret;
-        if (ret < 0 || id != 0 || key->keyblob+key->keyblob_len-p < len) {
+        if (ret < 0 || id != 0 || len < 0 ||
+            key->keyblob+key->keyblob_len-p < len) {
             errmsg = "ASN.1 decoding failure";
             retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
             goto error;
@@ -713,7 +719,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
         ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
                               &id, &len, &flags);
         p += ret;
-        if (ret < 0 || id != 6 || key->keyblob+key->keyblob_len-p < len) {
+        if (ret < 0 || id != 6 || len < 0 ||
+            key->keyblob+key->keyblob_len-p < len) {
             errmsg = "ASN.1 decoding failure";
             retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
             goto error;
@@ -729,7 +736,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
         ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
                               &id, &len, &flags);
         p += ret;
-        if (ret < 0 || id != 1 || key->keyblob+key->keyblob_len-p < len) {
+        if (ret < 0 || id != 1 || len < 0 ||
+            key->keyblob+key->keyblob_len-p < len) {
             errmsg = "ASN.1 decoding failure";
             retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
             goto error;
@@ -737,7 +745,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
         ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
                               &id, &len, &flags);
         p += ret;
-        if (ret < 0 || id != 3 || key->keyblob+key->keyblob_len-p < len ||
+        if (ret < 0 || id != 3 || len < 0 ||
+            key->keyblob+key->keyblob_len-p < len ||
             len != ((((curve->fieldBits + 7) / 8) * 2) + 2)) {
             errmsg = "ASN.1 decoding failure";
             retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
@@ -752,7 +761,7 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
             goto error;
         }
         retkey->alg = alg;
-        blob = snewn((4+19 + 4+8 + 4+len) + (4+privlen), unsigned char);
+        blob = snewn((4+19 + 4+8 + 4+len) + (4+1+privlen), unsigned char);
         if (!blob) {
             sfree(retkey);
             errmsg = "out of memory";
@@ -772,12 +781,20 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
         PUT_32BIT(q, len); q += 4;
         memcpy(q, p, len); q += len;
 
-        PUT_32BIT(q, privlen);
-        memcpy(q+4, priv, privlen);
+        /*
+         * To be acceptable to our createkey(), the private blob must
+         * contain a valid mpint, i.e. without the top bit set. But
+         * the input private string may have the top bit set, so we
+         * prefix a zero byte to ensure createkey() doesn't fail for
+         * that reason.
+         */
+        PUT_32BIT(q, privlen+1);
+        q[4] = 0;
+        memcpy(q+5, priv, privlen);
 
         retkey->data = retkey->alg->createkey(retkey->alg,
                                               blob, q-blob,
-                                              q, 4+privlen);
+                                              q, 5+privlen);
 
         if (!retkey->data) {
             sfree(retkey);
@@ -804,7 +821,7 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
             ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
                                   &id, &len, &flags);
             p += ret;
-            if (ret < 0 || id != 2 ||
+            if (ret < 0 || id != 2 || len < 0 ||
                 key->keyblob+key->keyblob_len-p < len) {
                 errmsg = "ASN.1 decoding failure";
                 retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
@@ -877,6 +894,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
 
     } else {
         assert(0 && "Bad key type from load_openssh_pem_key");
+       errmsg = "Bad key type from load_openssh_pem_key";
+       goto error;
     }
 
     /*
@@ -910,7 +929,7 @@ int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key,
     int outlen;
     struct mpint_pos numbers[9];
     int nnumbers, pos, len, seqlen, i;
-    char *header, *footer;
+    const char *header, *footer;
     char zero[1];
     unsigned char iv[8];
     int ret = 0;
@@ -1283,7 +1302,8 @@ static struct openssh_new_key *load_openssh_new_key(const Filename *filename,
     struct openssh_new_key *ret;
     FILE *fp = NULL;
     char *line = NULL;
-    char *errmsg, *p;
+    const char *errmsg;
+    char *p;
     char base64_bit[4];
     int base64_chars = 0;
     const void *filedata;
@@ -1523,18 +1543,14 @@ struct ssh2_userkey *openssh_new_read(const Filename *filename,
                                       const char **errmsg_p)
 {
     struct openssh_new_key *key = load_openssh_new_key(filename, errmsg_p);
-    struct ssh2_userkey *retkey;
+    struct ssh2_userkey *retkey = NULL;
     int i;
     struct ssh2_userkey *retval = NULL;
-    char *errmsg;
-    unsigned char *blob;
-    int blobsize = 0;
+    const char *errmsg;
     unsigned checkint0, checkint1;
     const void *priv, *string;
     int privlen, stringlen, key_index;
-    const struct ssh_signkey *alg;
-
-    blob = NULL;
+    const struct ssh_signkey *alg = NULL;
 
     if (!key)
        return NULL;
@@ -1658,10 +1674,10 @@ struct ssh2_userkey *openssh_new_read(const Filename *filename,
                            (const unsigned char *)thiskey);
         if (key_index == key->key_wanted) {
             retkey = snew(struct ssh2_userkey);
+            retkey->comment = NULL;
             retkey->alg = alg;
             retkey->data = alg->openssh_createkey(alg, &thiskey, &thiskeylen);
             if (!retkey->data) {
-                sfree(retkey);
                 errmsg = "unable to create key data structure";
                 goto error;
             }
@@ -1698,11 +1714,16 @@ struct ssh2_userkey *openssh_new_read(const Filename *filename,
 
     errmsg = NULL;                     /* no error */
     retval = retkey;
+    retkey = NULL;                     /* prevent the free */
 
     error:
-    if (blob) {
-        smemclr(blob, blobsize);
-        sfree(blob);
+    if (retkey) {
+        sfree(retkey->comment);
+        if (retkey->data) {
+            assert(alg);
+            alg->freekey(retkey->data);
+        }
+        sfree(retkey);
     }
     smemclr(key->keyblob, key->keyblob_size);
     sfree(key->keyblob);
@@ -1981,7 +2002,8 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
     FILE *fp;
     char *line = NULL;
     int hdrstart, len;
-    char *errmsg, *p;
+    const char *errmsg;
+    char *p;
     int headers_done;
     char base64_bit[4];
     int base64_chars = 0;
@@ -2226,7 +2248,7 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
                                 const char **errmsg_p)
 {
     struct sshcom_key *key = load_sshcom_key(filename, errmsg_p);
-    char *errmsg;
+    const char *errmsg;
     int pos, len;
     const char prefix_rsa[] = "if-modn{sign{rsa";
     const char prefix_dsa[] = "dl-modp{sign{dsa";
@@ -2470,7 +2492,7 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key,
     int outlen;
     struct mpint_pos numbers[6];
     int nnumbers, initial_zero, pos, lenpos, i;
-    char *type;
+    const char *type;
     char *ciphertext;
     int cipherlen;
     int ret = 0;
@@ -2566,7 +2588,7 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key,
     pos += 4;                         /* length field, fill in later */
     pos += put_string(outblob+pos, type, strlen(type));
     {
-       char *ciphertype = passphrase ? "3des-cbc" : "none";
+       const char *ciphertype = passphrase ? "3des-cbc" : "none";
        pos += put_string(outblob+pos, ciphertype, strlen(ciphertype));
     }
     lenpos = pos;                     /* remember this position */