[Ttssh2-commit] [5838] チケット #35047 SSH サーバホスト公開鍵の自動更新

Back to archive index

svnno****@sourc***** svnno****@sourc*****
2015年 4月 26日 (日) 23:46:49 JST


Revision: 5838
          http://sourceforge.jp/projects/ttssh2/scm/svn/commits/5838
Author:   yutakapon
Date:     2015-04-26 23:46:48 +0900 (Sun, 26 Apr 2015)
Log Message:
-----------
チケット #35047 SSH サーバホスト公開鍵の自動更新

・SSH2_MSG_GLOBAL_REQUESTの"hostk****@opens*****"に対して、
 OpenSSH 6.8の実装に合わせて、常に success を返すように変更した。
・ホスト鍵の自動更新処理を実装中。
 現時点では、サーバから送られてきた鍵のfingerprintをログ採取するところまで。
・key_from_blob()の引数チェックを追加した。
・SSHハンドラの pvar->ssh_state.payloadlen のコメント誤りを修正した。
 pvar->ssh_state.payload には type が含まれていないので、payloadlenに type 分の
 サイズが含まれているのは、オリジナルバグではないかと思う。

Ticket Links:
------------
    http://sourceforge.jp/projects/ttssh2/tracker/detail/35047

Modified Paths:
--------------
    trunk/ttssh2/ttxssh/key.c
    trunk/ttssh2/ttxssh/key.h
    trunk/ttssh2/ttxssh/ssh.c

-------------- next part --------------
Modified: trunk/ttssh2/ttxssh/key.c
===================================================================
--- trunk/ttssh2/ttxssh/key.c	2015-04-26 14:36:21 UTC (rev 5837)
+++ trunk/ttssh2/ttxssh/key.c	2015-04-26 14:46:48 UTC (rev 5838)
@@ -36,6 +36,33 @@
 #define INTBLOB_LEN 20
 #define SIGBLOB_LEN (2*INTBLOB_LEN)
 
+
+struct hostkeys_update_ctx {
+	/* The hostname and (optionally) IP address string for the server */
+	char *host_str, *ip_str;
+
+	/*
+	* Keys received from the server and a flag for each indicating
+	* whether they already exist in known_hosts.
+	* keys_seen is filled in by hostkeys_find() and later (for new
+	* keys) by client_global_hostkeys_private_confirm().
+	*/
+	Key **keys;
+	int *keys_seen;
+	size_t nkeys;
+
+	size_t nnew;
+
+	/*
+	* Keys that are in known_hosts, but were not present in the update
+	* from the server (i.e. scheduled to be deleted).
+	* Filled in by hostkeys_find().
+	*/
+	Key **old_keys;
+	size_t nold;
+};
+
+
 //////////////////////////////////////////////////////////////////////////////
 //
 // Key verify function
@@ -1110,10 +1137,13 @@
 	EC_KEY *ecdsa = NULL;
 	EC_POINT *q = NULL;
 	char *curve = NULL;
-	Key *hostkey;  // hostkey
+	Key *hostkey = NULL;  // hostkey
 	ssh_keytype type;
 	unsigned char *pk = NULL;
 
+	if (data == NULL)
+		goto error;
+
 	hostkey = malloc(sizeof(Key));
 	if (hostkey == NULL)
 		goto error;
@@ -1799,3 +1829,84 @@
 
 	return (k);
 }
