Fix a couple of code paths on which, if fxp_readdir returned an error,
[sgt/putty] / import.c
index 20a77e5..ce957bc 100644 (file)
--- a/import.c
+++ b/import.c
@@ -290,7 +290,7 @@ static int ssh2_read_mpint(void *data, int len, struct mpint_pos *ret)
     if (len < 4)
         goto error;
     bytes = GET_32BIT(d);
-    if (len < 4+bytes)
+    if (bytes < 0 || len-4 < bytes)
         goto error;
 
     ret->start = d + 4;
@@ -321,7 +321,7 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
                                            const char **errmsg_p)
 {
     struct openssh_key *ret;
-    FILE *fp;
+    FILE *fp = NULL;
     char *line = NULL;
     char *errmsg, *p;
     int headers_done;
@@ -334,7 +334,7 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
     ret->encrypted = 0;
     memset(ret->iv, 0, sizeof(ret->iv));
 
-    fp = f_open(*filename, "r", FALSE);
+    fp = f_open(filename, "r", FALSE);
     if (!fp) {
        errmsg = "unable to open key file";
        goto error;
@@ -358,7 +358,7 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
        errmsg = "unrecognised key type";
        goto error;
     }
-    memset(line, 0, strlen(line));
+    smemclr(line, strlen(line));
     sfree(line);
     line = NULL;
 
@@ -442,17 +442,20 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
                     memcpy(ret->keyblob + ret->keyblob_len, out, len);
                     ret->keyblob_len += len;
 
-                    memset(out, 0, sizeof(out));
+                    smemclr(out, sizeof(out));
                 }
 
                p++;
            }
        }
-       memset(line, 0, strlen(line));
+       smemclr(line, strlen(line));
        sfree(line);
        line = NULL;
     }
 
+    fclose(fp);
+    fp = NULL;
+
     if (ret->keyblob_len == 0 || !ret->keyblob) {
        errmsg = "key body not present";
        goto error;
@@ -463,26 +466,27 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
        goto error;
     }
 
-    memset(base64_bit, 0, sizeof(base64_bit));
+    smemclr(base64_bit, sizeof(base64_bit));
     if (errmsg_p) *errmsg_p = NULL;
     return ret;
 
     error:
     if (line) {
-       memset(line, 0, strlen(line));
+       smemclr(line, strlen(line));
        sfree(line);
        line = NULL;
     }
-    memset(base64_bit, 0, sizeof(base64_bit));
+    smemclr(base64_bit, sizeof(base64_bit));
     if (ret) {
        if (ret->keyblob) {
-            memset(ret->keyblob, 0, ret->keyblob_size);
+            smemclr(ret->keyblob, ret->keyblob_size);
             sfree(ret->keyblob);
         }
-        memset(ret, 0, sizeof(*ret));
+        smemclr(ret, sizeof(*ret));
        sfree(ret);
     }
     if (errmsg_p) *errmsg_p = errmsg;
+    if (fp) fclose(fp);
     return NULL;
 }
 
@@ -494,9 +498,9 @@ int openssh_encrypted(const Filename *filename)
     if (!key)
        return 0;
     ret = key->encrypted;
-    memset(key->keyblob, 0, key->keyblob_size);
+    smemclr(key->keyblob, key->keyblob_size);
     sfree(key->keyblob);
-    memset(key, 0, sizeof(*key));
+    smemclr(key, sizeof(*key));
     sfree(key);
     return ret;
 }
@@ -564,8 +568,8 @@ struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
            aes_free_context(ctx);
        }
 
-        memset(&md5c, 0, sizeof(md5c));
-        memset(keybuf, 0, sizeof(keybuf));
+        smemclr(&md5c, sizeof(md5c));
+        smemclr(keybuf, sizeof(keybuf));
     }
 
     /*
@@ -588,12 +592,13 @@ struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
     
     p = key->keyblob;
 
-    /* Expect the SEQUENCE header. Take its absence as a failure to decrypt. */
+    /* Expect the SEQUENCE header. Take its absence as a failure to
+     * 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) {
        errmsg = "ASN.1 decoding failure";
-       retval = SSH2_WRONG_PASSPHRASE;
+        retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
        goto error;
     }
 
@@ -625,7 +630,7 @@ struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
        if (ret < 0 || id != 2 ||
            key->keyblob+key->keyblob_len-p < len) {
            errmsg = "ASN.1 decoding failure";
-           retval = SSH2_WRONG_PASSPHRASE;
+           retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL;
            goto error;
        }
 
@@ -698,12 +703,12 @@ struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
 
     error:
     if (blob) {
-        memset(blob, 0, blobsize);
+        smemclr(blob, blobsize);
         sfree(blob);
     }
-    memset(key->keyblob, 0, key->keyblob_size);
+    smemclr(key->keyblob, key->keyblob_size);
     sfree(key->keyblob);
-    memset(key, 0, sizeof(*key));
+    smemclr(key, sizeof(*key));
     sfree(key);
     if (errmsg_p) *errmsg_p = errmsg;
     return retval;
@@ -911,15 +916,15 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
         */
        des3_encrypt_pubkey_ossh(keybuf, iv, outblob, outlen);
 
