• R/O
  • SSH
  • HTTPS

ttssh2: Commit


Commit MetaInfo

Revision6972 (tree)
Time2017-11-08 07:26:20
Authordoda

Log Message

EtM 絡みのコード整理。

・コメント追加
・読みやすいようにコードを修正

Change Summary

Incremental Difference

--- trunk/ttssh2/ttxssh/ssh.c (revision 6971)
+++ trunk/ttssh2/ttxssh/ssh.c (revision 6972)
@@ -774,12 +774,24 @@
774774 return pvar->ssh_state.payload[-1];
775775 }
776776
777+/*
778+ * パケット処理の為の以下の準備を行う。(SSHv2用)
779+ * ・データ復号
780+ * ・MAC の検証
781+ * ・padding を取り除く
782+ * ・メッセージタイプを判別して返す
783+ *
784+ * 引数:
785+ * data - ssh パケットの先頭を指すポインタ
786+ * len - パケット長 (先頭のパケット長領域(4バイト)を除いた値)
787+ * padding - パディング長 (EtMの場合は0となっているので、復号後に取得する必要あり)
788+ * etm - MAC 方式が EtM かどうかのフラグ
789+ */
790+
777791 static int prep_packet_ssh2(PTInstVar pvar, char *data, int len, int padding, int etm)
778792 {
779- pvar->ssh_state.payload = data + 4;
780- pvar->ssh_state.payloadlen = len;
781-
782793 if (etm) {
794+ // EtM の場合は先に MAC の検証を行う
783795 if (!CRYPT_verify_receiver_MAC(pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4, data + len + 4)) {
784796 UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, "Detected corrupted data; connection terminating.");
785797 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
@@ -786,14 +798,21 @@
786798 return SSH_MSG_NONE;
787799 }
788800
801+ // パケット長部分(先頭4バイト)は暗号化されていないので、そこをスキップして復号する。
789802 CRYPT_decrypt(pvar, data + 4, len);
803+
804+ // EtM の場合は 呼び出し元では padding 部分が読めない為、ここで値を取得する。
790805 padding = (unsigned int) data[4];
791806 }
792807 else {
808+ // E&M では先頭部分が事前復号されている。
809+ // 事前復号された長さを取得する。
793810 int already_decrypted = get_predecryption_amount(pvar);
794811
812+ // 事前復号された部分をスキップして、残りの部分を復号する。
795813 CRYPT_decrypt(pvar, data + already_decrypted, (4 + len) - already_decrypted);
796814
815+ // E&M では復号後に MAC の検証を行う。
797816 if (!CRYPT_verify_receiver_MAC(pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4, data + len + 4)) {
798817 UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, "Detected corrupted data; connection terminating.");
799818 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
@@ -801,9 +820,12 @@
801820 }
802821 }
803822
804- pvar->ssh_state.payload++;
805- pvar->ssh_state.payloadlen -= padding + 1;
823+ // パケット長(4バイト) 部分とパディング長(1バイト)部分をスキップした SSH ペイロードの先頭
824+ pvar->ssh_state.payload = data + 4 + 1;
806825
826+ // パディング長部分(1バイト)とパディングを除いた実際のペイロード長
827+ pvar->ssh_state.payloadlen = len - 1 - padding;
828+
807829 pvar->ssh_state.payload_grabbed = 0;
808830
809831 // data compression
@@ -1002,7 +1024,7 @@
10021024 unsigned int padding;
10031025 BOOL ret;
10041026 struct Mac *mac = &pvar->ssh2_keys[MODE_OUT].mac;
1005- int aadlen = 0;
1027+ int aadlen = 0, maclen = 0;
10061028
10071029 /*
10081030 データ構造
@@ -1056,6 +1078,7 @@
10561078 }
10571079
10581080 if (mac && mac->etm) {
1081+ // 暗号化対象では無いが、MAC の対象となる部分の長さ
10591082 aadlen = 4;
10601083 }
10611084
@@ -1066,7 +1089,6 @@
10661089 encryption_size += padding;
10671090 set_uint32(data, encryption_size - 4 + aadlen);
10681091 data[4] = (unsigned char) padding;
1069- data_length = encryption_size;
10701092 if (msg) {
10711093 // パケット圧縮の場合、バッファを拡張する。(2011.6.10 yutaka)
10721094 buffer_append_space(msg, padding + EVP_MAX_MD_SIZE);
@@ -1074,15 +1096,14 @@
10741096 data = buffer_ptr(msg);
10751097 }
10761098
1077- //if (pvar->ssh_state.outbuflen <= 7 + data_length) *(int *)0 = 0;
10781099 CRYPT_set_random_data(pvar, data + 5 + len, padding);
10791100
10801101 if (aadlen == 0) {
1102+ // E&M では先に MAC を計算する
10811103 ret = CRYPT_build_sender_MAC(pvar, pvar->ssh_state.sender_sequence_number,
10821104 data, encryption_size, data + encryption_size);
10831105 if (ret) {
1084- data_length += CRYPT_get_sender_MAC_size(pvar);
1085-// data[encryption_size + 5] = 0;
1106+ maclen = CRYPT_get_sender_MAC_size(pvar);
10861107 }
10871108 }
10881109
@@ -1090,19 +1111,19 @@
10901111 CRYPT_encrypt(pvar, data + aadlen, encryption_size);
10911112
10921113 if (aadlen) {
1093- int maclen;
1094- encryption_size += aadlen;
1114+ // EtM では暗号化後に MAC を計算する
10951115 ret = CRYPT_build_sender_MAC(pvar, pvar->ssh_state.sender_sequence_number,
1096- data, encryption_size, data + encryption_size);
1116+ data, aadlen + encryption_size, data + aadlen + encryption_size);
10971117 if (ret) {
10981118 maclen = CRYPT_get_sender_MAC_size(pvar);
1099- data_length = encryption_size + maclen;
11001119 }
1101- logprintf(LOG_LEVEL_ERROR, __FUNCTION__
1102- ": EtM test. aadlen:%d, enclen:%d, pad:%d, datalen:%d, maclen:%d",
1103- aadlen, encryption_size, padding, data_length, maclen);
11041120 }
11051121
1122+ data_length = encryption_size + aadlen + maclen;
1123+
1124+ logprintf(150, __FUNCTION__
1125+ ": built packet info: aadlen:%d, enclen:%d, padlen:%d, datalen:%d, maclen:%d, mode:%s",
1126+ aadlen, encryption_size, padding, data_length, maclen, aadlen ? "EtM" : "E&M");
11061127 }
11071128
11081129 send_packet_blocking(pvar, data, data_length);
--- trunk/ttssh2/ttxssh/pkt.c (revision 6971)
+++ trunk/ttssh2/ttxssh/pkt.c (revision 6972)
@@ -88,7 +88,6 @@
8888 return amount_read;
8989 }
9090
91-
9291 // 改行コードが出てくるまで読む
9392 static int recv_line_data(PTInstVar pvar)
9493 {
@@ -128,7 +127,6 @@
128127 return amount_read;
129128 }
130129
131-
132130 /* This function does two things:
133131 -- reads data from the sshd and feeds the SSH protocol packets to ssh.c
134132 -- copies any available decrypted session data into the application buffer
@@ -186,7 +184,11 @@
186184
187185 etm = mac && mac->enabled && mac->etm;
188186
189- // 暗号化パケットの一部を復号化する。
187+ /*
188+ * 通常の MAC 方式 (E&M: Encrypt & MAC) ではパケット長部分も暗号化されているため、
189+ * 先頭の 1 ブロックを復号する。MAC 方式が EtM (Encrypt then MAC) の時は
190+ * パケット長部分は暗号化されていないので復号は必要無い。
191+ */
190192 if (!pvar->pkt_state.predecrypted_packet && !etm) {
191193 SSH_predecrpyt_packet(pvar, data);
192194 pvar->pkt_state.predecrypted_packet = TRUE;
@@ -198,36 +200,43 @@
198200 padding = 8 - (realpktsize % 8);
199201 pktsize = realpktsize + padding;
200202 } else {
201- // SSH2のパケットは先頭に packet-size(4)+padding(1)+type(1) が続く。
203+ // SSH2 ではパケットの先頭に uint32 (4バイト) のパケット長が来る
202204 pktsize = get_uint32_MSBfirst(data);
205+
206+ // 続く 1 バイトは padding の長さ
203207 if (etm) {
208+ // EtM では padding length 以降は暗号化されている。
209+ // この時点ではまだ復号していないので padding length が分からない。
210+ // 仮に 0 を入れて置く。
204211 padding = 0;
205212 }
206213 else {
214+ // E&M では復号済み
207215 padding = (unsigned char) data[4];
208216 }
209217 }
210218
211- // パケット(TCPペイロード)の全体のサイズは、SSHペイロード+4(+MAC)となる。
219+ // パケット(TCPペイロード)の全体のサイズは、SSHペイロード+4(+MAC)となる。
212220 // +4は、SSHペイロードのサイズを格納している部分(int型)。
213221 total_packet_size = pktsize + 4 + SSH_get_clear_MAC_size(pvar);
214222
215223 if (total_packet_size <= pvar->pkt_state.datalen) {
216- /* the data must be 4 byte aligned. */
224+ // 受信済みデータが十分有る場合はパケットの実処理を行う
217225 if (SSHv1(pvar)) {
226+ // SSH1 は EtM 非対応
218227 SSH_handle_packet1(pvar, data, pktsize, padding);
219228 }
220229 else {
221230 SSH_handle_packet2(pvar, data, pktsize, padding, etm);
222231 }
232+
223233 pvar->pkt_state.predecrypted_packet = FALSE;
224-
225234 pvar->pkt_state.datastart += total_packet_size;
226235 pvar->pkt_state.datalen -= total_packet_size;
227236
228237 } else if (total_packet_size > PACKET_MAX_SIZE) {
229- // 4MBを超える巨大なパケットが届いたら、異常終了する。
230- // 実際にはデータ化けで復号失敗時に、誤認識することが多い。
238+ // パケット長が大きすぎる場合は異常終了する。
239+ // 実際には何らかの要因で復号失敗⇒パケット長部分が壊れている事が多い。
231240 UTIL_get_lang_msg("MSG_PKT_OVERSIZED_ERROR", pvar,
232241 "Oversized packet received from server; connection will close.");
233242 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
Show on old repository browser