[libvirt] [PATCH RFCv2 2/5] libssh2_transport: add ssh context support to virNetSocket
Michal Privoznik
mprivozn at redhat.com
Wed Jan 18 14:58:47 UTC 2012
On 04.01.2012 00:47, Peter Krempa wrote:
> 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;
Funky indentation
> +}
> +#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);
More information about the libvir-list
mailing list