From ef70cc73c69d04e93c9af5fb49c5d762ba226801 Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Sat, 28 Apr 2018 21:50:54 +0800 Subject: Add a connection info field in FQTermSocket - the connection info record contains the name of the cipher and MAC algorithms, and the key hash - after doing a key exchange, the connection info will be filled --- src/protocol/connect_info.h | 25 +++++++++++++++++++++++++ src/protocol/fqterm_local_socket.cpp | 1 + src/protocol/fqterm_socket.h | 6 ++++++ src/protocol/fqterm_ssh_socket.cpp | 17 ++++++++++++++--- src/protocol/fqterm_telnet_socket.cpp | 1 + src/protocol/internal/fqterm_ssh2_kex.cpp | 31 ++++++++++++++++++++++++++----- src/protocol/internal/fqterm_ssh2_kex.h | 9 ++++++--- src/protocol/internal/fqterm_ssh_kex.h | 2 +- 8 files changed, 80 insertions(+), 12 deletions(-) create mode 100644 src/protocol/connect_info.h diff --git a/src/protocol/connect_info.h b/src/protocol/connect_info.h new file mode 100644 index 0000000..0111a39 --- /dev/null +++ b/src/protocol/connect_info.h @@ -0,0 +1,25 @@ +#ifndef CONNECT_INFO_H +#define CONNECT_INFO_H + +enum protocol +{ + PROTO_LOCAL, + PROTO_TELNET, + PROTO_SSH +}; + +typedef struct +{ + enum protocol proto; + struct + { + int proto_version; + const char *c2s_cipher; + const char *s2c_cipher; + const char *c2s_mac; + const char *s2c_mac; + unsigned char hash[32]; + } ssh_proto_info; +} conn_info_t; + +#endif diff --git a/src/protocol/fqterm_local_socket.cpp b/src/protocol/fqterm_local_socket.cpp index dbfb5b1..dc81acd 100644 --- a/src/protocol/fqterm_local_socket.cpp +++ b/src/protocol/fqterm_local_socket.cpp @@ -15,6 +15,7 @@ FQTermLocalSocket::FQTermLocalSocket() //TODO: Error //FQ_VERIFY(connect(shell_process_, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(error(QAbstractSocket::SocketError)))); //FQ_VERIFY(connect(shell_process_, SIGNAL(socketState(int)), this, SIGNAL(socketState(int)))); + conn_info.proto = PROTO_LOCAL; } FQTermLocalSocket::~FQTermLocalSocket() diff --git a/src/protocol/fqterm_socket.h b/src/protocol/fqterm_socket.h index 11112c3..02b16eb 100644 --- a/src/protocol/fqterm_socket.h +++ b/src/protocol/fqterm_socket.h @@ -51,6 +51,8 @@ #include #include +#include "connect_info.h" + class QTcpSocket; namespace FQTerm { /* @@ -115,6 +117,9 @@ class FQTermSocketPrivate: public QObject { class FQTermSocket: public QObject { Q_OBJECT; +protected: + conn_info_t conn_info; + public: FQTermSocket(QObject *parent = 0): QObject(parent) {} @@ -133,6 +138,7 @@ class FQTermSocket: public QObject { virtual unsigned long bytesAvailable() = 0; virtual bool readyForInput() {return true;} virtual bool setTermSize(int col, int row) {return 0;} + virtual conn_info_t * connectionInfo() { return &conn_info; } signals: void sshAuthOK(); void connected(); diff --git a/src/protocol/fqterm_ssh_socket.cpp b/src/protocol/fqterm_ssh_socket.cpp index 20612bf..c48fc51 100644 --- a/src/protocol/fqterm_ssh_socket.cpp +++ b/src/protocol/fqterm_ssh_socket.cpp @@ -161,11 +161,22 @@ void FQTermSSHSocket::init(int ssh_version) { key_exchanger_->initKex(packet_receiver_, packet_sender_); } + + conn_info.proto = PROTO_SSH; + conn_info.ssh_proto_info.proto_version = ssh_version; } -void FQTermSSHSocket::kexOK() { - FQ_TRACE("sshsocket", 3) << "Key exchange completed!"; - authentication_->initAuth(packet_receiver_, packet_sender_); +void FQTermSSHSocket::kexOK() +{ + FQ_TRACE("sshsocket", 3) << "Key exchange completed!"; + conn_info.ssh_proto_info.c2s_cipher = packet_sender_->cipher->name; + conn_info.ssh_proto_info.s2c_cipher = packet_receiver_->cipher->name; + if (packet_sender_->mac) + conn_info.ssh_proto_info.c2s_mac = packet_sender_->mac->name; + if (packet_receiver_->mac) + conn_info.ssh_proto_info.s2c_mac = packet_receiver_->mac->name; + key_exchanger_->hostKeyHash(conn_info.ssh_proto_info.hash); + authentication_->initAuth(packet_receiver_, packet_sender_); } void FQTermSSHSocket::authOK() { diff --git a/src/protocol/fqterm_telnet_socket.cpp b/src/protocol/fqterm_telnet_socket.cpp index af04a8c..170edb9 100644 --- a/src/protocol/fqterm_telnet_socket.cpp +++ b/src/protocol/fqterm_telnet_socket.cpp @@ -13,6 +13,7 @@ FQTermTelnetSocket::FQTermTelnetSocket() FQ_VERIFY(connect(private_socket_, SIGNAL(readyRead()), this, SIGNAL(readyRead()))); FQ_VERIFY(connect(private_socket_, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(error(QAbstractSocket::SocketError)))); FQ_VERIFY(connect(private_socket_, SIGNAL(socketState(int)), this, SIGNAL(socketState(int)))); + conn_info.proto = PROTO_TELNET; } FQTermTelnetSocket::~FQTermTelnetSocket() { diff --git a/src/protocol/internal/fqterm_ssh2_kex.cpp b/src/protocol/internal/fqterm_ssh2_kex.cpp index 570c29f..f51f459 100644 --- a/src/protocol/internal/fqterm_ssh2_kex.cpp +++ b/src/protocol/internal/fqterm_ssh2_kex.cpp @@ -42,6 +42,7 @@ FQTermSSH2Kex::FQTermSSH2Kex(const char *V_C, const char *V_S) I_C_ = NULL; I_S_len_ = 0; I_S_ = NULL; + K_S_ = NULL; bn_x_ = BN_new(); bn_e_ = BN_new(); @@ -56,6 +57,8 @@ FQTermSSH2Kex::FQTermSSH2Kex(const char *V_C, const char *V_S) FQTermSSH2Kex::~FQTermSSH2Kex() { delete[] I_C_; delete[] I_S_; + if (K_S_) + delete [] K_S_; BN_clear_free(bn_x_); BN_clear_free(bn_e_); @@ -110,6 +113,24 @@ void FQTermSSH2Kex::handlePacket(int type) bool FQTermSSH2Kex::negotiateAlgorithms() { FQ_FUNC_TRACE("ssh2kex", 10); + /* + * RFC 4253 section 7: kex begins by the following packet + * byte SSH_MSG_KEXINIT + * byte[16] cookie (random bytes) + * name-list kex_algorithms + * name-list server_host_key_algorithms + * name-list encryption_algorithms_client_to_server + * name-list encryption_algorithms_server_to_client + * name-list mac_algorithms_client_to_server + * name-list mac_algorithms_server_to_client + * name-list compression_algorithms_client_to_server + * name-list compression_algorithms_server_to_client + * name-list languages_client_to_server + * name-list languages_server_to_client + * boolean first_kex_packet_follows + * uint32 0 (reserved for future extension) + */ + if (packet_receiver_->packetType() != SSH2_MSG_KEXINIT) { emit kexError(tr("startKex: First packet is not SSH_MSG_KEXINIT")); return false; @@ -256,8 +277,9 @@ bool FQTermSSH2Kex::verifyKey() { // Extract data - int K_S_len = -1; - unsigned char *K_S = (unsigned char *)packet_receiver_->getString(&K_S_len); + if (K_S_) + delete [] K_S_; + K_S_ = (char*)packet_receiver_->getString(&K_S_len_); packet_receiver_->getBN2(bn_f_); @@ -273,7 +295,7 @@ bool FQTermSSH2Kex::verifyKey() { buffer->putString(V_S_); buffer->putString(I_C_, I_C_len_); buffer->putString(I_S_, I_S_len_); - buffer->putString((char *)K_S, K_S_len); + buffer->putString(K_S_, K_S_len_); buffer->putSSH2BN(bn_e_); buffer->putSSH2BN(bn_f_); buffer->putSSH2BN(bn_K_); @@ -287,7 +309,7 @@ bool FQTermSSH2Kex::verifyKey() { // Ignore the first 15 bytes of the signature of H sent from server: // algorithm_name_length[4], algorithm_name[7]("ssh-rsa") and signature_length[4]. - RSA *rsactx = CreateRSAContext(K_S, K_S_len); + RSA *rsactx = CreateRSAContext((unsigned char*)K_S_, K_S_len_); int sig_len = s_len - 15; unsigned char *sig = s + 15; int res = RSA_verify(NID_sha1, s_H, SHA_DIGEST_LENGTH, @@ -295,7 +317,6 @@ bool FQTermSSH2Kex::verifyKey() { RSA_free(rsactx); - delete [] K_S; delete [] s; return res == 1; diff --git a/src/protocol/internal/fqterm_ssh2_kex.h b/src/protocol/internal/fqterm_ssh2_kex.h index 0a09cc1..80da76d 100644 --- a/src/protocol/internal/fqterm_ssh2_kex.h +++ b/src/protocol/internal/fqterm_ssh2_kex.h @@ -55,6 +55,8 @@ private: char *I_C_; int I_S_len_; char *I_S_; + int K_S_len_; + char *K_S_; SSH_DH *dh; BIGNUM *bn_x_; @@ -70,9 +72,6 @@ private: bool is_first_kex_; - ssh_pubkey_t *host_key_; - ssh_pubkey_t *server_key_; - u_char cookie_[16]; int server_flag_, ciphers_, auth_; // u_char session_id_[16]; @@ -92,6 +91,10 @@ public: virtual void initKex(FQTermSSHPacketReceiver *packetReceiver, FQTermSSHPacketSender *outputSender); + void hostKeyHash(unsigned char *md) + { + SHA256((const unsigned char*)K_S_, K_S_len_, md); + } public slots: void handlePacket(int type); diff --git a/src/protocol/internal/fqterm_ssh_kex.h b/src/protocol/internal/fqterm_ssh_kex.h index f84c0d5..2bd46b8 100644 --- a/src/protocol/internal/fqterm_ssh_kex.h +++ b/src/protocol/internal/fqterm_ssh_kex.h @@ -53,7 +53,7 @@ public: virtual void initKex(FQTermSSHPacketReceiver *packetReceiver, FQTermSSHPacketSender *outputSender) = 0; - + virtual void hostKeyHash(unsigned char *md) {} public slots: virtual void handlePacket(int type) = 0; -- cgit v1.2.3