Thanks for your feedback, Peter, Daniel and Alex.

Peter, I totally understand your concern. I took my time to reply because I
tried to do it right, but I have to be realistic here and honest with
myself.

I feel like reading the keys from memory to implement the same logic for
libgcrypt might not be too complicated, unfortunately my C skills are
really rusty, and I don't think I'm the right person to make it right. On
the other hand, I'll be super glad to assist anybody that can help me, we
can do a remote pair session or talk over skype or whatever is best to
reach a better solution.

As a sort term solution, I added the necessary methods to scr/libgcrypt.c
to return an unimplemented error, like it already does parting public keys
from private key files.

I'd still love to see this merged into the main project, I think it would
be really useful for people implemented on top of libssh2, and I'm at your
disposal for anything I can help.

This is the new patch with those methods inside libgcrypt:

https://github.com/calavera/libssh2/commit/c031101aede6195376415178a5fcce80c556a8e3
https://github.com/calavera/libssh2/commit/c031101aede6195376415178a5fcce80c556a8e3.patch

And this is the raw patch for everybody in the list to see:

>From c031101aede6195376415178a5fcce80c556a8e3 Mon Sep 17 00:00:00 2001
From: David Calavera <[email protected]>
Date: Mon, 1 Sep 2014 15:54:05 -0700
Subject: [PATCH] Allow authentication keys to be passed in memory.

All credits go to Joe Turpin, I'm just reaplying and cleaning his
patch:http://www.libssh2.org/mail/libssh2-devel-archive-2012-01/0015.shtml

* Adds libssh2_userauth_publickey_frommemory macro for
libssh2_userauth_publickey_frommemory_ex.
* Use an unimplemented error for extracting keys from memory with libgcrypt.
---
 docs/libssh2_userauth_publickey_frommemory.3    |  22 +++
 docs/libssh2_userauth_publickey_frommemory_ex.3 |  55 ++++++
 include/libssh2.h                               |  20 ++
 src/crypto.h                                    |  16 ++
 src/hostkey.c                                   |  66 +++++++
 src/libgcrypt.c                                 |  37 ++++
 src/libssh2_priv.h                              |   3 +
 src/openssl.c                                   | 121 +++++++++++++
 src/userauth.c                                  | 231 ++++++++++++++++++++++++
 9 files changed, 571 insertions(+)
 create mode 100644 docs/libssh2_userauth_publickey_frommemory.3
 create mode 100644 docs/libssh2_userauth_publickey_frommemory_ex.3

