[libvirt] [PATCHv2 3/4] libssh2_transport: Add libssh2 session support to net client code

Peter Krempa pkrempa at redhat.com
Sat Aug 11 21:21:01 UTC 2012


This patch adds a glue layer to enable using libssh2 code with the
network client code.

As in the original client implementation, shell code is sent to the
server to detect correct options for netcat.
---
 src/libvirt_private.syms |    1 +
 src/rpc/virnetclient.c   |  117 ++++++++++++++++++++++++++++++++++++++++++++++
 src/rpc/virnetclient.h   |   14 +++++-
 3 files changed, 131 insertions(+), 1 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 479613f..8ae4880 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1315,6 +1315,7 @@ virNetClientKeepAliveStart;
 virNetClientKeepAliveStop;
 virNetClientLocalAddrString;
 virNetClientNewExternal;
+virNetClientNewLibSSH2;
 virNetClientNewSSH;
 virNetClientNewTCP;
 virNetClientNewUNIX;
diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c
index 42bdc54..b86c6d9 100644
--- a/src/rpc/virnetclient.c
+++ b/src/rpc/virnetclient.c
@@ -422,6 +422,123 @@ virNetClientPtr virNetClientNewSSH(const char *nodename,
     return virNetClientNew(sock, NULL);
 }

+#define DEFAULT_VALUE(VAR, VAL)             \
+    if (!VAR)                               \
+        VAR = VAL;
+virNetClientPtr virNetClientNewLibSSH2(const char *host,
+                                       const char *port,
+                                       const char *username,
+                                       const char *password,
+                                       const char *privkeyPath,
+                                       const char *knownHostsPath,
+                                       const char *knownHostsVerify,
+                                       const char *authMethods,
+                                       const char *netcatPath,
+                                       const char *socketPath,
+                                       virConnectAuthPtr authPtr)
+{
+    virNetSocketPtr sock = NULL;
+    virNetClientPtr ret = NULL;
+
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char *nc = NULL;
+    char *command = NULL;
+
+    char *homedir = virGetUserDirectory();
+    char *knownhosts = NULL;
+    char *privkey = NULL;
+
+    /* Use default paths for known hosts an public keys if not provided */
+    if (homedir) {
+        if (!knownHostsPath) {
+            virBufferAsprintf(&buf, "%s/.ssh/known_hosts", homedir);
+            if (!(knownhosts = virBufferContentAndReset(&buf)))
+                goto no_memory;
+
+            if (!(virFileExists(knownhosts)))
+                VIR_FREE(knownhosts);
+        } else {
+            if (!(knownhosts = strdup(knownHostsPath)))
+                goto no_memory;
+        }
+
+        if (!privkeyPath) {
+            /* RSA */
+            virBufferAsprintf(&buf, "%s/.ssh/id_rsa", homedir);
+            if (!(privkey = virBufferContentAndReset(&buf)))
+                goto no_memory;
+
+            if (!(virFileExists(privkey)))
+                VIR_FREE(privkey);
+            /* DSA */
+            if (!privkey) {
+                virBufferAsprintf(&buf, "%s/.ssh/id_dsa", homedir);
+                if (!(privkey = virBufferContentAndReset(&buf)))
+                    goto no_memory;
+
+                if (!(virFileExists(privkey)))
+                    VIR_FREE(privkey);
+            }
+        } else {
+            if (!(privkey = strdup(privkeyPath)))
+                goto no_memory;
+        }
+    }
+
+    if (!authMethods) {
+        if (privkey)
+            authMethods = "agent,privkey,keyboard-interactive";
+        else
+            authMethods = "agent,keyboard-interactive";
+    }
+
+    DEFAULT_VALUE(host, "localhost");
+    DEFAULT_VALUE(port, "22");
+    DEFAULT_VALUE(username, "root");
+    DEFAULT_VALUE(netcatPath, "nc");
+    DEFAULT_VALUE(knownHostsVerify, "normal");
+
+    virBufferEscapeShell(&buf, netcatPath);
+    if (!(nc = virBufferContentAndReset(&buf)))
+        goto no_memory;
+
+    virBufferAsprintf(&buf,
+         "sh -c "
+         "'if '%s' -q 2>&1 | grep \"requires an argument\" >/dev/null 2>&1; then "
+             "ARG=-q0;"
+         "else "
+             "ARG=;"
+         "fi;"
+         "'%s' $ARG -U %s'",
+         nc, nc, socketPath);
+
+    if (!(command = virBufferContentAndReset(&buf)))
+        goto no_memory;
+
+    if (virNetSocketNewConnectLibSSH2(host, port, username, password, privkey,
+                                      knownhosts, knownHostsVerify, authMethods,
+                                      command, authPtr, &sock) != 0)
+        goto cleanup;
+
+    if (!(ret = virNetClientNew(sock, NULL)))
+        goto cleanup;
+    sock = NULL;
+
+cleanup:
+    VIR_FREE(command);
+    VIR_FREE(privkey);
+    VIR_FREE(knownhosts);
+    VIR_FREE(homedir);
+    VIR_FREE(nc);
+    virObjectUnref(sock);
+    return ret;
+
+no_memory:
+    virReportOOMError();
+    goto cleanup;
+}
+#undef DEFAULT_VALUE
+
 virNetClientPtr virNetClientNewExternal(const char **cmdargv)
 {
     virNetSocketPtr sock;
diff --git a/src/rpc/virnetclient.h b/src/rpc/virnetclient.h
index d6b9b3c..4df51c1 100644
--- a/src/rpc/virnetclient.h
+++ b/src/rpc/virnetclient.h
@@ -1,7 +1,7 @@
 /*
  * virnetclient.h: generic network RPC client
  *
- * Copyright (C) 2006-2011 Red Hat, Inc.
+ * Copyright (C) 2006-2012 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -50,6 +50,18 @@ virNetClientPtr virNetClientNewSSH(const char *nodename,
                                    const char *keyfile,
                                    const char *path);

+virNetClientPtr virNetClientNewLibSSH2(const char *host,
+                                       const char *port,
+                                       const char *username,
+                                       const char *password,
+                                       const char *privkeyPath,
+                                       const char *knownHostsPath,
+                                       const char *knownHostsVerify,
+                                       const char *authMethods,
+                                       const char *netcatPath,
+                                       const char *socketPath,
+                                       virConnectAuthPtr authPtr);
+
 virNetClientPtr virNetClientNewExternal(const char **cmdargv);

 typedef void (*virNetClientCloseFunc)(virNetClientPtr client,
-- 
1.7.8.6




More information about the libvir-list mailing list