SSH: Fix TCP/IP forwarding support.

We hardcoded the remote host to the SSH server for some reason, and the
originating port was bogus as well.

Change-Id: I8f6700bc12f4374302dd3bfc035c9c9f060f56ef
Reviewed-by: Caspar Romot <cro@icd.ee>
Reviewed-by: Christian Kandeler <christian.kandeler@theqtcompany.com>
This commit is contained in:
Christian Kandeler
2015-04-14 15:47:55 +02:00
parent aee5668b62
commit bde83c30bf
10 changed files with 57 additions and 48 deletions

View File

@@ -170,11 +170,11 @@ QSsh::SftpChannel::Ptr SshChannelManager::createSftpChannel()
return sftp;
}
SshDirectTcpIpTunnel::Ptr SshChannelManager::createTunnel(quint16 remotePort,
const SshConnectionInfo &connectionInfo)
SshDirectTcpIpTunnel::Ptr SshChannelManager::createTunnel(const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort)
{
SshDirectTcpIpTunnel::Ptr tunnel(new SshDirectTcpIpTunnel(m_nextLocalChannelId++, remotePort,
connectionInfo, m_sendFacility));
SshDirectTcpIpTunnel::Ptr tunnel(new SshDirectTcpIpTunnel(m_nextLocalChannelId++,
originatingHost, originatingPort, remoteHost, remotePort, m_sendFacility));
insertChannel(tunnel->d, tunnel);
return tunnel;
}

View File

@@ -37,7 +37,6 @@
namespace QSsh {
class SftpChannel;
class SshConnectionInfo;
class SshDirectTcpIpTunnel;
class SshRemoteProcess;
@@ -56,8 +55,8 @@ public:
QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command);
QSharedPointer<SshRemoteProcess> createRemoteShell();
QSharedPointer<SftpChannel> createSftpChannel();
QSharedPointer<SshDirectTcpIpTunnel> createTunnel(quint16 remotePort,
const SshConnectionInfo &connectionInfo);
QSharedPointer<SshDirectTcpIpTunnel> createTunnel(const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort);
int channelCount() const;
enum CloseAllMode { CloseAllRegular, CloseAllAndReset };

View File

@@ -184,10 +184,11 @@ QSharedPointer<SftpChannel> SshConnection::createSftpChannel()
return d->createSftpChannel();
}
SshDirectTcpIpTunnel::Ptr SshConnection::createTunnel(quint16 remotePort)
SshDirectTcpIpTunnel::Ptr SshConnection::createTunnel(const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort)
{
QSSH_ASSERT_AND_RETURN_VALUE(state() == Connected, SshDirectTcpIpTunnel::Ptr());
return d->createTunnel(remotePort);
return d->createTunnel(originatingHost, originatingPort, remoteHost, remotePort);
}
int SshConnection::closeAllChannels()
@@ -828,9 +829,10 @@ QSharedPointer<SftpChannel> SshConnectionPrivate::createSftpChannel()
return m_channelManager->createSftpChannel();
}
SshDirectTcpIpTunnel::Ptr SshConnectionPrivate::createTunnel(quint16 remotePort)
SshDirectTcpIpTunnel::Ptr SshConnectionPrivate::createTunnel(const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort)
{
return m_channelManager->createTunnel(remotePort, m_conn->connectionInfo());
return m_channelManager->createTunnel(originatingHost, originatingPort, remoteHost, remotePort);
}
const quint64 SshConnectionPrivate::InvalidSeqNr = static_cast<quint64>(-1);

View File

@@ -127,7 +127,8 @@ public:
QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command);
QSharedPointer<SshRemoteProcess> createRemoteShell();
QSharedPointer<SftpChannel> createSftpChannel();
QSharedPointer<SshDirectTcpIpTunnel> createTunnel(quint16 remotePort);
QSharedPointer<SshDirectTcpIpTunnel> createTunnel(const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort);
// -1 if an error occurred, number of channels closed otherwise.
int closeAllChannels();

View File

@@ -89,7 +89,8 @@ public:
QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command);
QSharedPointer<SshRemoteProcess> createRemoteShell();
QSharedPointer<SftpChannel> createSftpChannel();
QSharedPointer<SshDirectTcpIpTunnel> createTunnel(quint16 remotePort);
QSharedPointer<SshDirectTcpIpTunnel> createTunnel(const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort);
SshStateInternal state() const { return m_state; }
SshError error() const { return m_error; }