diff --git a/docs/libssh2_userauth_publickey_frommemory.3
b/docs/libssh2_userauth_publickey_frommemory.3
new file mode 100644
index 0000000..e464e71
--- /dev/null
+++ b/docs/libssh2_userauth_publickey_frommemory.3
@@ -0,0 +1,22 @@
+.TH libssh2_userauth_publickey_frommemory 3 "1 Sep 2014" "libssh2
1.5" "libssh2 manual"
+.SH NAME
+libssh2_userauth_publickey_frommemory - convenience macro for
\fIlibssh2_userauth_publickey_frommemory_ex(3)\fP calls
+.SH SYNOPSIS
+#include <libssh2.h>
+
+int
+libssh2_userauth_publickey_frommemory(LIBSSH2_SESSION *session,
+                                      const char *username,
+                                      const char *publickey,
+                                      const char *privatekey,
+                                      const char *passphrase);
+
+.SH DESCRIPTION
+This is a macro defined in a public libssh2 header file that is using the
+underlying function \fIlibssh2_userauth_publickey_frommemory_ex(3)\fP.
+.SH RETURN VALUE
+See \fIlibssh2_userauth_publickey_frommemory_ex(3)\fP
+.SH ERRORS
+See \fIlibssh2_userauth_publickey_frommemory_ex(3)\fP
+.SH SEE ALSO
+.BR libssh2_userauth_publickey_frommemory_ex(3)
diff --git a/docs/libssh2_userauth_publickey_frommemory_ex.3
b/docs/libssh2_userauth_publickey_frommemory_ex.3
new file mode 100644
index 0000000..6faf5d1
--- /dev/null
+++ b/docs/libssh2_userauth_publickey_frommemory_ex.3
@@ -0,0 +1,55 @@
+.TH libssh2_userauth_publickey_frommemory_ex 3 "1 Sep 2014" "libssh2
1.5" "libssh2 manual"
+.SH NAME
+libssh2_userauth_publickey_frommemory_ex - authenticate a session
with a public key, read from memory
+.SH SYNOPSIS
+#include <libssh2.h>
+
+.nf
+int libssh2_userauth_publickey_frommemory_ex(LIBSSH2_SESSION *session,
+                                           const char *username,
+                                           unsigned int username_len,
+                                           const char *publickeydata,
+                                           size_t publickeydata_len,
+                                           const char *privatekeydata,
+                                           size_t privatekeydata_len,
+                                           const char *passphrase);
+.SH DESCRIPTION
+\fIsession\fP - Session instance as returned by
+.BR libssh2_session_init_ex(3)
+
+\fIusername\fP - Remote user name to authenticate as.
+
+\fIusername_len\fP - Length of username.
+
+\fIpublickeydata\fP - Buffer containing the contents of a public key file.
+
+\fIpublickeydata_len\fP - Length of public key data.
+
+\fIprivatekeydata\fP - Buffer containing the contents of a private key file.
+
+\fIprivatekeydata_len\fP - Length of private key data.
+
+\fIpassphrase\fP - Passphrase to use when decoding private key file.
+
+Attempt public key authentication using a PEM encoded private key
file stored in memory.
+
+.SH RETURN VALUE
+Return 0 on success or negative on failure.  It returns
+LIBSSH2_ERROR_EAGAIN when it would otherwise block. While
+LIBSSH2_ERROR_EAGAIN is a negative number, it isn't really a failure per se.
+
+.SH ERRORS
+\fILIBSSH2_ERROR_ALLOC\fP -  An internal memory allocation call failed.
+
+\fILIBSSH2_ERROR_SOCKET_SEND\fP - Unable to send data on socket.
+
+\fILIBSSH2_ERROR_SOCKET_TIMEOUT\fP -
+
+\fILIBSSH2_ERROR_PUBLICKEY_UNVERIFIED\fP - The username/public key
+combination was invalid.
+
+\fILIBSSH2_ERROR_AUTHENTICATION_FAILED\fP - Authentication using the supplied
+public key was not accepted.
+
+.SH SEE ALSO
+.BR libssh2_session_init_ex(3)
diff --git a/include/libssh2.h b/include/libssh2.h
index 565bf06..6e519db 100644
--- a/include/libssh2.h
+++ b/include/libssh2.h
@@ -576,6 +576,26 @@
libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
                                         (username),                     \
                                         (unsigned int)strlen(username))

