svnno****@sourc*****
svnno****@sourc*****
2011年 7月 26日 (火) 17:50:11 JST
Revision: 4531 http://sourceforge.jp/projects/ttssh2/svn/view?view=rev&revision=4531 Author: doda Date: 2011-07-26 17:50:11 +0900 (Tue, 26 Jul 2011) Log Message: ----------- RFC 4255 "Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints" 対å¿ã®æºå http://tools.ietf.org/html/rfc4255 VerifyHostKeyDNS = 1 ã«ããã¨ããã¹ãéµã®æ¤è¨¼ãè¡ãã æ¤è¨¼ããã ãã§æ¤è¨¼çµæã¯ä½¿ã£ã¦ãªãããã©ã DNSSEC æªå¯¾å¿ã®åé¡ãæãã®ã§ããã®é¨åã«ã¤ãã¦æ¤è¨ä¸ã 解決ããç®éãç«ã£ã¦ããªãã®ã§ããããããã¨ãèµå ¥ãããããã Windows95/98/Me/NT4 ã§ã¯åããªãããã Modified Paths: -------------- trunk/ttssh2/ttxssh/hosts.c trunk/ttssh2/ttxssh/key.c trunk/ttssh2/ttxssh/key.h trunk/ttssh2/ttxssh/ssh.h trunk/ttssh2/ttxssh/ttxssh.c trunk/ttssh2/ttxssh/ttxssh.h trunk/ttssh2/ttxssh/ttxssh.vcproj -------------- next part -------------- Modified: trunk/ttssh2/ttxssh/hosts.c =================================================================== --- trunk/ttssh2/ttxssh/hosts.c 2011-07-26 08:18:19 UTC (rev 4530) +++ trunk/ttssh2/ttxssh/hosts.c 2011-07-26 08:50:11 UTC (rev 4531) @@ -49,7 +49,10 @@ #include <errno.h> #include <sys/stat.h> #include <direct.h> +#include <memory.h> +#include <windns.h> + static HFONT DlgHostsAddFont; static HFONT DlgHostsReplaceFont; @@ -128,12 +131,7 @@ void HOSTS_init(PTInstVar pvar) { pvar->hosts_state.prefetched_hostname = NULL; -#if 0 - pvar->hosts_state.key_exp = NULL; - pvar->hosts_state.key_mod = NULL; -#else init_hostkey(&pvar->hosts_state.hostkey); -#endif pvar->hosts_state.hosts_dialog = NULL; pvar->hosts_state.file_names = NULL; } @@ -693,16 +691,8 @@ return 0; } -#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 // hostkey type is KEY_UNSPEC. init_hostkey(&pvar->hosts_state.hostkey); -#endif do { if (pvar->hosts_state.file_data == NULL @@ -1631,6 +1621,107 @@ } } +int is_numeric_hostname(const char *hostname) +{ + struct addrinfo hints, *ai; + + if (hostname == NULL) { + return -1; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_NUMERICHOST; + + if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) { + freeaddrinfo(ai); + return 1; + } + + return 0; +} + +#define DNS_TYPE_SSHFP 44 +typedef struct { + BYTE Algorithm; + BYTE DigestType; + BYTE Digest[1]; +} DNS_SSHFP_DATA, *PDNS_SSHFP_DATA; +enum verifydns_result { + DNS_VERIFY_NONE, + DNS_VERIFY_MATCH, + DNS_VERIFY_MISMATCH, + DNS_VERIFY_DIFFERENTTYPE, + DNS_VERIFY_AUTH_MATCH, + DNS_VERIFY_AUTH_MISMATCH, + DNS_VERIFY_AUTH_DIFFERENTTYPE +}; + +int verify_hostkey_dns(char FAR *hostname, Key *key) +{ + DNS_STATUS status; + PDNS_RECORD rec, p; + PDNS_SSHFP_DATA t; + int hostkey_alg, hostkey_dtype, hostkey_dlen; + BYTE *hostkey_digest; + int found = DNS_VERIFY_NONE; + char buff[1024]; + + switch (key->type) { + case KEY_RSA: + hostkey_alg = SSHFP_KEY_RSA; + break; + case KEY_DSA: + hostkey_alg = SSHFP_KEY_DSA; + break; + // XXX KEY_ECDSA + default: // Un-supported algorighm + hostkey_alg = SSHFP_KEY_RESERVED; + } + + if (hostkey_alg) { + hostkey_dtype = SSHFP_HASH_SHA1; + hostkey_digest = key_fingerprint_raw(key, SSH_FP_SHA1, &hostkey_dlen); + } + else { + hostkey_dtype = SSHFP_HASH_RESERVED; + hostkey_digest = NULL; + } + + status = DnsQuery(hostname, DNS_TYPE_SSHFP, DNS_QUERY_STANDARD, NULL, &rec, NULL); + + if (status == 0) { + for (p=rec; p!=NULL; p=p->pNext) { + if (p->wType == DNS_TYPE_SSHFP) { + t = (PDNS_SSHFP_DATA)&(p->Data.Null); + if (t->Algorithm == hostkey_alg && t->DigestType == hostkey_dtype) { + if (hostkey_dlen == p->wDataLength-2 && memcmp(hostkey_digest, t->Digest, hostkey_dlen) == 0) { + found = DNS_VERIFY_MATCH; + _snprintf_s(buff, sizeof(buff), _TRUNCATE, "Match: alg=%d, dgst=%d, flags=%d (%x)", + t->Algorithm, t->DigestType, p->Flags); + MessageBox(NULL, buff, "DNS Verify Match", MB_OK); + break; + } + else { + found = DNS_VERIFY_MISMATCH; + _snprintf_s(buff, sizeof(buff), _TRUNCATE, "Missmatch: alg=%d, dgst=%d, flags=%d (%x)", + t->Algorithm, t->DigestType, p->Flags); + MessageBox(NULL, buff, "DNS Verify Missmatch", MB_OK); + break; + } + } + else { + found = DNS_VERIFY_DIFFERENTTYPE; + } + } + } + } + + free(hostkey_digest); + DnsRecordListFree(rec, DnsFreeRecordList); + return found; +} + // // T[o©ççêÄ«½zXgöJ®Ìëð`FbN·é // @@ -1638,7 +1729,7 @@ // BOOL HOSTS_check_host_key(PTInstVar pvar, char FAR * hostname, unsigned short tcpport, Key *key) { - int found_different_key = 0, found_different_type_key = 0; + int found_different_key = 0, found_different_type_key = 0, dns_sshfp_check = 0; // ·ÅÉ known_hosts t@C©çzXgöJ®ðÇÝñÅ¢éÈçA»êÆär·éB if (pvar->hosts_state.prefetched_hostname != NULL @@ -1687,6 +1778,11 @@ finish_read_host_files(pvar, 0); } + if (pvar->settings.VerifyHostKeyDNS) { + if (!is_numeric_hostname(hostname)) { + dns_sshfp_check = verify_hostkey_dns(hostname, key); + } + } // known_hosts ɶݵȢL[Í ÆÅt@CÖ«Þ½ßÉA±±ÅÛ¶µÄ¨B pvar->hosts_state.hostkey.type = key->type; @@ -1721,24 +1817,13 @@ // ±êÉæèknown_hostsÌmFðÒ½¸ÉAT[oÖ[UîñðÁĵܤâèðñð·éB // (2007.10.1 yutaka) if (found_different_key) { -#if 0 - PostMessage(pvar->NotificationWindow, WM_COMMAND, - ID_SSHDIFFERENTKEY, 0); -#else HOSTS_do_different_key_dialog(pvar->NotificationWindow, pvar); -#endif } else if (found_different_type_key) { HOSTS_do_different_type_key_dialog(pvar->NotificationWindow, pvar); } else { -#if 0 - PostMessage(pvar->NotificationWindow, WM_COMMAND, - ID_SSHUNKNOWNHOST, 0); -#else HOSTS_do_unknown_host_dialog(pvar->NotificationWindow, pvar); -#endif - } return TRUE; @@ -1747,8 +1832,7 @@ void HOSTS_notify_disconnecting(PTInstVar pvar) { if (pvar->hosts_state.hosts_dialog != NULL) { - PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, - 0); + PostMessage(pvar->hosts_state.hosts_dialog, WM_COMMAND, IDCANCEL, 0); /* the main window might not go away if it's not enabled. (see vtwin.cpp) */ EnableWindow(pvar->NotificationWindow, TRUE); } @@ -1759,12 +1843,7 @@ int i; free(pvar->hosts_state.prefetched_hostname); -#if 0 - free(pvar->hosts_state.key_exp); - free(pvar->hosts_state.key_mod); -#else init_hostkey(&pvar->hosts_state.hostkey); -#endif if (pvar->hosts_state.file_names != NULL) { for (i = 0; pvar->hosts_state.file_names[i] != NULL; i++) { Modified: trunk/ttssh2/ttxssh/key.c =================================================================== --- trunk/ttssh2/ttxssh/key.c 2011-07-26 08:18:19 UTC (rev 4530) +++ trunk/ttssh2/ttxssh/key.c 2011-07-26 08:50:11 UTC (rev 4531) @@ -435,7 +435,7 @@ } -char* key_fingerprint_raw(Key *k, int *dgst_raw_length) +char* key_fingerprint_raw(Key *k, enum fp_type dgst_type, int *dgst_raw_length) { const EVP_MD *md = NULL; EVP_MD_CTX ctx; @@ -447,8 +447,16 @@ *dgst_raw_length = 0; - // MD5ASYðgp·é - md = EVP_md5(); + switch (dgst_type) { + case SSH_FP_MD5: + md = EVP_md5(); + break; + case SSH_FP_SHA1: + md = EVP_sha1(); + break; + default: + md = EVP_md5(); + } switch (k->type) { case KEY_RSA1: @@ -633,7 +641,7 @@ int i, retval_len; // fingerprintÌnbV lioCijðßé - dgst_raw = key_fingerprint_raw(key, &dgst_raw_len); + dgst_raw = key_fingerprint_raw(key, SSH_FP_MD5, &dgst_raw_len); if (dgst_rep == SSH_FP_HEX) { // 16i\LÖÏ··é Modified: trunk/ttssh2/ttxssh/key.h =================================================================== --- trunk/ttssh2/ttxssh/key.h 2011-07-26 08:18:19 UTC (rev 4530) +++ trunk/ttssh2/ttxssh/key.h 2011-07-26 08:50:11 UTC (rev 4531) @@ -34,7 +34,7 @@ RSA *duplicate_RSA(RSA *src); DSA *duplicate_DSA(DSA *src); -char* key_fingerprint_raw(Key *k, int *dgst_raw_length); +char *key_fingerprint_raw(Key *k, enum fp_type dgst_type, int *dgst_raw_length); char *key_fingerprint(Key *key, enum fp_rep dgst_rep); const char *key_type(const Key *k); Modified: trunk/ttssh2/ttxssh/ssh.h =================================================================== --- trunk/ttssh2/ttxssh/ssh.h 2011-07-26 08:18:19 UTC (rev 4530) +++ trunk/ttssh2/ttxssh/ssh.h 2011-07-26 08:50:11 UTC (rev 4531) @@ -473,6 +473,22 @@ SSH_FP_RANDOMART }; +enum fp_type { + SSH_FP_SHA1, + SSH_FP_MD5 +}; + +enum sshfp_types { + SSHFP_KEY_RESERVED, + SSHFP_KEY_RSA, + SSHFP_KEY_DSA +}; + +enum sshfp_hashes { + SSHFP_HASH_RESERVED, + SSHFP_HASH_SHA1 +}; + enum scp_dir { TOREMOTE, FROMREMOTE, }; Modified: trunk/ttssh2/ttxssh/ttxssh.c =================================================================== --- trunk/ttssh2/ttxssh/ttxssh.c 2011-07-26 08:18:19 UTC (rev 4530) +++ trunk/ttssh2/ttxssh/ttxssh.c 2011-07-26 08:50:11 UTC (rev 4531) @@ -465,6 +465,9 @@ // agent forward mFðLøÉ·é settings->ForwardAgentConfirm = read_BOOL_option(fileName, "ForwardAgentConfirm", TRUE); + // zXg®Ì DNS ÅÌ`FbN (RFC 4255) + settings->VerifyHostKeyDNS = read_BOOL_option(fileName, "VerifyHostKeyDNS", FALSE); + clear_local_settings(pvar); } @@ -557,6 +560,12 @@ // agent forward mFðLøÉ·é WritePrivateProfileString("TTSSH", "ForwardAgentConfirm", settings->ForwardAgentConfirm ? "1" : "0", fileName); + +/* + // zXg®Ì DNS ÅÌ`FbN (RFC 4255) + WritePrivateProfileString("TTSSH", "VerifyHostKeyDNS", + settings->VerifyHostKeyDNS ? "1" : "0", fileName); + */ } Modified: trunk/ttssh2/ttxssh/ttxssh.h =================================================================== --- trunk/ttssh2/ttxssh/ttxssh.h 2011-07-26 08:18:19 UTC (rev 4530) +++ trunk/ttssh2/ttxssh/ttxssh.h 2011-07-26 08:50:11 UTC (rev 4531) @@ -145,6 +145,8 @@ char HostKeyOrder[KEY_MAX+1]; char MacOrder[HMAC_MAX+1]; char CompOrder[COMP_MAX+1]; + + BOOL VerifyHostKeyDNS; } TS_SSH; typedef struct _TInstVar { Modified: trunk/ttssh2/ttxssh/ttxssh.vcproj =================================================================== --- trunk/ttssh2/ttxssh/ttxssh.vcproj 2011-07-26 08:18:19 UTC (rev 4530) +++ trunk/ttssh2/ttxssh/ttxssh.vcproj 2011-07-26 08:50:11 UTC (rev 4531) @@ -78,11 +78,12 @@ <Tool Name="VCLinkerTool" AdditionalOptions="Version.lib 

