[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH RFCv2 2/5] libssh2_transport: add ssh context support to virNetSocket



This patch enables virNetSocket to be used as an ssh client when
properly configured.

Fucntion virNetSocketNewConnectLibSSH() is added, that takes all needed
parameters and creates a libssh2 session context and performs steps
needed to open the connection.

* src/libvirt_private.syms: Export the new symbol.
* src/rpc/virnetsocket.c: Add virNetSocketNewConnectLibSSH
* src/rpc/virnetsocket.h: Add header.
---
 src/libvirt_private.syms |    1 +
 src/rpc/virnetsocket.c   |  136 +++++++++++++++++++++++++++++++++++++++++++++-
 src/rpc/virnetsocket.h   |   12 ++++
 3 files changed, 148 insertions(+), 1 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ac2c52e..0c6066a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1315,6 +1315,7 @@ virNetSocketGetFD;
 virNetSocketHasPassFD;
 virNetSocketIsLocal;
 virNetSocketListen;
+virNetSocketNewConnectLibSSH;
 virNetSocketNewConnectTCP;
 virNetSocketNewListenUNIX;
 virNetSocketRecvFD;
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index af4fc5e..df7e88b 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -46,6 +46,10 @@

 #include "passfd.h"

+#if HAVE_LIBSSH2
+# include "virnetlibsshcontext.h"
+#endif
+
 #define VIR_FROM_THIS VIR_FROM_RPC

 #define virNetError(code, ...)                                    \
@@ -85,6 +89,9 @@ struct _virNetSocket {
     size_t saslEncodedLength;
     size_t saslEncodedOffset;
 #endif
+#if HAVE_LIBSSH2
+    virNetLibSSHSessionPtr sshSession;
+#endif
 };


@@ -684,6 +691,97 @@ int virNetSocketNewConnectSSH(const char *nodename,
     return virNetSocketNewConnectCommand(cmd, retsock);
 }

+#if HAVE_LIBSSH2
+int virNetSocketNewConnectLibSSH(const char *host,
+                                 const char *port,
+                                 const char *username,
+                                 const char *password,
+                                 const char *command,
+                                 const char *knownHostsFile,
+                                 const char *hostkeyVerify,
+                                 const char *privkey,
+                                 virConnectAuthPtr auth,
+                                 virNetSocketPtr *retsock)
+{
+    virNetSocketPtr sock = NULL;
+    virNetLibSSHSessionPtr sess = NULL;
+    int ret = -1;
+    int portN;
+    virNetLibSSHHostkeyVerify verify = VIR_NET_LIBSSH_HOSTKEY_VERIFY_NORMAL;
+
+
+    if ((ret = virNetSocketNewConnectTCP(host, port, &sock)) < 0)
+        goto error;
+
+    if (!(sess = virNetLibSSHSessionNew())) {
+        ret = -1;
+        goto error;
+    }
+
+    /* configure libssh2 session */
+    if ((ret = virNetLibSSHSessionSetCredentials(sess,
+                                                 username,
+                                                 password)) != 0)
+        goto error;
+
+    virNetLibSSHSessionSetAuthCallback(sess, auth); /* allways succeeds */
+
+
+    if ((ret = virNetLibSSHSessionSetChannelCommand(sess, command)) != 0)
+        goto error;
+
+    if ((ret = virNetLibSSHSessionSetPrivateKey(sess, privkey)) != 0)
+        goto error;
+
+    /* port was  verified while opening the socket */
+    sscanf(port, "%d", &portN);
+
+    if (hostkeyVerify) {
+        if (STRCASEEQ("auto", hostkeyVerify))
+            verify = VIR_NET_LIBSSH_HOSTKEY_VERIFY_AUTO_ADD;
+        else if (STRCASEEQ("ignore", hostkeyVerify))
+            verify = VIR_NET_LIBSSH_HOSTKEY_VERIFY_IGNORE;
+    }
+
+    if ((ret = virNetLibSSHSessionSetHostKeyVerification(sess,
+                                                         host,
+                                                         portN,
+                                                         knownHostsFile,
+                                                         false,
+                                                         verify) != 0))
+        goto error;
+
+    /* connect to the host using ssh */
+    if ((ret = virNetLibSSHSessionConnect(sess, virNetSocketGetFD(sock))) != 0)
+        goto error;
+
+    sock->sshSession = sess;
+    *retsock = sock;
+
+    return 0;
+
+error:
+        virNetSocketFree(sock);
+        virNetLibSSHSessionFree(sess);
+        return ret;
+}
+#else
+int virNetSocketNewConnectLibSSH(const char *host ATTRIBUTE_UNUSED,
+                                 const char *port ATTRIBUTE_UNUSED,
+                                 const char *username ATTRIBUTE_UNUSED,
+                                 const char *password ATTRIBUTE_UNUSED,
+                                 const char *command ATTRIBUTE_UNUSED,
+                                 const char *knownHostsFile ATTRIBUTE_UNUSED,
+                                 const char *hostkeyVerify ATTRIBUTE_UNUSED,
+                                 const char *privkey ATTRIBUTE_UNUSED,
+                                 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+                                 virNetSocketPtr *retsock ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS,
+                         _("libssh2 transport support was not enabled in this build"));
+    return -1;
+}
+#endif /* HAVE_LIBSSH2 */

 int virNetSocketNewConnectExternal(const char **cmdargv,
                                    virNetSocketPtr *retsock)
