| 765 |
finish_read_host_files(pvar, 1); |
finish_read_host_files(pvar, 1); |
| 766 |
} |
} |
| 767 |
|
|
| 768 |
|
|
| 769 |
|
// known_hostsファイルから該当するキー情報を取得する。 |
| 770 |
|
// |
| 771 |
|
// return: |
| 772 |
|
// *keyptr != NULL 取得成功 |
| 773 |
|
// |
| 774 |
|
static int parse_hostkey_file(PTInstVar pvar, char FAR * hostname, |
| 775 |
|
unsigned short tcpport, char FAR * data, Key **keyptr) |
| 776 |
|
{ |
| 777 |
|
int index = eat_spaces(data); |
| 778 |
|
int matched = 0; |
| 779 |
|
int keybits = 0; |
| 780 |
|
ssh_keytype ktype; |
| 781 |
|
|
| 782 |
|
*keyptr = NULL; |
| 783 |
|
|
| 784 |
|
if (data[index] == '#') { |
| 785 |
|
return index + eat_to_end_of_line(data + index); |
| 786 |
|
} |
| 787 |
|
|
| 788 |
|
/* if we find an empty line, then it won't have any patterns matching the hostname |
| 789 |
|
and so we skip it */ |
| 790 |
|
index--; |
| 791 |
|
do { |
| 792 |
|
int negated; |
| 793 |
|
int bracketed; |
| 794 |
|
char *end_bracket; |
| 795 |
|
int host_matched = 0; |
| 796 |
|
unsigned short keyfile_port = 22; |
| 797 |
|
|
| 798 |
|
index++; |
| 799 |
|
negated = data[index] == '!'; |
| 800 |
|
|
| 801 |
|
if (negated) { |
| 802 |
|
index++; |
| 803 |
|
bracketed = data[index] == '['; |
| 804 |
|
if (bracketed) { |
| 805 |
|
end_bracket = strstr(data + index + 1, "]:"); |
| 806 |
|
if (end_bracket != NULL) { |
| 807 |
|
*end_bracket = ' '; |
| 808 |
|
index++; |
| 809 |
|
} |
| 810 |
|
} |
| 811 |
|
host_matched = match_pattern(data + index, hostname); |
| 812 |
|
if (bracketed && end_bracket != NULL) { |
| 813 |
|
*end_bracket = ']'; |
| 814 |
|
keyfile_port = atoi(end_bracket + 2); |
| 815 |
|
} |
| 816 |
|
if (host_matched && keyfile_port == tcpport) { |
| 817 |
|
return index + eat_to_end_of_line(data + index); |
| 818 |
|
} |
| 819 |
|
} |
| 820 |
|
else { |
| 821 |
|
bracketed = data[index] == '['; |
| 822 |
|
if (bracketed) { |
| 823 |
|
end_bracket = strstr(data + index + 1, "]:"); |
| 824 |
|
if (end_bracket != NULL) { |
| 825 |
|
*end_bracket = ' '; |
| 826 |
|
index++; |
| 827 |
|
} |
| 828 |
|
} |
| 829 |
|
host_matched = match_pattern(data + index, hostname); |
| 830 |
|
if (bracketed && end_bracket != NULL) { |
| 831 |
|
*end_bracket = ']'; |
| 832 |
|
keyfile_port = atoi(end_bracket + 2); |
| 833 |
|
} |
| 834 |
|
if (host_matched && keyfile_port == tcpport) { |
| 835 |
|
matched = 1; |
| 836 |
|
} |
| 837 |
|
} |
| 838 |
|
|
| 839 |
|
index += eat_to_end_of_pattern(data + index); |
| 840 |
|
} while (data[index] == ','); |
| 841 |
|
|
| 842 |
|
if (!matched) { |
| 843 |
|
return index + eat_to_end_of_line(data + index); |
| 844 |
|
} |
| 845 |
|
else { |
| 846 |
|
// 鍵の種類によりフォーマットが異なる |
| 847 |
|
// また、最初に一致したエントリを取得することになる。 |
| 848 |
|
/* |
| 849 |
|
[SSH1] |
| 850 |
|
192.168.1.2 1024 35 13032.... |
| 851 |
|
|
| 852 |
|
[SSH2] |
| 853 |
|
192.168.1.2 ssh-rsa AAAAB3NzaC1.... |
| 854 |
|
192.168.1.2 ssh-dss AAAAB3NzaC1.... |
| 855 |
|
192.168.1.2 rsa AAAAB3NzaC1.... |
| 856 |
|
192.168.1.2 dsa AAAAB3NzaC1.... |
| 857 |
|
192.168.1.2 rsa1 AAAAB3NzaC1.... |
| 858 |
|
*/ |
| 859 |
|
int rsa1_key_bits; |
| 860 |
|
|
| 861 |
|
index += eat_spaces(data + index); |
| 862 |
|
|
| 863 |
|
rsa1_key_bits = atoi(data + index); |
| 864 |
|
if (rsa1_key_bits > 0) { // RSA1である |
| 865 |
|
if (!SSHv1(pvar)) { // SSH2接続であれば無視する |
| 866 |
|
return index + eat_to_end_of_line(data + index); |
| 867 |
|
} |
| 868 |
|
index += eat_digits(data + index); |
| 869 |
|
index += eat_spaces(data + index); |
| 870 |
|
|
| 871 |
|
index += eat_digits(data + index); |
| 872 |
|
index += eat_spaces(data + index); |
| 873 |
|
|
| 874 |
|
} |
| 875 |
|
else { |
| 876 |
|
char *cp, *p; |
| 877 |
|
Key *key; |
| 878 |
|
|
| 879 |
|
if (!SSHv2(pvar)) { // SSH1接続であれば無視する |
| 880 |
|
return index + eat_to_end_of_line(data + index); |
| 881 |
|
} |
| 882 |
|
|
| 883 |
|
cp = data + index; |
| 884 |
|
p = strchr(cp, ' '); |
| 885 |
|
if (p == NULL) { |
| 886 |
|
return index + eat_to_end_of_line(data + index); |
| 887 |
|
} |
| 888 |
|
index += (p - cp); // setup index |
| 889 |
|
*p = '\0'; |
| 890 |
|
ktype = get_keytype_from_name(cp); |
| 891 |
|
*p = ' '; |
| 892 |
|
|
| 893 |
|
index += eat_spaces(data + index); // update index |
| 894 |
|
|
| 895 |
|
// uudecode |
| 896 |
|
key = parse_uudecode(data + index); |
| 897 |
|
if (key == NULL) { |
| 898 |
|
return index + eat_to_end_of_line(data + index); |
| 899 |
|
} |
| 900 |
|
|
| 901 |
|
// setup |
| 902 |
|
*keyptr = key; |
| 903 |
|
|
| 904 |
|
index += eat_base64(data + index); |
| 905 |
|
index += eat_spaces(data + index); |
| 906 |
|
} |
| 907 |
|
|
| 908 |
|
return index + eat_to_end_of_line(data + index); |
| 909 |
|
} |
| 910 |
|
} |
| 911 |
|
|
| 912 |
|
// known_hostsファイルからホスト公開鍵を取得する。 |
| 913 |
|
// 既存の処理を改変したくないので、Host key rotation用に新規に用意する。 |
| 914 |
|
// |
| 915 |
|
// return 1: success |
| 916 |
|
// 0: fail |
| 917 |
|
int HOSTS_hostkey_foreach(PTInstVar pvar, hostkeys_foreach_fn *callback, void *ctx) |
| 918 |
|
{ |
| 919 |
|
int success = 0; |
| 920 |
|
int suppress_errors = 1; |
| 921 |
|
unsigned short tcpport; |
| 922 |
|
char FAR *filename; |
| 923 |
|
char *hostname; |
| 924 |
|
Key *key; |
| 925 |
|
|
| 926 |
|
if (!begin_read_host_files(pvar, 1)) { |
| 927 |
|
goto error; |
| 928 |
|
} |
| 929 |
|
|
| 930 |
|
// Host key rotationでは、known_hosts ファイルを書き換えるので、 |
| 931 |
|
// 検索するのは1つめのファイルのみでよい(2つめのファイルはReadOnlyのため)。 |
| 932 |
|
filename = pvar->hosts_state.file_names[pvar->hosts_state.file_num]; |
| 933 |
|
pvar->hosts_state.file_num++; |
| 934 |
|
|
| 935 |
|
pvar->hosts_state.file_data_index = -1; |
| 936 |
|
if (filename[0] != 0) { |
| 937 |
|
if (begin_read_file(pvar, filename, suppress_errors)) { |
| 938 |
|
pvar->hosts_state.file_data_index = 0; |
| 939 |
|
} |
| 940 |
|
} |
| 941 |
|
if (pvar->hosts_state.file_data_index == -1) |
| 942 |
|
goto error; |
| 943 |
|
|
| 944 |
|
// 検索対象となるホスト名とポート番号。 |
| 945 |
|
hostname = pvar->ssh_state.hostname; |
| 946 |
|
tcpport = pvar->ssh_state.tcpport; |
| 947 |
|
|
| 948 |
|
// known_hostsファイルの内容がすべて pvar->hosts_state.file_data に読み込まれている。 |
| 949 |
|
// 末尾は \0 。 |
| 950 |
|
while (pvar->hosts_state.file_data[pvar->hosts_state.file_data_index] != 0) { |
| 951 |
|
key = NULL; |
| 952 |
|
|
| 953 |
|
pvar->hosts_state.file_data_index += |
| 954 |
|
parse_hostkey_file(pvar, hostname, tcpport, |
| 955 |
|
pvar->hosts_state.file_data + |
| 956 |
|
pvar->hosts_state.file_data_index, |
| 957 |
|
&key); |
| 958 |
|
|
| 959 |
|
if (key != NULL) { |
| 960 |
|
key = key; |
| 961 |
|
key_free(key); |
| 962 |
|
} |
| 963 |
|
|
| 964 |
|
} |
| 965 |
|
|
| 966 |
|
success = 1; |
| 967 |
|
|
| 968 |
|
error: |
| 969 |
|
finish_read_host_files(pvar, 1); |
| 970 |
|
|
| 971 |
|
return (success); |
| 972 |
|
} |
| 973 |
|
|
| 974 |
|
|
| 975 |
static BOOL equal_mp_ints(unsigned char FAR * num1, |
static BOOL equal_mp_ints(unsigned char FAR * num1, |
| 976 |
unsigned char FAR * num2) |
unsigned char FAR * num2) |
| 977 |
{ |
{ |