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); }