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

Peter Krempa pkrempa at redhat.com
Tue Jan 3 23:47:38 UTC 2012


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




More information about the libvir-list mailing list