bool AbstractSshPacket::isComplete() const { if (currentDataSize() < minPacketSize()) return false; Q_ASSERT(4 + length() + macLength() >= currentDataSize()); return 4 + length() + macLength() == currentDataSize(); }
void SshIncomingPacket::consumeData(QByteArray &newData) { #ifdef CREATOR_SSH_DEBUG qDebug("%s: current data size = %d, new data size = %d", Q_FUNC_INFO, m_data.size(), newData.size()); #endif if (isComplete() || newData.isEmpty()) return; /* * Until we have reached the minimum packet size, we cannot decrypt the * length field. */ const quint32 minSize = minPacketSize(); if (currentDataSize() < minSize) { const int bytesToTake = qMin<quint32>(minSize - currentDataSize(), newData.size()); moveFirstBytes(m_data, newData, bytesToTake); #ifdef CREATOR_SSH_DEBUG qDebug("Took %d bytes from new data", bytesToTake); #endif if (currentDataSize() < minSize) return; } if (4 + length() + macLength() < currentDataSize()) throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, "Server sent invalid packet."); const int bytesToTake = qMin<quint32>(length() + 4 + macLength() - currentDataSize(), newData.size()); moveFirstBytes(m_data, newData, bytesToTake); #ifdef CREATOR_SSH_DEBUG qDebug("Took %d bytes from new data", bytesToTake); #endif if (isComplete()) { #ifdef CREATOR_SSH_DEBUG qDebug("Message complete. Overall size: %u, payload size: %u", m_data.size(), m_length - paddingLength() - 1); #endif decrypt(); ++m_serverSeqNr; } }
void SshIncomingPacket::calculateLength() const { Q_ASSERT(currentDataSize() >= minPacketSize()); #ifdef CREATOR_SSH_DEBUG qDebug("Length field before decryption: %d-%d-%d-%d", m_data.at(0) & 0xff, m_data.at(1) & 0xff, m_data.at(2) & 0xff, m_data.at(3) & 0xff); #endif m_decrypter.decrypt(m_data, 0, cipherBlockSize()); #ifdef CREATOR_SSH_DEBUG qDebug("Length field after decryption: %d-%d-%d-%d", m_data.at(0) & 0xff, m_data.at(1) & 0xff, m_data.at(2) & 0xff, m_data.at(3) & 0xff); qDebug("message type = %d", m_data.at(TypeOffset)); #endif m_length = SshPacketParser::asUint32(m_data, static_cast<quint32>(0)); #ifdef CREATOR_SSH_DEBUG qDebug("decrypted length is %u", m_length); #endif }
SshKeyExchangeReply SshIncomingPacket::extractKeyExchangeReply(const QByteArray &pubKeyAlgo) const { Q_ASSERT(isComplete()); Q_ASSERT(type() == SSH_MSG_KEXDH_REPLY); try { SshKeyExchangeReply replyData; quint32 offset = TypeOffset + 1; const quint32 k_sLength = SshPacketParser::asUint32(m_data, &offset); if (offset + k_sLength > currentDataSize()) throw SshPacketParseException(); replyData.k_s = m_data.mid(offset - 4, k_sLength + 4); if (SshPacketParser::asString(m_data, &offset) != pubKeyAlgo) throw SshPacketParseException(); // DSS: p and q, RSA: e and n replyData.parameters << SshPacketParser::asBigInt(m_data, &offset); replyData.parameters << SshPacketParser::asBigInt(m_data, &offset); // g and y if (pubKeyAlgo == SshCapabilities::PubKeyDss) { replyData.parameters << SshPacketParser::asBigInt(m_data, &offset); replyData.parameters << SshPacketParser::asBigInt(m_data, &offset); } replyData.f = SshPacketParser::asBigInt(m_data, &offset); offset += 4; if (SshPacketParser::asString(m_data, &offset) != pubKeyAlgo) throw SshPacketParseException(); replyData.signatureBlob = SshPacketParser::asString(m_data, &offset); return replyData; } catch (SshPacketParseException &) { throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED, "Key exchange failed: " "Server sent invalid SSH_MSG_KEXDH_REPLY packet."); } }