| 614 |
// known_hostsファイルからホスト名に合致する行を読む |
// known_hostsファイルからホスト名に合致する行を読む |
| 615 |
// |
// |
| 616 |
static int read_host_key(PTInstVar pvar, char FAR * hostname, |
static int read_host_key(PTInstVar pvar, char FAR * hostname, |
| 617 |
int suppress_errors) |
int suppress_errors, int return_always) |
| 618 |
{ |
{ |
| 619 |
int i; |
int i; |
| 620 |
|
int while_flg; |
| 621 |
|
|
| 622 |
for (i = 0; hostname[i] != 0; i++) { |
for (i = 0; hostname[i] != 0; i++) { |
| 623 |
int ch = hostname[i]; |
int ch = hostname[i]; |
| 687 |
check_host_key(pvar, hostname, |
check_host_key(pvar, hostname, |
| 688 |
pvar->hosts_state.file_data + |
pvar->hosts_state.file_data + |
| 689 |
pvar->hosts_state.file_data_index); |
pvar->hosts_state.file_data_index); |
| 690 |
} while (pvar->hosts_state.hostkey.type == KEY_UNSPEC); // 有効なキーが見つかるまで |
|
| 691 |
|
if (!return_always) { |
| 692 |
|
// 有効なキーが見つかるまで |
| 693 |
|
while_flg = (pvar->hosts_state.hostkey.type == KEY_UNSPEC); |
| 694 |
|
} |
| 695 |
|
else { |
| 696 |
|
while_flg = 0; |
| 697 |
|
} |
| 698 |
|
} while (while_flg); |
| 699 |
|
|
| 700 |
return 1; |
return 1; |
| 701 |
} |
} |
| 714 |
return; |
return; |
| 715 |
} |
} |
| 716 |
|
|
| 717 |
if (!read_host_key(pvar, hostname, 1)) { |
if (!read_host_key(pvar, hostname, 1, 0)) { |
| 718 |
return; |
return; |
| 719 |
} |
} |
| 720 |
|
|
| 948 |
} |
} |
| 949 |
} |
} |
| 950 |
|
|
| 951 |
|
static char FAR *copy_mp_int(char FAR * num) |
| 952 |
|
{ |
| 953 |
|
int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2; |
| 954 |
|
char FAR *result = (char FAR *) malloc(len); |
| 955 |
|
|
| 956 |
|
if (result != NULL) { |
| 957 |
|
memcpy(result, num, len); |
| 958 |
|
} |
| 959 |
|
|
| 960 |
|
return result; |
| 961 |
|
} |
| 962 |
|
|
| 963 |
|
// |
| 964 |
|
// 同じホストで内容の異なるキーを削除する |
| 965 |
|
// add_host_key のあとに呼ぶこと |
| 966 |
|
// |
| 967 |
|
static void delete_different_key(PTInstVar pvar) |
| 968 |
|
{ |
| 969 |
|
char FAR *name = pvar->hosts_state.file_names[0]; |
| 970 |
|
|
| 971 |
|
if (name == NULL || name[0] == 0) { |
| 972 |
|
notify_nonfatal_error(pvar, |
| 973 |
|
"The host and its key cannot be added, because no known-hosts file has been specified.\n" |
| 974 |
|
"Restart Teraterm and specify a read/write known-hosts file in the TTSSH Setup dialog box."); |
| 975 |
|
} |
| 976 |
|
else { |
| 977 |
|
Key key; // 接続中のホストのキー |
| 978 |
|
int length = strlen(name); |
| 979 |
|
char filename[L_tmpnam]; |
| 980 |
|
int fd; |
| 981 |
|
int amount_written = 0; |
| 982 |
|
int close_result; |
| 983 |
|
int data_index = 0; |
| 984 |
|
|
| 985 |
|
// 書き込み一時ファイルを開く |
| 986 |
|
tmpnam(filename); |
| 987 |
|
fd = |
| 988 |
|
_open(filename, |
| 989 |
|
_O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_BINARY | |
| 990 |
|
_O_TRUNC, |
| 991 |
|
_S_IREAD | _S_IWRITE); |
| 992 |
|
|
| 993 |
|
if (fd == -1) { |
| 994 |
|
if (errno == EACCES) { |
| 995 |
|
notify_nonfatal_error(pvar, |
| 996 |
|
"An error occurred while trying to write the host key.\n" |
| 997 |
|
"You do not have permission to write to the known-hosts file."); |
| 998 |
|
} else { |
| 999 |
|
notify_nonfatal_error(pvar, |
| 1000 |
|
"An error occurred while trying to write the host key.\n" |
| 1001 |
|
"The host key could not be written."); |
| 1002 |
|
} |
| 1003 |
|
free(filename); |
| 1004 |
|
return; |
| 1005 |
|
} |
| 1006 |
|
|
| 1007 |
|
// 接続中のサーバのキーを読み込む |
| 1008 |
|
if (pvar->hosts_state.hostkey.type == KEY_RSA1) { // SSH1 |
| 1009 |
|
key.type = KEY_RSA1; |
| 1010 |
|
key.bits = pvar->hosts_state.hostkey.bits; |
| 1011 |
|
key.exp = copy_mp_int(pvar->hosts_state.hostkey.exp); |
| 1012 |
|
key.mod = copy_mp_int(pvar->hosts_state.hostkey.mod); |
| 1013 |
|
} else if (pvar->hosts_state.hostkey.type == KEY_RSA) { // SSH2 RSA |
| 1014 |
|
key.type = KEY_RSA; |
| 1015 |
|
key.rsa = duplicate_RSA(pvar->hosts_state.hostkey.rsa); |
| 1016 |
|
} else { // SSH2 DSA |
| 1017 |
|
key.type = KEY_DSA; |
| 1018 |
|
key.dsa = duplicate_DSA(pvar->hosts_state.hostkey.dsa); |
| 1019 |
|
} |
| 1020 |
|
|
| 1021 |
|
// ファイルから読み込む |
| 1022 |
|
begin_read_host_files(pvar, 0); |
| 1023 |
|
do { |
| 1024 |
|
int host_index = 0; |
| 1025 |
|
int matched = 0; |
| 1026 |
|
int keybits = 0; |
| 1027 |
|
char FAR *data; |
| 1028 |
|
int do_write = 0; |
| 1029 |
|
length = amount_written = 0; |
| 1030 |
|
|
| 1031 |
|
if (!read_host_key(pvar, pvar->ssh_state.hostname, 0, 1)) { |
| 1032 |
|
break; |
| 1033 |
|
} |
| 1034 |
|
|
| 1035 |
|
if (data_index == pvar->hosts_state.file_data_index) { |
| 1036 |
|
// index が進まない == 最後まで読んだ |
| 1037 |
|
break; |
| 1038 |
|
} |
| 1039 |
|
|
| 1040 |
|
data = pvar->hosts_state.file_data + data_index; |
| 1041 |
|
host_index = eat_spaces(data); |
| 1042 |
|
|
| 1043 |
|
if (data[host_index] == '#') { |
| 1044 |
|
do_write = 1; |
| 1045 |
|
} |
| 1046 |
|
else { |
| 1047 |
|
// ホストの照合 |
| 1048 |
|
host_index--; |
| 1049 |
|
do { |
| 1050 |
|
int negated; |
| 1051 |
|
|
| 1052 |
|
host_index++; |
| 1053 |
|
negated = data[host_index] == '!'; |
| 1054 |
|
|
| 1055 |
|
if (negated) { |
| 1056 |
|
host_index++; |
| 1057 |
|
if (match_pattern(data + host_index, |
| 1058 |
|
pvar->ssh_state.hostname)) { |
| 1059 |
|
matched = 0; |
| 1060 |
|
// 接続バージョンチェックのために host_index を進めてから抜ける |
| 1061 |
|
host_index--; |
| 1062 |
|
do { |
| 1063 |
|
host_index++; |
| 1064 |
|
host_index += eat_to_end_of_pattern(data + host_index); |
| 1065 |
|
} while (data[host_index] == ','); |
| 1066 |
|
break; |
| 1067 |
|
} |
| 1068 |
|
} |
| 1069 |
|
else if (match_pattern(data + host_index, |
| 1070 |
|
pvar->ssh_state.hostname)) { |
| 1071 |
|
matched = 1; |
| 1072 |
|
} |
| 1073 |
|
host_index += eat_to_end_of_pattern(data + host_index); |
| 1074 |
|
} while (data[host_index] == ','); |
| 1075 |
|
|
| 1076 |
|
// ホストが等しくて合致するキーが見つかる |
| 1077 |
|
if (match_key(pvar, &key)) { |
| 1078 |
|
do_write = 1; |
| 1079 |
|
} |
| 1080 |
|
// ホストが等しくない |
| 1081 |
|
else if (!matched) { |
| 1082 |
|
do_write = 1; |
| 1083 |
|
} |
| 1084 |
|
// ホストが等しい and 接続のバージョンが違う |
| 1085 |
|
else { |
| 1086 |
|
int rsa1_key_bits=0; |
| 1087 |
|
rsa1_key_bits = atoi(data + host_index + eat_spaces(data + host_index)); |
| 1088 |
|
|
| 1089 |
|
if (rsa1_key_bits > 0) { // ファイルのキーは ssh1 |
| 1090 |
|
if (!SSHv1(pvar)) { |
| 1091 |
|
do_write = 1; |
| 1092 |
|
} |
| 1093 |
|
} |
| 1094 |
|
else { // ファイルのキーは ssh2 |
| 1095 |
|
if (!SSHv2(pvar)) { |
| 1096 |
|
do_write = 1; |
| 1097 |
|
} |
| 1098 |
|
} |
| 1099 |
|
} |
| 1100 |
|
} |
| 1101 |
|
|
| 1102 |
|
// 書き込み処理 |
| 1103 |
|
if (do_write) { |
| 1104 |
|
length = pvar->hosts_state.file_data_index - data_index; |
| 1105 |
|
amount_written = |
| 1106 |
|
_write(fd, pvar->hosts_state.file_data + data_index, |
| 1107 |
|
length); |
| 1108 |
|
|
| 1109 |
|
if (amount_written != length) { |
| 1110 |
|
goto error1; |
| 1111 |
|
} |
| 1112 |
|
} |
| 1113 |
|
data_index = pvar->hosts_state.file_data_index; |
| 1114 |
|
} while (1); // 最後まで読む |
| 1115 |
|
|
| 1116 |
|
error1: |
| 1117 |
|
close_result = _close(fd); |
| 1118 |
|
if (amount_written != length || close_result == -1) { |
| 1119 |
|
notify_nonfatal_error(pvar, |
| 1120 |
|
"An error occurred while trying to write the host key.\n" |
| 1121 |
|
"The host key could not be written."); |
| 1122 |
|
goto error2; |
| 1123 |
|
} |
| 1124 |
|
|
| 1125 |
|
// 書き込み一時ファイルからリネーム |
| 1126 |
|
_unlink(pvar->hosts_state.file_names[0]); |
| 1127 |
|
rename(filename, pvar->hosts_state.file_names[0]); |
| 1128 |
|
|
| 1129 |
|
error2: |
| 1130 |
|
_unlink(filename); |
| 1131 |
|
|
| 1132 |
|
finish_read_host_files(pvar, 0); |
| 1133 |
|
} |
| 1134 |
|
} |
| 1135 |
|
|
| 1136 |
// |
// |
| 1137 |
// Unknown hostのホスト公開鍵を known_hosts ファイルへ保存するかどうかを |
// Unknown hostのホスト公開鍵を known_hosts ファイルへ保存するかどうかを |
| 1138 |
// ユーザに確認させる。 |
// ユーザに確認させる。 |
| 1139 |
// TODO: finger printの表示も行う。 |
// TODO: finger printの表示も行う。 |
| 1140 |
// (2006.3.25 yutaka) |
// (2006.3.25 yutaka) |
| 1141 |
// |
// |
| 1142 |
static BOOL CALLBACK hosts_dlg_proc(HWND dlg, UINT msg, WPARAM wParam, |
static BOOL CALLBACK hosts_add_dlg_proc(HWND dlg, UINT msg, WPARAM wParam, |
| 1143 |
LPARAM lParam) |
LPARAM lParam) |
| 1144 |
{ |
{ |
| 1145 |
PTInstVar pvar; |
PTInstVar pvar; |
| 1146 |
|
|
| 1192 |
} |
} |
| 1193 |
} |
} |
| 1194 |
|
|
| 1195 |
static char FAR *copy_mp_int(char FAR * num) |
// |
| 1196 |
|
// 置き換え時の確認ダイアログを分離 |
| 1197 |
|
// |
| 1198 |
|
static BOOL CALLBACK hosts_replace_dlg_proc(HWND dlg, UINT msg, WPARAM wParam, |
| 1199 |
|
LPARAM lParam) |
| 1200 |
{ |
{ |
| 1201 |
int len = (get_ushort16_MSBfirst(num) + 7) / 8 + 2; |
PTInstVar pvar; |
|
char FAR *result = (char FAR *) malloc(len); |
|
| 1202 |
|
|
| 1203 |
if (result != NULL) { |
switch (msg) { |
| 1204 |
memcpy(result, num, len); |
case WM_INITDIALOG: |
| 1205 |
} |
pvar = (PTInstVar) lParam; |
| 1206 |
|
pvar->hosts_state.hosts_dialog = dlg; |
| 1207 |
|
SetWindowLong(dlg, DWL_USER, lParam); |
| 1208 |
|
|
| 1209 |
return result; |
init_hosts_dlg(pvar, dlg); |
| 1210 |
|
|
| 1211 |
|
// デフォルトでチェックは入れない |
| 1212 |
|
return TRUE; /* because we do not set the focus */ |
| 1213 |
|
|
| 1214 |
|
case WM_COMMAND: |
| 1215 |
|
pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER); |
| 1216 |
|
|
| 1217 |
|
switch (LOWORD(wParam)) { |
| 1218 |
|
case IDC_CONTINUE: |
| 1219 |
|
if (IsDlgButtonChecked(dlg, IDC_ADDTOKNOWNHOSTS)) { |
| 1220 |
|
add_host_key(pvar); |
| 1221 |
|
delete_different_key(pvar); |
| 1222 |
|
} |
| 1223 |
|
|
| 1224 |
|
if (SSHv1(pvar)) { |
| 1225 |
|
SSH_notify_host_OK(pvar); |
| 1226 |
|
} else { // SSH2 |
| 1227 |
|
// SSH2ではあとで SSH_notify_host_OK() を呼ぶ。 |
| 1228 |
|
} |
| 1229 |
|
|
| 1230 |
|
pvar->hosts_state.hosts_dialog = NULL; |
| 1231 |
|
|
| 1232 |
|
EndDialog(dlg, 1); |
| 1233 |
|
return TRUE; |
| 1234 |
|
|
| 1235 |
|
case IDCANCEL: /* kill the connection */ |
| 1236 |
|
pvar->hosts_state.hosts_dialog = NULL; |
| 1237 |
|
notify_closed_connection(pvar); |
| 1238 |
|
EndDialog(dlg, 0); |
| 1239 |
|
return TRUE; |
| 1240 |
|
|
| 1241 |
|
default: |
| 1242 |
|
return FALSE; |
| 1243 |
|
} |
| 1244 |
|
|
| 1245 |
|
default: |
| 1246 |
|
return FALSE; |
| 1247 |
|
} |
| 1248 |
} |
} |
| 1249 |
|
|
| 1250 |
void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar) |
void HOSTS_do_unknown_host_dialog(HWND wnd, PTInstVar pvar) |
| 1254 |
|
|
| 1255 |
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST), |
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHUNKNOWNHOST), |
| 1256 |
cur_active != NULL ? cur_active : wnd, |
cur_active != NULL ? cur_active : wnd, |
| 1257 |
hosts_dlg_proc, (LPARAM) pvar); |
hosts_add_dlg_proc, (LPARAM) pvar); |
| 1258 |
} |
} |
| 1259 |
} |
} |
| 1260 |
|
|
| 1265 |
|
|
| 1266 |
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST), |
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHDIFFERENTHOST), |
| 1267 |
cur_active != NULL ? cur_active : wnd, |
cur_active != NULL ? cur_active : wnd, |
| 1268 |
hosts_dlg_proc, (LPARAM) pvar); |
hosts_replace_dlg_proc, (LPARAM) pvar); |
| 1269 |
} |
} |
| 1270 |
} |
} |
| 1271 |
|
|
| 1294 |
// 先読みされていない場合は、この時点でファイルから読み込む |
// 先読みされていない場合は、この時点でファイルから読み込む |
| 1295 |
if (begin_read_host_files(pvar, 0)) { |
if (begin_read_host_files(pvar, 0)) { |
| 1296 |
do { |
do { |
| 1297 |
if (!read_host_key(pvar, hostname, 0)) { |
if (!read_host_key(pvar, hostname, 0, 0)) { |
| 1298 |
break; |
break; |
| 1299 |
} |
} |
| 1300 |
|
|
| 1380 |
|
|
| 1381 |
/* |
/* |
| 1382 |
* $Log: not supported by cvs2svn $ |
* $Log: not supported by cvs2svn $ |
| 1383 |
|
* Revision 1.6 2006/03/29 14:56:52 yutakakn |
| 1384 |
|
* known_hostsファイルにキー種別の異なる同一ホストのエントリがあると、アプリケーションエラーとなるバグを修正した。 |
| 1385 |
|
* |
| 1386 |
* Revision 1.5 2006/03/26 17:07:17 yutakakn |
* Revision 1.5 2006/03/26 17:07:17 yutakakn |
| 1387 |
* fingerprint表示を追加 |
* fingerprint表示を追加 |
| 1388 |
* |
* |