[Ttssh2-commit] [7024] SSH ペイロードの残りから、SSH の各データ型を取り出す関数を作成

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\x82𑱍s\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);
 	}
 



Ttssh2-commit メーリングリストの案内