+LIBSSH2_API int
+libssh2_userauth_publickey_frommemory_ex(LIBSSH2_SESSION *session,
+                                      const char *username,
+                                      unsigned int username_len,
+                                      const char *publickeyfiledata,
+                                      size_t publickeyfiledata_len,
+                                      const char *privatekeyfiledata,
+                                      size_t privatekeyfiledata_len,
+                                      const char *passphrase);
+
+#define libssh2_userauth_publickey_frommemory(session, username, publickey, \
+                                              privatekey, passphrase) \
+ libssh2_userauth_publickey_frommemory_ex((session), (username), \
+                                          (unsigned int)strlen(username),   \
+                                          (publickey),                      \
+                                          (unsigned int)strlen(publickey),  \
+                                          (privatekey),                     \
+                                          (unsigned int)strlen(privatekey), \
+                                          (passphrase))
+
 /*
  * response_callback is provided with filled by library prompts array,
  * but client must allocate and fill individual responses. Responses
diff --git a/src/crypto.h b/src/crypto.h
index a615bb1..05f5a5c 100644
--- a/src/crypto.h
+++ b/src/crypto.h
@@ -80,6 +80,10 @@ int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
                            size_t hash_len,
                            unsigned char **signature,
                            size_t *signature_len);
+int _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa,
+                                        LIBSSH2_SESSION * session,
+                                        const char *filedata, size_t
filedata_len,
+                                        unsigned const char *passphrase);

 #if LIBSSH2_DSA
 int _libssh2_dsa_new(libssh2_dsa_ctx ** dsa,
@@ -102,6 +106,10 @@ int _libssh2_dsa_sha1_verify(libssh2_dsa_ctx * dsactx,
 int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
                            const unsigned char *hash,
                            unsigned long hash_len, unsigned char *sig);
+int _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa,
+                                        LIBSSH2_SESSION * session,
+                                        const char *filedata, size_t
filedata_len,
+                                        unsigned const char *passphrase);
 #endif

 int _libssh2_cipher_init(_libssh2_cipher_ctx * h,
@@ -120,6 +128,14 @@ int _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
                               size_t *pubkeydata_len,
                               const char *privatekey,
                               const char *passphrase);
+int _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
+                                    unsigned char **method,
+                                    size_t *method_len,
+                                    unsigned char **pubkeydata,
+                                    size_t *pubkeydata_len,
+                                    const char *privatekeydata,
+                                    size_t privatekeydata_len,
+                                    const char *passphrase);

 void _libssh2_init_aes_ctr(void);

diff --git a/src/hostkey.c b/src/hostkey.c
index 753563d..02d085a 100644
--- a/src/hostkey.c
+++ b/src/hostkey.c
@@ -131,6 +131,38 @@ hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION * session,
 }

 /*
+ * hostkey_method_ssh_rsa_initPEMFromMemory
+ *
+ * Load a Private Key from a memory
+ */
+static int
+hostkey_method_ssh_rsa_initPEMFromMemory(LIBSSH2_SESSION * session,
+                                         const char *privkeyfiledata,
+                                         size_t privkeyfiledata_len,
+                                         unsigned const char *passphrase,
+                                         void **abstract)
+{
+    libssh2_rsa_ctx *rsactx;
+    int ret;
+
+    if (*abstract) {
+        hostkey_method_ssh_rsa_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    ret = _libssh2_rsa_new_private_frommemory(&rsactx, session,
+                                              privkeyfiledata,
+                                              privkeyfiledata_len, passphrase);
+    if (ret) {
+        return -1;
+    }
+
+    *abstract = rsactx;
+
+    return 0;
+}
+
+/*
  * hostkey_method_ssh_rsa_sign
  *
  * Verify signature created by remote
@@ -208,6 +240,7 @@ static const LIBSSH2_HOSTKEY_METHOD
hostkey_method_ssh_rsa = {
     MD5_DIGEST_LENGTH,
     hostkey_method_ssh_rsa_init,
     hostkey_method_ssh_rsa_initPEM,
+    hostkey_method_ssh_rsa_initPEMFromMemory,
     hostkey_method_ssh_rsa_sig_verify,
     hostkey_method_ssh_rsa_signv,
     NULL,                       /* encrypt */
@@ -306,6 +339,38 @@ hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION * session,
 }

 /*
+ * hostkey_method_ssh_dss_initPEMFromMemory
+ *
+ * Load a Private Key from memory
+ */
+static int
+hostkey_method_ssh_dss_initPEMFromMemory(LIBSSH2_SESSION * session,
+                                         const char *privkeyfiledata,
+                                         size_t privkeyfiledata_len,
+                                         unsigned const char *passphrase,
+                                         void **abstract)
+{
+    libssh2_dsa_ctx *dsactx;
+    int ret;
+
+    if (*abstract) {
+        hostkey_method_ssh_dss_dtor(session, abstract);
+        *abstract = NULL;
+    }
+
+    ret = _libssh2_dsa_new_private_frommemory(&dsactx, session,
+                                              privkeyfiledata,
+                                              privkeyfiledata_len, passphrase);
+    if (ret) {
+        return -1;
+    }
+
+    *abstract = dsactx;
+
+    return 0;
+}
+
+/*
  * libssh2_hostkey_method_ssh_dss_sign
  *
  * Verify signature created by remote
@@ -392,6 +457,7 @@ static const LIBSSH2_HOSTKEY_METHOD
hostkey_method_ssh_dss = {
     MD5_DIGEST_LENGTH,
     hostkey_method_ssh_dss_init,
     hostkey_method_ssh_dss_initPEM,
+    hostkey_method_ssh_dss_initPEMFromMemory,
     hostkey_method_ssh_dss_sig_verify,
     hostkey_method_ssh_dss_signv,
     NULL,                       /* encrypt */
