File kdump-move-SFTP-to-own-file.patch of Package kdump
From: Petr Tesarik <ptesarik@suse.cz>
Date: Mon, 13 Apr 2015 14:53:05 +0200
Subject: Split off SSH transfers from transfer.cc
References: FATE#318874, bsc#917747
Patch-mainline: v0.8.16
Git-commit: 97d7fde532b93a87b43db6a5ca15c6980b99c652
Putting all possible transfer classes into a single file is bad design.
Start by separating SSH-based transfers into its own file.
Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
---
kdumptool/CMakeLists.txt | 2
kdumptool/sshtransfer.cc | 466 +++++++++++++++++++++++++++++++++++++++++++++++
kdumptool/sshtransfer.h | 134 +++++++++++++
kdumptool/transfer.cc | 432 -------------------------------------------
kdumptool/transfer.h | 101 ----------
5 files changed, 603 insertions(+), 532 deletions(-)
--- a/kdumptool/CMakeLists.txt
+++ b/kdumptool/CMakeLists.txt
@@ -52,6 +52,8 @@ SET(COMMON_SRC
fileutil.h
transfer.cc
transfer.h
+ sshtransfer.cc
+ sshtransfer.h
socket.cc
socket.h
ledblink.cc
--- /dev/null
+++ b/kdumptool/sshtransfer.cc
@@ -0,0 +1,466 @@
+/*
+ * (c) 2015, Petr Tesarik <ptesarik@suse.cz>, SUSE LINUX Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <iostream>
+#include <string>
+#include <cstdlib>
+#include <cerrno>
+
+#if HAVE_LIBSSH2
+# include <libssh2.h>
+# include <libssh2_sftp.h>
+#endif
+
+#include "global.h"
+#include "debug.h"
+#include "configuration.h"
+#include "fileutil.h"
+#include "dataprovider.h"
+#include "process.h"
+#include "socket.h"
+#include "sshtransfer.h"
+
+using std::string;
+using std::cerr;
+using std::endl;
+
+//{{{ SSHTransfer -------------------------------------------------------------
+
+/* -------------------------------------------------------------------------- */
+SSHTransfer::SSHTransfer(const RootDirURLVector &urlv,
+ const std::string &subdir)
+ throw (KError)
+ : URLTransfer(urlv, subdir)
+{
+ if (urlv.size() > 1)
+ cerr << "WARNING: First dump target used; rest ignored." << endl;
+ const RootDirURL &target = urlv.front();
+
+ Debug::debug()->trace("SSHTransfer::SSHTransfer(%s)",
+ target.getURL().c_str());
+
+ string remote;
+ FilePath fp = target.getPath();
+ fp.appendPath(getSubDir());
+ remote.assign("mkdir -p ").append(fp);
+
+ SubProcess p;
+ p.spawn("ssh", makeArgs(remote));
+ int status = p.wait();
+ if (status != 0)
+ throw KError("SSHTransfer::SSHTransfer: ssh command failed"
+ " with status " + Stringutil::number2string(status));
+}
+
+/* -------------------------------------------------------------------------- */
+SSHTransfer::~SSHTransfer()
+ throw ()
+{
+ Debug::debug()->trace("SSHTransfer::~SSHTransfer()");
+}
+
+/* -------------------------------------------------------------------------- */
+void SSHTransfer::perform(DataProvider *dataprovider,
+ const StringVector &target_files,
+ bool *directSave)
+ throw (KError)
+{
+ Debug::debug()->trace("SSHTransfer::perform(%p, [ \"%s\"%s ])",
+ dataprovider, target_files.front().c_str(),
+ target_files.size() > 1 ? ", ..." : "");
+
+ bool prepared = false;
+ if (directSave)
+ *directSave = false;
+
+ RootDirURLVector &urlv = getURLVector();
+ const RootDirURL &target = urlv.front();
+
+ FilePath fp = target.getPath();
+ fp.appendPath(getSubDir()).appendPath(target_files.front());
+
+ string remote;
+ remote.assign("dd of=").append(fp).append("-incomplete");
+ remote.append(" && mv ").append(fp).append("-incomplete ").append(fp);
+ Debug::debug()->dbg("Remote command: %s", remote.c_str());
+
+ SubProcess p;
+ p.setPipeDirection(STDIN_FILENO, SubProcess::ParentToChild);
+ p.spawn("ssh", makeArgs(remote));
+
+ int fd = p.getPipeFD(STDIN_FILENO);
+ try {
+ dataprovider->prepare();
+ prepared = true;
+
+ while (true) {
+ size_t read_data = dataprovider->getData(m_buffer, BUFSIZ);
+
+ // finished?
+ if (read_data == 0)
+ break;
+
+ char *p = m_buffer;
+ while (read_data) {
+ ssize_t ret = write(fd, p, read_data);
+
+ if (ret < 0)
+ throw KSystemError("SSHTransfer::perform: write failed",
+ errno);
+ read_data -= ret;
+ p += ret;
+ }
+ }
+ } catch (...) {
+ close(fd);
+ if (prepared)
+ dataprovider->finish();
+ throw;
+ }
+ close(fd);
+
+ dataprovider->finish();
+ int status = p.wait();
+ if (status != 0)
+ throw KError("SSHTransfer::perform: ssh command failed"
+ " with status " + Stringutil::number2string(status));
+}
+
+StringVector SSHTransfer::makeArgs(std::string const &remote)
+{
+ const RootDirURL &target = getURLVector().front();
+ StringVector ret;
+
+ ret.push_back("-F");
+ ret.push_back("/kdump/.ssh/config");
+
+ ret.push_back("-l");
+ ret.push_back(target.getUsername());
+
+ int port = target.getPort();
+ if (port != -1) {
+ ret.push_back("-p");
+ ret.push_back(Stringutil::number2string(port));
+ }
+
+ ret.push_back(target.getHostname());
+ ret.push_back(remote);
+
+ return ret;
+}
+
+//}}}
+//{{{ SFTPTransfer -------------------------------------------------------------
+
+#if HAVE_LIBSSH2
+
+/* -------------------------------------------------------------------------- */
+SFTPTransfer::SFTPTransfer(const RootDirURLVector &urlv,
+ const std::string &subdir)
+ throw (KError)
+ : URLTransfer(urlv, subdir),
+ m_sshSession(NULL), m_sftp(NULL), m_socket(NULL)
+{
+ if (urlv.size() > 1)
+ cerr << "WARNING: First dump target used; rest ignored." << endl;
+ const RootDirURL &parser = urlv.front();
+
+ Debug::debug()->trace("SFTPTransfer::SFTPTransfer(%s)",
+ parser.getURL().c_str());
+
+ m_sshSession = libssh2_session_init();
+ if (!m_sshSession)
+ throw KError("libssh2_session_init() failed.");
+
+ // set blocking
+ libssh2_session_set_blocking(m_sshSession, 1);
+
+ // get the correct port
+ int port = parser.getPort();
+ if (port <= 0)
+ port = Socket::DP_SSH;
+
+ // create the socket and connect
+ m_socket = new Socket(parser.getHostname(), port, Socket::ST_TCP);
+ int fd = m_socket->connect();
+
+ // start it up
+ int ret = libssh2_session_startup(m_sshSession, fd);
+ if (ret != 0) {
+ close();
+ throw KError("libssh2_session_startup() failed with "+
+ Stringutil::number2string(ret) +".");
+ }
+
+ // get the hostkey fingerprints
+ const char *hostsha1 =
+ libssh2_hostkey_hash(m_sshSession, LIBSSH2_HOSTKEY_HASH_SHA1);
+ Debug::debug()->info
+ ("SSH SHA1 fingerprint: %s",
+ Stringutil::bytes2hexstr(hostsha1, SHA1SUM_LENGTH, true).c_str());
+
+ const char *hostmd5 =
+ libssh2_hostkey_hash(m_sshSession, LIBSSH2_HOSTKEY_HASH_MD5);
+ Debug::debug()->info
+ ("SSH MD5 fingerprint: %s",
+ Stringutil::bytes2hexstr(hostmd5, MD5SUM_LENGTH, true).c_str());
+
+#if HAVE_LIBSSL
+ // check the fingerprints if possible
+ Configuration *config = Configuration::config();
+ const string &hostkey = config->KDUMP_HOST_KEY.value();
+
+ if (!hostkey.empty() && hostkey != "*") {
+ char expectmd5[MD5SUM_LENGTH];
+ char expectsha1[SHA1SUM_LENGTH];
+ Stringutil::digest_base64(hostkey.c_str(), hostkey.size(),
+ expectmd5, expectsha1);
+
+ if (memcmp(hostsha1, expectsha1, SHA1SUM_LENGTH))
+ throw KError("Target host key SHA1 fingerprint mismatch!");
+ Debug::debug()->info("SHA1 fingerprint matches");
+
+ if (memcmp(hostmd5, expectmd5, MD5SUM_LENGTH))
+ throw KError("Target host key MD5 fingerprint mismatch!");
+ Debug::debug()->info("MD5 fingerprint matches");
+ } else
+ cerr << "WARNING: SSH host key accepted without checking!" << endl;
+#endif // HAVE_LIBSSL
+
+ // SSH authentication
+ bool authenticated = false;
+
+ // username and password
+ string username = parser.getUsername();
+ string password = parser.getPassword();
+
+ // public and private key
+ string homedir = getenv("HOME");
+ FilePath pubkey;
+ FilePath privkey;
+
+ // DSA
+ (pubkey = homedir).appendPath(".ssh").appendPath("id_dsa.pub");
+ (privkey = homedir).appendPath(".ssh").appendPath("id_dsa");
+ if (!authenticated && pubkey.exists() && privkey.exists()) {
+ Debug::debug()->dbg("Using private key %s and public key %s",
+ privkey.c_str(), pubkey.c_str());
+
+ ret = libssh2_userauth_publickey_fromfile(m_sshSession,
+ username.c_str(), pubkey.c_str(), privkey.c_str(),
+ password.c_str());
+ if (ret == 0)
+ authenticated = true;
+ else
+ Debug::debug()->dbg("id_dsa: "
+ "libssh2_userauth_publickey_fromfile() failed with "+
+ Stringutil::number2string(ret) + ".");
+ }
+
+ // RSA
+ (pubkey = homedir).appendPath(".ssh").appendPath("id_rsa.pub");
+ (privkey = homedir).appendPath(".ssh").appendPath("id_rsa");
+ if (!authenticated && pubkey.exists() && privkey.exists()) {
+ Debug::debug()->dbg("Using private key %s and public key %s",
+ privkey.c_str(), pubkey.c_str());
+
+ ret = libssh2_userauth_publickey_fromfile(m_sshSession,
+ username.c_str(), pubkey.c_str(), privkey.c_str(),
+ password.c_str());
+ if (ret == 0)
+ authenticated = true;
+ else
+ Debug::debug()->dbg("id_rsa: "
+ "libssh2_userauth_publickey_fromfile() failed with "+
+ Stringutil::number2string(ret) + ".");
+ }
+
+ // password
+ if (!authenticated) {
+ Debug::debug()->dbg("Using password auth");
+
+ ret = libssh2_userauth_password(m_sshSession, username.c_str(),
+ password.c_str());
+ if (ret == 0)
+ authenticated = true;
+ else
+ Debug::debug()->dbg("libssh2_userauth_password() failed with "+
+ Stringutil::number2string(ret) + ".");
+ }
+
+ if (!authenticated) {
+ close();
+ throw KError("SSH authentication failed.");
+ }
+
+ // SFTP session
+ m_sftp = libssh2_sftp_init(m_sshSession);
+ if (!m_sftp) {
+ close();
+ throw KError("libssh2_sftp_init() failed with "+
+ Stringutil::number2string(ret) + ".");
+ }
+
+ FilePath fp = parser.getPath();
+ mkdir(fp.appendPath(subdir), true);
+}
+
+/* -------------------------------------------------------------------------- */
+SFTPTransfer::~SFTPTransfer()
+ throw ()
+{
+ Debug::debug()->trace("SFTPTransfer::~SFTPTransfer()");
+
+ close();
+}
+
+// -----------------------------------------------------------------------------
+bool SFTPTransfer::exists(const string &file)
+ throw (KError)
+{
+ Debug::debug()->trace("SFTPTransfer::exists(%s)", file.c_str());
+
+ LIBSSH2_SFTP_ATTRIBUTES attrs;
+ int ret = libssh2_sftp_stat(m_sftp, file.c_str(), &attrs);
+
+ if (ret != 0) {
+ int errorcode = libssh2_sftp_last_error(m_sftp);
+ if (errorcode == LIBSSH2_FX_NO_SUCH_FILE)
+ return false;
+ else
+ throw KSFTPError("libssh2_sftp_stat on " + file + " failed.",
+ errorcode);
+ }
+
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+void SFTPTransfer::mkdir(const FilePath &dir, bool recursive)
+ throw (KError)
+{
+ Debug::debug()->trace("SFTPTransfer::mkdir(%s, %d)",
+ dir.c_str(), int(recursive));
+
+ if (!recursive) {
+ if (!exists(dir)) {
+ int ret = libssh2_sftp_mkdir(m_sftp, dir.c_str(), 0755);
+ if (ret != 0)
+ throw KSFTPError("mkdir of " + dir + " failed.",
+ libssh2_sftp_last_error(m_sftp));
+ }
+ } else {
+ string directory = dir;
+
+ // remove trailing '/' if there are any
+ while (directory[directory.size()-1] == '/')
+ directory = directory.substr(0, directory.size()-1);
+
+ string::size_type current_slash = 0;
+
+ while (true) {
+ current_slash = directory.find('/', current_slash+1);
+ if (current_slash == string::npos) {
+ mkdir(directory, false);
+ break;
+ }
+
+ mkdir(directory.substr(0, current_slash), false);
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void SFTPTransfer::perform(DataProvider *dataprovider,
+ const StringVector &target_files,
+ bool *directSave)
+ throw (KError)
+{
+ Debug::debug()->trace("SFTPTransfer::perform(%p, [ \"%s\"%s ])",
+ dataprovider, target_files.front().c_str(),
+ target_files.size() > 1 ? ", ..." : "");
+
+ bool prepared = false;
+ if (directSave)
+ *directSave = false;
+
+ RootDirURLVector &urlv = getURLVector();
+ const RootDirURL &parser = urlv.front();
+
+ LIBSSH2_SFTP_HANDLE *handle = NULL;
+ FilePath file = parser.getPath();
+ file.appendPath(getSubDir()).appendPath(target_files.front());
+
+ Debug::debug()->dbg("Using target file %s.", file.c_str());
+
+ try {
+ handle = libssh2_sftp_open(m_sftp, file.c_str(),
+ LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, 0644);
+ if (!handle)
+ throw KSFTPError("Cannot create file " + file + " remotely.",
+ libssh2_sftp_last_error(m_sftp));
+
+ dataprovider->prepare();
+ prepared = true;
+
+ while (true) {
+ size_t read_data = dataprovider->getData(m_buffer, BUFSIZ);
+
+ // finished?
+ if (read_data == 0)
+ break;
+
+ size_t ret = libssh2_sftp_write(handle, m_buffer, read_data);
+ if (ret != read_data)
+ throw KSFTPError("SFTPTransfer::perform: "
+ "libssh2_sftp_write() failed.",
+ libssh2_sftp_last_error(m_sftp));
+ }
+ } catch (...) {
+ if (handle)
+ libssh2_sftp_close(handle);
+ close();
+ if (prepared)
+ dataprovider->finish();
+ throw;
+ }
+
+ if (handle)
+ libssh2_sftp_close(handle);
+ dataprovider->finish();
+}
+
+
+/* -------------------------------------------------------------------------- */
+void SFTPTransfer::close()
+ throw ()
+{
+ Debug::debug()->trace("SFTPTransfer::close()");
+
+ if (m_sshSession) {
+ libssh2_session_disconnect(m_sshSession, "Normal Shutdown.");
+ libssh2_session_free(m_sshSession);
+ m_sshSession = NULL;
+ }
+ delete m_socket;
+ m_socket = NULL;
+}
+
+#endif // HAVE_LIBSSH2
+
+//}}}
--- /dev/null
+++ b/kdumptool/sshtransfer.h
@@ -0,0 +1,134 @@
+/*
+ * (c) 2015, Petr Tesarik <ptesarik@suse.cz>, SUSE LINUX Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef SSHTRANSFER_H
+#define SSHTRANSFER_H
+
+#include "global.h"
+#include "stringutil.h"
+#include "fileutil.h"
+#include "rootdirurl.h"
+#include "process.h"
+#include "socket.h"
+#include "transfer.h"
+
+#if HAVE_LIBSSH2
+# include <libssh2.h>
+# include <libssh2_sftp.h>
+#endif
+
+//{{{ SSHTransfer --------------------------------------------------------------
+
+/**
+ * Transfers a file to SSH (upload).
+ */
+class SSHTransfer : public URLTransfer {
+
+ public:
+
+ /**
+ * Creates a SSHTransfer object.
+ *
+ * @exception KError when initialising the underlying library fails
+ */
+ SSHTransfer(const RootDirURLVector &urlv, const std::string &subdir)
+ throw (KError);
+
+ /**
+ * Destroys a SSHTransfer object.
+ */
+ ~SSHTransfer()
+ throw ();
+
+ /**
+ * Transfers the file.
+ *
+ * @see Transfer::perform()
+ */
+ void perform(DataProvider *dataprovider,
+ const StringVector &target_files,
+ bool *directSave)
+ throw (KError);
+
+ private:
+ char m_buffer[BUFSIZ];
+
+ StringVector makeArgs(std::string const &remote);
+};
+
+//}}}
+//{{{ SFTPTransfer -------------------------------------------------------------
+
+#if HAVE_LIBSSH2
+
+/**
+ * Transfers a file to SFTP (upload).
+ */
+class SFTPTransfer : public URLTransfer {
+
+ public:
+
+ /**
+ * Creates a SFTPTransfer object.
+ *
+ * @exception KError when initialising the underlying library fails
+ */
+ SFTPTransfer(const RootDirURLVector &urlv, const std::string &subdir)
+ throw (KError);
+
+ /**
+ * Destroys a SFTPTransfer object.
+ */
+ ~SFTPTransfer()
+ throw ();
+
+ /**
+ * Transfers the file.
+ *
+ * @see Transfer::perform()
+ */
+ void perform(DataProvider *dataprovider,
+ const StringVector &target_files,
+ bool *directSave)
+ throw (KError);
+
+ protected:
+ void close()
+ throw ();
+
+ void mkdir(const FilePath &dir, bool recursive)
+ throw (KError);
+
+ bool exists(const std::string &file)
+ throw (KError);
+
+ private:
+ LIBSSH2_SESSION *m_sshSession;
+ LIBSSH2_SFTP *m_sftp;
+ Socket *m_socket;
+ char m_buffer[BUFSIZ];
+
+};
+
+#endif // HAVE_LIBSSH2
+
+//}}}
+
+#endif /* SSHTRANSFER_H */
+
+// vim: set sw=4 ts=4 fdm=marker et: :collapseFolds=1:
--- a/kdumptool/transfer.cc
+++ b/kdumptool/transfer.cc
@@ -26,10 +26,6 @@
#include <cstring>
#include <curl/curl.h>
-#if HAVE_LIBSSH2
-# include <libssh2.h>
-# include <libssh2_sftp.h>
-#endif
#include "dataprovider.h"
#include "global.h"
@@ -39,9 +35,8 @@
#include "util.h"
#include "fileutil.h"
#include "stringutil.h"
-#include "socket.h"
#include "configuration.h"
-#include "process.h"
+#include "sshtransfer.h"
using std::fopen;
using std::fread;
@@ -479,431 +474,6 @@ void FTPTransfer::open(DataProvider *dat
}
//}}}
-//{{{ SFTPTransfer -------------------------------------------------------------
-
-#if HAVE_LIBSSH2
-
-/* -------------------------------------------------------------------------- */
-SFTPTransfer::SFTPTransfer(const RootDirURLVector &urlv,
- const std::string &subdir)
- throw (KError)
- : URLTransfer(urlv, subdir),
- m_sshSession(NULL), m_sftp(NULL), m_socket(NULL)
-{
- if (urlv.size() > 1)
- cerr << "WARNING: First dump target used; rest ignored." << endl;
- const RootDirURL &parser = urlv.front();
-
- Debug::debug()->trace("SFTPTransfer::SFTPTransfer(%s)",
- parser.getURL().c_str());
-
- m_sshSession = libssh2_session_init();
- if (!m_sshSession)
- throw KError("libssh2_session_init() failed.");
-
- // set blocking
- libssh2_session_set_blocking(m_sshSession, 1);
-
- // get the correct port
- int port = parser.getPort();
- if (port <= 0)
- port = Socket::DP_SSH;
-
- // create the socket and connect
- m_socket = new Socket(parser.getHostname(), port, Socket::ST_TCP);
- int fd = m_socket->connect();
-
- // start it up
- int ret = libssh2_session_startup(m_sshSession, fd);
- if (ret != 0) {
- close();
- throw KError("libssh2_session_startup() failed with "+
- Stringutil::number2string(ret) +".");
- }
-
- // get the hostkey fingerprints
- const char *hostsha1 =
- libssh2_hostkey_hash(m_sshSession, LIBSSH2_HOSTKEY_HASH_SHA1);
- Debug::debug()->info
- ("SSH SHA1 fingerprint: %s",
- Stringutil::bytes2hexstr(hostsha1, SHA1SUM_LENGTH, true).c_str());
-
- const char *hostmd5 =
- libssh2_hostkey_hash(m_sshSession, LIBSSH2_HOSTKEY_HASH_MD5);
- Debug::debug()->info
- ("SSH MD5 fingerprint: %s",
- Stringutil::bytes2hexstr(hostmd5, MD5SUM_LENGTH, true).c_str());
-
-#if HAVE_LIBSSL
- // check the fingerprints if possible
- Configuration *config = Configuration::config();
- const string &hostkey = config->KDUMP_HOST_KEY.value();
-
- if (!hostkey.empty() && hostkey != "*") {
- char expectmd5[MD5SUM_LENGTH];
- char expectsha1[SHA1SUM_LENGTH];
- Stringutil::digest_base64(hostkey.c_str(), hostkey.size(),
- expectmd5, expectsha1);
-
- if (memcmp(hostsha1, expectsha1, SHA1SUM_LENGTH))
- throw KError("Target host key SHA1 fingerprint mismatch!");
- Debug::debug()->info("SHA1 fingerprint matches");
-
- if (memcmp(hostmd5, expectmd5, MD5SUM_LENGTH))
- throw KError("Target host key MD5 fingerprint mismatch!");
- Debug::debug()->info("MD5 fingerprint matches");
- } else
- cerr << "WARNING: SSH host key accepted without checking!" << endl;
-#endif // HAVE_LIBSSL
-
- // SSH authentication
- bool authenticated = false;
-
- // username and password
- string username = parser.getUsername();
- string password = parser.getPassword();
-
- // public and private key
- string homedir = getenv("HOME");
- FilePath pubkey;
- FilePath privkey;
-
- // DSA
- (pubkey = homedir).appendPath(".ssh").appendPath("id_dsa.pub");
- (privkey = homedir).appendPath(".ssh").appendPath("id_dsa");
- if (!authenticated && pubkey.exists() && privkey.exists()) {
- Debug::debug()->dbg("Using private key %s and public key %s",
- privkey.c_str(), pubkey.c_str());
-
- ret = libssh2_userauth_publickey_fromfile(m_sshSession,
- username.c_str(), pubkey.c_str(), privkey.c_str(),
- password.c_str());
- if (ret == 0)
- authenticated = true;
- else
- Debug::debug()->dbg("id_dsa: "
- "libssh2_userauth_publickey_fromfile() failed with "+
- Stringutil::number2string(ret) + ".");
- }
-
- // RSA
- (pubkey = homedir).appendPath(".ssh").appendPath("id_rsa.pub");
- (privkey = homedir).appendPath(".ssh").appendPath("id_rsa");
- if (!authenticated && pubkey.exists() && privkey.exists()) {
- Debug::debug()->dbg("Using private key %s and public key %s",
- privkey.c_str(), pubkey.c_str());
-
- ret = libssh2_userauth_publickey_fromfile(m_sshSession,
- username.c_str(), pubkey.c_str(), privkey.c_str(),
- password.c_str());
- if (ret == 0)
- authenticated = true;
- else
- Debug::debug()->dbg("id_rsa: "
- "libssh2_userauth_publickey_fromfile() failed with "+
- Stringutil::number2string(ret) + ".");
- }
-
- // password
- if (!authenticated) {
- Debug::debug()->dbg("Using password auth");
-
- ret = libssh2_userauth_password(m_sshSession, username.c_str(),
- password.c_str());
- if (ret == 0)
- authenticated = true;
- else
- Debug::debug()->dbg("libssh2_userauth_password() failed with "+
- Stringutil::number2string(ret) + ".");
- }
-
- if (!authenticated) {
- close();
- throw KError("SSH authentication failed.");
- }
-
- // SFTP session
- m_sftp = libssh2_sftp_init(m_sshSession);
- if (!m_sftp) {
- close();
- throw KError("libssh2_sftp_init() failed with "+
- Stringutil::number2string(ret) + ".");
- }
-
- FilePath fp = parser.getPath();
- mkdir(fp.appendPath(subdir), true);
-}
-
-/* -------------------------------------------------------------------------- */
-SFTPTransfer::~SFTPTransfer()
- throw ()
-{
- Debug::debug()->trace("SFTPTransfer::~SFTPTransfer()");
-
- close();
-}
-
-// -----------------------------------------------------------------------------
-bool SFTPTransfer::exists(const string &file)
- throw (KError)
-{
- Debug::debug()->trace("SFTPTransfer::exists(%s)", file.c_str());
-
- LIBSSH2_SFTP_ATTRIBUTES attrs;
- int ret = libssh2_sftp_stat(m_sftp, file.c_str(), &attrs);
-
- if (ret != 0) {
- int errorcode = libssh2_sftp_last_error(m_sftp);
- if (errorcode == LIBSSH2_FX_NO_SUCH_FILE)
- return false;
- else
- throw KSFTPError("libssh2_sftp_stat on " + file + " failed.",
- errorcode);
- }
-
- return true;
-}
-
-// -----------------------------------------------------------------------------
-void SFTPTransfer::mkdir(const FilePath &dir, bool recursive)
- throw (KError)
-{
- Debug::debug()->trace("SFTPTransfer::mkdir(%s, %d)",
- dir.c_str(), int(recursive));
-
- if (!recursive) {
- if (!exists(dir)) {
- int ret = libssh2_sftp_mkdir(m_sftp, dir.c_str(), 0755);
- if (ret != 0)
- throw KSFTPError("mkdir of " + dir + " failed.",
- libssh2_sftp_last_error(m_sftp));
- }
- } else {
- string directory = dir;
-
- // remove trailing '/' if there are any
- while (directory[directory.size()-1] == '/')
- directory = directory.substr(0, directory.size()-1);
-
- string::size_type current_slash = 0;
-
- while (true) {
- current_slash = directory.find('/', current_slash+1);
- if (current_slash == string::npos) {
- mkdir(directory, false);
- break;
- }
-
- mkdir(directory.substr(0, current_slash), false);
- }
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void SFTPTransfer::perform(DataProvider *dataprovider,
- const StringVector &target_files,
- bool *directSave)
- throw (KError)
-{
- Debug::debug()->trace("SFTPTransfer::perform(%p, [ \"%s\"%s ])",
- dataprovider, target_files.front().c_str(),
- target_files.size() > 1 ? ", ..." : "");
-
- bool prepared = false;
- if (directSave)
- *directSave = false;
-
- RootDirURLVector &urlv = getURLVector();
- const RootDirURL &parser = urlv.front();
-
- LIBSSH2_SFTP_HANDLE *handle = NULL;
- FilePath file = parser.getPath();
- file.appendPath(getSubDir()).appendPath(target_files.front());
-
- Debug::debug()->dbg("Using target file %s.", file.c_str());
-
- try {
- handle = libssh2_sftp_open(m_sftp, file.c_str(),
- LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, 0644);
- if (!handle)
- throw KSFTPError("Cannot create file " + file + " remotely.",
- libssh2_sftp_last_error(m_sftp));
-
- dataprovider->prepare();
- prepared = true;
-
- while (true) {
- size_t read_data = dataprovider->getData(m_buffer, BUFSIZ);
-
- // finished?
- if (read_data == 0)
- break;
-
- size_t ret = libssh2_sftp_write(handle, m_buffer, read_data);
- if (ret != read_data)
- throw KSFTPError("SFTPTransfer::perform: "
- "libssh2_sftp_write() failed.",
- libssh2_sftp_last_error(m_sftp));
- }
- } catch (...) {
- if (handle)
- libssh2_sftp_close(handle);
- close();
- if (prepared)
- dataprovider->finish();
- throw;
- }
-
- if (handle)
- libssh2_sftp_close(handle);
- dataprovider->finish();
-}
-
-
-/* -------------------------------------------------------------------------- */
-void SFTPTransfer::close()
- throw ()
-{
- Debug::debug()->trace("SFTPTransfer::close()");
-
- if (m_sshSession) {
- libssh2_session_disconnect(m_sshSession, "Normal Shutdown.");
- libssh2_session_free(m_sshSession);
- m_sshSession = NULL;
- }
- delete m_socket;
- m_socket = NULL;
-}
-
-#endif // HAVE_LIBSSH2
-
-//}}}
-//{{{ SSHTransfer -------------------------------------------------------------
-
-/* -------------------------------------------------------------------------- */
-SSHTransfer::SSHTransfer(const RootDirURLVector &urlv,
- const std::string &subdir)
- throw (KError)
- : URLTransfer(urlv, subdir)
-{
- if (urlv.size() > 1)
- cerr << "WARNING: First dump target used; rest ignored." << endl;
- const RootDirURL &target = urlv.front();
-
- Debug::debug()->trace("SSHTransfer::SSHTransfer(%s)",
- target.getURL().c_str());
-
- string remote;
- FilePath fp = target.getPath();
- fp.appendPath(getSubDir());
- remote.assign("mkdir -p ").append(fp);
-
- SubProcess p;
- p.spawn("ssh", makeArgs(remote));
- int status = p.wait();
- if (status != 0)
- throw KError("SSHTransfer::SSHTransfer: ssh command failed"
- " with status " + Stringutil::number2string(status));
-}
-
-/* -------------------------------------------------------------------------- */
-SSHTransfer::~SSHTransfer()
- throw ()
-{
- Debug::debug()->trace("SSHTransfer::~SSHTransfer()");
-}
-
-/* -------------------------------------------------------------------------- */
-void SSHTransfer::perform(DataProvider *dataprovider,
- const StringVector &target_files,
- bool *directSave)
- throw (KError)
-{
- Debug::debug()->trace("SSHTransfer::perform(%p, [ \"%s\"%s ])",
- dataprovider, target_files.front().c_str(),
- target_files.size() > 1 ? ", ..." : "");
-
- bool prepared = false;
- if (directSave)
- *directSave = false;
-
- RootDirURLVector &urlv = getURLVector();
- const RootDirURL &target = urlv.front();
-
- FilePath fp = target.getPath();
- fp.appendPath(getSubDir()).appendPath(target_files.front());
-
- string remote;
- remote.assign("dd of=").append(fp).append("-incomplete");
- remote.append(" && mv ").append(fp).append("-incomplete ").append(fp);
- Debug::debug()->dbg("Remote command: %s", remote.c_str());
-
- SubProcess p;
- p.setPipeDirection(STDIN_FILENO, SubProcess::ParentToChild);
- p.spawn("ssh", makeArgs(remote));
-
- int fd = p.getPipeFD(STDIN_FILENO);
- try {
- dataprovider->prepare();
- prepared = true;
-
- while (true) {
- size_t read_data = dataprovider->getData(m_buffer, BUFSIZ);
-
- // finished?
- if (read_data == 0)
- break;
-
- char *p = m_buffer;
- while (read_data) {
- ssize_t ret = write(fd, p, read_data);
-
- if (ret < 0)
- throw KSystemError("SSHTransfer::perform: write failed",
- errno);
- read_data -= ret;
- p += ret;
- }
- }
- } catch (...) {
- close(fd);
- if (prepared)
- dataprovider->finish();
- throw;
- }
- close(fd);
-
- dataprovider->finish();
- int status = p.wait();
- if (status != 0)
- throw KError("SSHTransfer::perform: ssh command failed"
- " with status " + Stringutil::number2string(status));
-}
-
-StringVector SSHTransfer::makeArgs(std::string const &remote)
-{
- const RootDirURL &target = getURLVector().front();
- StringVector ret;
-
- ret.push_back("-F");
- ret.push_back("/kdump/.ssh/config");
-
- ret.push_back("-l");
- ret.push_back(target.getUsername());
-
- int port = target.getPort();
- if (port != -1) {
- ret.push_back("-p");
- ret.push_back(Stringutil::number2string(port));
- }
-
- ret.push_back(target.getHostname());
- ret.push_back(remote);
-
- return ret;
-}
-
-//}}}
//{{{ NFSTransfer --------------------------------------------------------------
// -----------------------------------------------------------------------------
--- a/kdumptool/transfer.h
+++ b/kdumptool/transfer.h
@@ -23,16 +23,11 @@
#include <cstdarg>
#include <curl/curl.h>
-#if HAVE_LIBSSH2
-# include <libssh2.h>
-# include <libssh2_sftp.h>
-#endif
#include "global.h"
#include "stringutil.h"
#include "fileutil.h"
#include "rootdirurl.h"
-#include "socket.h"
class DataProvider;
@@ -252,102 +247,6 @@ class FTPTransfer : public URLTransfer {
};
//}}}
-//{{{ SFTPTransfer -------------------------------------------------------------
-
-#if HAVE_LIBSSH2
-
-/**
- * Transfers a file to SFTP (upload).
- */
-class SFTPTransfer : public URLTransfer {
-
- public:
-
- /**
- * Creates a SFTPTransfer object.
- *
- * @exception KError when initialising the underlying library fails
- */
- SFTPTransfer(const RootDirURLVector &urlv, const std::string &subdir)
- throw (KError);
-
- /**
- * Destroys a SFTPTransfer object.
- */
- ~SFTPTransfer()
- throw ();
-
- /**
- * Transfers the file.
- *
- * @see Transfer::perform()
- */
- void perform(DataProvider *dataprovider,
- const StringVector &target_files,
- bool *directSave)
- throw (KError);
-
- protected:
- void close()
- throw ();
-
- void mkdir(const FilePath &dir, bool recursive)
- throw (KError);
-
- bool exists(const std::string &file)
- throw (KError);
-
- private:
- LIBSSH2_SESSION *m_sshSession;
- LIBSSH2_SFTP *m_sftp;
- Socket *m_socket;
- char m_buffer[BUFSIZ];
-
-};
-
-#endif // HAVE_LIBSSH2
-
-//}}}
-//{{{ SSHTransfer --------------------------------------------------------------
-
-/**
- * Transfers a file to SSH (upload).
- */
-class SSHTransfer : public URLTransfer {
-
- public:
-
- /**
- * Creates a SSHTransfer object.
- *
- * @exception KError when initialising the underlying library fails
- */
- SSHTransfer(const RootDirURLVector &urlv, const std::string &subdir)
- throw (KError);
-
- /**
- * Destroys a SSHTransfer object.
- */
- ~SSHTransfer()
- throw ();
-
- /**
- * Transfers the file.
- *
- * @see Transfer::perform()
- */
- void perform(DataProvider *dataprovider,
- const StringVector &target_files,
- bool *directSave)
- throw (KError);
-
- private:
- char m_buffer[BUFSIZ];
-
- StringVector makeArgs(std::string const &remote);
-};
-
-//}}}
//{{{ NFSTransfer -------------------------------------------------------------
/**