SSH: Close channels before re-using a connection.

Otherwise a new client acquiring the connection could be affected by
things happening in channels that were not opened by that client, which
would certainly be unexpected.
In particular, if the new owner of the connection runs in a different
thread than the old one, crashes could occur since the connection
assumes its channels run in the same thread.

Change-Id: I4fdf2b5a3751ed506631d6878e94342da033c31c
Reviewed-by: Tobias Hunger <tobias.hunger@nokia.com>
This commit is contained in:
Christian Kandeler
2012-06-20 15:55:30 +02:00
parent 621e5c3dbe
commit c1a89d2c61
5 changed files with 23 additions and 4 deletions

View File

@@ -178,12 +178,14 @@ void SshChannelManager::insertChannel(AbstractSshChannel *priv,
m_sessions.insert(priv, pub);
}
void SshChannelManager::closeAllChannels()
int SshChannelManager::closeAllChannels()
{
const int count = m_channels.count();
for (ChannelIterator it = m_channels.begin(); it != m_channels.end(); ++it)
it.value()->closeChannel();
m_channels.clear();
m_sessions.clear();
return count;
}
void SshChannelManager::removeChannel(ChannelIterator it)

View File

@@ -57,7 +57,7 @@ public:
QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command);
QSharedPointer<SshRemoteProcess> createRemoteShell();
QSharedPointer<SftpChannel> createSftpChannel();
void closeAllChannels();
int closeAllChannels();
void handleChannelRequest(const SshIncomingPacket &packet);
void handleChannelOpen(const SshIncomingPacket &packet);

View File

@@ -193,6 +193,15 @@ QSharedPointer<SftpChannel> SshConnection::createSftpChannel()
return d->createSftpChannel();
}
int SshConnection::closeAllChannels()
{
try {
return d->m_channelManager->closeAllChannels();
} catch (const Botan::Exception &e) {
qDebug("%s: %s", Q_FUNC_INFO, e.what());
return -1;
}
}
namespace Internal {

View File

@@ -106,6 +106,9 @@ public:
QSharedPointer<SshRemoteProcess> createRemoteShell();
QSharedPointer<SftpChannel> createSftpChannel();
// -1 if an error occurred, number of channels closed otherwise.
int closeAllChannels();
signals:
void connected();
void disconnected();

View File

@@ -145,10 +145,15 @@ public:
break;
}
}
if (!haveConnection)
if (!haveConnection) {
// Let's nag clients who release connections with open channels.
const int channelCount = connection->closeAllChannels();
QSSH_ASSERT(channelCount == 0);
m_unacquiredConnections.append(connection);
else
} else {
doDelete = true;
}
}
if (doDelete) {