@@ -749,6 +847,10 @@ void virNetSocketFree(virNetSocketPtr sock)
     virNetSASLSessionFree(sock->saslSession);
 #endif

+#if HAVE_LIBSSH2
+    virNetLibSSHSessionFree(sock->sshSession);
+#endif
+
     VIR_FORCE_CLOSE(sock->fd);
     VIR_FORCE_CLOSE(sock->errfd);

@@ -930,6 +1032,12 @@ bool virNetSocketHasCachedData(virNetSocketPtr sock ATTRIBUTE_UNUSED)
 {
     bool hasCached = false;
     virMutexLock(&sock->lock);
+
+#if HAVE_LIBSSH2
+    if (virNetLibSSHHasCachedData(sock->sshSession))
+        hasCached = true;
+#endif
+
 #if HAVE_SASL
     if (sock->saslDecoded)
         hasCached = true;
@@ -938,6 +1046,21 @@ bool virNetSocketHasCachedData(virNetSocketPtr sock ATTRIBUTE_UNUSED)
     return hasCached;
 }

+#if HAVE_LIBSSH2
+static ssize_t virNetSocketLibSSHRead(virNetSocketPtr sock,
+                                      char *buf,
+                                      size_t len)
+{
+    return virNetLibSSHChannelRead(sock->sshSession, buf, len);
+}
+
+static ssize_t virNetSocketLibSSHWrite(virNetSocketPtr sock,
+                                const char *buf,
+                                size_t len)
+{
+    return virNetLibSSHChannelWrite(sock->sshSession, buf, len);
+}
+#endif

 bool virNetSocketHasPendingData(virNetSocketPtr sock ATTRIBUTE_UNUSED)
 {
@@ -956,6 +1079,12 @@ static ssize_t virNetSocketReadWire(virNetSocketPtr sock, char *buf, size_t len)
 {
     char *errout = NULL;
     ssize_t ret;
+
+#if HAVE_LIBSSH2
+    if (sock->sshSession)
+        return virNetSocketLibSSHRead(sock, buf, len);
+#endif
+
 reread:
     if (sock->tlsSession &&
         virNetTLSSessionGetHandshakeStatus(sock->tlsSession) ==
@@ -1004,6 +1133,12 @@ reread:
 static ssize_t virNetSocketWriteWire(virNetSocketPtr sock, const char *buf, size_t len)
 {
     ssize_t ret;
+
+#if HAVE_LIBSSH2
+    if (sock->sshSession)
+        return virNetSocketLibSSHWrite(sock, buf, len);
+#endif
+
 rewrite:
     if (sock->tlsSession &&
         virNetTLSSessionGetHandshakeStatus(sock->tlsSession) ==
@@ -1132,7 +1267,6 @@ static ssize_t virNetSocketWriteSASL(virNetSocketPtr sock, const char *buf, size
 }
 #endif

-
 ssize_t virNetSocketRead(virNetSocketPtr sock, char *buf, size_t len)
 {
     ssize_t ret;
diff --git a/src/rpc/virnetsocket.h b/src/rpc/virnetsocket.h
index ef9baa8..d04945d 100644
--- a/src/rpc/virnetsocket.h
+++ b/src/rpc/virnetsocket.h
@@ -74,6 +74,17 @@ int virNetSocketNewConnectSSH(const char *nodename,
                               const char *path,
                               virNetSocketPtr *addr);

+int virNetSocketNewConnectLibSSH(const char *host,
+                                 const char *port,
+                                 const char *username,
+                                 const char *password,
+                                 const char *command,
+                                 const char *knownHostsFile,
+                                 const char *hostkeyVerify,
+                                 const char *privkey,
+                                 virConnectAuthPtr auth,
+                                 virNetSocketPtr *retsock);
+
 int virNetSocketNewConnectExternal(const char **cmdargv,
                                    virNetSocketPtr *addr);

@@ -101,6 +112,7 @@ int virNetSocketRecvFD(virNetSocketPtr sock, int *fd);

 void virNetSocketSetTLSSession(virNetSocketPtr sock,
                                virNetTLSSessionPtr sess);
+
 # ifdef HAVE_SASL
 void virNetSocketSetSASLSession(virNetSocketPtr sock,
                                 virNetSASLSessionPtr sess);
-- 
1.7.3.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]