+
+
+static void hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx)
+{
+	size_t i;
+
+	if (ctx == NULL)
+		return;
+	for (i = 0; i < ctx->nkeys; i++)
+		key_free(ctx->keys[i]);
+	free(ctx->keys);
+	free(ctx->keys_seen);
+	for (i = 0; i < ctx->nold; i++)
+		key_free(ctx->old_keys[i]);
+	free(ctx->old_keys);
+	free(ctx->host_str);
+	free(ctx->ip_str);
+	free(ctx);
+}
+
+//
+// SSH\x83T\x81[\x83o\x83z\x83X\x83g\x8C\xAE(known_hosts)\x82̎\xA9\x93\xAE\x8DX\x90V(OpenSSH 6.8 or later: host key rotation support)
+//
+// return 1: success
+//        0: fail
+//
+int update_client_input_hostkeys(PTInstVar pvar, char *dataptr, int datalen)
+{
+	int success = 1;  // OpenSSH 6.8\x82̎\xC0\x91\x95\x82ł́A\x8F\xED\x82ɐ\xAC\x8C\xF7\x82ŕԂ\xB7\x82悤\x82ɂȂ\xC1\x82Ă\xA2\x82邽\x82߁A
+	                  // \x82\xBB\x82\xEA\x82ɍ\x87\x82킹\x82\xC4 Tera Term \x82ł\xE0\x90\xAC\x8C\xF7\x82ƕԂ\xB7\x82\xB1\x82Ƃɂ\xB7\x82\xE9\x81B
+	int len;
+	char *cp, *fp;
+	char msg[128];
+	unsigned char *blob = NULL;
+	buffer_t *b = NULL;
+	struct hostkeys_update_ctx *ctx = NULL;
+	Key *key = NULL;
+
+	// TODO: Tera Term\x82̐ݒ\xE8\x82ŁA\x93\x96\x8AY\x8B@\x94\\x82̃I\x83\x93\x83I\x83t\x82𐧌\xE4\x82ł\xAB\x82\xE9\x82悤\x82ɂ\xB7\x82\xE9\x81B
+
+	ctx = calloc(1, sizeof(struct hostkeys_update_ctx));
+	if (ctx == NULL)
+		goto error;
+
+	b = buffer_init();
+	if (b == NULL)
+		goto error;
+
+	cp = buffer_append_space(b, datalen);
+	memcpy(cp, dataptr, datalen);
+
+	while (buffer_remain_len(b) > 0) {
+		key_free(key);
+		key = NULL;
+
+		blob = buffer_get_string_msg(b, &len);
+		key = key_from_blob(blob, len);
+		if (key == NULL) {
+			_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Not found key into blob %p (%d)", blob, len);
+			notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
+			goto error;
+		}
+		free(blob);
+		blob = NULL;
+
+		fp = key_fingerprint(key, SSH_FP_HEX);
+		_snprintf_s(msg, sizeof(msg), _TRUNCATE, "SSH2_MSG_GLOBAL_REQUEST: received %s key %s", 
+			get_sshname_from_key(key), fp);
+		notify_verbose_message(pvar, msg, LOG_LEVEL_VERBOSE);
+		free(fp);
+	}
+
+	success = 1;
+
+error:
+	buffer_free(b);
+	hostkeys_update_ctx_free(ctx);
+	free(blob);
+
+	return (success);
+}

Modified: trunk/ttssh2/ttxssh/key.h
===================================================================
--- trunk/ttssh2/ttxssh/key.h	2015-04-26 14:36:21 UTC (rev 5837)
+++ trunk/ttssh2/ttxssh/key.h	2015-04-26 14:46:48 UTC (rev 5838)
@@ -66,4 +66,6 @@
 void key_private_serialize(Key *key, buffer_t *b);
 Key *key_private_deserialize(buffer_t *blob);
 
+int update_client_input_hostkeys(PTInstVar pvar, char *dataptr, int datalen);
+
 #endif

