scmno****@osdn*****
scmno****@osdn*****
2018年 1月 25日 (木) 21:21:52 JST
Revision: 7024 http://sourceforge.jp/projects/ttssh2/scm/svn/commits/7024 Author: doda Date: 2018-01-25 21:21:51 +0900 (Thu, 25 Jan 2018) Log Message: ----------- SSH ペイロードの残りから、SSH の各データ型を取り出す関数を作成 SSH のパケットハンドラ関数では、殆どの場合はペイロードの先頭から順番に データを取り出して行くだけなので、現在のポインタ位置やペイロードの残りの 長さを関数の中で管理するようにすれば、処理が楽になる(はず) 試験的に handle_SSH2_kexinit() にこの関数を適用してみた。 検討事項: ・byte や uint32 はあまり手間が変わらない気がするのでもう少し評価が必要 ・boolean を格納する領域として unsigned char の領域を渡しているが、 Windows の BOOL 型は int 型なので紛らわしくはないか Modified Paths: -------------- trunk/ttssh2/ttxssh/ssh.c -------------- next part -------------- Modified: trunk/ttssh2/ttxssh/ssh.c =================================================================== --- trunk/ttssh2/ttxssh/ssh.c 2018-01-12 03:49:46 UTC (rev 7023) +++ trunk/ttssh2/ttxssh/ssh.c 2018-01-25 12:21:51 UTC (rev 7024) @@ -83,6 +83,12 @@ // #define NonNull(msg) ((msg)?(msg):"(null)") +typedef enum { + GetPayloadError = 0, + GetPayloadOK = 1, + GetPayloadTruncate = 2 +} PayloadStat; + static struct global_confirm global_confirms; static Channel_t channels[CHANNEL_MAX]; @@ -723,6 +729,109 @@ } } +static PayloadStat get_byte_from_payload(PTInstVar pvar, unsigned char *val) +{ + unsigned char *data; + + data = remained_payload(pvar); + if (!grab_payload(pvar, 1)) { + return GetPayloadError; + } + + *val = *data; + return GetPayloadOK; +} +#define get_boolean_from_payload(pvar, val) get_byte_from_payload(pvar, val) + +static PayloadStat get_bytearray_from_payload(PTInstVar pvar, unsigned char *buff, unsigned int len) +{ + unsigned char *data; + + data = remained_payload(pvar); + if (!grab_payload(pvar, len)) { + return GetPayloadError; + } + + memcpy_s(buff, len, data, len); + return GetPayloadOK; +} + +static PayloadStat get_uint32_from_payload(PTInstVar pvar, unsigned int *val) +{ + unsigned char *data; + + data = remained_payload(pvar); + if (!grab_payload(pvar, 4)) { + return GetPayloadError; + } + + *val = get_uint32(data); + return GetPayloadOK; +} + +static PayloadStat get_string_from_payload( + PTInstVar pvar, unsigned char *buff, unsigned int bufflen, unsigned int *len, BOOL null_terminate) +{ + unsigned int size; + unsigned char *data; + + if (!get_uint32_from_payload(pvar, &size)) { + return GetPayloadError; + } + + data = remained_payload(pvar); + if (!grab_payload(pvar, size)) { + return GetPayloadError; + } + + *len = size; + + if (size < bufflen) { + memcpy_s(buff, bufflen, data, size); + if (null_terminate) { + buff[size] = 0; + } + return GetPayloadOK; + } + else if (size == bufflen) { + memcpy_s(buff, bufflen, data, bufflen); + if (null_terminate) { + buff[bufflen-1] = 0; + return GetPayloadTruncate; + } + else { + return GetPayloadOK; + } + } + else { + memcpy_s(buff, bufflen, data, bufflen); + if (null_terminate) { + buff[bufflen-1] = 0; + } + return GetPayloadTruncate; + } +} +#define get_namelist_from_payload(pvar, buff, bufflen, size) get_string_from_payload(pvar, buff, bufflen, size, TRUE) + +static PayloadStat get_mpint_from_payload(PTInstVar pvar, BIGNUM *bn) +{ + unsigned int len; + unsigned char *data; + + if (!get_uint32_from_payload(pvar, &len)) { + return GetPayloadError; + } + + data = remained_payload(pvar); + if (!grab_payload(pvar, len)) { + return GetPayloadError; + } + + BN_bin2bn(data, len, bn); + + return GetPayloadOK; +} + #define do_crc(buf, len) (~(uint32)crc32(0xFFFFFFFF, (buf), (len))) /* @@ -4892,9 +5001,6 @@ goto error; } - // get rid of Cookie length - data += SSH2_COOKIE_LENGTH; - // \x8Ae\x97v\x91f(\x8C\xAE\x8C\xF0\x8A\xB7,\x88Í\x86\x89\xBB\x93\x99)\x82Ŏg\x97p\x82\xB7\x82\xE9\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x82̌\x88\x92\xE8\x81B // \x83T\x81[\x83o\x82\xA9\x82\xE7\x82̓J\x83\x93\x83}\x8B\xE6\x90\xE8\x82ł̃\x8A\x83X\x83g\x82\xAA\x91\x97\x82\xE7\x82\xEA\x82ė\x88\x82\xE9\x81B // \x83N\x83\x89\x83C\x83A\x83\x93\x83g\x82ƃT\x81[\x83o\x97\xBC\x95\xFB\x82\xAA\x83T\x83|\x81[\x83g\x82\xB5\x82Ă\xA2\x82镨\x82̂\xA4\x82\xBF\x81A @@ -4901,18 +5007,14 @@ // \x83N\x83\x89\x83C\x83A\x83\x93\x83g\x91\xA4\x82ōł\xE0\x91O\x82Ɏw\x92肵\x82\xBD\x95\xA8\x82\xAA\x8Eg\x82\xED\x82\xEA\x82\xE9\x81B // \x8C\xAE\x8C\xF0\x8A\xB7\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80 - if (!grab_payload(pvar, 4) - || !grab_payload(pvar, size = get_uint32(data))) { + switch (get_namelist_from_payload(pvar, buf, sizeof(buf), &size)) { + case GetPayloadError: msg = __FUNCTION__ ": truncated packet (kex algorithms)"; goto error; - } - data += 4; - - if (size >= sizeof(buf)) { + case GetPayloadTruncate: logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed kex algorithms is too long."); + break; } - strncpy_s(buf, sizeof(buf), data, _TRUNCATE); - data += size; logprintf(LOG_LEVEL_VERBOSE, "server proposal: KEX algorithm: %s", buf); @@ -4925,18 +5027,14 @@ } // \x83z\x83X\x83g\x8C\xAE\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80 - if (!grab_payload(pvar, 4) - || !grab_payload(pvar, size = get_uint32(data))) { + switch (get_namelist_from_payload(pvar, buf, sizeof(buf), &size)) { + case GetPayloadError: msg = __FUNCTION__ ": truncated packet (hostkey algorithms)"; goto error; - } - data += 4; - - if (size >= sizeof(buf)) { + case GetPayloadTruncate: logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed hostkey algorithms is too long."); + break; } - strncpy_s(buf, sizeof(buf), data, _TRUNCATE); - data += size; logprintf(LOG_LEVEL_VERBOSE, "server proposal: server host key algorithm: %s", buf); @@ -4957,18 +5055,14 @@ } // \x88Í\x86\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80(\x83N\x83\x89\x83C\x83A\x83\x93\x83g -> \x83T\x81[\x83o) - if (!grab_payload(pvar, 4) - || !grab_payload(pvar, size = get_uint32(data))) { + switch (get_namelist_from_payload(pvar, buf, sizeof(buf), &size)) { + case GetPayloadError: msg = __FUNCTION__ ": truncated packet (encryption algorithms client to server)"; goto error; - } - data += 4; - - if (size >= sizeof(buf)) { + case GetPayloadTruncate: logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed encryption algorithms (client to server) is too long."); + break; } - strncpy_s(buf, sizeof(buf), data, _TRUNCATE); - data += size; logprintf(LOG_LEVEL_VERBOSE, "server proposal: encryption algorithm client to server: %s", buf); @@ -4981,18 +5075,14 @@ } // \x88Í\x86\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80(\x83T\x81[\x83o -> \x83N\x83\x89\x83C\x83A\x83\x93\x83g) - if (!grab_payload(pvar, 4) - || !grab_payload(pvar, size = get_uint32(data))) { + switch (get_namelist_from_payload(pvar, buf, sizeof(buf), &size)) { + case GetPayloadError: msg = __FUNCTION__ ": truncated packet (encryption algorithms server to client)"; goto error; - } - data += 4; - - if (size >= sizeof(buf)) { + case GetPayloadTruncate: logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed encryption algorithms (server to client) is too long."); + break; } - strncpy_s(buf, sizeof(buf), data, _TRUNCATE); - data += size; logprintf(LOG_LEVEL_VERBOSE, "server proposal: encryption algorithm server to client: %s", buf); @@ -5005,18 +5095,14 @@ } // MAC\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80(\x83N\x83\x89\x83C\x83A\x83\x93\x83g -> \x83T\x81[\x83o) - if (!grab_payload(pvar, 4) - || !grab_payload(pvar, size = get_uint32(data))) { + switch (get_namelist_from_payload(pvar, buf, sizeof(buf), &size)) { + case GetPayloadError: msg = __FUNCTION__ ": truncated packet (MAC algorithms client to server)"; goto error; - } - data += 4; - - if (size >= sizeof(buf)) { + case GetPayloadTruncate: logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed MAC algorithms (client to server) is too long."); + break; } - strncpy_s(buf, sizeof(buf), data, _TRUNCATE); - data += size; logprintf(LOG_LEVEL_VERBOSE, "server proposal: MAC algorithm client to server: %s", buf); @@ -5035,18 +5121,14 @@ } // MAC\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80(\x83T\x81[\x83o -> \x83N\x83\x89\x83C\x83A\x83\x93\x83g) - if (!grab_payload(pvar, 4) - || !grab_payload(pvar, size = get_uint32(data))) { + switch (get_namelist_from_payload(pvar, buf, sizeof(buf), &size)) { + case GetPayloadError: msg = __FUNCTION__ ": truncated packet (MAC algorithms server to client)"; goto error; - } - data += 4; - - if (size >= sizeof(buf)) { + case GetPayloadTruncate: logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed MAC algorithms (server to client) is too long."); + break; } - strncpy_s(buf, sizeof(buf), data, _TRUNCATE); - data += size; logprintf(LOG_LEVEL_VERBOSE, "server proposal: MAC algorithm server to client: %s", buf); @@ -5065,18 +5147,14 @@ } // \x88\xB3\x8Fk\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80(\x83N\x83\x89\x83C\x83A\x83\x93\x83g -> \x83T\x81[\x83o) - if (!grab_payload(pvar, 4) - || !grab_payload(pvar, size = get_uint32(data))) { + switch (get_namelist_from_payload(pvar, buf, sizeof(buf), &size)) { + case GetPayloadError: msg = __FUNCTION__ ": truncated packet (compression algorithms client to server)"; goto error; - } - data += 4; - - if (size >= sizeof(buf)) { + case GetPayloadTruncate: logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed compression algorithms (client to server) is too long."); + break; } - strncpy_s(buf, sizeof(buf), data, _TRUNCATE); - data += size; logprintf(LOG_LEVEL_VERBOSE, "server proposal: compression algorithm client to server: %s", buf); @@ -5089,18 +5167,14 @@ } // \x88\xB3\x8Fk\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80(\x83T\x81[\x83o -> \x83N\x83\x89\x83C\x83A\x83\x93\x83g) - if (!grab_payload(pvar, 4) - || !grab_payload(pvar, size = get_uint32(data))) { + switch (get_namelist_from_payload(pvar, buf, sizeof(buf), &size)) { + case GetPayloadError: msg = __FUNCTION__ ": truncated packet (compression algorithms server to client)"; goto error; - } - data += 4; - - if (size >= sizeof(buf)) { + case GetPayloadTruncate: logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed compression algorithms (server to client) is too long."); + break; } - strncpy_s(buf, sizeof(buf), data, _TRUNCATE); - data += size; logprintf(LOG_LEVEL_VERBOSE, "server proposal: compression algorithm server to client: %s", buf); @@ -5114,39 +5188,31 @@ // \x8C\xBE\x8C\xEA(\x83N\x83\x89\x83C\x83A\x83\x93\x83g -> \x83T\x81[\x83o) // \x8C\xBB\x8F\xF3\x82ł͖\xA2\x8Eg\x97p\x81B\x83\x8D\x83O\x82ɋL\x98^\x82\xB7\x82邾\x82\xAF\x81B - if (!grab_payload(pvar, 4) - || !grab_payload(pvar, size = get_uint32(data))) { + switch (get_namelist_from_payload(pvar, buf, sizeof(buf), &size)) { + case GetPayloadError: // \x8C\xBE\x8C\xEA\x82\xCC name-list \x82\xAA\x8E\xE6\x82\xEA\x82Ȃ\xA2\x82Ƃ\xA2\x82\xA4\x8E\x96\x82\xCD KEXINIT \x83p\x83P\x83b\x83g\x82̃t\x83H\x81[\x83}\x83b\x83g\x8E\xA9\x91̂\xAA\x91z\x92\xE8\x8AO\x82ł\xA0\x82\xE8 // \x88ُ\xED\x82ȏ\xF3\x91Ԃł\xA0\x82邪\x81A\x92ʐM\x82ɕK\x97v\x82ȃA\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x82͂\xB7\x82łɃl\x83S\x8Dς݂ŒʐM\x8E\xA9\x91͍̂s\x82\xA6\x82\xE9\x81B // \x8D\xA1\x82܂ł͂\xB1\x82̕\x94\x95\xAA\x82̃`\x83F\x83b\x83N\x82\xF0\x8Ds\x82\xC1\x82Ă\xA2\x82Ȃ\xA9\x82\xC1\x82\xBD\x82̂ŁA\x8Cx\x8D\x90\x82\xF0\x8BL\x98^\x82\xB7\x82\xE9\x82݂̂ŏ\x88\x97\x9D\x82s\x82\xB7\x82\xE9\x81B logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": truncated packet (language client to server)"); goto skip; - } - data += 4; - - if (size >= sizeof(buf)) { + case GetPayloadTruncate: logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed language (client to server) is too long."); + break; } - strncpy_s(buf, sizeof(buf), data, _TRUNCATE); - data += size; logprintf(LOG_LEVEL_VERBOSE, "server proposal: language client to server: %s", buf); // \x8C\xBE\x8C\xEA(\x83T\x81[\x83o -> \x83N\x83\x89\x83C\x83A\x83\x93\x83g) // \x8C\xBB\x8F\xF3\x82ł͖\xA2\x8Eg\x97p\x81B\x83\x8D\x83O\x82ɋL\x98^\x82\xB7\x82邾\x82\xAF\x81B - if (!grab_payload(pvar, 4) - || !grab_payload(pvar, size = get_uint32(data))) { + switch (get_namelist_from_payload(pvar, buf, sizeof(buf), &size)) { + case GetPayloadError: // \x8C\xBE\x8C\xEA(\x83N\x83\x89\x83C\x83A\x83\x93\x83g -> \x83T\x81[\x83o) \x82Ɠ\xAF\x97l\x82ɁA\x96\xE2\x91肪\x82\xA0\x82\xC1\x82Ă\xE0\x8Cx\x8D\x90\x82݂̂Ƃ\xB7\x82\xE9\x81B logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": truncated packet (language server to client)"); - goto skip; - } - data += 4; - - if (size >= sizeof(buf)) { + goto error; + case GetPayloadTruncate: logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed language (server to client) is too long."); + break; } - strncpy_s(buf, sizeof(buf), data, _TRUNCATE); - data += size; logprintf(LOG_LEVEL_VERBOSE, "server proposal: language server to client: %s", buf); @@ -5153,24 +5219,23 @@ // first_kex_packet_follows: // KEXINIT \x83p\x83P\x83b\x83g\x82̌\xE3\x82ɁA\x83A\x83\x8B\x83S\x83\x8A\x83Y\x83\x80\x82̃l\x83S\x8C\x8B\x89ʂ𐄑\xAA\x82\xB5\x82Č\xAE\x8C\xF0\x8A\xB7\x83p\x83P\x83b\x83g\x82𑗂\xC1\x82Ă\xA2\x82邩\x81B // SSH_MSG_KEXINIT \x82̌\xE3\x82̌\xAE\x8C\xF0\x8A\xB7\x82̓N\x83\x89\x83C\x83A\x83\x93\x83g\x91\xA4\x82\xA9\x82瑗\x82\xE9\x82̂ŃT\x81[\x83o\x91\xA4\x82\xAA 1 \x82ɂ\xB7\x82鎖\x82͂Ȃ\xA2\x82͂\xB8\x81B - if (!grab_payload(pvar, 1)) { + if (!get_boolean_from_payload(pvar, buf)) { // \x8C\xBE\x8C\xEA(\x83N\x83\x89\x83C\x83A\x83\x93\x83g -> \x83T\x81[\x83o) \x82Ɠ\xAF\x97l\x82ɁA\x96\xE2\x91肪\x82\xA0\x82\xC1\x82Ă\xE0\x8Cx\x8D\x90\x82݂̂Ƃ\xB7\x82\xE9\x81B logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": truncated packet (first_kex_packet_follows)"); goto skip; } - if (data[0] != 0) { + if (buf[0] != 0) { // \x91O\x8Fq\x82̂悤\x82ɃT\x81[\x83o\x91\xA4\x82\xCD 0 \x88ȊO\x82ɂ\xB7\x82鎖\x82͂Ȃ\xA2\x82͂\xB8\x82Ȃ̂ŁA\x8Cx\x8D\x90\x82\xF0\x8BL\x98^\x82\xB7\x82\xE9\x81B - logprintf(LOG_LEVEL_WARNING, __FUNCTION__ ": first_kex_packet_follows is not 0. (%d)", data[0]); + logprintf(LOG_LEVEL_WARNING, __FUNCTION__ ": first_kex_packet_follows is not 0. (%d)", buf[0]); } - data++; // reserved: \x8C\xBB\x8F\xF3\x82͏\xED\x82\xC9 0 \x82ƂȂ\xE9\x81B - if (!grab_payload(pvar, 4)) { + if (!get_uint32_from_payload(pvar, &size)) { // \x8C\xBE\x8C\xEA(\x83N\x83\x89\x83C\x83A\x83\x93\x83g -> \x83T\x81[\x83o) \x82Ɠ\xAF\x97l\x82ɁA\x96\xE2\x91肪\x82\xA0\x82\xC1\x82Ă\xE0\x8Cx\x8D\x90\x82݂̂Ƃ\xB7\x82\xE9\x81B logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": truncated packet (reserved)"); goto skip; } - if ((size = get_uint32(data)) != 0) { + if (size != 0) { logprintf(LOG_LEVEL_INFO, __FUNCTION__ ": reserved data is not 0. (%d)", size); }