-        memset(&md5c, 0, sizeof(md5c));
-        memset(keybuf, 0, sizeof(keybuf));
+        smemclr(&md5c, sizeof(md5c));
+        smemclr(keybuf, sizeof(keybuf));
     }
 
     /*
      * And save it. We'll use Unix line endings just in case it's
      * subsequently transferred in binary mode.
      */
-    fp = f_open(*filename, "wb", TRUE);      /* ensure Unix line endings */
+    fp = f_open(filename, "wb", TRUE);      /* ensure Unix line endings */
     if (!fp)
        goto error;
     fputs(header, fp);
@@ -936,19 +941,19 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
 
     error:
     if (outblob) {
-        memset(outblob, 0, outlen);
+        smemclr(outblob, outlen);
         sfree(outblob);
     }
     if (spareblob) {
-        memset(spareblob, 0, sparelen);
+        smemclr(spareblob, sparelen);
         sfree(spareblob);
     }
     if (privblob) {
-        memset(privblob, 0, privlen);
+        smemclr(privblob, privlen);
         sfree(privblob);
     }
     if (pubblob) {
-        memset(pubblob, 0, publen);
+        smemclr(pubblob, publen);
         sfree(pubblob);
     }
     return ret;
@@ -1053,7 +1058,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
     ret->keyblob = NULL;
     ret->keyblob_len = ret->keyblob_size = 0;
 
-    fp = f_open(*filename, "r", FALSE);
+    fp = f_open(filename, "r", FALSE);
     if (!fp) {
        errmsg = "unable to open key file";
        goto error;
@@ -1067,7 +1072,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
        errmsg = "file does not begin with ssh.com key header";
        goto error;
     }
-    memset(line, 0, strlen(line));
+    smemclr(line, strlen(line));
     sfree(line);
     line = NULL;
 
@@ -1112,7 +1117,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
                len += line2len - 1;
                assert(!line[len]);
 
-               memset(line2, 0, strlen(line2));
+               smemclr(line2, strlen(line2));
                sfree(line2);
                line2 = NULL;
             }
@@ -1158,7 +1163,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
                p++;
            }
        }
-       memset(line, 0, strlen(line));
+       smemclr(line, strlen(line));
        sfree(line);
        line = NULL;
     }
@@ -1173,16 +1178,16 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
 
     error:
     if (line) {
-       memset(line, 0, strlen(line));
+       smemclr(line, strlen(line));
        sfree(line);
        line = NULL;
     }
     if (ret) {
        if (ret->keyblob) {
-            memset(ret->keyblob, 0, ret->keyblob_size);
+            smemclr(ret->keyblob, ret->keyblob_size);
             sfree(ret->keyblob);
         }
-        memset(ret, 0, sizeof(*ret));
+        smemclr(ret, sizeof(*ret));
        sfree(ret);
     }
     if (errmsg_p) *errmsg_p = errmsg;
@@ -1222,9 +1227,9 @@ int sshcom_encrypted(const Filename *filename, char **comment)
 
     done:
     *comment = dupstr(key->comment);
-    memset(key->keyblob, 0, key->keyblob_size);
+    smemclr(key->keyblob, key->keyblob_size);
     sfree(key->keyblob);
-    memset(key, 0, sizeof(*key));
+    smemclr(key, sizeof(*key));
     sfree(key);
     return answer;
 }
@@ -1390,8 +1395,8 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
        des3_decrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext,
                                 cipherlen);
 
-        memset(&md5c, 0, sizeof(md5c));
-        memset(keybuf, 0, sizeof(keybuf));
+        smemclr(&md5c, sizeof(md5c));
+        smemclr(keybuf, sizeof(keybuf));
 
         /*
          * Hereafter we return WRONG_PASSPHRASE for any parsing
@@ -1494,12 +1499,12 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
 
     error:
     if (blob) {
-        memset(blob, 0, blobsize);
+        smemclr(blob, blobsize);
         sfree(blob);
     }
-    memset(key->keyblob, 0, key->keyblob_size);
+    smemclr(key->keyblob, key->keyblob_size);
     sfree(key->keyblob);
-    memset(key, 0, sizeof(*key));
+    smemclr(key, sizeof(*key));
     sfree(key);
     if (errmsg_p) *errmsg_p = errmsg;
     return ret;
@@ -1664,15 +1669,15 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key,
        des3_encrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext,
                                 cipherlen);
 
-        memset(&md5c, 0, sizeof(md5c));
-        memset(keybuf, 0, sizeof(keybuf));
+        smemclr(&md5c, sizeof(md5c));
+        smemclr(keybuf, sizeof(keybuf));
     }
 
     /*
      * And save it. We'll use Unix line endings just in case it's
      * subsequently transferred in binary mode.
      */
-    fp = f_open(*filename, "wb", TRUE);      /* ensure Unix line endings */
+    fp = f_open(filename, "wb", TRUE);      /* ensure Unix line endings */
     if (!fp)
        goto error;
     fputs("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n", fp);
@@ -1700,15 +1705,15 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key,
 
     error:
     if (outblob) {
-        memset(outblob, 0, outlen);
+        smemclr(outblob, outlen);
         sfree(outblob);
     }
     if (privblob) {
-        memset(privblob, 0, privlen);
+        smemclr(privblob, privlen);
         sfree(privblob);
     }
     if (pubblob) {
-        memset(pubblob, 0, publen);
+        smemclr(pubblob, publen);
         sfree(pubblob);
     }
     return ret;