Modified: trunk/ttssh2/ttxssh/ssh.c
===================================================================
--- trunk/ttssh2/ttxssh/ssh.c	2015-04-26 14:36:21 UTC (rev 5837)
+++ trunk/ttssh2/ttxssh/ssh.c	2015-04-26 14:46:48 UTC (rev 5838)
@@ -7426,7 +7426,7 @@
 // SSH2_MSG_GLOBAL_REQUEST for OpenSSH 6.8
 static BOOL handle_SSH2_client_global_request(PTInstVar pvar)
 {
-	int len;
+	int len, n;
 	char *data;
 	char *rtype;
 	int want_reply;
@@ -7437,18 +7437,33 @@
 
 	notify_verbose_message(pvar, "SSH2_MSG_GLOBAL_REQUEST was received.", LOG_LEVEL_VERBOSE);
 
-	// 6byte\x81i\x83T\x83C\x83Y\x81{\x83p\x83f\x83B\x83\x93\x83O\x81{\x83^\x83C\x83v\x81j\x82\xF0\x8E\xE6\x82菜\x82\xA2\x82\xBD\x88ȍ~\x82̃y\x83C\x83\x8D\x81[\x83h
+	// SSH2 packet format:
+	// [size(4) + padding size(1) + type(1)] + [payload(N) + padding(X)]
+	//  header                                     body
+	//                                         ^data
+	//            <-----------------size------------------------------->
+	//                              <---------len-------->
+	//
+	// data = payload(N) + padding(X): \x83p\x83f\x83B\x83\x93\x83O\x82\xE0\x8A܂߂\xBD\x83{\x83f\x83B\x82\xB7\x82ׂĂ\xF0\x8Ew\x82\xB7\x81B
 	data = pvar->ssh_state.payload;
-	// \x83p\x83P\x83b\x83g\x83T\x83C\x83Y - (\x83p\x83f\x83B\x83\x93\x83O\x83T\x83C\x83Y+1)\x81G\x90^\x82̃p\x83P\x83b\x83g\x83T\x83C\x83Y
+	// len = size - (padding size + 1): \x83p\x83f\x83B\x83\x93\x83O\x82\xF0\x8F\x9C\x82\xAD\x83{\x83f\x83B\x81Btype\x82\xAA\x90擪\x82Ɋ܂܂\xEA\x82\xE9\x81B
 	len = pvar->ssh_state.payloadlen;
 
-	rtype = buffer_get_string(&data, NULL);
+	len--;   // type \x95\xAA\x82\xF0\x8F\x9C\x82\xAD
+
+	rtype = buffer_get_string(&data, &n);
+	len -= (n + 4);
+
 	want_reply = data[0];
+	data++;
+	len--;
 
 	// OpenSSH 6.8\x82ł́A\x83T\x81[\x83o\x82̃z\x83X\x83g\x8C\xAE\x82\xAA\x8DX\x90V\x82\xB3\x82\xEA\x82\xE9\x82ƁA\x89\xBA\x8BL\x82̒ʒm\x82\xAA\x97\x88\x82\xE9\x81B
 	if (strcmp(rtype, "hostk****@opens*****") == 0) {
-		// TODO: \x8C\xBB\x8F\xF3\x81ATera Term\x82Ƃ\xB5\x82Ă͖\xA2\x83T\x83|\x81[\x83g\x82Ȃ̂ŁA\x8E\xB8\x94s\x82ŕԂ\xB7\x81B
-		success = 0;
+		// OpenSSH 6.8\x82̎\xC0\x91\x95\x82ł́A\x8F\xED\x82ɐ\xAC\x8C\xF7\x82ŕԂ\xB7\x82悤\x82ɂȂ\xC1\x82Ă\xA2\x82邽\x82߁A
+		// \x82\xBB\x82\xEA\x82ɍ\x87\x82킹\x82\xC4 Tera Term \x82ł\xE0\x90\xAC\x8C\xF7\x82ƕԂ\xB7\x82\xB1\x82Ƃɂ\xB7\x82\xE9\x81B
+		success = update_client_input_hostkeys(pvar, data, len);
+
 	}
 	free(rtype);
 
@@ -7457,9 +7472,6 @@
 		if (msg) {
 			len = buffer_len(msg);
 			type = success ? SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE;
-			if (type == SSH2_MSG_REQUEST_SUCCESS) {
-				// TBD
-			}
 			outmsg = begin_send_packet(pvar, type, len);
 			memcpy(outmsg, buffer_ptr(msg), len);
 			finish_send_packet(pvar);



Ttssh2-commit メーリングリストの案内
Back to archive index