| 4833 |
char buf[1024]; |
char buf[1024]; |
| 4834 |
char *data; |
char *data; |
| 4835 |
int len, size; |
int len, size; |
|
int offset = 0; |
|
| 4836 |
char *msg = NULL; |
char *msg = NULL; |
| 4837 |
char tmp[1024+512]; |
char tmp[1024+512]; |
| 4838 |
char str_keytype[20]; |
char str_keytype[20]; |
| 4852 |
data = remained_payload(pvar); |
data = remained_payload(pvar); |
| 4853 |
len = remained_payloadlen(pvar); |
len = remained_payloadlen(pvar); |
| 4854 |
|
|
| 4855 |
// KEX の最後で hash (session-id) を計算するのに使うので保存しておく |
// KEX の最後で exchange-hash (session-id) を計算するのに使うので保存しておく |
| 4856 |
if (pvar->peer_kex != NULL) { |
if (pvar->peer_kex != NULL) { |
| 4857 |
// already allocated |
// already allocated |
| 4858 |
buffer_clear(pvar->peer_kex); |
buffer_clear(pvar->peer_kex); |
| 4866 |
} |
} |
| 4867 |
buffer_append(pvar->peer_kex, data, len); |
buffer_append(pvar->peer_kex, data, len); |
| 4868 |
|
|
|
// TODO: buffer overrun check |
|
|
|
|
| 4869 |
push_memdump("KEXINIT", "exchange algorithm list: receiving", data, len); |
push_memdump("KEXINIT", "exchange algorithm list: receiving", data, len); |
| 4870 |
|
|
| 4871 |
if (offset + 20 >= len) { |
// cookie; ここでは使わないので読み飛ばす |
| 4872 |
msg = "payload size too small @ handle_SSH2_kexinit()"; |
if (! grab_payload(pvar, SSH2_COOKIE_LENGTH)) { |
| 4873 |
|
msg = __FUNCTION__ ": truncated packet (cookie)"; |
| 4874 |
goto error; |
goto error; |
| 4875 |
} |
} |
| 4876 |
|
|
| 4877 |
// get rid of Cookie length |
// get rid of Cookie length |
| 4878 |
offset += SSH2_COOKIE_LENGTH; |
data += SSH2_COOKIE_LENGTH; |
|
|
|
| 4879 |
|
|
| 4880 |
// KEXの決定。判定順をmyproposal[PROPOSAL_KEX_ALGS]の並びと合わせること。 |
// 各要素(鍵交換,暗号化等)で使用するアルゴリズムの決定。 |
| 4881 |
// サーバは、クライアントから送られてきた myproposal[PROPOSAL_KEX_ALGS] のカンマ文字列のうち、 |
// サーバからはカンマ区切りでのリストが送られて来る。 |
| 4882 |
// 先頭から自分の myproposal[] と比較を行い、最初にマッチしたものがKEXアルゴリズムとして |
// クライアントとサーバ両方がサポートしている物のうち、 |
| 4883 |
// 選択される。(2004.10.30 yutaka) |
// クライアント側で最も前に指定した物が使われる。 |
| 4884 |
|
|
| 4885 |
// キー交換アルゴリズムチェック |
// 鍵交換アルゴリズム |
| 4886 |
size = get_payload_uint32(pvar, offset); |
if (!grab_payload(pvar, 4) |
| 4887 |
offset += 4; |
|| !grab_payload(pvar, size = get_uint32(data))) { |
| 4888 |
|
msg = __FUNCTION__ ": truncated packet (kex algorithms)"; |
| 4889 |
|
goto error; |
| 4890 |
|
} |
| 4891 |
|
data += 4; |
| 4892 |
|
|
| 4893 |
if (size >= sizeof(buf)) { |
if (size >= sizeof(buf)) { |
| 4894 |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed kex algorithms is too long."); |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed kex algorithms is too long."); |
| 4895 |
} |
} |
| 4896 |
strncpy_s(buf, sizeof(buf), data+offset, _TRUNCATE); |
strncpy_s(buf, sizeof(buf), data, _TRUNCATE); |
| 4897 |
offset += size; |
data += size; |
| 4898 |
|
|
| 4899 |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: KEX algorithm: %s", buf); |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: KEX algorithm: %s", buf); |
| 4900 |
|
|
| 4906 |
goto error; |
goto error; |
| 4907 |
} |
} |
| 4908 |
|
|
| 4909 |
|
// ホスト鍵アルゴリズム |
| 4910 |
// ホストキーアルゴリズムチェック |
if (!grab_payload(pvar, 4) |
| 4911 |
size = get_payload_uint32(pvar, offset); |
|| !grab_payload(pvar, size = get_uint32(data))) { |
| 4912 |
offset += 4; |
msg = __FUNCTION__ ": truncated packet (hostkey algorithms)"; |
| 4913 |
|
goto error; |
| 4914 |
|
} |
| 4915 |
|
data += 4; |
| 4916 |
|
|
| 4917 |
if (size >= sizeof(buf)) { |
if (size >= sizeof(buf)) { |
| 4918 |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed hostkey algorithms is too long."); |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed hostkey algorithms is too long."); |
| 4919 |
} |
} |
| 4920 |
strncpy_s(buf, sizeof(buf), data+offset, _TRUNCATE); |
strncpy_s(buf, sizeof(buf), data, _TRUNCATE); |
| 4921 |
offset += size; |
data += size; |
| 4922 |
|
|
| 4923 |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: server host key algorithm: %s", buf); |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: server host key algorithm: %s", buf); |
| 4924 |
|
|
| 4938 |
goto error; |
goto error; |
| 4939 |
} |
} |
| 4940 |
|
|
| 4941 |
|
// 暗号アルゴリズム(クライアント -> サーバ) |
| 4942 |
// クライアント -> サーバ暗号アルゴリズムチェック |
if (!grab_payload(pvar, 4) |
| 4943 |
size = get_payload_uint32(pvar, offset); |
|| !grab_payload(pvar, size = get_uint32(data))) { |
| 4944 |
offset += 4; |
msg = __FUNCTION__ ": truncated packet (encryption algorithms client to server)"; |
| 4945 |
|
goto error; |
| 4946 |
|
} |
| 4947 |
|
data += 4; |
| 4948 |
|
|
| 4949 |
if (size >= sizeof(buf)) { |
if (size >= sizeof(buf)) { |
| 4950 |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed encryption algorithms (client to server) is too long."); |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed encryption algorithms (client to server) is too long."); |
| 4951 |
} |
} |
| 4952 |
strncpy_s(buf, sizeof(buf), data+offset, _TRUNCATE); |
strncpy_s(buf, sizeof(buf), data, _TRUNCATE); |
| 4953 |
offset += size; |
data += size; |
| 4954 |
|
|
| 4955 |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: encryption algorithm client to server: %s", buf); |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: encryption algorithm client to server: %s", buf); |
| 4956 |
|
|
| 4957 |
pvar->ciphers[MODE_OUT] = choose_SSH2_cipher_algorithm(buf, myproposal[PROPOSAL_ENC_ALGS_CTOS]); |
pvar->ciphers[MODE_OUT] = choose_SSH2_cipher_algorithm(buf, myproposal[PROPOSAL_ENC_ALGS_CTOS]); |
| 4958 |
if (pvar->ciphers[MODE_OUT] == NULL) { |
if (pvar->ciphers[MODE_OUT]->id == SSH_CIPHER_NONE) { |
| 4959 |
strncpy_s(tmp, sizeof(tmp), "unknown Encrypt algorithm(ctos): ", _TRUNCATE); |
strncpy_s(tmp, sizeof(tmp), "unknown Encrypt algorithm(client to server): ", _TRUNCATE); |
| 4960 |
strncat_s(tmp, sizeof(tmp), buf, _TRUNCATE); |
strncat_s(tmp, sizeof(tmp), buf, _TRUNCATE); |
| 4961 |
msg = tmp; |
msg = tmp; |
| 4962 |
goto error; |
goto error; |
| 4963 |
} |
} |
| 4964 |
|
|
| 4965 |
|
// 暗号アルゴリズム(サーバ -> クライアント) |
| 4966 |
// サーバ -> クライアント暗号アルゴリズムチェック |
if (!grab_payload(pvar, 4) |
| 4967 |
size = get_payload_uint32(pvar, offset); |
|| !grab_payload(pvar, size = get_uint32(data))) { |
| 4968 |
offset += 4; |
msg = __FUNCTION__ ": truncated packet (encryption algorithms server to client)"; |
| 4969 |
|
goto error; |
| 4970 |
|
} |
| 4971 |
|
data += 4; |
| 4972 |
|
|
| 4973 |
if (size >= sizeof(buf)) { |
if (size >= sizeof(buf)) { |
| 4974 |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed encryption algorithms (server to client) is too long."); |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed encryption algorithms (server to client) is too long."); |
| 4975 |
} |
} |
| 4976 |
strncpy_s(buf, sizeof(buf), data+offset, _TRUNCATE); |
strncpy_s(buf, sizeof(buf), data, _TRUNCATE); |
| 4977 |
offset += size; |
data += size; |
| 4978 |
|
|
| 4979 |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: encryption algorithm server to client: %s", buf); |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: encryption algorithm server to client: %s", buf); |
| 4980 |
|
|
| 4981 |
pvar->ciphers[MODE_IN] = choose_SSH2_cipher_algorithm(buf, myproposal[PROPOSAL_ENC_ALGS_STOC]); |
pvar->ciphers[MODE_IN] = choose_SSH2_cipher_algorithm(buf, myproposal[PROPOSAL_ENC_ALGS_STOC]); |
| 4982 |
if (pvar->ciphers[MODE_IN] == NULL) { |
if (pvar->ciphers[MODE_IN]->id == SSH_CIPHER_NONE) { |
| 4983 |
strncpy_s(tmp, sizeof(tmp), "unknown Encrypt algorithm(stoc): ", _TRUNCATE); |
strncpy_s(tmp, sizeof(tmp), "unknown Encrypt algorithm(server to client): ", _TRUNCATE); |
| 4984 |
strncat_s(tmp, sizeof(tmp), buf, _TRUNCATE); |
strncat_s(tmp, sizeof(tmp), buf, _TRUNCATE); |
| 4985 |
msg = tmp; |
msg = tmp; |
| 4986 |
goto error; |
goto error; |
| 4987 |
} |
} |
| 4988 |
|
|
| 4989 |
|
// MACアルゴリズム(クライアント -> サーバ) |
| 4990 |
// MAC(Message Authentication Code)アルゴリズムの決定 (2004.12.17 yutaka) |
if (!grab_payload(pvar, 4) |
| 4991 |
size = get_payload_uint32(pvar, offset); |
|| !grab_payload(pvar, size = get_uint32(data))) { |
| 4992 |
offset += 4; |
msg = __FUNCTION__ ": truncated packet (MAC algorithms client to server)"; |
| 4993 |
|
goto error; |
| 4994 |
|
} |
| 4995 |
|
data += 4; |
| 4996 |
|
|
| 4997 |
if (size >= sizeof(buf)) { |
if (size >= sizeof(buf)) { |
| 4998 |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed MAC algorithms (client to server) is too long."); |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed MAC algorithms (client to server) is too long."); |
| 4999 |
} |
} |
| 5000 |
strncpy_s(buf, sizeof(buf), data+offset, _TRUNCATE); |
strncpy_s(buf, sizeof(buf), data, _TRUNCATE); |
| 5001 |
offset += size; |
data += size; |
| 5002 |
|
|
| 5003 |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: MAC algorithm client to server: %s", buf); |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: MAC algorithm client to server: %s", buf); |
| 5004 |
|
|
| 5005 |
if (pvar->ciphers[MODE_OUT]->auth_len > 0) { |
if (pvar->ciphers[MODE_OUT]->auth_len > 0) { |
| 5006 |
logputs(LOG_LEVEL_VERBOSE, "AEAD cipher is selected, ignoring MAC algorithms. (c2s)"); |
logputs(LOG_LEVEL_VERBOSE, "AEAD cipher is selected, ignoring MAC algorithms. (client to server)"); |
| 5007 |
pvar->macs[MODE_OUT] = get_ssh2_mac(HMAC_IMPLICIT); |
pvar->macs[MODE_OUT] = get_ssh2_mac(HMAC_IMPLICIT); |
| 5008 |
} |
} |
| 5009 |
else { |
else { |
| 5016 |
} |
} |
| 5017 |
} |
} |
| 5018 |
|
|
| 5019 |
size = get_payload_uint32(pvar, offset); |
// MACアルゴリズム(サーバ -> クライアント) |
| 5020 |
offset += 4; |
if (!grab_payload(pvar, 4) |
| 5021 |
|
|| !grab_payload(pvar, size = get_uint32(data))) { |
| 5022 |
|
msg = __FUNCTION__ ": truncated packet (MAC algorithms server to client)"; |
| 5023 |
|
goto error; |
| 5024 |
|
} |
| 5025 |
|
data += 4; |
| 5026 |
|
|
| 5027 |
if (size >= sizeof(buf)) { |
if (size >= sizeof(buf)) { |
| 5028 |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed MAC algorithms (server to client) is too long."); |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed MAC algorithms (server to client) is too long."); |
| 5029 |
} |
} |
| 5030 |
strncpy_s(buf, sizeof(buf), data+offset, _TRUNCATE); |
strncpy_s(buf, sizeof(buf), data, _TRUNCATE); |
| 5031 |
offset += size; |
data += size; |
| 5032 |
|
|
| 5033 |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: MAC algorithm server to client: %s", buf); |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: MAC algorithm server to client: %s", buf); |
| 5034 |
|
|
| 5035 |
if (pvar->ciphers[MODE_IN]->auth_len > 0) { |
if (pvar->ciphers[MODE_IN]->auth_len > 0) { |
| 5036 |
logputs(LOG_LEVEL_VERBOSE, "AEAD cipher is selected, ignoring MAC algorithms. (s2c)"); |
logputs(LOG_LEVEL_VERBOSE, "AEAD cipher is selected, ignoring MAC algorithms. (server to client)"); |
| 5037 |
pvar->macs[MODE_IN] = get_ssh2_mac(HMAC_IMPLICIT); |
pvar->macs[MODE_IN] = get_ssh2_mac(HMAC_IMPLICIT); |
| 5038 |
} |
} |
| 5039 |
else { |
else { |
| 5046 |
} |
} |
| 5047 |
} |
} |
| 5048 |
|
|
| 5049 |
// 圧縮アルゴリズムの決定 |
// 圧縮アルゴリズム(クライアント -> サーバ) |
| 5050 |
// pvar->ssh_state.compressing = FALSE; として下記メンバを使用する。 |
if (!grab_payload(pvar, 4) |
| 5051 |
// (2005.7.9 yutaka) |
|| !grab_payload(pvar, size = get_uint32(data))) { |
| 5052 |
size = get_payload_uint32(pvar, offset); |
msg = __FUNCTION__ ": truncated packet (compression algorithms client to server)"; |
| 5053 |
offset += 4; |
goto error; |
| 5054 |
|
} |
| 5055 |
|
data += 4; |
| 5056 |
|
|
| 5057 |
if (size >= sizeof(buf)) { |
if (size >= sizeof(buf)) { |
| 5058 |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed compression algorithms (client to server) is too long."); |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed compression algorithms (client to server) is too long."); |
| 5059 |
} |
} |
| 5060 |
strncpy_s(buf, sizeof(buf), data+offset, _TRUNCATE); |
strncpy_s(buf, sizeof(buf), data, _TRUNCATE); |
| 5061 |
offset += size; |
data += size; |
| 5062 |
|
|
| 5063 |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: compression algorithm client to server: %s", buf); |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: compression algorithm client to server: %s", buf); |
| 5064 |
|
|
| 5070 |
goto error; |
goto error; |
| 5071 |
} |
} |
| 5072 |
|
|
| 5073 |
|
// 圧縮アルゴリズム(サーバ -> クライアント) |
| 5074 |
size = get_payload_uint32(pvar, offset); |
if (!grab_payload(pvar, 4) |
| 5075 |
offset += 4; |
|| !grab_payload(pvar, size = get_uint32(data))) { |
| 5076 |
|
msg = __FUNCTION__ ": truncated packet (compression algorithms server to client)"; |
| 5077 |
|
goto error; |
| 5078 |
|
} |
| 5079 |
|
data += 4; |
| 5080 |
|
|
| 5081 |
if (size >= sizeof(buf)) { |
if (size >= sizeof(buf)) { |
| 5082 |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed compression algorithms (server to client) is too long."); |
logputs(LOG_LEVEL_WARNING, __FUNCTION__ ": server proposed compression algorithms (server to client) is too long."); |
| 5083 |
} |
} |
| 5084 |
strncpy_s(buf, sizeof(buf), data+offset, _TRUNCATE); |
strncpy_s(buf, sizeof(buf), data, _TRUNCATE); |
| 5085 |
offset += size; |
data += size; |
| 5086 |
|
|
| 5087 |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: compression algorithm server to client: %s", buf); |
logprintf(LOG_LEVEL_VERBOSE, "server proposal: compression algorithm server to client: %s", buf); |
| 5088 |
|
|
| 5094 |
goto error; |
goto error; |
| 5095 |
} |
} |
| 5096 |
|
|
| 5097 |
|
skip: |
| 5098 |
// 決定 |
// 決定した方式をログに出力 |
| 5099 |
logprintf(LOG_LEVEL_VERBOSE, "KEX algorithm: %s", |
logprintf(LOG_LEVEL_VERBOSE, "KEX algorithm: %s", |
| 5100 |
get_kex_algorithm_name(pvar->kex_type)); |
get_kex_algorithm_name(pvar->kex_type)); |
| 5101 |
|
|
| 5102 |
logprintf(LOG_LEVEL_VERBOSE, |
logprintf(LOG_LEVEL_VERBOSE, "server host key algorithm: %s", |
|
"server host key algorithm: %s", |
|
| 5103 |
get_ssh_keytype_name(pvar->hostkey_type)); |
get_ssh_keytype_name(pvar->hostkey_type)); |
| 5104 |
|
|
| 5105 |
logprintf(LOG_LEVEL_VERBOSE, |
logprintf(LOG_LEVEL_VERBOSE, "encryption algorithm client to server: %s", |
|
"encryption algorithm client to server: %s", |
|
| 5106 |
get_cipher_string(pvar->ciphers[MODE_OUT])); |
get_cipher_string(pvar->ciphers[MODE_OUT])); |
| 5107 |
|
|
| 5108 |
logprintf(LOG_LEVEL_VERBOSE, |
logprintf(LOG_LEVEL_VERBOSE, "encryption algorithm server to client: %s", |
|
"encryption algorithm server to client: %s", |
|
| 5109 |
get_cipher_string(pvar->ciphers[MODE_IN])); |
get_cipher_string(pvar->ciphers[MODE_IN])); |
| 5110 |
|
|
| 5111 |
logprintf(LOG_LEVEL_VERBOSE, |
logprintf(LOG_LEVEL_VERBOSE, "MAC algorithm client to server: %s", |
|
"MAC algorithm client to server: %s", |
|
| 5112 |
get_ssh2_mac_name(pvar->macs[MODE_OUT])); |
get_ssh2_mac_name(pvar->macs[MODE_OUT])); |
| 5113 |
|
|
| 5114 |
logprintf(LOG_LEVEL_VERBOSE, |
logprintf(LOG_LEVEL_VERBOSE, "MAC algorithm server to client: %s", |
|
"MAC algorithm server to client: %s", |
|
| 5115 |
get_ssh2_mac_name(pvar->macs[MODE_IN])); |
get_ssh2_mac_name(pvar->macs[MODE_IN])); |
| 5116 |
|
|
| 5117 |
logprintf(LOG_LEVEL_VERBOSE, |
logprintf(LOG_LEVEL_VERBOSE, "compression algorithm client to server: %s", |
|
"compression algorithm client to server: %s", |
|
| 5118 |
get_ssh2_comp_name(pvar->ctos_compression)); |
get_ssh2_comp_name(pvar->ctos_compression)); |
| 5119 |
|
|
| 5120 |
logprintf(LOG_LEVEL_VERBOSE, |
logprintf(LOG_LEVEL_VERBOSE, "compression algorithm server to client: %s", |
|
"compression algorithm server to client: %s", |
|
| 5121 |
get_ssh2_comp_name(pvar->stoc_compression)); |
get_ssh2_comp_name(pvar->stoc_compression)); |
| 5122 |
|
|
|
|
|
| 5123 |
// we_needの決定 (2004.11.6 yutaka) |
// we_needの決定 (2004.11.6 yutaka) |
| 5124 |
// キー再作成の場合はスキップする。 |
// キー再作成の場合はスキップする。 |
| 5125 |
if (pvar->rekeying == 0) { |
if (pvar->rekeying == 0) { |