diff --git a/src/libgcrypt.c b/src/libgcrypt.c
index 7d09ffb..e85aecd 100644
--- a/src/libgcrypt.c
+++ b/src/libgcrypt.c
@@ -150,6 +150,17 @@ _libssh2_dsa_new(libssh2_dsa_ctx ** dsactx,
 }

 int
+_libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa,
+                                    LIBSSH2_SESSION * session,
+                                    const char *filedata, size_t filedata_len,
+                                    unsigned const char *passphrase)
+{
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                         "Unable to extract private key from memory: "
+                         "Method unimplemented in libgcrypt backend");
+}
+
+int
 _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
                          LIBSSH2_SESSION * session,
                          const char *filename, unsigned const char *passphrase)
@@ -252,6 +263,17 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
 }

 int
+_libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa,
+                                    LIBSSH2_SESSION * session,
+                                    const char *filedata, size_t filedata_len,
+                                    unsigned const char *passphrase)
+{
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                         "Unable to extract private key from memory: "
+                         "Method unimplemented in libgcrypt backend");
+}
+
+int
 _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
                          LIBSSH2_SESSION * session,
                          const char *filename, unsigned const char *passphrase)
@@ -567,6 +589,21 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
 }

 int
+_libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
+                                unsigned char **method,
+                                size_t *method_len,
+                                unsigned char **pubkeydata,
+                                size_t *pubkeydata_len,
+                                const char *privatekeydata,
+                                size_t privatekeydata_len,
+                                const char *passphrase)
+{
+    return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
+                         "Unable to extract public key from private
key in memory: "
+                         "Method unimplemented in libgcrypt backend");
+}
+
+int
 _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
                           unsigned char **method,
                           size_t *method_len,
diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h
index 00ed240..0274d83 100644
--- a/src/libssh2_priv.h
+++ b/src/libssh2_priv.h
@@ -853,6 +853,9 @@ struct _LIBSSH2_HOSTKEY_METHOD
                  size_t hostkey_data_len, void **abstract);
     int (*initPEM) (LIBSSH2_SESSION * session, const char *privkeyfile,
                     unsigned const char *passphrase, void **abstract);
+    int (*initPEMFromMemory) (LIBSSH2_SESSION * session,
+                              const char *privkeyfiledata, size_t
privkeyfiledata_len,
+                              unsigned const char *passphrase, void
**abstract);
     int (*sig_verify) (LIBSSH2_SESSION * session, const unsigned char *sig,
                        size_t sig_len, const unsigned char *m,
                        size_t m_len, void **abstract);
diff --git a/src/openssl.c b/src/openssl.c
index 056b0b7..2e31472 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -388,6 +388,28 @@ typedef void * (*pem_read_bio_func)(BIO *, void
**, pem_password_cb *,
                                     void * u);

 static int
