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 | 137 +++++++++++++++++++++++++++++++++++++++++++++- src/rpc/virnetsocket.h | 12 ++++ 3 files changed, 149 insertions(+), 1 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b15a8db..af286d2 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1301,6 +1301,7 @@ virNetSocketGetFD; virNetSocketHasPassFD; virNetSocketIsLocal; virNetSocketListen; +virNetSocketNewConnectLibSSH; virNetSocketNewConnectTCP; virNetSocketNewListenUNIX; virNetSocketRecvFD; diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c index 30b8fe6..976a4ac 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -45,6 +45,10 @@ #include "passfd.h" +#if HAVE_LIBSSH2 +# include "virnetlibsshcontext.h" +#endif + #define VIR_FROM_THIS VIR_FROM_RPC #define virNetError(code, ...) \ @@ -84,6 +88,9 @@ struct _virNetSocket { size_t saslEncodedLength; size_t saslEncodedOffset; #endif +#if HAVE_LIBSSH2 + virNetLibSSHSessionPtr sshSession; +#endif }; @@ -676,6 +683,98 @@ 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; + + sess = virNetLibSSHSessionNew(); + if (!sess){ + 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) @@ -741,6 +840,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); @@ -922,6 +1025,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; @@ -930,11 +1039,32 @@ 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 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) == @@ -983,6 +1113,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) == @@ -1111,7 +1247,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 e444aef..15b860b 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@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list