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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list