View File

@@ -38,11 +38,14 @@
namespace QSsh {
namespace Internal {
SshDirectTcpIpTunnelPrivate::SshDirectTcpIpTunnelPrivate(quint32 channelId, quint16 remotePort,
const SshConnectionInfo &connectionInfo, SshSendFacility &sendFacility)
SshDirectTcpIpTunnelPrivate::SshDirectTcpIpTunnelPrivate(quint32 channelId,
const QString &originatingHost, quint16 originatingPort, const QString &remoteHost,
quint16 remotePort, SshSendFacility &sendFacility)
: AbstractSshChannel(channelId, sendFacility),
m_remotePort(remotePort),
m_connectionInfo(connectionInfo)
m_originatingHost(originatingHost),
m_originatingPort(originatingPort),
m_remoteHost(remoteHost),
m_remotePort(remotePort)
{
connect(this, SIGNAL(eof()), SLOT(handleEof()));
}
@@ -112,9 +115,11 @@ void SshDirectTcpIpTunnelPrivate::handleEof()
using namespace Internal;
SshDirectTcpIpTunnel::SshDirectTcpIpTunnel(quint32 channelId, quint16 remotePort,
const SshConnectionInfo &connectionInfo, SshSendFacility &sendFacility)
: d(new SshDirectTcpIpTunnelPrivate(channelId, remotePort, connectionInfo, sendFacility))
SshDirectTcpIpTunnel::SshDirectTcpIpTunnel(quint32 channelId, const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort,
SshSendFacility &sendFacility)
: d(new SshDirectTcpIpTunnelPrivate(channelId, originatingHost, originatingPort, remoteHost,
remotePort, sendFacility))
{
connect(d, SIGNAL(initialized()), SIGNAL(initialized()), Qt::QueuedConnection);
connect(d, SIGNAL(readyRead()), SIGNAL(readyRead()), Qt::QueuedConnection);
@@ -156,9 +161,8 @@ void SshDirectTcpIpTunnel::initialize()
try {
QIODevice::open(QIODevice::ReadWrite);
d->m_sendFacility.sendDirectTcpIpPacket(d->localChannelId(), d->initialWindowSize(),
d->maxPacketSize(), d->m_connectionInfo.peerAddress.toString().toUtf8(),
d->m_remotePort, d->m_connectionInfo.localAddress.toString().toUtf8(),
d->m_connectionInfo.localPort);
d->maxPacketSize(), d->m_remoteHost.toUtf8(), d->m_remotePort,
d->m_originatingHost.toUtf8(), d->m_originatingPort);
d->setChannelState(AbstractSshChannel::SessionRequested);
d->m_timeoutTimer.start(d->ReplyTimeout);
} catch (const Botan::Exception &e) { // Won't happen, but let's play it safe.

View File

@@ -37,7 +37,6 @@
#include <QSharedPointer>
namespace QSsh {
class SshConnectionInfo;
namespace Internal {
class SshChannelManager;
@@ -71,8 +70,9 @@ signals:
void tunnelClosed();
private:
SshDirectTcpIpTunnel(quint32 channelId, quint16 remotePort,
const SshConnectionInfo &connectionInfo, Internal::SshSendFacility &sendFacility);
SshDirectTcpIpTunnel(quint32 channelId, const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort,
Internal::SshSendFacility &sendFacility);
// QIODevice stuff
qint64 readData(char *data, qint64 maxlen);

View File

@@ -32,8 +32,6 @@
#include "sshchannel_p.h"
#include "sshconnection.h"
namespace QSsh {
class SshDirectTcpIpTunnel;
@@ -46,8 +44,9 @@ class SshDirectTcpIpTunnelPrivate : public AbstractSshChannel
friend class QSsh::SshDirectTcpIpTunnel;
public:
explicit SshDirectTcpIpTunnelPrivate(quint32 channelId, quint16 remotePort,
const SshConnectionInfo &connectionInfo, SshSendFacility &sendFacility);
explicit SshDirectTcpIpTunnelPrivate(quint32 channelId, const QString &originatingHost,
quint16 originatingPort, const QString &remoteHost, quint16 remotePort,
SshSendFacility &sendFacility);
signals:
void initialized();
@@ -71,8 +70,10 @@ private:
void closeHook();
const QString m_originatingHost;
const quint16 m_originatingPort;
const QString m_remoteHost;
const quint16 m_remotePort;
const SshConnectionInfo m_connectionInfo;
QByteArray m_data;
};

View File

@@ -48,7 +48,7 @@ using namespace QSsh;
Tunnel::Tunnel(const SshConnectionParameters &parameters, QObject *parent)
: QObject(parent),
m_connection(new SshConnection(parameters, this)),
m_tunnelServer(new QTcpServer(this)),
m_targetServer(new QTcpServer(this)),
m_expectingChannelClose(false)
{
connect(m_connection, SIGNAL(connected()), SLOT(handleConnected()));
@@ -74,16 +74,17 @@ void Tunnel::handleConnectionError()
void Tunnel::handleConnected()
{
std::cout << "Opening server side..." << std::endl;
if (!m_tunnelServer->listen(QHostAddress::LocalHost)) {
if (!m_targetServer->listen(QHostAddress::LocalHost)) {
std::cerr << "Error opening port: "
<< m_tunnelServer->errorString().toLocal8Bit().constData() << std::endl;
<< m_targetServer->errorString().toLocal8Bit().constData() << std::endl;
qApp->exit(EXIT_FAILURE);
return;
}
m_forwardedPort = m_tunnelServer->serverPort();
connect(m_tunnelServer, SIGNAL(newConnection()), SLOT(handleNewConnection()));
m_targetPort = m_targetServer->serverPort();
connect(m_targetServer, SIGNAL(newConnection()), SLOT(handleNewConnection()));
m_tunnel = m_connection->createTunnel(m_forwardedPort);
m_tunnel = m_connection->createTunnel(QLatin1String("localhost"), 1024, // made-up values
QLatin1String("localhost"), m_targetPort);
connect(m_tunnel.data(), SIGNAL(initialized()), SLOT(handleInitialized()));
connect(m_tunnel.data(), SIGNAL(error(QString)), SLOT(handleTunnelError(QString)));
connect(m_tunnel.data(), SIGNAL(readyRead()), SLOT(handleServerData()));
@@ -108,7 +109,7 @@ void Tunnel::handleServerData()
if (m_dataReceivedFromServer == ServerDataPrefix + TestData) {
std::cout << "Data exchange successful. Closing server socket..." << std::endl;
m_expectingChannelClose = true;
m_tunnelSocket->close();
m_targetSocket->close();
}
}
@@ -132,27 +133,27 @@ void Tunnel::handleTunnelClosed()
void Tunnel::handleNewConnection()
{
m_tunnelSocket = m_tunnelServer->nextPendingConnection();
m_tunnelServer->close();
connect(m_tunnelSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(handleSocketError()));
connect(m_tunnelSocket, SIGNAL(readyRead()), SLOT(handleClientData()));
m_targetSocket = m_targetServer->nextPendingConnection();
m_targetServer->close();
connect(m_targetSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(handleSocketError()));
connect(m_targetSocket, SIGNAL(readyRead()), SLOT(handleClientData()));
handleClientData();
}
void Tunnel::handleSocketError()
{
std::cerr << "Socket error: " << m_tunnelSocket->errorString().toLocal8Bit().constData()
std::cerr << "Socket error: " << m_targetSocket->errorString().toLocal8Bit().constData()
<< std::endl;
qApp->exit(EXIT_FAILURE);
}
void Tunnel::handleClientData()
{
m_dataReceivedFromClient += m_tunnelSocket->readAll();
m_dataReceivedFromClient += m_targetSocket->readAll();
if (m_dataReceivedFromClient == TestData) {
std::cout << "Client data successfully received by server, now sending data to client..."
<< std::endl;
m_tunnelSocket->write(ServerDataPrefix + m_dataReceivedFromClient);
m_targetSocket->write(ServerDataPrefix + m_dataReceivedFromClient);
}
}

View File

@@ -68,9 +68,9 @@ private slots:
private:
QSsh::SshConnection * const m_connection;
QSharedPointer<QSsh::SshDirectTcpIpTunnel> m_tunnel;
QTcpServer * const m_tunnelServer;
QTcpSocket *m_tunnelSocket;
quint16 m_forwardedPort;
QTcpServer * const m_targetServer;
QTcpSocket *m_targetSocket;
quint16 m_targetPort;
QByteArray m_dataReceivedFromServer;
QByteArray m_dataReceivedFromClient;
bool m_expectingChannelClose;