File kdump-sftp-init-session.patch of Package kdump

From: Petr Tesarik <ptesarik@suse.cz>
Date: Tue, 14 Apr 2015 11:40:43 +0200
Subject: Initialize an SFTP session
References: FATE#318874, bsc#917747
Patch-mainline: v0.8.16
Git-commit: b3e46fd6db3e681915a1a686805bbdf24563a938

Implement the initial SFTP request-response handling.

Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
---
 kdumptool/sshtransfer.cc |   67 +++++++++++++++++++++++++++++++++++++++++++++++
 kdumptool/sshtransfer.h  |   16 +++++++++++
 2 files changed, 83 insertions(+)

--- a/kdumptool/sshtransfer.cc
+++ b/kdumptool/sshtransfer.cc
@@ -368,6 +368,18 @@ SFTPTransfer::SFTPTransfer(const RootDir
 
     m_fdreq = m_process.getPipeFD(STDIN_FILENO);
     m_fdresp = m_process.getPipeFD(STDOUT_FILENO);
+
+    SFTPPacket initpkt;
+    initpkt.addByte(SSH_FXP_INIT);
+    initpkt.addInt32(MY_PROTO_VER);
+    sendPacket(initpkt);
+    recvPacket(initpkt);
+    unsigned char type = initpkt.getByte();
+    if (type != SSH_FXP_VERSION)
+	throw KError(KString("Invalid response to SSH_FXP_INIT: type ") +
+		     Stringutil::number2string(unsigned(type)));
+    m_proto_ver = initpkt.getInt32();
+    Debug::debug()->dbg("Remote SFTP version %lu", m_proto_ver);
 }
 
 /* -------------------------------------------------------------------------- */
@@ -424,4 +436,59 @@ StringVector SFTPTransfer::makeArgs(void
     return ret;
 }
 
+/* -------------------------------------------------------------------------- */
+void SFTPTransfer::sendPacket(SFTPPacket &pkt)
+{
+    const ByteVector bv = pkt.update();
+    const unsigned char *bufp = bv.data();
+    size_t buflen = bv.size();
+
+    while (buflen) {
+	ssize_t len = write(m_fdreq, bufp, buflen);
+	if (len < 0)
+	    throw KSystemError("SFTPTransfer::sendPacket: write failed",
+			       errno);
+	bufp += len;
+	buflen -= len;
+    }
+}
+
+/* -------------------------------------------------------------------------- */
+void SFTPTransfer::recvBuffer(unsigned char *bufp, size_t buflen)
+{
+    while (buflen) {
+	ssize_t len = read(m_fdresp, bufp, buflen);
+	if (len < 0)
+	    throw KSystemError("SFTPTransfer::recvPacket: read failed",
+			       errno);
+	else if (!len)
+	    throw KError("SFTPTransfer::recvPacket: unexpected EOF");
+
+	bufp += len;
+	buflen -= len;
+    }
+}
+
+/* -------------------------------------------------------------------------- */
+void SFTPTransfer::recvPacket(SFTPPacket &pkt)
+{
+    ByteVector buffer;
+
+    buffer.resize(sizeof(uint32_t));
+    recvBuffer(buffer.data(), sizeof(uint32_t));
+    pkt.setData(buffer);
+    size_t length = pkt.getInt32();
+
+    buffer.resize(BUFSIZ);
+    while (length > 0) {
+	if (buffer.size() > length)
+	    buffer.resize(length);
+
+	recvBuffer(buffer.data(), buffer.size());
+	pkt.addByteVector(buffer);
+
+	length -= buffer.size();
+    }
+}
+
 //}}}
--- a/kdumptool/sshtransfer.h
+++ b/kdumptool/sshtransfer.h
@@ -117,6 +117,14 @@ typedef KCodeError<KSFTPErrorCode> KSFTP
 //{{{ SFTPPacket ---------------------------------------------------------------
 
 /**
+ * Packet types defined by protocol (incomplete list)
+ */
+enum {
+    SSH_FXP_INIT	=   1,
+    SSH_FXP_VERSION	=   2,
+};
+
+/**
  * Encode/decode an SFTP packet.
  */
 class SFTPPacket {
@@ -196,11 +204,19 @@ class SFTPTransfer : public URLTransfer
                      bool *directSave)
         throw (KError);
 
+    protected:
+	static const int MY_PROTO_VER = 3; // our advertised version
+
     private:
 	SubProcess m_process;
 	int m_fdreq, m_fdresp;
+	unsigned long m_proto_ver; // remote SFTP protocol version
 
 	StringVector makeArgs(void);
+
+	void sendPacket(SFTPPacket &pkt);
+	void recvPacket(SFTPPacket &pkt);
+	void recvBuffer(unsigned char *bufp, size_t buflen);
 };
 
 //}}}
openSUSE Build Service is sponsored by