summaryrefslogtreecommitdiffstats
path: root/coreplugin/ssh/sshoutgoingpacket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'coreplugin/ssh/sshoutgoingpacket.cpp')
-rw-r--r--coreplugin/ssh/sshoutgoingpacket.cpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/coreplugin/ssh/sshoutgoingpacket.cpp b/coreplugin/ssh/sshoutgoingpacket.cpp
new file mode 100644
index 0000000..c6cf994
--- /dev/null
+++ b/coreplugin/ssh/sshoutgoingpacket.cpp
@@ -0,0 +1,284 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "sshoutgoingpacket_p.h"
+
+#include "sshcapabilities_p.h"
+#include "sshcryptofacility_p.h"
+
+#include <QtCore/QtEndian>
+
+namespace Core {
+namespace Internal {
+
+SshOutgoingPacket::SshOutgoingPacket(const SshEncryptionFacility &encrypter,
+ const quint32 &seqNr) : m_encrypter(encrypter), m_seqNr(seqNr)
+{
+}
+
+quint32 SshOutgoingPacket::cipherBlockSize() const
+{
+ return qMax(m_encrypter.cipherBlockSize(), 4U);
+}
+
+quint32 SshOutgoingPacket::macLength() const
+{
+ return m_encrypter.macLength();
+}
+
+void SshOutgoingPacket::generateKeyExchangeInitPacket()
+{
+ const QByteArray &supportedkeyExchangeMethods
+ = encodeNameList(SshCapabilities::KeyExchangeMethods);
+ const QByteArray &supportedPublicKeyAlgorithms
+ = encodeNameList(SshCapabilities::PublicKeyAlgorithms);
+ const QByteArray &supportedEncryptionAlgorithms
+ = encodeNameList(SshCapabilities::EncryptionAlgorithms);
+ const QByteArray &supportedMacAlgorithms
+ = encodeNameList(SshCapabilities::MacAlgorithms);
+ const QByteArray &supportedCompressionAlgorithms
+ = encodeNameList(SshCapabilities::CompressionAlgorithms);
+ const QByteArray &supportedLanguages = encodeNameList(QList<QByteArray>());
+
+ init(SSH_MSG_KEXINIT);
+ m_data += m_encrypter.getRandomNumbers(16);
+ m_data.append(supportedkeyExchangeMethods);
+ m_data.append(supportedPublicKeyAlgorithms);
+ m_data.append(supportedEncryptionAlgorithms)
+ .append(supportedEncryptionAlgorithms);
+ m_data.append(supportedMacAlgorithms).append(supportedMacAlgorithms);
+ m_data.append(supportedCompressionAlgorithms)
+ .append(supportedCompressionAlgorithms);
+ m_data.append(supportedLanguages).append(supportedLanguages);
+ appendBool(false); // No guessed packet.
+ m_data.append(QByteArray(4, 0)); // Reserved.
+ finalize();
+}
+
+void SshOutgoingPacket::generateKeyDhInitPacket(const Botan::BigInt &e)
+{
+ init(SSH_MSG_KEXDH_INIT).appendMpInt(e).finalize();
+}
+
+void SshOutgoingPacket::generateNewKeysPacket()
+{
+ init(SSH_MSG_NEWKEYS).finalize();
+}
+
+void SshOutgoingPacket::generateUserAuthServiceRequestPacket()
+{
+ generateServiceRequest("ssh-userauth");
+}
+
+void SshOutgoingPacket::generateServiceRequest(const QByteArray &service)
+{
+ init(SSH_MSG_SERVICE_REQUEST).appendString(service).finalize();
+}
+
+void SshOutgoingPacket::generateUserAuthByPwdRequestPacket(const QByteArray &user,
+ const QByteArray &service, const QByteArray &pwd)
+{
+ init(SSH_MSG_USERAUTH_REQUEST).appendString(user).appendString(service)
+ .appendString("password").appendBool(false).appendString(pwd)
+ .finalize();
+}
+
+void SshOutgoingPacket::generateUserAuthByKeyRequestPacket(const QByteArray &user,
+ const QByteArray &service)
+{
+ init(SSH_MSG_USERAUTH_REQUEST).appendString(user).appendString(service)
+ .appendString("publickey").appendBool(true)
+ .appendString(m_encrypter.authenticationAlgorithmName())
+ .appendString(m_encrypter.authenticationPublicKey());
+ const QByteArray &dataToSign = m_data.mid(PayloadOffset);
+ appendString(m_encrypter.authenticationKeySignature(dataToSign));
+ finalize();
+}
+
+void SshOutgoingPacket::generateRequestFailurePacket()
+{
+ init(SSH_MSG_REQUEST_FAILURE).finalize();
+}
+
+void SshOutgoingPacket::generateSessionPacket(quint32 channelId,
+ quint32 windowSize, quint32 maxPacketSize)
+{
+ init(SSH_MSG_CHANNEL_OPEN).appendString("session").appendInt(channelId)
+ .appendInt(windowSize).appendInt(maxPacketSize).finalize();
+}
+
+void SshOutgoingPacket::generateEnvPacket(quint32 remoteChannel,
+ const QByteArray &var, const QByteArray &value)
+{
+ init(SSH_MSG_CHANNEL_REQUEST).appendInt(remoteChannel).appendString("env")
+ .appendBool(false).appendString(var).appendString(value);
+}
+
+void SshOutgoingPacket::generateExecPacket(quint32 remoteChannel,
+ const QByteArray &command)
+{
+ init(SSH_MSG_CHANNEL_REQUEST).appendInt(remoteChannel).appendString("exec")
+ .appendBool(true).appendString(command).finalize();
+}
+
+void SshOutgoingPacket::generateSftpPacket(quint32 remoteChannel)
+{
+ init(SSH_MSG_CHANNEL_REQUEST).appendInt(remoteChannel)
+ .appendString("subsystem").appendBool(true).appendString("sftp")
+ .finalize();
+}
+
+void SshOutgoingPacket::generateWindowAdjustPacket(quint32 remoteChannel,
+ quint32 bytesToAdd)
+{
+ init(SSH_MSG_CHANNEL_WINDOW_ADJUST).appendInt(remoteChannel)
+ .appendInt(bytesToAdd).finalize();
+}
+
+void SshOutgoingPacket::generateChannelDataPacket(quint32 remoteChannel,
+ const QByteArray &data)
+{
+ init(SSH_MSG_CHANNEL_DATA).appendInt(remoteChannel).appendString(data)
+ .finalize();
+}
+
+void SshOutgoingPacket::generateChannelSignalPacket(quint32 remoteChannel,
+ const QByteArray &signalName)
+{
+ init(SSH_MSG_CHANNEL_REQUEST).appendInt(remoteChannel)
+ .appendString("signal").appendBool(false).appendString(signalName)
+ .finalize();
+}
+
+void SshOutgoingPacket::generateChannelEofPacket(quint32 remoteChannel)
+{
+ init(SSH_MSG_CHANNEL_EOF).appendInt(remoteChannel).finalize();
+}
+
+void SshOutgoingPacket::generateChannelClosePacket(quint32 remoteChannel)
+{
+ init(SSH_MSG_CHANNEL_CLOSE).appendInt(remoteChannel).finalize();
+}
+
+void SshOutgoingPacket::generateDisconnectPacket(SshErrorCode reason,
+ const QByteArray &reasonString)
+{
+ init(SSH_MSG_DISCONNECT).appendInt(reason).appendString(reasonString)
+ .appendString(QByteArray()).finalize();
+}
+
+void SshOutgoingPacket::generateMsgUnimplementedPacket(quint32 serverSeqNr)
+{
+ init(SSH_MSG_UNIMPLEMENTED).appendInt(serverSeqNr).finalize();
+}
+
+SshOutgoingPacket &SshOutgoingPacket::appendInt(quint32 val)
+{
+ m_data.append(encodeInt(val));
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::appendMpInt(const Botan::BigInt &number)
+{
+ m_data.append(encodeMpInt(number));
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::appendBool(bool b)
+{
+ m_data += static_cast<char>(b);
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::appendString(const QByteArray &string)
+{
+ m_data.append(encodeString(string));
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::init(SshPacketType type)
+{
+ m_data.resize(TypeOffset + 1);
+ m_data[TypeOffset] = type;
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::setPadding()
+{
+ m_data += m_encrypter.getRandomNumbers(MinPaddingLength);
+ int padLength = MinPaddingLength;
+ const int divisor = sizeDivisor();
+ const int mod = m_data.size() % divisor;
+ padLength += divisor - mod;
+ m_data += m_encrypter.getRandomNumbers(padLength - MinPaddingLength);
+ m_data[PaddingLengthOffset] = padLength;
+ return *this;
+}
+
+SshOutgoingPacket &SshOutgoingPacket::encrypt()
+{
+ const QByteArray &mac
+ = generateMac(m_encrypter, m_seqNr);
+ m_encrypter.encrypt(m_data);
+ m_data += mac;
+ return *this;
+}
+
+void SshOutgoingPacket::finalize()
+{
+ setPadding();
+ setLengthField(m_data);
+ m_length = m_data.size() - 4;
+#ifdef CREATOR_SSH_DEBUG
+ qDebug("Encrypting packet of type %u", m_data.at(TypeOffset));
+#endif
+ encrypt();
+ Q_ASSERT(isComplete());
+}
+
+int SshOutgoingPacket::sizeDivisor() const
+{
+ return qMax(cipherBlockSize(), 8U);
+}
+
+QByteArray SshOutgoingPacket::encodeNameList(const QList<QByteArray> &list)
+{
+ QByteArray data;
+ data.resize(4);
+ for (int i = 0; i < list.count(); ++i) {
+ if (i > 0)
+ data.append(',');
+ data.append(list.at(i));
+ }
+ AbstractSshPacket::setLengthField(data);
+ return data;
+}
+
+} // namespace Internal
+} // namespace Core