| 245 |
} |
} |
| 246 |
} |
} |
| 247 |
|
|
|
|
|
| 248 |
static void ssh2_channel_retry_send_bufchain(PTInstVar pvar, Channel_t *c) |
static void ssh2_channel_retry_send_bufchain(PTInstVar pvar, Channel_t *c) |
| 249 |
{ |
{ |
| 250 |
bufchain_t *ch; |
bufchain_t *ch; |
| 270 |
} |
} |
| 271 |
} |
} |
| 272 |
|
|
|
|
|
|
|
|
| 273 |
// channel close時にチャネル構造体をリストへ返却する |
// channel close時にチャネル構造体をリストへ返却する |
| 274 |
// (2007.4.26 yutaka) |
// (2007.4.26 yutaka) |
| 275 |
static void ssh2_channel_delete(Channel_t *c) |
static void ssh2_channel_delete(Channel_t *c) |
| 327 |
c->used = 0; |
c->used = 0; |
| 328 |
} |
} |
| 329 |
|
|
|
|
|
| 330 |
// connection close時に呼ばれる |
// connection close時に呼ばれる |
| 331 |
void ssh2_channel_free(void) |
void ssh2_channel_free(void) |
| 332 |
{ |
{ |
| 337 |
c = &channels[i]; |
c = &channels[i]; |
| 338 |
ssh2_channel_delete(c); |
ssh2_channel_delete(c); |
| 339 |
} |
} |
|
|
|
| 340 |
} |
} |
| 341 |
|
|
| 342 |
static Channel_t *ssh2_channel_lookup(int id) |
static Channel_t *ssh2_channel_lookup(int id) |
| 371 |
return (NULL); |
return (NULL); |
| 372 |
} |
} |
| 373 |
|
|
|
|
|
| 374 |
// |
// |
| 375 |
// SSH heartbeat mutex |
// SSH heartbeat mutex |
| 376 |
// |
// |
| 400 |
//LeaveCriticalSection(&g_ssh_heartbeat_lock); |
//LeaveCriticalSection(&g_ssh_heartbeat_lock); |
| 401 |
} |
} |
| 402 |
|
|
|
|
|
| 403 |
// |
// |
| 404 |
// SSH memory dump (for debug) |
// SSH memory dump (for debug) |
| 405 |
// |
// |
| 596 |
free(buf); // free |
free(buf); // free |
| 597 |
} |
} |
| 598 |
|
|
|
|
|
|
// |
|
|
// |
|
|
// |
|
|
|
|
|
|
|
| 599 |
static int get_predecryption_amount(PTInstVar pvar) |
static int get_predecryption_amount(PTInstVar pvar) |
| 600 |
{ |
{ |
| 601 |
static int small_block_decryption_sizes[] = { 5, 5, 6, 6, 8 }; |
static int small_block_decryption_sizes[] = { 5, 5, 6, 6, 8 }; |
| 624 |
return pvar->ssh_state.payloadlen; |
return pvar->ssh_state.payloadlen; |
| 625 |
} else { |
} else { |
| 626 |
int cur_decompressed_bytes = |
int cur_decompressed_bytes = |
| 627 |
pvar->ssh_state.decompress_stream.next_out - |
pvar->ssh_state.decompress_stream.next_out - pvar->ssh_state.postdecompress_inbuf; |
|
pvar->ssh_state.postdecompress_inbuf; |
|
| 628 |
|
|
| 629 |
while (limit > cur_decompressed_bytes) { |
while (limit > cur_decompressed_bytes) { |
| 630 |
int result; |
int result; |
| 631 |
|
|
| 632 |
pvar->ssh_state.payload = |
pvar->ssh_state.payload = pvar->ssh_state.postdecompress_inbuf + 1; |
|
pvar->ssh_state.postdecompress_inbuf + 1; |
|
| 633 |
if (pvar->ssh_state.postdecompress_inbuflen == cur_decompressed_bytes) { |
if (pvar->ssh_state.postdecompress_inbuflen == cur_decompressed_bytes) { |
| 634 |
buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf, |
buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf, |
| 635 |
&pvar->ssh_state.postdecompress_inbuflen, |
&pvar->ssh_state.postdecompress_inbuflen, |
| 637 |
} |
} |
| 638 |
|
|
| 639 |
pvar->ssh_state.decompress_stream.next_out = |
pvar->ssh_state.decompress_stream.next_out = |
| 640 |
pvar->ssh_state.postdecompress_inbuf + |
pvar->ssh_state.postdecompress_inbuf + cur_decompressed_bytes; |
|
cur_decompressed_bytes; |
|
| 641 |
pvar->ssh_state.decompress_stream.avail_out = |
pvar->ssh_state.decompress_stream.avail_out = |
| 642 |
min(limit, pvar->ssh_state.postdecompress_inbuflen) |
min(limit, pvar->ssh_state.postdecompress_inbuflen) - cur_decompressed_bytes; |
|
- cur_decompressed_bytes; |
|
| 643 |
|
|
| 644 |
result = |
result = inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH); |
|
inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH); |
|
| 645 |
cur_decompressed_bytes = |
cur_decompressed_bytes = |
| 646 |
pvar->ssh_state.decompress_stream.next_out - |
pvar->ssh_state.decompress_stream.next_out - pvar->ssh_state.postdecompress_inbuf; |
|
pvar->ssh_state.postdecompress_inbuf; |
|
| 647 |
|
|
| 648 |
switch (result) { |
switch (result) { |
| 649 |
case Z_OK: |
case Z_OK: |
| 720 |
|
|
| 721 |
#define do_crc(buf, len) (~(uint32)crc32(0xFFFFFFFF, (buf), (len))) |
#define do_crc(buf, len) (~(uint32)crc32(0xFFFFFFFF, (buf), (len))) |
| 722 |
|
|
| 723 |
/* Decrypt the payload, checksum it, eat the padding, get the packet type |
/* |
| 724 |
and return it. |
* Decrypt the payload, checksum it, eat the padding, get the packet type and return it. |
| 725 |
'data' points to the start of the packet --- its length field. |
* 'data' points to the start of the packet --- its length field. |
| 726 |
'len' is the length of the |
* 'len' is the length of the * payload + padding (+ length of CRC for SSHv1). |
| 727 |
payload + padding (+ length of CRC for SSHv1). 'padding' is the length |
* 'padding' is the length of the padding alone. |
| 728 |
of the padding alone. */ |
*/ |
| 729 |
static int prep_packet(PTInstVar pvar, char *data, int len, |
static int prep_packet(PTInstVar pvar, char *data, int len, int padding) |
|
int padding) |
|
| 730 |
{ |
{ |
| 731 |
pvar->ssh_state.payload = data + 4; |
pvar->ssh_state.payload = data + 4; |
| 732 |
pvar->ssh_state.payloadlen = len; |
pvar->ssh_state.payloadlen = len; |
| 733 |
|
|
| 734 |
if (SSHv1(pvar)) { |
if (SSHv1(pvar)) { |
| 735 |
if (CRYPT_detect_attack(pvar, pvar->ssh_state.payload, len)) { |
if (CRYPT_detect_attack(pvar, pvar->ssh_state.payload, len)) { |
| 736 |
UTIL_get_lang_msg("MSG_SSH_COREINS_ERROR", pvar, |
UTIL_get_lang_msg("MSG_SSH_COREINS_ERROR", pvar, "'CORE insertion attack' detected. Aborting connection."); |
|
"'CORE insertion attack' detected. Aborting connection."); |
|
| 737 |
notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE); |
notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE); |
| 738 |
} |
} |
| 739 |
|
|
| 740 |
CRYPT_decrypt(pvar, pvar->ssh_state.payload, len); |
CRYPT_decrypt(pvar, pvar->ssh_state.payload, len); |
| 741 |
/* PKT guarantees that the data is always 4-byte aligned */ |
/* PKT guarantees that the data is always 4-byte aligned */ |
| 742 |
if (do_crc(pvar->ssh_state.payload, len - 4) != |
if (do_crc(pvar->ssh_state.payload, len - 4) != get_uint32_MSBfirst(pvar->ssh_state.payload + len - 4)) { |
| 743 |
get_uint32_MSBfirst(pvar->ssh_state.payload + len - 4)) { |
UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, "Detected corrupted data; connection terminating."); |
|
UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, |
|
|
"Detected corrupted data; connection terminating."); |
|
| 744 |
notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE); |
notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE); |
| 745 |
return SSH_MSG_NONE; |
return SSH_MSG_NONE; |
| 746 |
} |
} |
| 750 |
} else { |
} else { |
| 751 |
int already_decrypted = get_predecryption_amount(pvar); |
int already_decrypted = get_predecryption_amount(pvar); |
| 752 |
|
|
| 753 |
CRYPT_decrypt(pvar, data + already_decrypted, |
CRYPT_decrypt(pvar, data + already_decrypted, (4 + len) - already_decrypted); |
|
(4 + len) - already_decrypted); |
|
| 754 |
|
|
| 755 |
if (!CRYPT_verify_receiver_MAC |
if (!CRYPT_verify_receiver_MAC(pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4, data + len + 4)) { |
|
(pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4, |
|
|
data + len + 4)) { |
|
| 756 |
UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, |
UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, |
| 757 |
"Detected corrupted data; connection terminating."); |
"Detected corrupted data; connection terminating."); |
| 758 |
notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE); |
notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE); |
| 774 |
notify_nonfatal_error(pvar, pvar->ts->UIMsg); |
notify_nonfatal_error(pvar, pvar->ts->UIMsg); |
| 775 |
} |
} |
| 776 |
|
|
| 777 |
pvar->ssh_state.decompress_stream.next_in = |
pvar->ssh_state.decompress_stream.next_in = pvar->ssh_state.payload; |
| 778 |
pvar->ssh_state.payload; |
pvar->ssh_state.decompress_stream.avail_in = pvar->ssh_state.payloadlen; |
| 779 |
pvar->ssh_state.decompress_stream.avail_in = |
pvar->ssh_state.decompress_stream.next_out = pvar->ssh_state.postdecompress_inbuf; |
|
pvar->ssh_state.payloadlen; |
|
|
pvar->ssh_state.decompress_stream.next_out = |
|
|
pvar->ssh_state.postdecompress_inbuf; |
|
| 780 |
pvar->ssh_state.payloadlen = -1; |
pvar->ssh_state.payloadlen = -1; |
| 781 |
} else { |
} else { |
| 782 |
pvar->ssh_state.payload++; |
pvar->ssh_state.payload++; |
| 903 |
int code = 0; |
int code = 0; |
| 904 |
char *kind = NULL, buf[256]; |
char *kind = NULL, buf[256]; |
| 905 |
|
|
| 906 |
#if 0 |
if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow, 0, 0) == SOCKET_ERROR) { |
| 907 |
if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow, |
code = WSAGetLastError(); |
| 908 |
0, 0) == SOCKET_ERROR |
kind = "WSAAsyncSelect1"; |
| 909 |
|| ioctlsocket(pvar->socket, FIONBIO, &do_block) == SOCKET_ERROR |
goto error; |
|
|| retry_send_packet(pvar, data, len) |
|
|
|| (pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow, |
|
|
pvar->notification_msg, |
|
|
pvar->notification_events) == |
|
|
SOCKET_ERROR) { |
|
|
UTIL_get_lang_msg("MSG_SSH_SEND_PKT_ERROR", pvar, |
|
|
"A communications error occurred while sending an SSH packet.\n" |
|
|
"The connection will close."); |
|
|
notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE); |
|
|
return FALSE; |
|
|
} else { |
|
|
return TRUE; |
|
|
} |
|
|
#else |
|
|
if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow, |
|
|
0, 0) == SOCKET_ERROR) { |
|
|
code = WSAGetLastError(); |
|
|
kind = "WSAAsyncSelect1"; |
|
|
goto error; |
|
| 910 |
} |
} |
| 911 |
if (ioctlsocket(pvar->socket, FIONBIO, &do_block) == SOCKET_ERROR) { |
if (ioctlsocket(pvar->socket, FIONBIO, &do_block) == SOCKET_ERROR) { |
| 912 |
code = WSAGetLastError(); |
code = WSAGetLastError(); |
| 913 |
kind = "ioctlsocket"; |
kind = "ioctlsocket"; |
| 914 |
goto error; |
goto error; |
| 915 |
} |
} |
| 916 |
if (retry_send_packet(pvar, data, len) != 0) { |
if (retry_send_packet(pvar, data, len) != 0) { |
| 917 |
code = WSAGetLastError(); |
code = WSAGetLastError(); |
| 918 |
kind = "retry_send_packet"; |
kind = "retry_send_packet"; |
| 919 |
goto error; |
goto error; |
| 920 |
} |
} |
| 921 |
if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow, |
if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow, |
| 922 |
pvar->notification_msg, |
pvar->notification_msg, |
| 923 |
pvar->notification_events) == |
pvar->notification_events) == SOCKET_ERROR) { |
| 924 |
SOCKET_ERROR) { |
code = WSAGetLastError(); |
| 925 |
code = WSAGetLastError(); |
kind = "WSAAsyncSelect2"; |
| 926 |
kind = "WSAAsyncSelect2"; |
goto error; |
|
goto error; |
|
| 927 |
} |
} |
| 928 |
return TRUE; |
return TRUE; |
| 929 |
|
|
| 935 |
kind, code); |
kind, code); |
| 936 |
notify_fatal_error(pvar, buf, TRUE); |
notify_fatal_error(pvar, buf, TRUE); |
| 937 |
return FALSE; |
return FALSE; |
|
#endif |
|
| 938 |
} |
} |
| 939 |
|
|
| 940 |
/* if skip_compress is true, then the data has already been compressed |
/* if skip_compress is true, then the data has already been compressed |
| 950 |
if (!skip_compress) { |
if (!skip_compress) { |
| 951 |
buf_ensure_size(&pvar->ssh_state.outbuf, |
buf_ensure_size(&pvar->ssh_state.outbuf, |
| 952 |
&pvar->ssh_state.outbuflen, |
&pvar->ssh_state.outbuflen, |
| 953 |
(int)(len + (len >> 6) + 50 + |
(int)(len + (len >> 6) + 50 + CRYPT_get_sender_MAC_size(pvar))); |
| 954 |
CRYPT_get_sender_MAC_size(pvar))); |
pvar->ssh_state.compress_stream.next_in = pvar->ssh_state.precompress_outbuf; |
|
pvar->ssh_state.compress_stream.next_in = |
|
|
pvar->ssh_state.precompress_outbuf; |
|
| 955 |
pvar->ssh_state.compress_stream.avail_in = len; |
pvar->ssh_state.compress_stream.avail_in = len; |
| 956 |
pvar->ssh_state.compress_stream.next_out = |
pvar->ssh_state.compress_stream.next_out = pvar->ssh_state.outbuf + 12; |
| 957 |
pvar->ssh_state.outbuf + 12; |
pvar->ssh_state.compress_stream.avail_out = pvar->ssh_state.outbuflen - 12; |
|
pvar->ssh_state.compress_stream.avail_out = |
|
|
pvar->ssh_state.outbuflen - 12; |
|
| 958 |
|
|
| 959 |
if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) != Z_OK) { |
if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) != Z_OK) { |
| 960 |
UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar, |
UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar, |
| 965 |
} |
} |
| 966 |
} |
} |
| 967 |
|
|
| 968 |
len = |
len = pvar->ssh_state.outbuflen - 12 - pvar->ssh_state.compress_stream.avail_out; |
|
pvar->ssh_state.outbuflen - 12 - |
|
|
pvar->ssh_state.compress_stream.avail_out; |
|
| 969 |
} |
} |
| 970 |
|
|
| 971 |
if (SSHv1(pvar)) { |
if (SSHv1(pvar)) { |
| 980 |
} else { |
} else { |
| 981 |
memset(data + 4, 0, padding); |
memset(data + 4, 0, padding); |
| 982 |
} |
} |
| 983 |
set_uint32(data + data_length - 4, |
set_uint32(data + data_length - 4, do_crc(data + 4, data_length - 8)); |
|
do_crc(data + 4, data_length - 8)); |
|
| 984 |
CRYPT_encrypt(pvar, data + 4, data_length - 4); |
CRYPT_encrypt(pvar, data + 4, data_length - 4); |
| 985 |
} else { //for SSH2(yutaka) |
} else { //for SSH2(yutaka) |
| 986 |
int block_size = CRYPT_get_encryption_block_size(pvar); |
int block_size = CRYPT_get_encryption_block_size(pvar); |
| 993 |
pvar->ssh_state.outbuf: |
pvar->ssh_state.outbuf: |
| 994 |
offset: 0 1 2 3 4 5 6 7 8 9 10 11 12 ... EOD |
offset: 0 1 2 3 4 5 6 7 8 9 10 11 12 ... EOD |
| 995 |
<--ignore---> ^^^^^^^^ <---- payload ---> |
<--ignore---> ^^^^^^^^ <---- payload ---> |
| 996 |
packet length |
packet length |
| 997 |
|
|
| 998 |
^^padding |
^^padding |
| 999 |
|
|
| 1000 |
<----------------------------> |
<----------------------------> |
| 1001 |
SSH2 sending data on TCP |
SSH2 sending data on TCP |
| 1002 |
|
|
| 1003 |
NOTE: |
NOTE: |
| 1004 |
payload = type(1) + raw-data |
payload = type(1) + raw-data |
| 1032 |
} else { |
} else { |
| 1033 |
// 無圧縮 |
// 無圧縮 |
| 1034 |
data = pvar->ssh_state.outbuf + 7; |
data = pvar->ssh_state.outbuf + 7; |
|
|
|
| 1035 |
} |
} |
| 1036 |
|
|
| 1037 |
// 送信パケット構築(input parameter: data, len) |
// 送信パケット構築(input parameter: data, len) |
| 1038 |
if (block_size < 8) { |
if (block_size < 8) { |
| 1039 |
block_size = 8; |
block_size = 8; |
| 1040 |
} |
} |
|
#if 0 |
|
|
encryption_size = ((len + 8) / block_size + 1) * block_size; |
|
|
data_length = encryption_size + CRYPT_get_sender_MAC_size(pvar); |
|
| 1041 |
|
|
|
set_uint32(data, encryption_size - 4); |
|
|
padding = encryption_size - len - 5; |
|
|
data[4] = (unsigned char) padding; |
|
|
#else |
|
|
// でかいパケットを送ろうとすると、サーバ側で"Bad packet length"になってしまう問題への対処。 |
|
|
// (2007.10.29 yutaka) |
|
| 1042 |
encryption_size = 4 + 1 + len; |
encryption_size = 4 + 1 + len; |
| 1043 |
padding = block_size - (encryption_size % block_size); |
padding = block_size - (encryption_size % block_size); |
| 1044 |
if (padding < 4) |
if (padding < 4) |
| 1053 |
// realloc()されると、ポインタが変わる可能性があるので、再度取り直す。 |
// realloc()されると、ポインタが変わる可能性があるので、再度取り直す。 |
| 1054 |
data = buffer_ptr(msg); |
data = buffer_ptr(msg); |
| 1055 |
} |
} |
| 1056 |
#endif |
|
| 1057 |
//if (pvar->ssh_state.outbuflen <= 7 + data_length) *(int *)0 = 0; |
//if (pvar->ssh_state.outbuflen <= 7 + data_length) *(int *)0 = 0; |
| 1058 |
CRYPT_set_random_data(pvar, data + 5 + len, padding); |
CRYPT_set_random_data(pvar, data + 5 + len, padding); |
| 1059 |
ret = CRYPT_build_sender_MAC(pvar, |
ret = CRYPT_build_sender_MAC(pvar, |
| 2034 |
} |
} |
| 2035 |
|
|
| 2036 |
|
|
| 2037 |
void SSH_handle_packet(PTInstVar pvar, char *data, int len, |
void SSH_handle_packet(PTInstVar pvar, char *data, int len, int padding) |
|
int padding) |
|
| 2038 |
{ |
{ |
| 2039 |
unsigned char message = prep_packet(pvar, data, len, padding); |
unsigned char message = prep_packet(pvar, data, len, padding); |
| 2040 |
|
|
| 2049 |
if (!SSH2_dispatch_enabled_check(message) || handler == NULL) { |
if (!SSH2_dispatch_enabled_check(message) || handler == NULL) { |
| 2050 |
char buf[1024]; |
char buf[1024]; |
| 2051 |
|
|
| 2052 |
UTIL_get_lang_msg("MSG_SSH_UNEXP_MSG2_ERROR", pvar, |
UTIL_get_lang_msg("MSG_SSH_UNEXP_MSG2_ERROR", pvar, "Unexpected SSH2 message(%d) on current stage(%d)"); |
| 2053 |
"Unexpected SSH2 message(%d) on current stage(%d)"); |
_snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, message, handle_message_stage); |
|
_snprintf_s(buf, sizeof(buf), _TRUNCATE, |
|
|
pvar->ts->UIMsg, message, handle_message_stage); |
|
| 2054 |
notify_fatal_error(pvar, buf, TRUE); |
notify_fatal_error(pvar, buf, TRUE); |
| 2055 |
return; |
return; |
| 2056 |
} |
} |
| 2060 |
if (SSHv1(pvar)) { |
if (SSHv1(pvar)) { |
| 2061 |
char buf[1024]; |
char buf[1024]; |
| 2062 |
|
|
| 2063 |
UTIL_get_lang_msg("MSG_SSH_UNEXP_MSG_ERROR", pvar, |
UTIL_get_lang_msg("MSG_SSH_UNEXP_MSG_ERROR", pvar, "Unexpected packet type received: %d"); |
| 2064 |
"Unexpected packet type received: %d"); |
_snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, message, handle_message_stage); |
|
_snprintf_s(buf, sizeof(buf), _TRUNCATE, |
|
|
pvar->ts->UIMsg, message, handle_message_stage); |
|
| 2065 |
notify_fatal_error(pvar, buf, TRUE); |
notify_fatal_error(pvar, buf, TRUE); |
| 2066 |
} else { |
} else { |
| 2067 |
unsigned char *outmsg = |
unsigned char *outmsg = begin_send_packet(pvar, SSH2_MSG_UNIMPLEMENTED, 4); |
|
begin_send_packet(pvar, SSH2_MSG_UNIMPLEMENTED, 4); |
|
| 2068 |
|
|
| 2069 |
set_uint32(outmsg, |
set_uint32(outmsg, pvar->ssh_state.receiver_sequence_number - 1); |
|
pvar->ssh_state.receiver_sequence_number - 1); |
|
| 2070 |
finish_send_packet(pvar); |
finish_send_packet(pvar); |
| 2071 |
|
|
| 2072 |
logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_UNIMPLEMENTED was sent at SSH_handle_packet()."); |
logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_UNIMPLEMENTED was sent at SSH_handle_packet()."); |
| 2087 |
enque_handler(pvar, SSH_SMSG_STDOUT_DATA, handle_data); |
enque_handler(pvar, SSH_SMSG_STDOUT_DATA, handle_data); |
| 2088 |
enque_handler(pvar, SSH_SMSG_STDERR_DATA, handle_data); |
enque_handler(pvar, SSH_SMSG_STDERR_DATA, handle_data); |
| 2089 |
enque_handler(pvar, SSH_MSG_CHANNEL_DATA, handle_channel_data); |
enque_handler(pvar, SSH_MSG_CHANNEL_DATA, handle_channel_data); |
| 2090 |
enque_handler(pvar, SSH_MSG_CHANNEL_INPUT_EOF, |
enque_handler(pvar, SSH_MSG_CHANNEL_INPUT_EOF, handle_channel_input_eof); |
| 2091 |
handle_channel_input_eof); |
enque_handler(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED, handle_channel_output_eof); |
|
enque_handler(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED, |
|
|
handle_channel_output_eof); |
|
| 2092 |
enque_handler(pvar, SSH_MSG_PORT_OPEN, handle_channel_open); |
enque_handler(pvar, SSH_MSG_PORT_OPEN, handle_channel_open); |
| 2093 |
enque_handler(pvar, SSH_SMSG_X11_OPEN, handle_X11_channel_open); |
enque_handler(pvar, SSH_SMSG_X11_OPEN, handle_X11_channel_open); |
| 2094 |
enque_handler(pvar, SSH_SMSG_AGENT_OPEN, handle_agent_open); |
enque_handler(pvar, SSH_SMSG_AGENT_OPEN, handle_agent_open); |
| 2107 |
static void prep_pty(PTInstVar pvar) |
static void prep_pty(PTInstVar pvar) |
| 2108 |
{ |
{ |
| 2109 |
int len = strlen(pvar->ts->TermType); |
int len = strlen(pvar->ts->TermType); |
| 2110 |
unsigned char *outmsg = |
unsigned char *outmsg = begin_send_packet(pvar, SSH_CMSG_REQUEST_PTY, 4 + len + 16 + sizeof(ssh_ttymodes)); |
|
begin_send_packet(pvar, SSH_CMSG_REQUEST_PTY, |
|
|
4 + len + 16 + sizeof(ssh_ttymodes)); |
|
| 2111 |
static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE }; |
static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE }; |
| 2112 |
static const SSHPacketHandler handlers[] |
static const SSHPacketHandler handlers[] |
| 2113 |
= { handle_pty_success, handle_pty_failure }; |
= { handle_pty_success, handle_pty_failure }; |
| 2146 |
static void prep_agent_request(PTInstVar pvar) |
static void prep_agent_request(PTInstVar pvar) |
| 2147 |
{ |
{ |
| 2148 |
static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE }; |
static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE }; |
| 2149 |
static const SSHPacketHandler handlers[] |
static const SSHPacketHandler handlers[] = { handle_agent_request_success, handle_agent_request_failure }; |
|
= { handle_agent_request_success, handle_agent_request_failure }; |
|
| 2150 |
|
|
| 2151 |
enque_handlers(pvar, 2, msgs, handlers); |
enque_handlers(pvar, 2, msgs, handlers); |
| 2152 |
|
|
| 2166 |
} |
} |
| 2167 |
} |
} |
| 2168 |
|
|
|
|
|
| 2169 |
// |
// |
| 2170 |
// |
// |
| 2171 |
// (2005.7.10 yutaka) |
// (2005.7.10 yutaka) |
| 2181 |
pvar->ssh_state.compress_stream.zalloc = NULL; |
pvar->ssh_state.compress_stream.zalloc = NULL; |
| 2182 |
pvar->ssh_state.compress_stream.zfree = NULL; |
pvar->ssh_state.compress_stream.zfree = NULL; |
| 2183 |
pvar->ssh_state.compress_stream.opaque = NULL; |
pvar->ssh_state.compress_stream.opaque = NULL; |
| 2184 |
if (deflateInit |
if (deflateInit(&pvar->ssh_state.compress_stream, pvar->ssh_state.compression_level) != Z_OK) { |
|
(&pvar->ssh_state.compress_stream, |
|
|
pvar->ssh_state.compression_level) != Z_OK) { |
|
| 2185 |
UTIL_get_lang_msg("MSG_SSH_SETUP_COMP_ERROR", pvar, |
UTIL_get_lang_msg("MSG_SSH_SETUP_COMP_ERROR", pvar, |
| 2186 |
"An error occurred while setting up compression.\n" |
"An error occurred while setting up compression.\n" |
| 2187 |
"The connection will close."); |
"The connection will close."); |
| 2224 |
pvar->ssh_state.decompressing = TRUE; |
pvar->ssh_state.decompressing = TRUE; |
| 2225 |
} |
} |
| 2226 |
|
|
| 2227 |
buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf, |
buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf, &pvar->ssh_state.postdecompress_inbuflen, 1000); |
|
&pvar->ssh_state.postdecompress_inbuflen, 1000); |
|
| 2228 |
} |
} |
| 2229 |
} |
} |
| 2230 |
|
|
| 2238 |
pvar->ssh_state.compressing = FALSE; |
pvar->ssh_state.compressing = FALSE; |
| 2239 |
pvar->ssh_state.decompressing = FALSE; |
pvar->ssh_state.decompressing = FALSE; |
| 2240 |
} |
} |
|
|
|
| 2241 |
} |
} |
| 2242 |
|
|
| 2243 |
static BOOL handle_enable_compression(PTInstVar pvar) |
static BOOL handle_enable_compression(PTInstVar pvar) |
| 2259 |
// added if statement (2005.7.10 yutaka) |
// added if statement (2005.7.10 yutaka) |
| 2260 |
if (SSHv1(pvar)) { |
if (SSHv1(pvar)) { |
| 2261 |
static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE }; |
static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE }; |
| 2262 |
static const SSHPacketHandler handlers[] |
static const SSHPacketHandler handlers[] = { handle_enable_compression, handle_disable_compression }; |
|
= { handle_enable_compression, handle_disable_compression }; |
|
| 2263 |
|
|
| 2264 |
unsigned char *outmsg = |
unsigned char *outmsg = begin_send_packet(pvar, SSH_CMSG_REQUEST_COMPRESSION, 4); |
|
begin_send_packet(pvar, SSH_CMSG_REQUEST_COMPRESSION, 4); |
|
| 2265 |
|
|
| 2266 |
set_uint32(outmsg, pvar->session_settings.CompressionLevel); |
set_uint32(outmsg, pvar->session_settings.CompressionLevel); |
| 2267 |
finish_send_packet(pvar); |
finish_send_packet(pvar); |
| 2269 |
enque_handlers(pvar, 2, msgs, handlers); |
enque_handlers(pvar, 2, msgs, handlers); |
| 2270 |
} |
} |
| 2271 |
|
|
| 2272 |
pvar->ssh_state.compression_level = |
pvar->ssh_state.compression_level = pvar->session_settings.CompressionLevel; |
|
pvar->session_settings.CompressionLevel; |
|
| 2273 |
|
|
| 2274 |
} else { |
} else { |
| 2275 |
// added if statement (2005.7.10 yutaka) |
// added if statement (2005.7.10 yutaka) |
| 2282 |
static void enque_simple_auth_handlers(PTInstVar pvar) |
static void enque_simple_auth_handlers(PTInstVar pvar) |
| 2283 |
{ |
{ |
| 2284 |
static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE }; |
static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE }; |
| 2285 |
static const SSHPacketHandler handlers[] |
static const SSHPacketHandler handlers[] = { handle_auth_success, handle_auth_failure }; |
|
= { handle_auth_success, handle_auth_failure }; |
|
| 2286 |
|
|
| 2287 |
enque_handlers(pvar, 2, msgs, handlers); |
enque_handlers(pvar, 2, msgs, handlers); |
| 2288 |
} |
} |
| 2298 |
challenge_bytes = get_mpint_len(pvar, 0); |
challenge_bytes = get_mpint_len(pvar, 0); |
| 2299 |
|
|
| 2300 |
if (grab_payload(pvar, challenge_bytes)) { |
if (grab_payload(pvar, challenge_bytes)) { |
| 2301 |
unsigned char *outmsg = |
unsigned char *outmsg = begin_send_packet(pvar, SSH_CMSG_AUTH_RSA_RESPONSE, 16); |
|
begin_send_packet(pvar, SSH_CMSG_AUTH_RSA_RESPONSE, 16); |
|
| 2302 |
|
|
| 2303 |
if (pvar->auth_state.cur_cred.method == SSH_AUTH_RSA) { |
if (pvar->auth_state.cur_cred.method == SSH_AUTH_RSA) { |
| 2304 |
if (CRYPT_generate_RSA_challenge_response |
if (CRYPT_generate_RSA_challenge_response |
| 2306 |
|
|
| 2307 |
// セッション複製時にパスワードを使い回したいので、ここでのリソース解放はやめる。 |
// セッション複製時にパスワードを使い回したいので、ここでのリソース解放はやめる。 |
| 2308 |
// socket close時にもこの関数は呼ばれているので、たぶん問題ない。(2005.4.8 yutaka) |
// socket close時にもこの関数は呼ばれているので、たぶん問題ない。(2005.4.8 yutaka) |
|
#if 0 |
|
| 2309 |
//AUTH_destroy_cur_cred(pvar); |
//AUTH_destroy_cur_cred(pvar); |
|
#endif |
|
| 2310 |
|
|
| 2311 |
finish_send_packet(pvar); |
finish_send_packet(pvar); |
| 2312 |
|
|
| 2332 |
|
|
| 2333 |
/* Pageant にハッシュを計算してもらう */ |
/* Pageant にハッシュを計算してもらう */ |
| 2334 |
// 公開鍵の長さ |
// 公開鍵の長さ |
| 2335 |
pubkeylen = putty_get_ssh1_keylen(pvar->pageant_curkey, |
pubkeylen = putty_get_ssh1_keylen(pvar->pageant_curkey, pvar->pageant_keylistlen); |
|
pvar->pageant_keylistlen); |
|
| 2336 |
// セッションIDを作成 |
// セッションIDを作成 |
| 2337 |
BN_bn2bin(pvar->crypt_state.host_key.RSA_key->n, session_buf); |
BN_bn2bin(pvar->crypt_state.host_key.RSA_key->n, session_buf); |
| 2338 |
BN_bn2bin(pvar->crypt_state.server_key.RSA_key->n, |
BN_bn2bin(pvar->crypt_state.server_key.RSA_key->n, session_buf + host_key_bytes); |
| 2339 |
session_buf + host_key_bytes); |
memcpy(session_buf + server_key_bytes + host_key_bytes, pvar->crypt_state.server_cookie, 8); |
|
memcpy(session_buf + server_key_bytes + host_key_bytes, |
|
|
pvar->crypt_state.server_cookie, 8); |
|
| 2340 |
MD5(session_buf, session_buf_len, session_id); |
MD5(session_buf, session_buf_len, session_id); |
| 2341 |
// ハッシュを受け取る |
// ハッシュを受け取る |
| 2342 |
hash = putty_hash_ssh1_challenge(pvar->pageant_curkey, |
hash = putty_hash_ssh1_challenge(pvar->pageant_curkey, |
| 2392 |
|
|
| 2393 |
// セッション複製時にパスワードを使い回したいので、ここでのリソース解放はやめる。 |
// セッション複製時にパスワードを使い回したいので、ここでのリソース解放はやめる。 |
| 2394 |
// socket close時にもこの関数は呼ばれているので、たぶん問題ない。(2005.4.8 yutaka) |
// socket close時にもこの関数は呼ばれているので、たぶん問題ない。(2005.4.8 yutaka) |
|
#if 0 |
|
| 2395 |
//AUTH_destroy_cur_cred(pvar); |
//AUTH_destroy_cur_cred(pvar); |
|
#endif |
|
| 2396 |
|
|
| 2397 |
enque_simple_auth_handlers(pvar); |
enque_simple_auth_handlers(pvar); |
| 2398 |
break; |
break; |
| 3108 |
pvar->ssh_state.decompressing = FALSE; |
pvar->ssh_state.decompressing = FALSE; |
| 3109 |
} |
} |
| 3110 |
|
|
|
#if 1 |
|
| 3111 |
// SSH2のデータを解放する (2004.12.27 yutaka) |
// SSH2のデータを解放する (2004.12.27 yutaka) |
| 3112 |
if (SSHv2(pvar)) { |
if (SSHv2(pvar)) { |
| 3113 |
if (pvar->kexdh) { |
if (pvar->kexdh) { |
| 3175 |
} |
} |
| 3176 |
} |
} |
| 3177 |
} |
} |
|
#endif |
|
|
|
|
| 3178 |
} |
} |
| 3179 |
|
|
| 3180 |
void SSH2_send_channel_data(PTInstVar pvar, Channel_t *c, unsigned char *buf, unsigned int buflen, int retry) |
void SSH2_send_channel_data(PTInstVar pvar, Channel_t *c, unsigned char *buf, unsigned int buflen, int retry) |
| 4781 |
goto error; |
goto error; |
| 4782 |
} |
} |
| 4783 |
|
|
|
#if 0 |
|
|
for (i = 0; i < SSH2_COOKIE_LENGTH; i++) { |
|
|
cookie[i] = data[i]; |
|
|
} |
|
|
#endif |
|
| 4784 |
// get rid of Cookie length |
// get rid of Cookie length |
| 4785 |
offset += SSH2_COOKIE_LENGTH; |
offset += SSH2_COOKIE_LENGTH; |
| 4786 |
|
|
| 5238 |
// (3) 要求の最小値は満たすが、要求値よりは小さい。確認ダイアログは出さない。 |
// (3) 要求の最小値は満たすが、要求値よりは小さい。確認ダイアログは出さない。 |
| 5239 |
logprintf(LOG_LEVEL_NOTICE, |
logprintf(LOG_LEVEL_NOTICE, |
| 5240 |
"DH-GEX: grp_bits(%d) < kexgex_bits(%d)", grp_bits, pvar->kexgex_bits); |
"DH-GEX: grp_bits(%d) < kexgex_bits(%d)", grp_bits, pvar->kexgex_bits); |
|
#if 1 |
|
| 5241 |
tmpbuf[0] = 0; // no message |
tmpbuf[0] = 0; // no message |
|
#else |
|
|
_snprintf_s(tmpbuf, sizeof(tmpbuf), _TRUNCATE, |
|
|
"Received group size is smaller than requested.\nrequested: %d, received: %d\nAccept this?", |
|
|
pvar->kexgex_bits, grp_bits); |
|
|
#endif |
|
| 5242 |
} |
} |
| 5243 |
else if (grp_bits <= pvar->kexgex_max) { |
else if (grp_bits <= pvar->kexgex_max) { |
| 5244 |
// (4) 要求値以上、かつ要求の最大値以下。問題なし。 |
// (4) 要求値以上、かつ要求の最大値以下。問題なし。 |
| 5385 |
|
|
| 5386 |
static void ssh2_set_newkeys(PTInstVar pvar, int mode) |
static void ssh2_set_newkeys(PTInstVar pvar, int mode) |
| 5387 |
{ |
{ |
|
#if 1 |
|
| 5388 |
// free already allocated buffer |
// free already allocated buffer |
| 5389 |
if (pvar->ssh2_keys[mode].enc.iv != NULL) { |
if (pvar->ssh2_keys[mode].enc.iv != NULL) { |
| 5390 |
free(pvar->ssh2_keys[mode].enc.iv); |
free(pvar->ssh2_keys[mode].enc.iv); |
| 5395 |
if (pvar->ssh2_keys[mode].mac.key != NULL) { |
if (pvar->ssh2_keys[mode].mac.key != NULL) { |
| 5396 |
free(pvar->ssh2_keys[mode].mac.key); |
free(pvar->ssh2_keys[mode].mac.key); |
| 5397 |
} |
} |
|
#endif |
|
| 5398 |
|
|
| 5399 |
pvar->ssh2_keys[mode] = current_keys[mode]; |
pvar->ssh2_keys[mode] = current_keys[mode]; |
| 5400 |
} |
} |