+read_private_key_from_memory(void ** key_ctx,
+                             pem_read_bio_func read_private_key,
+                             const char * filedata,
+                             size_t filedata_len,
+                             unsigned const char *passphrase)
+{
+    BIO * bp;
+
+    *key_ctx = NULL;
+
+    bp = BIO_new_mem_buf(filedata, filedata_len);
+    if (!bp) {
+        return -1;
+    }
+    *key_ctx = read_private_key(bp, NULL, (pem_password_cb *) passphrase_cb,
+                                (void *) passphrase);
+
+    BIO_free(bp);
+    return (*key_ctx) ? 0 : -1;
+}
+
+static int
 read_private_key_from_file(void ** key_ctx,
                            pem_read_bio_func read_private_key,
                            const char * filename,
@@ -409,6 +431,22 @@ read_private_key_from_file(void ** key_ctx,
     return (*key_ctx) ? 0 : -1;
 }

+ int
+_libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx ** rsa,
+                                    LIBSSH2_SESSION * session,
+                                    const char *filedata, size_t filedata_len,
+                                    unsigned const char *passphrase)
+{
+    pem_read_bio_func read_rsa =
+        (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey;
+    (void) session;
+
+    _libssh2_init_if_needed();
+
+    return read_private_key_from_memory((void **) rsa, read_rsa,
+                                        filedata, filedata_len, passphrase);
+}
+
 int
 _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
                          LIBSSH2_SESSION * session,
@@ -426,6 +464,22 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,

 #if LIBSSH2_DSA
 int
+_libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx ** dsa,
+                                    LIBSSH2_SESSION * session,
+                                    const char *filedata, size_t filedata_len,
+                                    unsigned const char *passphrase)
+{
+    pem_read_bio_func read_dsa =
+        (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
+    (void) session;
+
+    _libssh2_init_if_needed();
+
+    return read_private_key_from_memory((void **) dsa, read_dsa,
+                                        filedata, filedata_len, passphrase);
+}
+
+int
 _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
                          LIBSSH2_SESSION * session,
                          const char *filename, unsigned const char *passphrase)
@@ -817,4 +871,71 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
     return st;
 }

+int
+_libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
+                                unsigned char **method,
+                                size_t *method_len,
+                                unsigned char **pubkeydata,
+                                size_t *pubkeydata_len,
+                                const char *privatekeydata,
+                                size_t privatekeydata_len,
+                                const char *passphrase)
+{
+    int       st;
+    BIO*      bp;
+    EVP_PKEY* pk;
+
+    _libssh2_debug(session,
+                   LIBSSH2_TRACE_AUTH,
+                   "Computing public key from private key.");
+
+    bp = BIO_new_mem_buf(privatekeydata, privatekeydata_len);
+    if (!bp) {
+        return -1;
+    }
+    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
+         * ($#&%#$(%$#( Someone buy me an OpenSSL manual and I'll read up on
+         * it.
+         */
+        OpenSSL_add_all_ciphers();
+    }
+    BIO_reset(bp);
+    pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void*)passphrase);
+    BIO_free(bp);
+
+    if (pk == NULL) {
+        return _libssh2_error(session,
+                              LIBSSH2_ERROR_FILE,
+                              "Unable to extract public key "
+                              "from private key file: "
+                              "Wrong passphrase or invalid/unrecognized "
+                              "private key file format");
+    }
+
+    switch (pk->type) {
+    case EVP_PKEY_RSA :
+        st = gen_publickey_from_rsa_evp(session, method, method_len,
+                                        pubkeydata, pubkeydata_len, pk);
+        break;
+
+    case EVP_PKEY_DSA :
+        st = gen_publickey_from_dsa_evp(session, method, method_len,
+                                        pubkeydata, pubkeydata_len, pk);
+        break;
+
+    default :
+        st = _libssh2_error(session,
+                            LIBSSH2_ERROR_FILE,
+                            "Unable to extract public key "
+                            "from private key file: "
+                            "Unsupported private key file format");
+        break;
+    }
+
+    EVP_PKEY_free(pk);
+    return st;
+}
+
 #endif /* LIBSSH2_OPENSSL */
diff --git a/src/userauth.c b/src/userauth.c
index edfe729..afbe172 100644
--- a/src/userauth.c
+++ b/src/userauth.c
@@ -441,6 +441,76 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION
*session, const char *username,
     return rc;
 }

