From 1b8f730801c6ffc9434251c2f3eef96a6243fb75 Mon Sep 17 00:00:00 2001
From: Alexander Lamaison <awl03@doc.ic.ac.uk>
Date: Tue, 14 Jul 2009 13:19:14 +0100
Subject: [PATCH] Replaced calls to OpenSSL FILE-pointer private-key functions.

Calling a function with a FILE* argument in a DLL causes problems on Windows.  Instead the keys are read into memory by libssh2 and passed to the OpenSSL function that take BIO* arguments.
---
 src/openssl.c |   99 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 87 insertions(+), 12 deletions(-)

diff --git a/src/openssl.c b/src/openssl.c
index 87e86dd..5b3981b 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -212,12 +212,70 @@ passphrase_cb(char *buf, int size, int rwflag, char *passphrase)
     return passphrase_len;
 }
 
+static int
+read_file_into_string(char ** key, LIBSSH2_SESSION * session, FILE * fp)
+{
+    long size;
+    size_t read;
+
+    *key = NULL;
+
+    fseek(fp, 0, SEEK_END);
+    size = ftell(fp);
+    if (size < 0) {
+        return -1;
+    }
+    fseek(fp, 0, SEEK_SET);
+
+    size *= sizeof(char); /* TODO: guard for maximum allowed file size */
+
+    *key = LIBSSH2_ALLOC(session, size + 1);
+    if (!*key) {
+        return -1;
+    }
+
+    read = fread(*key, 1, size, fp);
+    if (read != size) {
+        LIBSSH2_FREE(session, *key);
+        return -1;
+    }
+
+    (*key)[size] = '\0';
+    return 0;
+}
+
+static int
+read_rsa_from_file(libssh2_rsa_ctx ** rsa, LIBSSH2_SESSION * session,
+                   FILE * fp, unsigned const char *passphrase)
+{
+    char * key;
+    BIO * bp;
+
+    *rsa = NULL;
+
+    if(read_file_into_string(&key, session, fp)) {
+        return -1;
+    }
+
+    bp = BIO_new_mem_buf(key, -1);
+    if (!bp) {
+        LIBSSH2_FREE(session, key);
+        return -1;
+    }
+
+    *rsa = PEM_read_bio_RSAPrivateKey(bp, NULL, (void *) passphrase_cb,
+                                      (void *) passphrase);
+
+    BIO_free(bp);
+    LIBSSH2_FREE(session, key);
+    return (*rsa) ? 0 : -1;
+}
+
 int
 _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
                          LIBSSH2_SESSION * session,
                          FILE * fp, unsigned const char *passphrase)
 {
-    (void) session;
     if (!EVP_get_cipherbyname("des")) {
 /* If this cipher isn't loaded it's a pretty good indication that none are.
  * I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
@@ -225,12 +283,35 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
  */
         OpenSSL_add_all_ciphers();
     }
-    *rsa = PEM_read_RSAPrivateKey(fp, NULL, (void *) passphrase_cb,
-                                  (void *) passphrase);
-    if (!*rsa) {
+
+    return read_rsa_from_file(rsa, session, fp, passphrase);
+}
+
+static int
+read_dsa_from_file(libssh2_dsa_ctx ** dsa, LIBSSH2_SESSION * session,
+                   FILE * fp, unsigned const char *passphrase)
+{
+    char * key;
+    BIO * bp;
+
+    *dsa = NULL;
+
+    if(read_file_into_string(&key, session, fp)) {
         return -1;
     }
-    return 0;
+
+    bp = BIO_new_mem_buf(key, -1);
+    if (!bp) {
+        LIBSSH2_FREE(session, key);
+        return -1;
+    }
+
+    *dsa = PEM_read_bio_DSAPrivateKey(bp, NULL, (void *) passphrase_cb,
+                                      (void *) passphrase);
+
+    BIO_free(bp);
+    LIBSSH2_FREE(session, key);
+    return (*dsa) ? 0 : -1;
 }
 
 int
@@ -238,7 +319,6 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
                          LIBSSH2_SESSION * session,
                          FILE * fp, unsigned const char *passphrase)
 {
-    (void) session;
     if (!EVP_get_cipherbyname("des")) {
 /* If this cipher isn't loaded it's a pretty good indication that none are.
  * I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#(
@@ -246,12 +326,7 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
  */
         OpenSSL_add_all_ciphers();
     }
-    *dsa = PEM_read_DSAPrivateKey(fp, NULL, (void *) passphrase_cb,
-                                  (void *) passphrase);
-    if (!*dsa) {
-        return -1;
-    }
-    return 0;
+    return read_dsa_from_file(dsa, session, fp, passphrase);
 }
 
 int
-- 
1.6.3.2.1299.gee46c

