[libvirt] [PATCH RFCv2 4/5] libssh2_transport: Use libssh2 driver code in remote driver

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


This patch adds URI options to support libssh2 transport in the remote
driver.

A new transport sceme is introduced eg. "qemu+libssh://..." that
utilizes the libssh2 code added in previous patches.

The libssh2 code requires the authentication callback to be able to
perform keyboard-interactive authentication or to ask t passprhases or
add host keys to known hosts database.

Added URI components:
- known_hosts -  path to a knownHosts file in OpenSSH format to check
                 for known ssh host keys
- no_verify - this old option is abused to indicate desired behavior,
              what to do while checking host keys:
              options: - normal: behave as ssh, ask to add a new key,
                                 reject unknown
                       - auto_add: add new keys automaticaly, reject
                                   unknown
                       - ignore: don't check host key.

*src/remote/remote_driver.c: -Clean up whitespace between function name
                              and parentheses.
                             - Add libssh2 transport scheme
                             - Add URI components to configure libssh2
                               transport

TODO:
- Add documentation to web-page documents and man pages regarding new
  URI options
- Add support for tunelled cleartext passwords?
---
 src/remote/remote_driver.c |  116 ++++++++++++++++++++++++++++++++------------
 1 files changed, 84 insertions(+), 32 deletions(-)

diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 7580477..0787775 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -304,12 +304,14 @@ enum virDrvOpenRemoteFlags {
  *   - xxx+tcp:///            -> TCP connection to localhost
  *   - xxx+unix:///           -> UNIX domain socket
  *   - xxx:///                -> UNIX domain socket
+ *   - xxx+ssh:///            -> SSH connection (legacy)
+ *   - xxx+libssh:///         -> SSH connection (using libssh2)
  */
 static int
-doRemoteOpen (virConnectPtr conn,
-              struct private_data *priv,
-              virConnectAuthPtr auth ATTRIBUTE_UNUSED,
-              unsigned int flags)
+doRemoteOpen(virConnectPtr conn,
+             struct private_data *priv,
+             virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+             unsigned int flags)
 {
     struct qparam_set *vars = NULL;
     char *transport_str = NULL;
@@ -317,6 +319,7 @@ doRemoteOpen (virConnectPtr conn,
         trans_tls,
         trans_unix,
         trans_ssh,
+        trans_libssh,
         trans_ext,
         trans_tcp,
     } transport;
@@ -345,9 +348,9 @@ doRemoteOpen (virConnectPtr conn,
                 else
                     transport = trans_unix;
             } else {
-                if (STRCASEEQ (transport_str, "tls"))
+                if (STRCASEEQ(transport_str, "tls"))
                     transport = trans_tls;
-                else if (STRCASEEQ (transport_str, "unix")) {
+                else if (STRCASEEQ(transport_str, "unix")) {
                     if (conn->uri->server) {
                         remoteError(VIR_ERR_INVALID_ARG,
                                     _("using unix socket and remote "
@@ -357,16 +360,18 @@ doRemoteOpen (virConnectPtr conn,
                     } else {
                         transport = trans_unix;
                     }
-                } else if (STRCASEEQ (transport_str, "ssh"))
+                } else if (STRCASEEQ(transport_str, "ssh"))
                     transport = trans_ssh;
-                else if (STRCASEEQ (transport_str, "ext"))
+                else if (STRCASEEQ(transport_str, "libssh"))
+                    transport = trans_libssh;
+                else if (STRCASEEQ(transport_str, "ext"))
                     transport = trans_ext;
-                else if (STRCASEEQ (transport_str, "tcp"))
+                else if (STRCASEEQ(transport_str, "tcp"))
                     transport = trans_tcp;
                 else {
                     remoteError(VIR_ERR_INVALID_ARG, "%s",
                                 _("remote_open: transport in URL not recognised "
-                                  "(should be tls|unix|ssh|ext|tcp)"));
+                                  "(should be tls|unix|ssh|ext|tcp|libssh)"));
                     return VIR_DRV_OPEN_ERROR;
                 }
             }
@@ -384,6 +389,8 @@ doRemoteOpen (virConnectPtr conn,
     bool sanity = true, verify = true, tty ATTRIBUTE_UNUSED = true;
     char *pkipath = NULL, *keyfile = NULL;

+    char *knownHostsVerify = NULL,  *knownHosts = NULL;
+
     /* Return code from this function, and the private data. */
     int retcode = VIR_DRV_OPEN_ERROR;

@@ -430,49 +437,57 @@ doRemoteOpen (virConnectPtr conn,

         for (i = 0; i < vars->n; i++) {
             var = &vars->p[i];
-            if (STRCASEEQ (var->name, "name")) {
+            if (STRCASEEQ(var->name, "name")) {
                 VIR_FREE(name);
-                name = strdup (var->value);
+                name = strdup(var->value);
                 if (!name) goto out_of_memory;
                 var->ignore = 1;
-            } else if (STRCASEEQ (var->name, "command")) {
+            } else if (STRCASEEQ(var->name, "command")) {
                 VIR_FREE(command);
-                command = strdup (var->value);
+                command = strdup(var->value);
                 if (!command) goto out_of_memory;
                 var->ignore = 1;
-            } else if (STRCASEEQ (var->name, "socket")) {
+            } else if (STRCASEEQ(var->name, "socket")) {
                 VIR_FREE(sockname);
-                sockname = strdup (var->value);
+                sockname = strdup(var->value);
                 if (!sockname) goto out_of_memory;
                 var->ignore = 1;
-            } else if (STRCASEEQ (var->name, "auth")) {
+            } else if (STRCASEEQ(var->name, "auth")) {
                 VIR_FREE(authtype);
-                authtype = strdup (var->value);
+                authtype = strdup(var->value);
                 if (!authtype) goto out_of_memory;
                 var->ignore = 1;
-            } else if (STRCASEEQ (var->name, "netcat")) {
+            } else if (STRCASEEQ(var->name, "netcat")) {
                 VIR_FREE(netcat);
-                netcat = strdup (var->value);
+                netcat = strdup(var->value);
                 if (!netcat) goto out_of_memory;
                 var->ignore = 1;
-            } else if (STRCASEEQ (var->name, "keyfile")) {
+            } else if (STRCASEEQ(var->name, "keyfile")) {
                 VIR_FREE(keyfile);
-                keyfile = strdup (var->value);
+                keyfile = strdup(var->value);
                 if (!keyfile) goto out_of_memory;
-            } else if (STRCASEEQ (var->name, "no_sanity")) {
+            } else if (STRCASEEQ(var->name, "no_sanity")) {
                 sanity = atoi(var->value) == 0;
                 var->ignore = 1;
-            } else if (STRCASEEQ (var->name, "no_verify")) {
-                verify = atoi (var->value) == 0;
+            } else if (STRCASEEQ(var->name, "no_verify")) {
+                VIR_FREE(knownHostsVerify);
+                knownHostsVerify = strdup(var->value);
+                if (!knownHostsVerify) goto out_of_memory;
+                verify = atoi(var->value) == 0;
                 var->ignore = 1;
-            } else if (STRCASEEQ (var->name, "no_tty")) {
-                tty = atoi (var->value) == 0;
+            } else if (STRCASEEQ(var->name, "no_tty")) {
+                tty = atoi(var->value) == 0;
                 var->ignore = 1;
             } else if (STRCASEEQ(var->name, "pkipath")) {
                 VIR_FREE(pkipath);
                 pkipath = strdup(var->value);
                 if (!pkipath) goto out_of_memory;
                 var->ignore = 1;
+            } else if (STRCASEEQ(var->name, "known_hosts")) {
+                VIR_FREE(knownHosts);
+                knownHosts = strdup(var->value);
+                if (!knownHosts) goto out_of_memory;
+                var->ignore = 1;
             } else {
                 VIR_DEBUG("passing through variable '%s' ('%s') to remote end",
                       var->name, var->value);
@@ -565,6 +580,34 @@ doRemoteOpen (virConnectPtr conn,

         break;

+    case trans_libssh:
+        if (!sockname) {
+            if (flags & VIR_DRV_OPEN_REMOTE_RO)
+                sockname = strdup(LIBVIRTD_PRIV_UNIX_SOCKET_RO);
+            else
+                sockname = strdup(LIBVIRTD_PRIV_UNIX_SOCKET);
+            if (sockname == NULL)
+                goto out_of_memory;
+        }
+
+        VIR_DEBUG("Starting LibSSH2 session");
+
+        priv->client = virNetClientNewLibSSH(priv->hostname,
+                                             port,
+                                             username,
+                                             NULL,
+                                             netcat,
+                                             sockname,
+                                             knownHosts,
+                                             knownHostsVerify,
+                                             keyfile,
+                                             auth);
+        if (!priv->client)
+            goto failed;
+
+        priv->is_secure = 1;
+        break;
+
 #ifndef WIN32
     case trans_unix:
         if (!sockname) {
@@ -2569,18 +2612,27 @@ remoteAuthenticate (virConnectPtr conn, struct private_data *priv,
 {
     struct remote_auth_list_ret ret;
     int err, type = REMOTE_AUTH_NONE;
+    virErrorPtr verr;

     memset(&ret, 0, sizeof ret);
     err = call (conn, priv, 0,
                 REMOTE_PROC_AUTH_LIST,
                 (xdrproc_t) xdr_void, (char *) NULL,
                 (xdrproc_t) xdr_remote_auth_list_ret, (char *) &ret);
+
     if (err < 0) {
-        virErrorPtr verr = virGetLastError();
-        if (verr && verr->code == VIR_ERR_NO_SUPPORT) {
-            /* Missing RPC - old server - ignore */
-            virResetLastError();
-            return 0;
+        if ((verr = virGetLastError())) {
+            if (verr->code == VIR_ERR_NO_SUPPORT) {
+                /* Missing RPC - old server - ignore */
+                virResetLastError();
+                return 0;
+            }
+
+            if (verr->code == VIR_ERR_LIBSSH_REMOTE_COMMAND) {
+                virResetLastError();
+                remoteError(VIR_ERR_LIBSSH_REMOTE_COMMAND, "%s",
+                            _("Remote daemon is not running or remote command has failed"));
+            }
         }
         return -1;
     }
-- 
1.7.3.4




More information about the libvir-list mailing list