+static int
+memory_read_publickey(LIBSSH2_SESSION * session, unsigned char **method,
+                      size_t *method_len,
+                      unsigned char **pubkeydata,
+                      size_t *pubkeydata_len,
+                      const char *pubkeyfiledata,
+                      size_t pubkeyfiledata_len)
+{
+    unsigned char *pubkey = NULL, *sp1, *sp2, *tmp;
+    size_t pubkey_len = pubkeyfiledata_len;
+    unsigned int tmp_len;
+
+    if (pubkeyfiledata_len <= 1) {
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Invalid data in public key file");
+    }
+
+    pubkey = LIBSSH2_ALLOC(session, pubkeyfiledata_len);
+    if (!pubkey) {
+        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+                              "Unable to allocate memory for public key data");
+    }
+
+    memcpy(pubkey, pubkeyfiledata, pubkeyfiledata_len);
+
+    /*
+     *   Remove trailing whitespace
+     */
+    while (pubkey_len && isspace(pubkey[pubkey_len - 1]))
+        pubkey_len--;
+
+    if (!pubkey_len) {
+        LIBSSH2_FREE(session, pubkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Missing public key data");
+    }
+
+    if ((sp1 = memchr(pubkey, ' ', pubkey_len)) == NULL) {
+        LIBSSH2_FREE(session, pubkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Invalid public key data");
+    }
+
+    sp1++;
+
+    if ((sp2 = memchr(sp1, ' ', pubkey_len - (sp1 - pubkey - 1))) == NULL) {
+        /* Assume that the id string is missing, but that it's okay */
+        sp2 = pubkey + pubkey_len;
+    }
+
+    if (libssh2_base64_decode(session, (char **) &tmp, &tmp_len,
+                              (char *) sp1, sp2 - sp1)) {
+        LIBSSH2_FREE(session, pubkey);
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                                  "Invalid key data, not base64 encoded");
+    }
+
+    /* Wasting some bytes here (okay, more than some), but since it's likely
+     * to be freed soon anyway, we'll just avoid the extra free/alloc and call
+     * it a wash
+     */
+    *method = pubkey;
+    *method_len = sp1 - pubkey - 1;
+
+    *pubkeydata = tmp;
+    *pubkeydata_len = tmp_len;
+
+    return 0;
+}
+
 /*
  * file_read_publickey
  *
@@ -543,7 +613,43 @@ file_read_publickey(LIBSSH2_SESSION * session,
unsigned char **method,
     return 0;
 }

+static int
+memory_read_privatekey(LIBSSH2_SESSION * session,
+                       const LIBSSH2_HOSTKEY_METHOD ** hostkey_method,
+                       void **hostkey_abstract,
+                       const unsigned char *method, int method_len,
+                       const char *privkeyfiledata, size_t privkeyfiledata_len,
+                       const char *passphrase)
+{
+    const LIBSSH2_HOSTKEY_METHOD **hostkey_methods_avail =
+        libssh2_hostkey_methods();
+
+    *hostkey_method = NULL;
+    *hostkey_abstract = NULL;
+    while (*hostkey_methods_avail && (*hostkey_methods_avail)->name) {
+        if ((*hostkey_methods_avail)->initPEMFromMemory
+             && strncmp((*hostkey_methods_avail)->name, (const char *) method,
+                        method_len) == 0) {
+            *hostkey_method = *hostkey_methods_avail;
+            break;
+        }
+        hostkey_methods_avail++;
+    }
+    if (!*hostkey_method) {
+        return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
+                              "No handler for specified private key");
+    }
+
+    if ((*hostkey_method)->
+        initPEMFromMemory(session, privkeyfiledata, privkeyfiledata_len,
+                          (unsigned char *) passphrase,
+                          hostkey_abstract)) {
+        return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                              "Unable to initialize private key from file");
+    }

+    return 0;
+}

 /* libssh2_file_read_privatekey
  * Read a PEM encoded private key from an id_??? style file
@@ -592,6 +698,42 @@ struct privkey_file {
 };

 static int
+sign_frommemory(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
+                const unsigned char *data, size_t data_len, void **abstract)
+{
+    struct privkey_file *pk_file = (struct privkey_file *) (*abstract);
+    const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
+    void *hostkey_abstract;
+    struct iovec datavec;
+    int rc;
+
+    rc = memory_read_privatekey(session, &privkeyobj, &hostkey_abstract,
+                                session->userauth_pblc_method,
+                                session->userauth_pblc_method_len,
+                                pk_file->filename,
+                                strlen(pk_file->filename),
+                                pk_file->passphrase);
+    if(rc)
+        return rc;
+
+    datavec.iov_base = (void *)data;
+    datavec.iov_len  = data_len;
+
+    if (privkeyobj->signv(session, sig, sig_len, 1, &datavec,
+                          &hostkey_abstract)) {
+        if (privkeyobj->dtor) {
+            privkeyobj->dtor(session, abstract);
+        }
+        return -1;
+    }
+
+    if (privkeyobj->dtor) {
+        privkeyobj->dtor(session, &hostkey_abstract);
+    }
+    return 0;
+}
+
+static int
 sign_fromfile(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
               const unsigned char *data, size_t data_len, void **abstract)
 {
@@ -1211,6 +1353,65 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
                           "username/public key combination");
 }

+ /*
+  * userauth_publickey_frommemory
+  * Authenticate using a keypair from memory
+  */
+static int
+userauth_publickey_frommemory(LIBSSH2_SESSION *session,
+                              const char *username,
+                              size_t username_len,
+                              const char *publickeydata,
+                              size_t publickeydata_len,
+                              const char *privatekeydata,
+                              size_t privatekeydata_len,
+                              const char *passphrase)
+{
+    unsigned char *pubkeydata = NULL;
+    size_t pubkeydata_len = 0;
+    struct privkey_file privkey_file;
+    void *abstract = &privkey_file;
+    int rc;
+
+    privkey_file.filename = privatekeydata;
+    privkey_file.passphrase = passphrase;
+
+    if (session->userauth_pblc_state == libssh2_NB_state_idle) {
+        if (publickeydata_len && publickeydata) {
+            rc = memory_read_publickey(session, &session->userauth_pblc_method,
+                                       &session->userauth_pblc_method_len,
+                                       &pubkeydata, &pubkeydata_len,
+                                       publickeydata, publickeydata_len);
+            if(rc)
+                return rc;
+        }
+        else if (privatekeydata_len && privatekeydata) {
+            /* Compute public key from private key. */
+            if (_libssh2_pub_priv_keyfilememory(session,
+                                                &session->userauth_pblc_method,
+
&session->userauth_pblc_method_len,
+                                                &pubkeydata, &pubkeydata_len,
+                                                privatekeydata,
privatekeydata_len,
+                                                passphrase))
+                return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                                      "Unable to extract public key "
+                                      "from private key.");
+        }
+        else {
+            return _libssh2_error(session, LIBSSH2_ERROR_FILE,
+                                  "Invalid data in public and private key.");
+        }
+    }
+
+    rc = _libssh2_userauth_publickey(session, username, username_len,
+                                     pubkeydata, pubkeydata_len,
+                                     sign_frommemory, &abstract);
+    if(pubkeydata)
+        LIBSSH2_FREE(session, pubkeydata);
+
+    return rc;
+}
+
 /*
  * userauth_publickey_fromfile
  * Authenticate using a keypair found in the named files
@@ -1263,6 +1464,36 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
     return rc;
 }

+/* libssh2_userauth_publickey_frommemory
+ * Authenticate using a keypair from memory
+ */
+LIBSSH2_API int
+libssh2_userauth_publickey_frommemory_ex(LIBSSH2_SESSION *session,
+                                      const char *user,
+                                      unsigned int user_len,
+                                      const char *publickeyfiledata,
+                                      size_t publickeyfiledata_len,
+                                      const char *privatekeyfiledata,
+                                      size_t privatekeyfiledata_len,
+                                      const char *passphrase)
+{
+    int rc;
+
+    if(NULL == passphrase)
+        /* if given a NULL pointer, make it point to a zero-length
+           string to save us from having to check this all over */
+        passphrase="";
+
+    BLOCK_ADJUST(rc, session,
+                 userauth_publickey_frommemory(session, user, user_len,
+                                               publickeyfiledata,
+                                               publickeyfiledata_len,
+                                               privatekeyfiledata,
+                                               privatekeyfiledata_len,
+                                               passphrase));
+    return rc;
+}
+
 /* libssh2_userauth_publickey_fromfile_ex
  * Authenticate using a keypair found in the named files
  */


Cheers,
David

On Tue, Sep 16, 2014 at 10:14 AM, Peter Stuge <[email protected]> wrote:

> Alexander Lamaison wrote:
> > we're already in this situation.
>
> Yeah, and I want that to get better instead of worse.
>
>
> //Peter
> _______________________________________________
> libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
>
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel

Reply via email to