]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
libssh2_transport: Add libssh2 session support to net client code
authorPeter Krempa <pkrempa@redhat.com>
Mon, 14 Nov 2011 15:12:53 +0000 (16:12 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 21 Aug 2012 12:47:09 +0000 (14:47 +0200)
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 and connect to libvirt's
unix socket.

src/libvirt_private.syms
src/rpc/virnetclient.c
src/rpc/virnetclient.h

index 86cc8167f7daf89b17c330b7239509e4d08cd32a..4cfa95f06a6df2ee1abacee9db3c8fd47ec8d315 100644 (file)
@@ -1335,6 +1335,7 @@ virNetClientKeepAliveStart;
 virNetClientKeepAliveStop;
 virNetClientLocalAddrString;
 virNetClientNewExternal;
+virNetClientNewLibSSH2;
 virNetClientNewSSH;
 virNetClientNewTCP;
 virNetClientNewUNIX;
index cec5efbba6d0cc8920a617a5966733d32eb9b374..8ff5e09e73dacf0322d127c5bc51bb202a8e87af 100644 (file)
@@ -395,6 +395,122 @@ 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 *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, NULL, 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;
index 3d55a74e05e6084de178629b6dc72ff0cd562a42..d10224f591db0b6d3dfea23cc338360b7f05102b 100644 (file)
@@ -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,17 @@ virNetClientPtr virNetClientNewSSH(const char *nodename,
                                    const char *keyfile,
                                    const char *path);
 
+virNetClientPtr virNetClientNewLibSSH2(const char *host,
+                                       const char *port,
+                                       const char *username,
+                                       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);
 
 int virNetClientRegisterAsyncIO(virNetClientPtr client);