| 49 |
#include <errno.h> |
#include <errno.h> |
| 50 |
#include <sys/stat.h> |
#include <sys/stat.h> |
| 51 |
#include <direct.h> |
#include <direct.h> |
| 52 |
|
#include <memory.h> |
| 53 |
|
|
| 54 |
|
#include <windns.h> |
| 55 |
|
|
| 56 |
static HFONT DlgHostsAddFont; |
static HFONT DlgHostsAddFont; |
| 57 |
static HFONT DlgHostsReplaceFont; |
static HFONT DlgHostsReplaceFont; |
| 131 |
void HOSTS_init(PTInstVar pvar) |
void HOSTS_init(PTInstVar pvar) |
| 132 |
{ |
{ |
| 133 |
pvar->hosts_state.prefetched_hostname = NULL; |
pvar->hosts_state.prefetched_hostname = NULL; |
|
#if 0 |
|
|
pvar->hosts_state.key_exp = NULL; |
|
|
pvar->hosts_state.key_mod = NULL; |
|
|
#else |
|
| 134 |
init_hostkey(&pvar->hosts_state.hostkey); |
init_hostkey(&pvar->hosts_state.hostkey); |
|
#endif |
|
| 135 |
pvar->hosts_state.hosts_dialog = NULL; |
pvar->hosts_state.hosts_dialog = NULL; |
| 136 |
pvar->hosts_state.file_names = NULL; |
pvar->hosts_state.file_names = NULL; |
| 137 |
} |
} |
| 691 |
return 0; |
return 0; |
| 692 |
} |
} |
| 693 |
|
|
|
#if 0 |
|
|
pvar->hosts_state.key_bits = 0; |
|
|
free(pvar->hosts_state.key_exp); |
|
|
pvar->hosts_state.key_exp = NULL; |
|
|
free(pvar->hosts_state.key_mod); |
|
|
pvar->hosts_state.key_mod = NULL; |
|
|
#else |
|
| 694 |
// hostkey type is KEY_UNSPEC. |
// hostkey type is KEY_UNSPEC. |
| 695 |
init_hostkey(&pvar->hosts_state.hostkey); |
init_hostkey(&pvar->hosts_state.hostkey); |
|
#endif |
|
| 696 |
|
|
| 697 |
do { |
do { |
| 698 |
if (pvar->hosts_state.file_data == NULL |
if (pvar->hosts_state.file_data == NULL |
| 1621 |
} |
} |
| 1622 |
} |
} |
| 1623 |
|
|
| 1624 |
|
int is_numeric_hostname(const char *hostname) |
| 1625 |
|
{ |
| 1626 |
|
struct addrinfo hints, *ai; |
| 1627 |
|
|
| 1628 |
|
if (hostname == NULL) { |
| 1629 |
|
return -1; |
| 1630 |
|
} |
| 1631 |
|
|
| 1632 |
|
memset(&hints, 0, sizeof(hints)); |
| 1633 |
|
hints.ai_socktype = SOCK_DGRAM; |
| 1634 |
|
hints.ai_flags = AI_NUMERICHOST; |
| 1635 |
|
|
| 1636 |
|
if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) { |
| 1637 |
|
freeaddrinfo(ai); |
| 1638 |
|
return 1; |
| 1639 |
|
} |
| 1640 |
|
|
| 1641 |
|
return 0; |
| 1642 |
|
} |
| 1643 |
|
|
| 1644 |
|
#define DNS_TYPE_SSHFP 44 |
| 1645 |
|
typedef struct { |
| 1646 |
|
BYTE Algorithm; |
| 1647 |
|
BYTE DigestType; |
| 1648 |
|
BYTE Digest[1]; |
| 1649 |
|
} DNS_SSHFP_DATA, *PDNS_SSHFP_DATA; |
| 1650 |
|
enum verifydns_result { |
| 1651 |
|
DNS_VERIFY_NONE, |
| 1652 |
|
DNS_VERIFY_MATCH, |
| 1653 |
|
DNS_VERIFY_MISMATCH, |
| 1654 |
|
DNS_VERIFY_DIFFERENTTYPE, |
| 1655 |
|
DNS_VERIFY_AUTH_MATCH, |
| 1656 |
|
DNS_VERIFY_AUTH_MISMATCH, |
| 1657 |
|
DNS_VERIFY_AUTH_DIFFERENTTYPE |
| 1658 |
|
}; |
| 1659 |
|
|
| 1660 |
|
int verify_hostkey_dns(char FAR *hostname, Key *key) |
| 1661 |
|
{ |
| 1662 |
|
DNS_STATUS status; |
| 1663 |
|
PDNS_RECORD rec, p; |
| 1664 |
|
PDNS_SSHFP_DATA t; |
| 1665 |
|
int hostkey_alg, hostkey_dtype, hostkey_dlen; |
| 1666 |
|
BYTE *hostkey_digest; |
| 1667 |
|
int found = DNS_VERIFY_NONE; |
| 1668 |
|
char buff[1024]; |
| 1669 |
|
|
| 1670 |
|
switch (key->type) { |
| 1671 |
|
case KEY_RSA: |
| 1672 |
|
hostkey_alg = SSHFP_KEY_RSA; |
| 1673 |
|
break; |
| 1674 |
|
case KEY_DSA: |
| 1675 |
|
hostkey_alg = SSHFP_KEY_DSA; |
| 1676 |
|
break; |
| 1677 |
|
// XXX KEY_ECDSA |
| 1678 |
|
default: // Un-supported algorighm |
| 1679 |
|
hostkey_alg = SSHFP_KEY_RESERVED; |
| 1680 |
|
} |
| 1681 |
|
|
| 1682 |
|
if (hostkey_alg) { |
| 1683 |
|
hostkey_dtype = SSHFP_HASH_SHA1; |
| 1684 |
|
hostkey_digest = key_fingerprint_raw(key, SSH_FP_SHA1, &hostkey_dlen); |
| 1685 |
|
} |
| 1686 |
|
else { |
| 1687 |
|
hostkey_dtype = SSHFP_HASH_RESERVED; |
| 1688 |
|
hostkey_digest = NULL; |
| 1689 |
|
} |
| 1690 |
|
|
| 1691 |
|
status = DnsQuery(hostname, DNS_TYPE_SSHFP, DNS_QUERY_STANDARD, NULL, &rec, NULL); |
| 1692 |
|
|
| 1693 |
|
if (status == 0) { |
| 1694 |
|
for (p=rec; p!=NULL; p=p->pNext) { |
| 1695 |
|
if (p->wType == DNS_TYPE_SSHFP) { |
| 1696 |
|
t = (PDNS_SSHFP_DATA)&(p->Data.Null); |
| 1697 |
|
if (t->Algorithm == hostkey_alg && t->DigestType == hostkey_dtype) { |
| 1698 |
|
if (hostkey_dlen == p->wDataLength-2 && memcmp(hostkey_digest, t->Digest, hostkey_dlen) == 0) { |
| 1699 |
|
found = DNS_VERIFY_MATCH; |
| 1700 |
|
_snprintf_s(buff, sizeof(buff), _TRUNCATE, "Match: alg=%d, dgst=%d, flags=%d (%x)", |
| 1701 |
|
t->Algorithm, t->DigestType, p->Flags); |
| 1702 |
|
MessageBox(NULL, buff, "DNS Verify Match", MB_OK); |
| 1703 |
|
break; |
| 1704 |
|
} |
| 1705 |
|
else { |
| 1706 |
|
found = DNS_VERIFY_MISMATCH; |
| 1707 |
|
_snprintf_s(buff, sizeof(buff), _TRUNCATE, "Missmatch: alg=%d, dgst=%d, flags=%d (%x)", |
| 1708 |
|
t->Algorithm, t->DigestType, p->Flags); |
| 1709 |
|
MessageBox(NULL, buff, "DNS Verify Missmatch", MB_OK); |
| 1710 |
|
break; |
| 1711 |
|
} |
| 1712 |
|
} |
| 1713 |
|
else { |
| 1714 |
|
found = DNS_VERIFY_DIFFERENTTYPE; |
| 1715 |
|
} |
| 1716 |
|
} |
| 1717 |
|
} |
| 1718 |
|
} |
| 1719 |
|
|
| 1720 |
|
free(hostkey_digest); |
| 1721 |
|
DnsRecordListFree(rec, DnsFreeRecordList); |
| 1722 |
|
return found; |
| 1723 |
|
} |
| 1724 |
|
|
| 1725 |
// |
// |
| 1726 |
// サーバから送られてきたホスト公開鍵の妥当性をチェックする |
// サーバから送られてきたホスト公開鍵の妥当性をチェックする |
| 1727 |
// |
// |
| 1729 |
// |
// |
| 1730 |
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) |
| 1731 |
{ |
{ |
| 1732 |
int found_different_key = 0, found_different_type_key = 0; |
int found_different_key = 0, found_different_type_key = 0, dns_sshfp_check = 0; |
| 1733 |
|
|
| 1734 |
// すでに known_hosts ファイルからホスト公開鍵を読み込んでいるなら、それと比較する。 |
// すでに known_hosts ファイルからホスト公開鍵を読み込んでいるなら、それと比較する。 |
| 1735 |
if (pvar->hosts_state.prefetched_hostname != NULL |
if (pvar->hosts_state.prefetched_hostname != NULL |
| 1778 |
finish_read_host_files(pvar, 0); |
finish_read_host_files(pvar, 0); |
| 1779 |
} |
} |
| 1780 |
|
|
| 1781 |
|
if (pvar->settings.VerifyHostKeyDNS) { |
| 1782 |
|
if (!is_numeric_hostname(hostname)) { |
| 1783 |
|
dns_sshfp_check = verify_hostkey_dns(hostname, key); |
| 1784 |
|
} |
| 1785 |
|
} |
| 1786 |
|
|
| 1787 |
// known_hosts に存在しないキーはあとでファイルへ書き込むために、ここで保存しておく。 |
// known_hosts に存在しないキーはあとでファイルへ書き込むために、ここで保存しておく。 |
| 1788 |
pvar->hosts_state.hostkey.type = key->type; |
pvar->hosts_state.hostkey.type = key->type; |
| 1817 |
// これによりknown_hostsの確認を待たずに、サーバへユーザ情報を送ってしまう問題を回避する。 |
// これによりknown_hostsの確認を待たずに、サーバへユーザ情報を送ってしまう問題を回避する。 |
| 1818 |
// (2007.10.1 yutaka) |
// (2007.10.1 yutaka) |
| 1819 |
if (found_different_key) { |
if (found_different_key) { |
|
#if 0 |
|
|
PostMessage(pvar->NotificationWindow, WM_COMMAND, |
|
|
ID_SSHDIFFERENTKEY, 0); |
|
|
#else |
|
| 1820 |
HOSTS_do_different_key_dialog(pvar->NotificationWindow, pvar); |
HOSTS_do_different_key_dialog(pvar->NotificationWindow, pvar); |
|
#endif |
|
| 1821 |
} |
} |
| 1822 |
else if (found_different_type_key) { |
else if (found_different_type_key) { |
| 1823 |
HOSTS_do_different_type_key_dialog(pvar->NotificationWindow, pvar); |
HOSTS_do_different_type_key_dialog(pvar->NotificationWindow, pvar); |
| 1824 |
} |
} |
| 1825 |
else { |
else { |
|
#if 0 |
|
|
PostMessage(pvar->NotificationWindow, WM_COMMAND, |
|
|
ID_SSHUNKNOWNHOST, 0); |
|
|
#else |
|
| 1826 |
HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar); |
HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar); |
|
#endif |
|
|
|
|
| 1827 |
} |
} |
| 1828 |
|
|
| 1829 |
return TRUE; |
return TRUE; |
| 1832 |
void HOSTS_notify_disconnecting(PTInstVar pvar) |
void HOSTS_notify_disconnecting(PTInstVar pvar) |
| 1833 |
{ |
{ |
| 1834 |
if (pvar->hosts_state.hosts_dialog != NULL) { |
if (pvar->hosts_state.hosts_dialog != NULL) { |
| 1835 |
PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, |
PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, 0); |
|
0); |
|
| 1836 |
/* the main window might not go away if it's not enabled. (see vtwin.cpp) */ |
/* the main window might not go away if it's not enabled. (see vtwin.cpp) */ |
| 1837 |
EnableWindow(pvar->NotificationWindow, TRUE); |
EnableWindow(pvar->NotificationWindow, TRUE); |
| 1838 |
} |
} |
| 1843 |
int i; |
int i; |
| 1844 |
|
|
| 1845 |
free(pvar->hosts_state.prefetched_hostname); |
free(pvar->hosts_state.prefetched_hostname); |
|
#if 0 |
|
|
free(pvar->hosts_state.key_exp); |
|
|
free(pvar->hosts_state.key_mod); |
|
|
#else |
|
| 1846 |
init_hostkey(&pvar->hosts_state.hostkey); |
init_hostkey(&pvar->hosts_state.hostkey); |
|
#endif |
|
| 1847 |
|
|
| 1848 |
if (pvar->hosts_state.file_names != NULL) { |
if (pvar->hosts_state.file_names != NULL) { |
| 1849 |
for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) { |
for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) { |