" - AdditionalDependencies="odbc32.lib odbccp32.lib ws2_32.lib libeay32.lib zlibd.lib ttpcmn.lib" + AdditionalDependencies="odbc32.lib odbccp32.lib ws2_32.lib libeay32.lib zlibd.lib ttpcmn.lib dnsapi.lib" OutputFile=".\Debug/ttxssh.dll" LinkIncremental="2" SuppressStartupBanner="true" AdditionalLibraryDirectories="..\..\libs\openssl\out32.dbg;..\..\libs\zlib;..\..\teraterm\Debug" + DelayLoadDLLs="dnsapi.dll" ModuleDefinitionFile="ttxssh.def" GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug/ttxssh.pdb" @@ -182,11 +183,12 @@ <Tool Name="VCLinkerTool" AdditionalOptions="Version.lib 
" - AdditionalDependencies="odbc32.lib odbccp32.lib ws2_32.lib libeay32.lib zlib.lib ttpcmn.lib" + AdditionalDependencies="odbc32.lib odbccp32.lib ws2_32.lib libeay32.lib zlib.lib ttpcmn.lib dnsapi.lib" OutputFile=".\Release/ttxssh.dll" LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories="..\..\libs\openssl\out32;..\..\libs\zlib;..\..\teraterm\Release" + DelayLoadDLLs="dnsapi.dll" ModuleDefinitionFile="ttxssh.def" GenerateDebugInformation="true" ProgramDatabaseFile=".\Release/ttxssh.pdb"