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

アーカイブの一覧に戻る

svnno****@sourc***** svnno****@sourc*****
2015年 5月 7日 (木) 02:08:00 JST


Revision: 5851
          http://sourceforge.jp/projects/ttssh2/scm/svn/commits/5851
Author:   yutakapon
Date:     2015-05-07 02:08:00 +0900 (Thu, 07 May 2015)
Log Message:
-----------
チケット #35047 SSH サーバホスト公開鍵の自動更新

新規の公開鍵を登録する処理に、サーバとのシグネチャチェックを行い、鍵の更新を実施するようにした。

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

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

-------------- next part --------------
Modified: trunk/ttssh2/ttxssh/key.c
===================================================================
--- trunk/ttssh2/ttxssh/key.c	2015-05-06 15:57:02 UTC (rev 5850)
+++ trunk/ttssh2/ttxssh/key.c	2015-05-06 17:08:00 UTC (rev 5851)
@@ -1953,9 +1953,95 @@
 static void client_global_hostkeys_private_confirm(PTInstVar pvar, int type, u_int32_t seq, void *_ctx)
 {
 	struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
+	char msg[128];
+	char *data;
+	int len;
+	unsigned char *blob = NULL;
+	int bloblen;
+	buffer_t *b = NULL;
+	buffer_t *bsig = NULL;
+	char *cp, *sig;
+	size_t i, ndone, siglen;
+	int ret;
 
+	// 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;
+	// 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;
+	len--;   // type \x95\xAA\x82\xF0\x8F\x9C\x82\xAD
+
+	bsig = buffer_init();
+	if (bsig == NULL)
+		goto error;
+	cp = buffer_append_space(bsig, len);
+	memcpy(cp, data, len);
+
+	if (ctx->nnew == 0) {
+		_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because ctx->nnew %d(program bug).", ctx->nnew);
+		notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
+		goto error;
+	}
+	if (type != SSH2_MSG_REQUEST_SUCCESS) {
+		_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Server failed to confirm ownership of private host keys(type %d)", type);
+		notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
+		goto error;
+	}
+	if (pvar->session_id_len == 0) {
+		_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because pvar->session_id_len %d(program bug).", pvar->session_id_len);
+		notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
+		goto error;
+	}
+
+	b = buffer_init();
+	if (b == NULL)
+		goto error;
+
+	ndone = 0;
+	for (i = 0; i < ctx->nkeys; i++) {
+		if (ctx->keys_seen[i])
+			continue;
+
+		buffer_clear(b);
+		buffer_put_cstring(b, "hostk****@opens*****");
+		buffer_put_string(b, pvar->session_id, pvar->session_id_len);
+		key_to_blob(ctx->keys[i], &blob, &bloblen);
+		buffer_put_string(b, blob, bloblen);
+		free(blob);
+		blob = NULL;
+
+		sig = buffer_get_string_msg(bsig, &siglen);
+		// Verify signature
+		ret = key_verify(ctx->keys[i], sig, siglen, buffer_ptr(b), buffer_len(b));
+		free(sig);
+		sig = NULL;
+		if (ret != 1) {
+			_snprintf_s(msg, sizeof(msg), _TRUNCATE, "server gave bad signature for %s key %u", 
+				get_sshname_from_key(ctx->keys[i]), i);
+			notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
+			goto error;
+		}
+		ndone++;
+	}
+
+	if (ndone != ctx->nnew) {
+		_snprintf_s(msg, sizeof(msg), _TRUNCATE, "Hostkey can not be updated because ndone != ctx->nnew (%u / %u)(program bug).",
+			ndone, ctx->nnew);
+		notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
+		goto error;
+	}
+
 	update_known_hosts(pvar, ctx);
 
+error:
+	buffer_free(b);
+	buffer_free(bsig);
 	hostkeys_update_ctx_free(ctx);
 }
 



Ttssh2-commit メーリングリストの案内
アーカイブの一覧に戻る