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