summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIru Cai <mytbk920423@gmail.com>2018-05-09 16:33:50 +0800
committerIru Cai <mytbk920423@gmail.com>2018-05-10 14:16:42 +0800
commitedaca3e9ce514aeddde04d9f022dddfc179bf744 (patch)
tree504083543bc7c795d2875ca12de13c0be6f5847d
parent456110b0c3165498f3b2b41a0dd10c7d6769ebaa (diff)
downloadfqterm-edaca3e9ce514aeddde04d9f022dddfc179bf744.tar.xz
fqterm packet: use C buffer
Tested using SSH2
-rw-r--r--src/protocol/fqterm_ssh_socket.cpp9
-rw-r--r--src/protocol/internal/fqterm_ssh1_packet.cpp65
-rw-r--r--src/protocol/internal/fqterm_ssh2_kex.cpp40
-rw-r--r--src/protocol/internal/fqterm_ssh2_packet.cpp189
-rw-r--r--src/protocol/internal/fqterm_ssh2_packet.h1
-rw-r--r--src/protocol/internal/fqterm_ssh_channel.cpp15
-rw-r--r--src/protocol/internal/fqterm_ssh_kex.cpp2
-rw-r--r--src/protocol/internal/fqterm_ssh_packet.cpp148
-rw-r--r--src/protocol/internal/fqterm_ssh_packet.h16
-rw-r--r--src/protocol/internal/ssh_mac.h2
10 files changed, 271 insertions, 216 deletions
diff --git a/src/protocol/fqterm_ssh_socket.cpp b/src/protocol/fqterm_ssh_socket.cpp
index c48fc51..ea0f774 100644
--- a/src/protocol/fqterm_ssh_socket.cpp
+++ b/src/protocol/fqterm_ssh_socket.cpp
@@ -270,10 +270,11 @@ void FQTermSSHSocket::connectToHost(const QString &host_name, quint16 port) {
private_socket_->connectToHost(host_name, port);
}
-void FQTermSSHSocket::writeData() {
- socketWriteBlock((const char*)packet_sender_->output_buffer_->data(),
- packet_sender_->output_buffer_->len());
- private_socket_->flush();
+void FQTermSSHSocket::writeData()
+{
+ socketWriteBlock((const char*)buffer_data(&packet_sender_->data_to_send),
+ buffer_len(&packet_sender_->data_to_send));
+ private_socket_->flush();
}
void FQTermSSHSocket::handlePacket(int type) {
diff --git a/src/protocol/internal/fqterm_ssh1_packet.cpp b/src/protocol/internal/fqterm_ssh1_packet.cpp
index aab8f92..78a8bda 100644
--- a/src/protocol/internal/fqterm_ssh1_packet.cpp
+++ b/src/protocol/internal/fqterm_ssh1_packet.cpp
@@ -47,34 +47,31 @@ namespace FQTerm {
cipher = new_3des_ssh1(1);
}
-void FQTermSSH1PacketSender::makePacket() {
- int len, padding, i;
- u_int32_t rand_val = 0;
-
- delete output_buffer_;
-
- len = buffer_->len() + 4; //CRC32
- padding = 8-(len % 8);
-
- output_buffer_ = new FQTermSSHBuffer(len + padding + 4); //pktlen and crc32
- output_buffer_->putInt(len);
-
- for (i = 0; i < padding; i++) {
- if (i % 4 == 0) {
- rand_val = rand(); // FIXME: rand() doesn't range from 0 to 2^32.
- }
-
- output_buffer_->putByte(rand_val &0xff);
- rand_val >>= 8;
- }
-
- output_buffer_->putRawData((const char*)buffer_->data(), buffer_->len());
- output_buffer_->putInt(ssh_crc32(output_buffer_->data() + 4, output_buffer_->len() - 4));
-
- if (is_encrypt_) {
- cipher->crypt(cipher, output_buffer_->data() + 4, output_buffer_->data() + 4, output_buffer_->len() - 4);
- }
-
+void FQTermSSH1PacketSender::makePacket()
+{
+ int len, padding_len;
+ uint32_t padding[2];
+ uint8_t *data = buffer_data(&orig_data);
+ size_t data_len = buffer_len(&orig_data);
+
+ len = data_len + 4; //CRC32
+ padding_len = 8 - (len % 8);
+ padding[0] = rand();
+ padding[1] = rand();
+
+ buffer_clear(&data_to_send);
+ buffer_append_be32(&data_to_send, len);
+ buffer_append(&data_to_send, (const uint8_t*)padding, padding_len);
+ buffer_append(&data_to_send, data, data_len);
+ buffer_append_be32(&data_to_send, ssh_crc32(
+ buffer_data(&data_to_send) + 4,
+ buffer_len(&data_to_send) - 4));
+
+ if (is_encrypt_) {
+ cipher->crypt(cipher, buffer_data(&data_to_send) + 4,
+ buffer_data(&data_to_send) + 4,
+ buffer_len(&data_to_send) - 4);
+ }
}
//==============================================================================
@@ -110,7 +107,7 @@ void FQTermSSH1PacketReceiver::parseData(FQTermSSHBuffer *input) {
u_int padding_len = total_len - real_data_len_;
real_data_len_ -= 5;
- buffer_->clear();
+ buffer_clear(&recvbuf);
// Get the data of the packet.
if (input->len() - 4 < (long)total_len) {
@@ -131,12 +128,12 @@ void FQTermSSH1PacketReceiver::parseData(FQTermSSHBuffer *input) {
memcpy(targetData, sourceData, total_len);
}
- buffer_->putRawData((char*)targetData, total_len);
+ buffer_append(&recvbuf, targetData, total_len);
// Check the crc32.
- buf = buffer_->data() + total_len - 4;
+ buf = buffer_data(&recvbuf) + total_len - 4;
mycrc = ntohu32(buf);
- gotcrc = ssh_crc32(buffer_->data(), total_len - 4);
+ gotcrc = ssh_crc32(buffer_data(&recvbuf), total_len - 4);
if (mycrc != gotcrc) {
emit packetError(tr("parseData: bad CRC32"));
@@ -144,9 +141,9 @@ void FQTermSSH1PacketReceiver::parseData(FQTermSSHBuffer *input) {
}
// Drop the padding.
- buffer_->consume(padding_len);
+ buffer_consume(&recvbuf, padding_len);
- packet_type_ = buffer_->getByte();
+ packet_type_ = buffer_get_u8(&recvbuf);
emit packetAvaliable(packet_type_);
diff --git a/src/protocol/internal/fqterm_ssh2_kex.cpp b/src/protocol/internal/fqterm_ssh2_kex.cpp
index 8566e92..ab62ede 100644
--- a/src/protocol/internal/fqterm_ssh2_kex.cpp
+++ b/src/protocol/internal/fqterm_ssh2_kex.cpp
@@ -128,7 +128,7 @@ bool FQTermSSH2Kex::negotiateAlgorithms() {
delete[] I_S_;
I_S_ = new char[I_S_len_];
I_S_[0] = SSH2_MSG_KEXINIT;
- memcpy(I_S_ + 1, packet_receiver_->buffer_->data(), I_S_len_ - 1);
+ memcpy(I_S_ + 1, buffer_data(&packet_receiver_->recvbuf), I_S_len_ - 1);
// 1. Parse server kex init packet
packet_receiver_->getRawData((char*)cookie_, 16);
@@ -218,7 +218,7 @@ bool FQTermSSH2Kex::negotiateAlgorithms() {
// 2. compose a kex init packet.
packet_sender_->startPacket(SSH2_MSG_KEXINIT);
- packet_sender_->putRawData((const char*)cookie_, 16); // FIXME: generate new cookie_;
+ packet_sender_->putRawData((const uint8_t*)cookie_, 16); // FIXME: generate new cookie_;
packet_sender_->putString(all_dh_list);
packet_sender_->putString("ssh-rsa");
packet_sender_->putString(all_ciphers_list);
@@ -234,10 +234,10 @@ bool FQTermSSH2Kex::negotiateAlgorithms() {
packet_sender_->putInt(0);
// 3. backup the payload of this client packet.
- I_C_len_ = packet_sender_->buffer_->len();
+ I_C_len_ = buffer_len(&packet_sender_->orig_data);
delete[] I_C_;
I_C_ = new char[I_C_len_];
- memcpy(I_C_, packet_sender_->buffer_->data(), I_C_len_);
+ memcpy(I_C_, buffer_data(&packet_sender_->orig_data), I_C_len_);
// 4. send packet to server
packet_sender_->write();
@@ -259,10 +259,11 @@ bool FQTermSSH2Kex::negotiateAlgorithms() {
* string signature of H
*/
-void FQTermSSH2Kex::exchangeKey() {
- packet_sender_->startPacket(SSH2_MSG_KEXDH_INIT);
- packet_sender_->putRawData((const char*)sess.dh->mpint_e, sess.dh->e_len);
- packet_sender_->write();
+void FQTermSSH2Kex::exchangeKey()
+{
+ packet_sender_->startPacket(SSH2_MSG_KEXDH_INIT);
+ packet_sender_->putRawData(sess.dh->mpint_e, sess.dh->e_len);
+ packet_sender_->write();
}
static RSA *CreateRSAContext(unsigned char *host_key, int len);
@@ -289,19 +290,20 @@ bool FQTermSSH2Kex::verifyKey() {
int s_len = -1;
unsigned char *s = (unsigned char *)packet_receiver_->getString(&s_len);
- FQTermSSHBuffer *buffer = packet_sender_->output_buffer_;
+ buffer vbuf;
+ buffer_init(&vbuf);
+ buffer_append_string(&vbuf, V_C_, strlen(V_C_));
+ buffer_append_string(&vbuf, V_S_, strlen(V_S_));
+ buffer_append_string(&vbuf, I_C_, I_C_len_);
+ buffer_append_string(&vbuf, I_S_, I_S_len_);
+ buffer_append_string(&vbuf, K_S_, K_S_len_);
+ buffer_append(&vbuf, sess.dh->mpint_e, sess.dh->e_len);
+ buffer_append_string(&vbuf, (const char*)mpint_f, mpint_f_len);
+ buffer_append(&vbuf, sess.dh->secret, sess.dh->secret_len);
- buffer->clear();
- buffer->putString(V_C_);
- buffer->putString(V_S_);
- buffer->putString(I_C_, I_C_len_);
- buffer->putString(I_S_, I_S_len_);
- buffer->putString(K_S_, K_S_len_);
- buffer->putRawData((const char*)sess.dh->mpint_e, sess.dh->e_len);
- buffer->putString((const char*)mpint_f, mpint_f_len);
- buffer->putRawData((const char*)sess.dh->secret, sess.dh->secret_len);
+ ssh_dh_hash(sess.dh, buffer_data(&vbuf), sess.H, buffer_len(&vbuf));
- ssh_dh_hash(sess.dh, buffer->data(), sess.H, buffer->len());
+ buffer_deinit(&vbuf);
// Start verify
// ssh-rsa specifies SHA-1 hashing
diff --git a/src/protocol/internal/fqterm_ssh2_packet.cpp b/src/protocol/internal/fqterm_ssh2_packet.cpp
index 6b95972..4399757 100644
--- a/src/protocol/internal/fqterm_ssh2_packet.cpp
+++ b/src/protocol/internal/fqterm_ssh2_packet.cpp
@@ -23,7 +23,7 @@
#include "fqterm_ssh2_packet.h"
#include "fqterm_serialization.h"
-#include "crc32.h"
+#include "buffer.h"
namespace FQTerm {
//==============================================================================
@@ -37,103 +37,89 @@ namespace FQTerm {
// byte[m] mac (Message Authentication Code - MAC); m = mac_length
//==============================================================================
-void FQTermSSH2PacketSender::makePacket() {
- FQ_TRACE("ssh2packet", 9) << "----------------------------Send "
- << (is_encrypt_ ? "Encrypted": "plain")
- << " Packet---->>>>>>>";
+void FQTermSSH2PacketSender::makePacket()
+{
+ FQ_TRACE("ssh2packet", 9) << "----------------------------Send "
+ << (is_encrypt_ ? "Encrypted": "plain")
+ << " Packet---->>>>>>>";
- // 0. compress
- if (is_compressed_) {
- FQ_VERIFY(false);
- }
+ // 0. compress
+ if (is_compressed_)
+ FQ_VERIFY(false);
- // 1. compute the padding length for padding.
- int non_padding_len = 4 + 1 + buffer_->len();
+ // 1. compute the padding length for padding.
+ int non_padding_len = 4 + 1 + buffer_len(&orig_data);
- int padding_block_len = 8;
- if (is_encrypt_ && cipher->blkSize > padding_block_len) {
- padding_block_len = cipher->blkSize;
- }
+ int padding_block_len = 8;
+ if (is_encrypt_ && cipher->blkSize > padding_block_len)
+ padding_block_len = cipher->blkSize;
- int padding_len = padding_block_len - (non_padding_len % padding_block_len);
- if (padding_len < 4) {
- padding_len += padding_block_len;
- }
+ int padding_len = padding_block_len - (non_padding_len % padding_block_len);
+ if (padding_len < 4)
+ padding_len += padding_block_len;
- // 2. renew the output buffer.
- int total_len = non_padding_len + padding_len;
- if (is_mac_)
- total_len += mac->dgstSize;
+ // 2. renew the output buffer.
+ int total_len = non_padding_len + padding_len;
+ if (is_mac_)
+ total_len += mac->dgstSize;
- delete output_buffer_;
- output_buffer_ = new FQTermSSHBuffer(total_len);
+ buffer_clear(&data_to_send);
- // 3. Fill the output buffer.
- int packet_len = 1 + buffer_->len() + padding_len;
+ // 3. Fill the output buffer.
+ int packet_len = 1 + buffer_len(&orig_data) + padding_len;
- output_buffer_->putInt(packet_len);
- output_buffer_->putByte(padding_len);
- output_buffer_->putRawData((const char*)buffer_->data(), buffer_->len());
+ buffer_append_be32(&data_to_send, packet_len);
+ buffer_append_byte(&data_to_send, padding_len);
+ buffer_append(&data_to_send, buffer_data(&orig_data), buffer_len(&orig_data));
- u_int32_t rand_val = 0;
- for (int i = 0; i < padding_len; i++) {
- if (i % 4 == 0) {
- rand_val = rand(); // FIXME: rand() doesn't range from 0 to 2^32.
- }
- output_buffer_->putByte(rand_val & 0xff);
- rand_val >>= 8;
- }
+ uint32_t padding[8]; /* padding at most 256 bits */
+ for (int i = 0; i < 8; i++)
+ padding[i] = rand();
+ buffer_append(&data_to_send, (const uint8_t*)padding, padding_len);
- // 4. Add MAC on the entire unencrypted packet,
- // including two length fields, 'payload' and 'random padding'.
- if (is_mac_) {
- const unsigned char *packet = output_buffer_->data();
- int len = output_buffer_->len();
-
- FQTermSSHBuffer buffer(4 + len);
- buffer.putInt(sequence_no_);
- buffer.putRawData((const char *)packet, len);
-
- std::vector<u_char> digest(mac->dgstSize);
- mac->getmac(mac, buffer.data(), buffer.len(), &digest[0]);
-
- FQ_TRACE("ssh2packet", 9) << "Making packets...";
- FQ_TRACE("ssh2packet", 9) << "Append MAC with sequence_no_" << sequence_no_;
- FQ_TRACE("ssh2packet", 9) << "Compute MAC with "
- << buffer.len() << " bytes data:\n"
- << dumpHexString << std::string((char *)buffer.data(), buffer.len());
- FQ_TRACE("ssh2packet", 9) << "MAC data "
- << digest.size() << " bytes:\n"
- << dumpHexString << std::string((const char *)&digest[0], digest.size());
-
- output_buffer_->putRawData((const char *)&digest[0], digest.size());
- }
+ // 4. Add MAC on the entire unencrypted packet,
+ // including two length fields, 'payload' and 'random padding'.
+ if (is_mac_) {
+ const unsigned char *packet = buffer_data(&data_to_send);
+ int len = buffer_len(&data_to_send);
- if (is_compressed_) {
- FQ_VERIFY(false);
- }
+ uint8_t digest[MAX_DGSTLEN];
+
+ buffer mbuffer;
+ buffer_init(&mbuffer);
+ buffer_append_be32(&mbuffer, sequence_no_);
+ buffer_append(&mbuffer, packet, len);
+ mac->getmac(mac, buffer_data(&mbuffer), buffer_len(&mbuffer), digest);
+ buffer_deinit(&mbuffer);
+
+ buffer_append(&data_to_send, digest, mac->dgstSize);
+ }
+
+ if (is_compressed_) {
+ FQ_VERIFY(false);
+ }
- if (is_encrypt_) {
- // as RFC 4253:
- // When encryption is in effect, the packet length, padding
- // length, payload, and padding fields of each packet MUST be encrypted
- // with the given algorithm.
+ if (is_encrypt_) {
+ // as RFC 4253:
+ // When encryption is in effect, the packet length, padding
+ // length, payload, and padding fields of each packet MUST be encrypted
+ // with the given algorithm.
- u_char *data = output_buffer_->data();
- int len = output_buffer_->len() - mac->dgstSize;
+ uint8_t *data = buffer_data(&data_to_send);
+ int len = buffer_len(&data_to_send) - mac->dgstSize;
- FQ_TRACE("ssh2packet", 9) << "An packet (without MAC) to be encrypted:"
- << len << " bytes:\n"
- << dumpHexString << std::string((const char *)data, len);
+ FQ_TRACE("ssh2packet", 9) << "An packet (without MAC) to be encrypted:"
+ << len << " bytes:\n"
+ << dumpHexString << std::string((const char *)data, len);
- FQ_VERIFY(cipher->crypt(cipher, data, data, len)==1);
+ FQ_VERIFY(cipher->crypt(cipher, data, data, len)==1);
- FQ_TRACE("ssh2packet", 9) << "An encrypted packet (without MAC) made:"
- << len << " bytes:\n"
- << dumpHexString << std::string((const char *)data, len);
- }
+ FQ_TRACE("ssh2packet", 9) << "An encrypted packet (without MAC) made:"
+ << len << " bytes:\n"
+ << dumpHexString << std::string((const char *)data, len);
+ }
- ++sequence_no_;
+ ++sequence_no_;
}
//==============================================================================
@@ -192,23 +178,26 @@ void FQTermSSH2PacketReceiver::parseData(FQTermSSHBuffer *input) {
FQ_VERIFY(cipher->crypt(cipher, tmp, tmp, left_len)==1);
}
- // 3. check MAC
+ // 3. check MAC
if (is_mac_) {
- int digest_len = mac->dgstSize;
- std::vector<u_char> digest(digest_len);
-
- FQTermSSHBuffer buffer(4 + expected_input_len - digest_len);
- buffer.putInt(sequence_no_);
- buffer.putRawData((const char *)input->data(), expected_input_len - digest_len);
- mac->getmac(mac, buffer.data(), buffer.len(), &digest[0]);
-
- u_char *received_digest = input->data() + expected_input_len - digest_len;
-
- if (memcmp(&digest[0], received_digest, digest_len) != 0) {
- emit packetError("incorrect MAC.");
- return ;
- }
- }
+ int digest_len = mac->dgstSize;
+ uint8_t digest[MAX_DGSTLEN];
+
+ buffer mbuf;
+ buffer_init(&mbuf);
+ buffer_append_be32(&mbuf, sequence_no_);
+ buffer_append(&mbuf, (const uint8_t*)input->data(),
+ expected_input_len - digest_len);
+ mac->getmac(mac, buffer_data(&mbuf), buffer_len(&mbuf), digest);
+ buffer_deinit(&mbuf);
+
+ u_char *received_digest = input->data() + expected_input_len - digest_len;
+
+ if (memcmp(digest, received_digest, digest_len) != 0) {
+ emit packetError("incorrect MAC.");
+ return ;
+ }
+ }
// 4. get every field of the ssh packet.
packet_len = input->getInt();
@@ -223,14 +212,14 @@ void FQTermSSH2PacketReceiver::parseData(FQTermSSHBuffer *input) {
real_data_len_ = packet_len - 1 - padding_len;
- buffer_->clear();
- buffer_->putRawData((char*)&data[0] + 1, real_data_len_);
+ buffer_clear(&recvbuf);
+ buffer_append(&recvbuf, &data[0] + 1, real_data_len_);
FQ_TRACE("ssh2packet", 9) << "Receive " << real_data_len_ << " bytes payload:\n"
<< dumpHexString << std::string((char *)&data[0] + 1, real_data_len_);
// 5. notify others a ssh packet is parsed successfully.
- packet_type_ = buffer_->getByte();
+ packet_type_ = buffer_get_u8(&recvbuf);
real_data_len_ -= 1;
emit packetAvaliable(packet_type_);
diff --git a/src/protocol/internal/fqterm_ssh2_packet.h b/src/protocol/internal/fqterm_ssh2_packet.h
index f2e6b0f..7c7bf63 100644
--- a/src/protocol/internal/fqterm_ssh2_packet.h
+++ b/src/protocol/internal/fqterm_ssh2_packet.h
@@ -22,6 +22,7 @@
#define FQTERM_SSH2_PACKET_H
#include "fqterm_ssh_packet.h"
+#include "buffer.h"
namespace FQTerm {
diff --git a/src/protocol/internal/fqterm_ssh_channel.cpp b/src/protocol/internal/fqterm_ssh_channel.cpp
index 1e338c9..e997121 100644
--- a/src/protocol/internal/fqterm_ssh_channel.cpp
+++ b/src/protocol/internal/fqterm_ssh_channel.cpp
@@ -67,7 +67,7 @@ void FQTermSSH1Channel::changeTermSize(int col, int row) {
void FQTermSSH1Channel::sendData(const char *data, int len) {
packet_sender_->startPacket(SSH1_CMSG_STDIN_DATA);
packet_sender_->putInt(len);
- packet_sender_->putRawData(data, len);
+ packet_sender_->putRawData((const uint8_t *)data, len);
packet_sender_->write();
}
@@ -98,7 +98,7 @@ void FQTermSSH1Channel::handlePacket(int type) {
case SSH1_SMSG_STDOUT_DATA:
case SSH1_SMSG_STDERR_DATA:
{
- const char *data = (const char *)packet_receiver_->buffer_->data() + 4;
+ const char *data = (const char*)buffer_data(&packet_receiver_->recvbuf) + 4;
int len = packet_receiver_->packetDataLen() - 4;
emit channelReadyRead(data, len);
}
@@ -336,7 +336,7 @@ void FQTermSSH2Channel::processChannelPacket() {
// string data
packet_receiver_->consume(4);
int len = packet_receiver_->getInt();
- const char *data = (const char *)packet_receiver_->buffer_->data();
+ const char *data = (const char*)buffer_data(&packet_receiver_->recvbuf);
local_window_size_ -= len;
checkLocalWindowSize();
emit channelReadyRead(data, len);
@@ -349,7 +349,7 @@ void FQTermSSH2Channel::processChannelPacket() {
// string data
packet_receiver_->consume(4);
int len = packet_receiver_->getInt();
- const char *data = (const char *)packet_receiver_->buffer_->data();
+ const char *data = (const char*)buffer_data(&packet_receiver_->recvbuf);
local_window_size_ -= len;
checkLocalWindowSize();
emit channelReadyRead(data, len);
@@ -377,9 +377,10 @@ void FQTermSSH2Channel::processChannelPacket() {
}
}
-void FQTermSSH2Channel::handlePacket(int type) {
+void FQTermSSH2Channel::handlePacket(int type)
+{
// first check the channel id.
- u_int32_t channel_id = ntohu32(packet_receiver_->buffer_->data());
+ u_int32_t channel_id = ntohu32(buffer_data(&packet_receiver_->recvbuf));
if (channel_id != channel_id_) {
return;
}
@@ -400,7 +401,7 @@ void FQTermSSH2Channel::handlePacket(int type) {
FQ_TRACE("ssh2channel", 8) << "SSH2_MSG_CHANNEL_REQUEST isn't supported, just send back a packet with SSH2_MSG_CHANNEL_SUCCESS if reply is needed.";
packet_receiver_->consume(4);
- u_int32_t len = ntohu32(packet_receiver_->buffer_->data());
+ u_int32_t len = ntohu32(buffer_data(&packet_receiver_->recvbuf));
packet_receiver_->consume(4 + len);
bool replyNeeded = packet_receiver_->getByte();
diff --git a/src/protocol/internal/fqterm_ssh_kex.cpp b/src/protocol/internal/fqterm_ssh_kex.cpp
index e2975d1..910eb26 100644
--- a/src/protocol/internal/fqterm_ssh_kex.cpp
+++ b/src/protocol/internal/fqterm_ssh_kex.cpp
@@ -178,7 +178,7 @@ void FQTermSSH1Kex::makeSessionKey() {
packet_sender_->startPacket(SSH1_CMSG_SESSION_KEY);
packet_sender_->putByte(SSH_CIPHER_3DES);
- packet_sender_->putRawData((const char*)cookie_, 8);
+ packet_sender_->putRawData((const uint8_t*)cookie_, 8);
packet_sender_->putBN(key);
BN_free(key);
diff --git a/src/protocol/internal/fqterm_ssh_packet.cpp b/src/protocol/internal/fqterm_ssh_packet.cpp
index 6e40de8..5db2385 100644
--- a/src/protocol/internal/fqterm_ssh_packet.cpp
+++ b/src/protocol/internal/fqterm_ssh_packet.cpp
@@ -25,6 +25,7 @@
#include "fqterm_serialization.h"
#include "crc32.h"
+#include <openssl/bn.h>
namespace FQTerm {
@@ -32,9 +33,10 @@ namespace FQTerm {
//FQTermSSHPacketSender
//==============================================================================
-FQTermSSHPacketSender::FQTermSSHPacketSender() {
- buffer_ = new FQTermSSHBuffer(1024);
- output_buffer_ = new FQTermSSHBuffer(1024);
+FQTermSSHPacketSender::FQTermSSHPacketSender()
+{
+ buffer_init(&orig_data);
+ buffer_init(&data_to_send);
is_encrypt_ = false;
cipher_type_ = SSH_CIPHER_NONE;
@@ -48,43 +50,56 @@ FQTermSSHPacketSender::FQTermSSHPacketSender() {
sequence_no_ = 0;
}
-FQTermSSHPacketSender::~FQTermSSHPacketSender() {
- delete buffer_;
- delete output_buffer_;
+FQTermSSHPacketSender::~FQTermSSHPacketSender()
+{
if (cipher)
cipher->cleanup(cipher);
if (mac)
mac->cleanup(mac);
+ buffer_deinit(&data_to_send);
+ buffer_deinit(&orig_data);
}
-void FQTermSSHPacketSender::putRawData(const char *data, int len) {
- buffer_->putRawData(data, len);
-}
-
-void FQTermSSHPacketSender::putByte(int data) {
- buffer_->putByte(data);
-}
-
-void FQTermSSHPacketSender::putInt(u_int data) {
- buffer_->putInt(data);
-}
-
-void FQTermSSHPacketSender::putString(const char *string, int len) {
- buffer_->putString(string, len);
-}
+void FQTermSSHPacketSender::putString(const char *s, int len)
+{
+ if (len < 0)
+ len = strlen(s);
-void FQTermSSHPacketSender::putBN(BIGNUM *bn) {
- buffer_->putSSH1BN(bn);
+ putInt(len);
+ putRawData((const uint8_t *)s, len);
}
-void FQTermSSHPacketSender::startPacket(int pkt_type) {
- buffer_->clear();
- buffer_->putByte(pkt_type);
+void FQTermSSHPacketSender::putBN(BIGNUM *bignum)
+{
+ int bits = BN_num_bits(bignum);
+ int bin_size = (bits + 7) / 8;
+ uint8_t buf[bin_size];
+ int oi;
+ uint8_t msg[2];
+
+ // Get the value of in binary
+ oi = BN_bn2bin(bignum, buf);
+ if (oi != bin_size) {
+ FQ_TRACE("sshbuffer", 0) << "BN_bn2bin() failed: oi = " << oi
+ << " != bin_size." << bin_size;
+ }
+
+ // Store the number of bits in the buffer in two bytes, msb first
+ buffer_append_be16(&orig_data, bits);
+ // Store the binary data.
+ putRawData(buf, oi);
+}
+
+void FQTermSSHPacketSender::startPacket(uint8_t pkt_type)
+{
+ buffer_clear(&orig_data);
+ putByte(pkt_type);
}
-void FQTermSSHPacketSender::write() {
- makePacket();
- emit dataToWrite();
+void FQTermSSHPacketSender::write()
+{
+ makePacket();
+ emit dataToWrite();
}
void FQTermSSHPacketSender::startEncryption(const u_char *key, const u_char *IV) {
@@ -114,8 +129,9 @@ void FQTermSSHPacketSender::resetMac() {
//FQTermSSHPacketReceiver
//==============================================================================
-FQTermSSHPacketReceiver::FQTermSSHPacketReceiver() {
- buffer_ = new FQTermSSHBuffer(1024);
+FQTermSSHPacketReceiver::FQTermSSHPacketReceiver()
+{
+ buffer_init(&recvbuf);
is_decrypt_ = false;
cipher_type_ = SSH_CIPHER_NONE;
@@ -131,35 +147,79 @@ FQTermSSHPacketReceiver::FQTermSSHPacketReceiver() {
FQTermSSHPacketReceiver::~FQTermSSHPacketReceiver()
{
- delete buffer_;
+ buffer_deinit(&recvbuf);
if (cipher)
cipher->cleanup(cipher);
if (mac)
mac->cleanup(mac);
}
-void FQTermSSHPacketReceiver::getRawData(char *data, int length) {
- buffer_->getRawData(data, length);
+void FQTermSSHPacketReceiver::getRawData(char *data, int length)
+{
+ if (buffer_len(&recvbuf) >= length)
+ buffer_get(&recvbuf, (uint8_t*)data, length);
+ else
+ emit packetError("Read too many bytes!");
}
-u_char FQTermSSHPacketReceiver::getByte() {
- return buffer_->getByte();
+u_char FQTermSSHPacketReceiver::getByte()
+{
+ if (buffer_len(&recvbuf) >= 1)
+ return buffer_get_u8(&recvbuf);
+ else
+ emit packetError("Read too many bytes!");
}
-u_int FQTermSSHPacketReceiver::getInt() {
- return buffer_->getInt();
+u_int FQTermSSHPacketReceiver::getInt()
+{
+ if (buffer_len(&recvbuf) >= 4)
+ return buffer_get_u32(&recvbuf);
+ else
+ emit packetError("Read too many bytes!");
}
-void *FQTermSSHPacketReceiver::getString(int *length) {
- return buffer_->getString(length);
+void *FQTermSSHPacketReceiver::getString(int *length)
+{
+ uint32_t l = getInt();
+ char *data = new char[l+1];
+ getRawData(data, l);
+ data[l] = 0;
+ if (length != NULL)
+ *length = l;
+ return data;
}
-void FQTermSSHPacketReceiver::getBN(BIGNUM *bignum) {
- buffer_->getSSH1BN(bignum);
+void FQTermSSHPacketReceiver::getBN(BIGNUM *bignum)
+{
+ int bits, bytes;
+ u_char buf[2];
+ u_char *bin;
+
+ // Get the number for bits.
+ if (buffer_len(&recvbuf) >= 2) {
+ bits = buffer_get_u16(&recvbuf);
+ } else {
+ emit packetError("Read too many bytes!");
+ return;
+ }
+ // Compute the number of binary bytes that follow.
+ bytes = (bits + 7) / 8;
+ if (bytes > 8 *1024) {
+ emit packetError("Can't handle BN of size!");
+ return ;
+ }
+ if (buffer_len(&recvbuf) < bytes) {
+ emit packetError("The input buffer is too small!");
+ return ;
+ }
+ bin = buffer_data(&recvbuf);
+ BN_bin2bn(bin, bytes, bignum);
+ buffer_consume(&recvbuf, bytes);
}
-void FQTermSSHPacketReceiver::consume(int len) {
- buffer_->consume(len);
+void FQTermSSHPacketReceiver::consume(int len)
+{
+ buffer_consume(&recvbuf, len);
}
void FQTermSSHPacketReceiver::startEncryption(const u_char *key, const u_char *IV) {
diff --git a/src/protocol/internal/fqterm_ssh_packet.h b/src/protocol/internal/fqterm_ssh_packet.h
index 83dcac7..32f9a29 100644
--- a/src/protocol/internal/fqterm_ssh_packet.h
+++ b/src/protocol/internal/fqterm_ssh_packet.h
@@ -30,25 +30,27 @@
#include "ssh_mac.h"
#include "fqterm_serialization.h"
#include "ssh_cipher.h"
+#include "buffer.h"
namespace FQTerm {
class FQTermSSHPacketSender: public QObject {
Q_OBJECT;
public:
- FQTermSSHBuffer *output_buffer_;
- FQTermSSHBuffer *buffer_;
+ buffer orig_data; /* always unencrypted */
+ buffer data_to_send;
ssh_cipher_t *cipher;
ssh_mac_t *mac;
FQTermSSHPacketSender();
virtual ~FQTermSSHPacketSender();
- void startPacket(int pkt_type);
- void putByte(int data);
- void putInt(u_int data);
+ void startPacket(uint8_t pkt_type);
+ inline void putByte(uint8_t b) { buffer_append_byte(&orig_data, b); }
+ inline void putInt(uint32_t x) { buffer_append_be32(&orig_data, x); }
void putString(const char *string, int len = -1);
- void putRawData(const char *data, int length);
+ inline void putRawData(const uint8_t *data, size_t len)
+ { buffer_append(&orig_data, data, len); }
void putBN(BIGNUM *bignum);
void write();
@@ -84,7 +86,7 @@ class FQTermSSHPacketSender: public QObject {
class FQTermSSHPacketReceiver: public QObject {
Q_OBJECT;
public:
- FQTermSSHBuffer *buffer_;
+ buffer recvbuf;
ssh_cipher_t *cipher;
ssh_mac_t *mac;
diff --git a/src/protocol/internal/ssh_mac.h b/src/protocol/internal/ssh_mac.h
index 507a9cd..8e44095 100644
--- a/src/protocol/internal/ssh_mac.h
+++ b/src/protocol/internal/ssh_mac.h
@@ -24,6 +24,8 @@
#include <stdint.h>
#include <openssl/evp.h>
+#define MAX_DGSTLEN 128
+
#ifdef __cplusplus
extern "C" {
#endif