| 471 |
// known_hostsファイルの内容を解析し、指定したホストの公開鍵を探す。 |
// known_hostsファイルの内容を解析し、指定したホストの公開鍵を探す。 |
| 472 |
// |
// |
| 473 |
static int check_host_key(PTInstVar pvar, char FAR * hostname, |
static int check_host_key(PTInstVar pvar, char FAR * hostname, |
| 474 |
unsigned short tcpport, char FAR * data) |
unsigned short tcpport, char FAR * data, |
| 475 |
|
Key *key) |
| 476 |
{ |
{ |
| 477 |
int index = eat_spaces(data); |
int index = eat_spaces(data); |
| 478 |
int matched = 0; |
int matched = 0; |
| 561 |
return index + eat_to_end_of_line(data + index); |
return index + eat_to_end_of_line(data + index); |
| 562 |
} |
} |
| 563 |
|
|
| 564 |
pvar->hosts_state.hostkey.type = KEY_RSA1; |
key->type = KEY_RSA1; |
| 565 |
|
|
| 566 |
pvar->hosts_state.hostkey.bits = rsa1_key_bits; |
key->bits = rsa1_key_bits; |
| 567 |
index += eat_digits(data + index); |
index += eat_digits(data + index); |
| 568 |
index += eat_spaces(data + index); |
index += eat_spaces(data + index); |
| 569 |
|
|
| 570 |
pvar->hosts_state.hostkey.exp = parse_bignum(data + index); |
key->exp = parse_bignum(data + index); |
| 571 |
index += eat_digits(data + index); |
index += eat_digits(data + index); |
| 572 |
index += eat_spaces(data + index); |
index += eat_spaces(data + index); |
| 573 |
|
|
| 574 |
pvar->hosts_state.hostkey.mod = parse_bignum(data + index); |
key->mod = parse_bignum(data + index); |
|
|
|
|
/* |
|
|
if (pvar->hosts_state.key_bits < 0 |
|
|
|| pvar->hosts_state.key_exp == NULL |
|
|
|| pvar->hosts_state.key_mod == NULL) { |
|
|
pvar->hosts_state.key_bits = 0; |
|
|
free(pvar->hosts_state.key_exp); |
|
|
free(pvar->hosts_state.key_mod); |
|
|
}*/ |
|
|
|
|
| 575 |
} else { |
} else { |
| 576 |
char *cp, *p; |
char *cp, *p; |
| 577 |
Key *key; |
Key *key2; |
| 578 |
|
ssh_keytype key_type; |
| 579 |
|
|
| 580 |
if (!SSHv2(pvar)) { // SSH1接続であれば無視する |
if (!SSHv2(pvar)) { // SSH1接続であれば無視する |
| 581 |
return index + eat_to_end_of_line(data + index); |
return index + eat_to_end_of_line(data + index); |
| 588 |
} |
} |
| 589 |
index += (p - cp); // setup index |
index += (p - cp); // setup index |
| 590 |
*p = '\0'; |
*p = '\0'; |
| 591 |
pvar->hosts_state.hostkey.type = get_keytype_from_name(cp); |
key_type = get_keytype_from_name(cp); |
| 592 |
*p = ' '; |
*p = ' '; |
| 593 |
|
|
| 594 |
index += eat_spaces(data + index); // update index |
index += eat_spaces(data + index); // update index |
| 595 |
|
|
| 596 |
// uudecode |
// uudecode |
| 597 |
key = parse_uudecode(data + index); |
key2 = parse_uudecode(data + index); |
| 598 |
if (key == NULL) { |
if (key2 == NULL) { |
| 599 |
return index + eat_to_end_of_line(data + index); |
return index + eat_to_end_of_line(data + index); |
| 600 |
} |
} |
| 601 |
|
|
| 602 |
// setup |
// setup |
| 603 |
pvar->hosts_state.hostkey.type = key->type; |
key->type = key2->type; |
| 604 |
pvar->hosts_state.hostkey.dsa = key->dsa; |
key->dsa = key2->dsa; |
| 605 |
pvar->hosts_state.hostkey.rsa = key->rsa; |
key->rsa = key2->rsa; |
| 606 |
pvar->hosts_state.hostkey.ecdsa = key->ecdsa; |
key->ecdsa = key2->ecdsa; |
| 607 |
pvar->hosts_state.hostkey.ed25519_pk = key->ed25519_pk; |
key->ed25519_pk = key2->ed25519_pk; |
| 608 |
|
|
| 609 |
index += eat_base64(data + index); |
index += eat_base64(data + index); |
| 610 |
index += eat_spaces(data + index); |
index += eat_spaces(data + index); |
| 611 |
|
|
| 612 |
// Key構造体自身を解放する (2008.3.2 yutaka) |
// Key構造体自身を解放する (2008.3.2 yutaka) |
| 613 |
free(key); |
free(key2); |
| 614 |
} |
} |
| 615 |
|
|
| 616 |
return index + eat_to_end_of_line(data + index); |
return index + eat_to_end_of_line(data + index); |
| 619 |
|
|
| 620 |
// |
// |
| 621 |
// known_hostsファイルからホスト名に合致する行を読む |
// known_hostsファイルからホスト名に合致する行を読む |
| 622 |
|
// return_always |
| 623 |
|
// 0: 見つかるまで探す |
| 624 |
|
// 1: 1行だけ探して戻る |
| 625 |
// |
// |
| 626 |
static int read_host_key(PTInstVar pvar, |
static int read_host_key(PTInstVar pvar, |
| 627 |
char FAR * hostname, unsigned short tcpport, |
char FAR * hostname, unsigned short tcpport, |
| 628 |
int suppress_errors, int return_always) |
int suppress_errors, int return_always, |
| 629 |
|
Key *key) |
| 630 |
{ |
{ |
| 631 |
int i; |
int i; |
| 632 |
int while_flg; |
int while_flg; |
| 656 |
} |
} |
| 657 |
|
|
| 658 |
// hostkey type is KEY_UNSPEC. |
// hostkey type is KEY_UNSPEC. |
| 659 |
key_init(&pvar->hosts_state.hostkey); |
key_init(key); |
| 660 |
|
|
| 661 |
do { |
do { |
| 662 |
if (pvar->hosts_state.file_data == NULL |
if (pvar->hosts_state.file_data == NULL |
| 690 |
pvar->hosts_state.file_data_index += |
pvar->hosts_state.file_data_index += |
| 691 |
check_host_key(pvar, hostname, tcpport, |
check_host_key(pvar, hostname, tcpport, |
| 692 |
pvar->hosts_state.file_data + |
pvar->hosts_state.file_data + |
| 693 |
pvar->hosts_state.file_data_index); |
pvar->hosts_state.file_data_index, |
| 694 |
|
key); |
| 695 |
|
|
| 696 |
if (!return_always) { |
if (!return_always) { |
| 697 |
// 有効なキーが見つかるまで |
// 有効なキーが見つかるまで |
| 698 |
while_flg = (pvar->hosts_state.hostkey.type == KEY_UNSPEC); |
while_flg = (key->type == KEY_UNSPEC); |
| 699 |
} |
} |
| 700 |
else { |
else { |
| 701 |
while_flg = 0; |
while_flg = 0; |
| 715 |
// サーバへ接続する前に、known_hostsファイルからホスト公開鍵を先読みしておく。 |
// サーバへ接続する前に、known_hostsファイルからホスト公開鍵を先読みしておく。 |
| 716 |
void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport) |
void HOSTS_prefetch_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport) |
| 717 |
{ |
{ |
| 718 |
|
Key key; // known_hostsに登録されている鍵 |
| 719 |
|
|
| 720 |
if (!begin_read_host_files(pvar, 1)) { |
if (!begin_read_host_files(pvar, 1)) { |
| 721 |
return; |
return; |
| 722 |
} |
} |
| 723 |
|
|
| 724 |
if (!read_host_key(pvar, hostname, tcpport, 1, 0)) { |
memset(&key, 0, sizeof(key)); |
| 725 |
|
if (!read_host_key(pvar, hostname, tcpport, 1, 0, &key)) { |
| 726 |
return; |
return; |
| 727 |
} |
} |
| 728 |
|
|
| 729 |
|
key_copy(&pvar->hosts_state.hostkey, &key); |
| 730 |
|
key_init(&key); |
| 731 |
|
|
| 732 |
free(pvar->hosts_state.prefetched_hostname); |
free(pvar->hosts_state.prefetched_hostname); |
| 733 |
pvar->hosts_state.prefetched_hostname = _strdup(hostname); |
pvar->hosts_state.prefetched_hostname = _strdup(hostname); |
| 734 |
|
|
| 1035 |
} |
} |
| 1036 |
} |
} |
| 1037 |
|
|
| 1038 |
|
#if 0 |
| 1039 |
// 公開鍵が等しいかを検証する |
// pvar->hosts_state.hostkey と渡された公開鍵が等しいかを検証する |
| 1040 |
// -1 ... 鍵の型が違う |
// -1 ... 鍵の型が違う |
| 1041 |
// 0 ... 等しくない |
// 0 ... 等しくない |
| 1042 |
// 1 ... 等しい |
// 1 ... 等しい |
| 1044 |
{ |
{ |
| 1045 |
return HOSTS_compare_public_key(&pvar->hosts_state.hostkey, key); |
return HOSTS_compare_public_key(&pvar->hosts_state.hostkey, key); |
| 1046 |
} |
} |
| 1047 |
|
#endif |
| 1048 |
|
|
| 1049 |
static void hosts_dlg_set_fingerprint(PTInstVar pvar, HWND dlg, digest_algorithm dgst_alg) |
static void hosts_dlg_set_fingerprint(PTInstVar pvar, HWND dlg, digest_algorithm dgst_alg) |
| 1050 |
{ |
{ |
| 1444 |
notify_nonfatal_error(pvar, pvar->ts->UIMsg); |
notify_nonfatal_error(pvar, pvar->ts->UIMsg); |
| 1445 |
} |
} |
| 1446 |
else { |
else { |
| 1447 |
Key key; // 接続中のホストのキー |
Key key; // known_hostsに登録されている鍵 |
| 1448 |
int length; |
int length; |
| 1449 |
char filename[MAX_PATH]; |
char filename[MAX_PATH]; |
| 1450 |
char tmp[L_tmpnam]; |
char tmp[L_tmpnam]; |
| 1477 |
return; |
return; |
| 1478 |
} |
} |
| 1479 |
|
|
|
// 接続中のサーバのキーを読み込む |
|
|
memset(&key, 0, sizeof(key)); |
|
|
key_copy(&key, &pvar->hosts_state.hostkey); |
|
|
|
|
| 1480 |
// ファイルから読み込む |
// ファイルから読み込む |
| 1481 |
|
memset(&key, 0, sizeof(key)); |
| 1482 |
begin_read_host_files(pvar, 0); |
begin_read_host_files(pvar, 0); |
| 1483 |
do { |
do { |
| 1484 |
int host_index = 0; |
int host_index = 0; |
| 1488 |
int do_write = 0; |
int do_write = 0; |
| 1489 |
length = amount_written = 0; |
length = amount_written = 0; |
| 1490 |
|
|
| 1491 |
if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) { |
if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1, &key)) { |
| 1492 |
break; |
break; |
| 1493 |
} |
} |
| 1494 |
|
|
| 1570 |
// ホストが等しい |
// ホストが等しい |
| 1571 |
else { |
else { |
| 1572 |
// 鍵の形式が違う or 合致するキー |
// 鍵の形式が違う or 合致するキー |
| 1573 |
if (match_key(pvar, &key) != 0) { |
if (HOSTS_compare_public_key(&pvar->hosts_state.hostkey, &key) != 0) { |
| 1574 |
do_write = 1; |
do_write = 1; |
| 1575 |
} |
} |
| 1576 |
// 鍵の形式が同じで合致しないキーはスキップされる |
// 鍵の形式が同じで合致しないキーはスキップされる |
| 1633 |
notify_nonfatal_error(pvar, pvar->ts->UIMsg); |
notify_nonfatal_error(pvar, pvar->ts->UIMsg); |
| 1634 |
} |
} |
| 1635 |
else { |
else { |
| 1636 |
Key key; // 接続中のホストのキー |
Key key; // known_hostsに登録されている鍵 |
| 1637 |
int length; |
int length; |
| 1638 |
char filename[MAX_PATH]; |
char filename[MAX_PATH]; |
| 1639 |
char tmp[L_tmpnam]; |
char tmp[L_tmpnam]; |
| 1667 |
return; |
return; |
| 1668 |
} |
} |
| 1669 |
|
|
|
// 接続中のサーバのキーを読み込む |
|
|
memset(&key, 0, sizeof(key)); |
|
|
key_copy(&key, &pvar->hosts_state.hostkey); |
|
|
|
|
| 1670 |
// ファイルから読み込む |
// ファイルから読み込む |
| 1671 |
|
memset(&key, 0, sizeof(key)); |
| 1672 |
begin_read_host_files(pvar, 0); |
begin_read_host_files(pvar, 0); |
| 1673 |
do { |
do { |
| 1674 |
int host_index = 0; |
int host_index = 0; |
| 1678 |
int do_write = 0; |
int do_write = 0; |
| 1679 |
length = amount_written = 0; |
length = amount_written = 0; |
| 1680 |
|
|
| 1681 |
if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1)) { |
if (!read_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, 0, 1, &key)) { |
| 1682 |
break; |
break; |
| 1683 |
} |
} |
| 1684 |
|
|
| 2338 |
|
|
| 2339 |
// |
// |
| 2340 |
// サーバから送られてきたホスト公開鍵の妥当性をチェックする |
// サーバから送られてきたホスト公開鍵の妥当性をチェックする |
| 2341 |
|
// key: サーバからの公開鍵 |
| 2342 |
// |
// |
| 2343 |
// SSH2対応を追加 (2006.3.24 yutaka) |
// SSH2対応を追加 (2006.3.24 yutaka) |
| 2344 |
// |
// |
| 2345 |
BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key) |
BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key) |
| 2346 |
{ |
{ |
| 2347 |
int found_different_key = 0, found_different_type_key = 0; |
int found_different_key = 0, found_different_type_key = 0; |
| 2348 |
|
Key key2; // known_hostsに登録されている鍵 |
| 2349 |
|
|
| 2350 |
pvar->dns_key_check = DNS_VERIFY_NONE; |
pvar->dns_key_check = DNS_VERIFY_NONE; |
| 2351 |
|
|
| 2352 |
// すでに known_hosts ファイルからホスト公開鍵を読み込んでいるなら、それと比較する。 |
// すでに known_hosts ファイルからホスト公開鍵を読み込んでいるなら、それと比較する。 |
| 2353 |
if (pvar->hosts_state.prefetched_hostname != NULL |
if (pvar->hosts_state.prefetched_hostname != NULL |
| 2354 |
&& _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0 |
&& _stricmp(pvar->hosts_state.prefetched_hostname, hostname) == 0 |
| 2355 |
&& match_key(pvar, key) == 1) { |
&& HOSTS_compare_public_key(&pvar->hosts_state.hostkey, key) == 1) { |
| 2356 |
|
|
| 2357 |
if (SSHv1(pvar)) { |
if (SSHv1(pvar)) { |
| 2358 |
SSH_notify_host_OK(pvar); |
SSH_notify_host_OK(pvar); |
| 2363 |
} |
} |
| 2364 |
|
|
| 2365 |
// 先読みされていない場合は、この時点でファイルから読み込む |
// 先読みされていない場合は、この時点でファイルから読み込む |
| 2366 |
|
memset(&key2, 0, sizeof(key2)); |
| 2367 |
if (begin_read_host_files(pvar, 0)) { |
if (begin_read_host_files(pvar, 0)) { |
| 2368 |
do { |
do { |
| 2369 |
if (!read_host_key(pvar, hostname, tcpport, 0, 0)) { |
if (!read_host_key(pvar, hostname, tcpport, 0, 0, &key2)) { |
| 2370 |
break; |
break; |
| 2371 |
} |
} |
| 2372 |
|
|
| 2373 |
if (pvar->hosts_state.hostkey.type != KEY_UNSPEC) { |
if (key2.type != KEY_UNSPEC) { |
| 2374 |
int match = match_key(pvar, key); |
int match = HOSTS_compare_public_key(&key2, key); |
| 2375 |
if (match == 1) { |
if (match == 1) { |
| 2376 |
finish_read_host_files(pvar, 0); |
finish_read_host_files(pvar, 0); |
| 2377 |
// すべてのエントリを参照して、合致するキーが見つかったら戻る。 |
// すべてのエントリを参照して、合致するキーが見つかったら戻る。 |
| 2392 |
found_different_type_key = 1; |
found_different_type_key = 1; |
| 2393 |
} |
} |
| 2394 |
} |
} |
| 2395 |
} while (pvar->hosts_state.hostkey.type != KEY_UNSPEC); // キーが見つかっている間はループする |
} while (key2.type != KEY_UNSPEC); // キーが見つかっている間はループする |
| 2396 |
|
|
| 2397 |
|
key_init(&key2); |
| 2398 |
finish_read_host_files(pvar, 0); |
finish_read_host_files(pvar, 0); |
| 2399 |
} |
} |
| 2400 |
|
|