svnno****@sourc*****
svnno****@sourc*****
2015年 5月 4日 (月) 01:46:30 JST
Revision: 5846 http://sourceforge.jp/projects/ttssh2/scm/svn/commits/5846 Author: yutakapon Date: 2015-05-04 01:46:29 +0900 (Mon, 04 May 2015) Log Message: ----------- チケット #35047 SSH サーバホスト公開鍵の自動更新 known_hosts ファイルを検索する関数(host key rotation用)を追加した。 Ticket Links: ------------ http://sourceforge.jp/projects/ttssh2/tracker/detail/35047 Modified Paths: -------------- trunk/ttssh2/ttxssh/hosts.c trunk/ttssh2/ttxssh/hosts.h trunk/ttssh2/ttxssh/key.c -------------- next part -------------- Modified: trunk/ttssh2/ttxssh/hosts.c =================================================================== --- trunk/ttssh2/ttxssh/hosts.c 2015-05-01 13:27:34 UTC (rev 5845) +++ trunk/ttssh2/ttxssh/hosts.c 2015-05-03 16:46:29 UTC (rev 5846) @@ -765,6 +765,213 @@ finish_read_host_files(pvar, 1); } + +// known_hosts\x83t\x83@\x83C\x83\x8B\x82\xA9\x82\xE7\x8AY\x93\x96\x82\xB7\x82\xE9\x83L\x81[\x8F\xEE\x95\xF1\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B +// +// return: +// *keyptr != NULL \x8E擾\x90\xAC\x8C\xF7 +// +static int parse_hostkey_file(PTInstVar pvar, char FAR * hostname, + unsigned short tcpport, char FAR * data, Key **keyptr) +{ + int index = eat_spaces(data); + int matched = 0; + int keybits = 0; + ssh_keytype ktype; + + *keyptr = NULL; + + if (data[index] == '#') { + return index + eat_to_end_of_line(data + index); + } + + /* if we find an empty line, then it won't have any patterns matching the hostname + and so we skip it */ + index--; + do { + int negated; + int bracketed; + char *end_bracket; + int host_matched = 0; + unsigned short keyfile_port = 22; + + index++; + negated = data[index] == '!'; + + if (negated) { + index++; + bracketed = data[index] == '['; + if (bracketed) { + end_bracket = strstr(data + index + 1, "]:"); + if (end_bracket != NULL) { + *end_bracket = ' '; + index++; + } + } + host_matched = match_pattern(data + index, hostname); + if (bracketed && end_bracket != NULL) { + *end_bracket = ']'; + keyfile_port = atoi(end_bracket + 2); + } + if (host_matched && keyfile_port == tcpport) { + return index + eat_to_end_of_line(data + index); + } + } + else { + bracketed = data[index] == '['; + if (bracketed) { + end_bracket = strstr(data + index + 1, "]:"); + if (end_bracket != NULL) { + *end_bracket = ' '; + index++; + } + } + host_matched = match_pattern(data + index, hostname); + if (bracketed && end_bracket != NULL) { + *end_bracket = ']'; + keyfile_port = atoi(end_bracket + 2); + } + if (host_matched && keyfile_port == tcpport) { + matched = 1; + } + } + + index += eat_to_end_of_pattern(data + index); + } while (data[index] == ','); + + if (!matched) { + return index + eat_to_end_of_line(data + index); + } + else { + // \x8C\xAE\x82̎\xED\x97ނɂ\xE6\x82\xE8\x83t\x83H\x81[\x83}\x83b\x83g\x82\xAA\x88قȂ\xE9 + // \x82܂\xBD\x81A\x8Dŏ\x89\x82Ɉ\xEA\x92v\x82\xB5\x82\xBD\x83G\x83\x93\x83g\x83\x8A\x82\xF0\x8E擾\x82\xB7\x82邱\x82ƂɂȂ\xE9\x81B + /* + [SSH1] + 192.168.1.2 1024 35 13032.... + + [SSH2] + 192.168.1.2 ssh-rsa AAAAB3NzaC1.... + 192.168.1.2 ssh-dss AAAAB3NzaC1.... + 192.168.1.2 rsa AAAAB3NzaC1.... + 192.168.1.2 dsa AAAAB3NzaC1.... + 192.168.1.2 rsa1 AAAAB3NzaC1.... + */ + int rsa1_key_bits; + + index += eat_spaces(data + index); + + rsa1_key_bits = atoi(data + index); + if (rsa1_key_bits > 0) { // RSA1\x82ł\xA0\x82\xE9 + if (!SSHv1(pvar)) { // SSH2\x90ڑ\xB1\x82ł\xA0\x82\xEA\x82Ζ\xB3\x8E\x8B\x82\xB7\x82\xE9 + return index + eat_to_end_of_line(data + index); + } + index += eat_digits(data + index); + index += eat_spaces(data + index); + + index += eat_digits(data + index); + index += eat_spaces(data + index); + + } + else { + char *cp, *p; + Key *key; + + if (!SSHv2(pvar)) { // SSH1\x90ڑ\xB1\x82ł\xA0\x82\xEA\x82Ζ\xB3\x8E\x8B\x82\xB7\x82\xE9 + return index + eat_to_end_of_line(data + index); + } + + cp = data + index; + p = strchr(cp, ' '); + if (p == NULL) { + return index + eat_to_end_of_line(data + index); + } + index += (p - cp); // setup index + *p = '\0'; + ktype = get_keytype_from_name(cp); + *p = ' '; + + index += eat_spaces(data + index); // update index + + // uudecode + key = parse_uudecode(data + index); + if (key == NULL) { + return index + eat_to_end_of_line(data + index); + } + + // setup + *keyptr = key; + + index += eat_base64(data + index); + index += eat_spaces(data + index); + } + + return index + eat_to_end_of_line(data + index); + } +} + +// known_hosts\x83t\x83@\x83C\x83\x8B\x82\xA9\x82\xE7\x83z\x83X\x83g\x8C\xF6\x8AJ\x8C\xAE\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B +// \x8A\xF9\x91\xB6\x82̏\x88\x97\x9D\x82\xF0\x89\xFC\x95ς\xB5\x82\xBD\x82\xAD\x82Ȃ\xA2\x82̂ŁAHost key rotation\x97p\x82ɐV\x8BK\x82ɗp\x88ӂ\xB7\x82\xE9\x81B +// +// return 1: success +// 0: fail +int HOSTS_hostkey_foreach(PTInstVar pvar, hostkeys_foreach_fn *callback, void *ctx) +{ + int success = 0; + int suppress_errors = 1; + unsigned short tcpport; + char FAR *filename; + char *hostname; + Key *key; + + if (!begin_read_host_files(pvar, 1)) { + goto error; + } + + // Host key rotation\x82ł́Aknown_hosts \x83t\x83@\x83C\x83\x8B\x82\xF0\x8F\x91\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x82̂ŁA + // \x8C\x9F\x8D\x{142DC2}\xE9\x82̂\xCD1\x82߂̃t\x83@\x83C\x83\x8B\x82݂̂ł悢\x81i2\x82߂̃t\x83@\x83C\x83\x8B\x82\xCDReadOnly\x82̂\xBD\x82߁j\x81B + filename = pvar->hosts_state.file_names[pvar->hosts_state.file_num]; + pvar->hosts_state.file_num++; + + pvar->hosts_state.file_data_index = -1; + if (filename[0] != 0) { + if (begin_read_file(pvar, filename, suppress_errors)) { + pvar->hosts_state.file_data_index = 0; + } + } + if (pvar->hosts_state.file_data_index == -1) + goto error; + + // \x8C\x9F\x8D\xF5\x91ΏۂƂȂ\xE9\x83z\x83X\x83g\x96\xBC\x82ƃ|\x81[\x83g\x94ԍ\x86\x81B + hostname = pvar->ssh_state.hostname; + tcpport = pvar->ssh_state.tcpport; + + // known_hosts\x83t\x83@\x83C\x83\x8B\x82̓\xE0\x97e\x82\xAA\x82\xB7\x82ׂ\xC4 pvar->hosts_state.file_data \x82ɓǂݍ\x9E\x82܂\xEA\x82Ă\xA2\x82\xE9\x81B + // \x96\x96\x94\xF6\x82\xCD \0 \x81B + while (pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] != 0) { + key = NULL; + + pvar->hosts_state.file_data_index += + parse_hostkey_file(pvar, hostname, tcpport, + pvar->hosts_state.file_data + + pvar->hosts_state.file_data_index, + &key); + + if (key != NULL) { + key = key; + key_free(key); + } + + } + + success = 1; + +error: + finish_read_host_files(pvar, 1); + + return (success); +} + + static BOOL equal_mp_ints(unsigned char FAR * num1, unsigned char FAR * num2) { Modified: trunk/ttssh2/ttxssh/hosts.h =================================================================== --- trunk/ttssh2/ttxssh/hosts.h 2015-05-01 13:27:34 UTC (rev 5845) +++ trunk/ttssh2/ttxssh/hosts.h 2015-05-03 16:46:29 UTC (rev 5846) @@ -55,6 +55,8 @@ HWND hosts_dialog; } HOSTSState; +typedef int hostkeys_foreach_fn(void *ctx); + void HOSTS_init(PTInstVar pvar); void HOSTS_open(PTInstVar pvar); void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport); @@ -72,5 +74,6 @@ int uudecode(unsigned char *src, int srclen, unsigned char *target, int targsize); int HOSTS_compare_public_key(Key *src, Key *key); +int HOSTS_hostkey_foreach(PTInstVar pvar, hostkeys_foreach_fn *callback, void *ctx); #endif Modified: trunk/ttssh2/ttxssh/key.c =================================================================== --- trunk/ttssh2/ttxssh/key.c 2015-05-01 13:27:34 UTC (rev 5845) +++ trunk/ttssh2/ttxssh/key.c 2015-05-03 16:46:29 UTC (rev 5846) @@ -1968,6 +1968,8 @@ goto error; } + //HOSTS_hostkey_foreach(pvar, NULL, ctx); + success = 1; error: