| 63 |
#define SSH2_DEBUG |
#define SSH2_DEBUG |
| 64 |
#endif |
#endif |
| 65 |
|
|
| 66 |
#define DONT_WANTCONFIRM 1 // (2005.3.28 yutaka) |
//#define DONT_WANTCONFIRM 1 // (2005.3.28 yutaka) |
| 67 |
|
#undef DONT_WANTCONFIRM // (2008.11.25 maya) |
| 68 |
#define INTBLOB_LEN 20 |
#define INTBLOB_LEN 20 |
| 69 |
#define SIGBLOB_LEN (2*INTBLOB_LEN) |
#define SIGBLOB_LEN (2*INTBLOB_LEN) |
| 70 |
|
|
| 76 |
#define CHANNEL_MAX 100 |
#define CHANNEL_MAX 100 |
| 77 |
|
|
| 78 |
enum channel_type { |
enum channel_type { |
| 79 |
TYPE_SHELL, TYPE_PORTFWD, TYPE_SCP, TYPE_SFTP, |
TYPE_SHELL, TYPE_PORTFWD, TYPE_SCP, TYPE_SFTP, TYPE_AGENT, |
| 80 |
}; |
}; |
| 81 |
|
|
| 82 |
enum scp_state { |
enum scp_state { |
| 119 |
int local_num; |
int local_num; |
| 120 |
bufchain_t *bufchain; |
bufchain_t *bufchain; |
| 121 |
scp_t scp; |
scp_t scp; |
| 122 |
|
buffer_t *agent_msg; |
| 123 |
|
int agent_request_len; |
| 124 |
} Channel_t; |
} Channel_t; |
| 125 |
|
|
| 126 |
static Channel_t channels[CHANNEL_MAX]; |
static Channel_t channels[CHANNEL_MAX]; |
| 147 |
static BOOL handle_SSH2_request_success(PTInstVar pvar); |
static BOOL handle_SSH2_request_success(PTInstVar pvar); |
| 148 |
static BOOL handle_SSH2_request_failure(PTInstVar pvar); |
static BOOL handle_SSH2_request_failure(PTInstVar pvar); |
| 149 |
static BOOL handle_SSH2_channel_success(PTInstVar pvar); |
static BOOL handle_SSH2_channel_success(PTInstVar pvar); |
| 150 |
|
static BOOL handle_SSH2_channel_failure(PTInstVar pvar); |
| 151 |
static BOOL handle_SSH2_channel_data(PTInstVar pvar); |
static BOOL handle_SSH2_channel_data(PTInstVar pvar); |
| 152 |
static BOOL handle_SSH2_channel_extended_data(PTInstVar pvar); |
static BOOL handle_SSH2_channel_extended_data(PTInstVar pvar); |
| 153 |
static BOOL handle_SSH2_channel_eof(PTInstVar pvar); |
static BOOL handle_SSH2_channel_eof(PTInstVar pvar); |
| 162 |
int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub); |
int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub); |
| 163 |
static void start_ssh_heartbeat_thread(PTInstVar pvar); |
static void start_ssh_heartbeat_thread(PTInstVar pvar); |
| 164 |
static void SSH2_send_channel_data(PTInstVar pvar, Channel_t *c, unsigned char FAR * buf, unsigned int buflen); |
static void SSH2_send_channel_data(PTInstVar pvar, Channel_t *c, unsigned char FAR * buf, unsigned int buflen); |
| 165 |
|
void ssh2_channel_send_close(PTInstVar pvar, Channel_t *c); |
| 166 |
|
static BOOL SSH_agent_response(PTInstVar pvar, Channel_t *c, unsigned char *data, unsigned int buflen); |
| 167 |
|
|
| 168 |
// |
// |
| 169 |
// channel function |
// channel function |
| 206 |
c->scp.thread = (HANDLE)-1; |
c->scp.thread = (HANDLE)-1; |
| 207 |
c->scp.localfp = NULL; |
c->scp.localfp = NULL; |
| 208 |
} |
} |
| 209 |
|
if (type == TYPE_AGENT) { |
| 210 |
|
c->agent_msg = buffer_init(); |
| 211 |
|
c->agent_request_len = 0; |
| 212 |
|
} |
| 213 |
|
|
| 214 |
return (c); |
return (c); |
| 215 |
} |
} |
| 298 |
c->scp.thread = (HANDLE)-1L; |
c->scp.thread = (HANDLE)-1L; |
| 299 |
} |
} |
| 300 |
} |
} |
| 301 |
|
if (c->type == TYPE_AGENT) { |
| 302 |
|
buffer_free(c->agent_msg); |
| 303 |
|
} |
| 304 |
|
|
| 305 |
memset(c, 0, sizeof(Channel_t)); |
memset(c, 0, sizeof(Channel_t)); |
| 306 |
c->used = 0; |
c->used = 0; |
| 1686 |
enque_handler(pvar, SSH2_MSG_CHANNEL_REQUEST, handle_SSH2_channel_request); |
enque_handler(pvar, SSH2_MSG_CHANNEL_REQUEST, handle_SSH2_channel_request); |
| 1687 |
enque_handler(pvar, SSH2_MSG_CHANNEL_WINDOW_ADJUST, handle_SSH2_window_adjust); |
enque_handler(pvar, SSH2_MSG_CHANNEL_WINDOW_ADJUST, handle_SSH2_window_adjust); |
| 1688 |
enque_handler(pvar, SSH2_MSG_CHANNEL_SUCCESS, handle_SSH2_channel_success); |
enque_handler(pvar, SSH2_MSG_CHANNEL_SUCCESS, handle_SSH2_channel_success); |
| 1689 |
|
enque_handler(pvar, SSH2_MSG_CHANNEL_FAILURE, handle_SSH2_channel_failure); |
| 1690 |
// enque_handler(pvar, SSH2_MSG_GLOBAL_REQUEST, handle_unimplemented); |
// enque_handler(pvar, SSH2_MSG_GLOBAL_REQUEST, handle_unimplemented); |
| 1691 |
enque_handler(pvar, SSH2_MSG_REQUEST_FAILURE, handle_SSH2_request_failure); |
enque_handler(pvar, SSH2_MSG_REQUEST_FAILURE, handle_SSH2_request_failure); |
| 1692 |
enque_handler(pvar, SSH2_MSG_REQUEST_SUCCESS, handle_SSH2_request_success); |
enque_handler(pvar, SSH2_MSG_REQUEST_SUCCESS, handle_SSH2_request_success); |
| 1892 |
|
|
| 1893 |
static BOOL handle_channel_data(PTInstVar pvar) |
static BOOL handle_channel_data(PTInstVar pvar) |
| 1894 |
{ |
{ |
| 1895 |
int len; |
int len, local_channel; |
| 1896 |
|
|
| 1897 |
if (grab_payload(pvar, 8) |
if (grab_payload(pvar, 8) |
| 1898 |
&& grab_payload(pvar, len = get_payload_uint32(pvar, 4))) { |
&& grab_payload(pvar, len = get_payload_uint32(pvar, 4))) { |
| 1899 |
FWD_received_data(pvar, get_payload_uint32(pvar, 0), |
local_channel = get_payload_uint32(pvar, 0); |
| 1900 |
pvar->ssh_state.payload + 8, len); |
if (local_channel == pvar->agent_channel.local_id) { |
| 1901 |
|
SSH_agent_response(pvar, NULL, |
| 1902 |
|
pvar->ssh_state.payload + 8, len); |
| 1903 |
|
} |
| 1904 |
|
else { |
| 1905 |
|
FWD_received_data(pvar, local_channel, |
| 1906 |
|
pvar->ssh_state.payload + 8, len); |
| 1907 |
|
} |
| 1908 |
} |
} |
| 1909 |
return TRUE; |
return TRUE; |
| 1910 |
} |
} |
| 1912 |
static BOOL handle_channel_input_eof(PTInstVar pvar) |
static BOOL handle_channel_input_eof(PTInstVar pvar) |
| 1913 |
{ |
{ |
| 1914 |
if (grab_payload(pvar, 4)) { |
if (grab_payload(pvar, 4)) { |
| 1915 |
FWD_channel_input_eof(pvar, get_payload_uint32(pvar, 0)); |
int local_id = get_payload_uint32(pvar, 0); |
| 1916 |
|
if (local_id == pvar->agent_channel.local_id) { |
| 1917 |
|
SSH_channel_input_eof(pvar, pvar->agent_channel.remote_id, |
| 1918 |
|
pvar->agent_channel.local_id); |
| 1919 |
|
} |
| 1920 |
|
else { |
| 1921 |
|
FWD_channel_input_eof(pvar, local_id); |
| 1922 |
|
} |
| 1923 |
} |
} |
| 1924 |
return TRUE; |
return TRUE; |
| 1925 |
} |
} |
| 1927 |
static BOOL handle_channel_output_eof(PTInstVar pvar) |
static BOOL handle_channel_output_eof(PTInstVar pvar) |
| 1928 |
{ |
{ |
| 1929 |
if (grab_payload(pvar, 4)) { |
if (grab_payload(pvar, 4)) { |
| 1930 |
FWD_channel_output_eof(pvar, get_payload_uint32(pvar, 0)); |
int local_id = get_payload_uint32(pvar, 0); |
| 1931 |
|
if (local_id == pvar->agent_channel.local_id) { |
| 1932 |
|
SSH_channel_output_eof(pvar, pvar->agent_channel.remote_id); |
| 1933 |
|
buffer_free(pvar->agent_channel.agent_msg); |
| 1934 |
|
} |
| 1935 |
|
else { |
| 1936 |
|
FWD_channel_output_eof(pvar, get_payload_uint32(pvar, 0)); |
| 1937 |
|
} |
| 1938 |
|
} |
| 1939 |
|
return TRUE; |
| 1940 |
|
} |
| 1941 |
|
|
| 1942 |
|
static BOOL handle_agent_open(PTInstVar pvar) |
| 1943 |
|
{ |
| 1944 |
|
if (grab_payload(pvar, 4)) { |
| 1945 |
|
pvar->agent_channel.remote_id = get_payload_uint32(pvar, 0); |
| 1946 |
|
if (pvar->agentfwd_enable) { |
| 1947 |
|
// SSH1 の channel 実装が port forward しか想定していなかったので、 |
| 1948 |
|
// agent forward では固定値を使う |
| 1949 |
|
pvar->agent_channel.local_id = SSH1_AGENT_CHANNEL_ID; |
| 1950 |
|
pvar->agent_channel.agent_msg = buffer_init(); |
| 1951 |
|
pvar->agent_channel.agent_request_len = 0; |
| 1952 |
|
SSH_confirm_channel_open(pvar, |
| 1953 |
|
pvar->agent_channel.remote_id, |
| 1954 |
|
pvar->agent_channel.local_id); |
| 1955 |
|
} |
| 1956 |
|
else { |
| 1957 |
|
SSH_fail_channel_open(pvar, pvar->agent_channel.remote_id); |
| 1958 |
|
} |
| 1959 |
|
} |
| 1960 |
|
/* |
| 1961 |
|
else { |
| 1962 |
|
// 通知する相手channelが分からないので何もできない |
| 1963 |
} |
} |
| 1964 |
|
*/ |
| 1965 |
|
|
| 1966 |
return TRUE; |
return TRUE; |
| 1967 |
} |
} |
| 1968 |
|
|
| 2105 |
handle_channel_output_eof); |
handle_channel_output_eof); |
| 2106 |
enque_handler(pvar, SSH_MSG_PORT_OPEN, handle_channel_open); |
enque_handler(pvar, SSH_MSG_PORT_OPEN, handle_channel_open); |
| 2107 |
enque_handler(pvar, SSH_SMSG_X11_OPEN, handle_X11_channel_open); |
enque_handler(pvar, SSH_SMSG_X11_OPEN, handle_X11_channel_open); |
| 2108 |
|
enque_handler(pvar, SSH_SMSG_AGENT_OPEN, handle_agent_open); |
| 2109 |
return FALSE; |
return FALSE; |
| 2110 |
} |
} |
| 2111 |
|
|
| 2143 |
finish_send_packet(pvar); |
finish_send_packet(pvar); |
| 2144 |
} |
} |
| 2145 |
|
|
| 2146 |
|
static BOOL handle_agent_request_success(PTInstVar pvar) |
| 2147 |
|
{ |
| 2148 |
|
pvar->agentfwd_enable = TRUE; |
| 2149 |
|
prep_pty(pvar); |
| 2150 |
|
return FALSE; |
| 2151 |
|
} |
| 2152 |
|
|
| 2153 |
|
static BOOL handle_agent_request_failure(PTInstVar pvar) |
| 2154 |
|
{ |
| 2155 |
|
prep_pty(pvar); |
| 2156 |
|
return FALSE; |
| 2157 |
|
} |
| 2158 |
|
|
| 2159 |
|
static void prep_agent_request(PTInstVar pvar) |
| 2160 |
|
{ |
| 2161 |
|
static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE }; |
| 2162 |
|
static const SSHPacketHandler handlers[] |
| 2163 |
|
= { handle_agent_request_success, handle_agent_request_failure }; |
| 2164 |
|
|
| 2165 |
|
enque_handlers(pvar, 2, msgs, handlers); |
| 2166 |
|
|
| 2167 |
|
begin_send_packet(pvar, SSH_CMSG_AGENT_REQUEST_FORWARDING, 0); |
| 2168 |
|
finish_send_packet(pvar); |
| 2169 |
|
} |
| 2170 |
|
|
| 2171 |
static void prep_forwarding(PTInstVar pvar) |
static void prep_forwarding(PTInstVar pvar) |
| 2172 |
{ |
{ |
| 2173 |
FWD_prep_forwarding(pvar); |
FWD_prep_forwarding(pvar); |
| 2174 |
prep_pty(pvar); |
|
| 2175 |
|
if (pvar->session_settings.ForwardAgent) { |
| 2176 |
|
prep_agent_request(pvar); |
| 2177 |
|
} |
| 2178 |
|
else { |
| 2179 |
|
prep_pty(pvar); |
| 2180 |
|
} |
| 2181 |
} |
} |
| 2182 |
|
|
| 2183 |
|
|
| 2698 |
pvar->decomp_buffer = NULL; |
pvar->decomp_buffer = NULL; |
| 2699 |
pvar->ssh2_authlist = NULL; // (2007.4.27 yutaka) |
pvar->ssh2_authlist = NULL; // (2007.4.27 yutaka) |
| 2700 |
pvar->tryed_ssh2_authlist = FALSE; |
pvar->tryed_ssh2_authlist = FALSE; |
| 2701 |
|
pvar->agentfwd_enable = FALSE; |
| 2702 |
|
|
| 2703 |
} |
} |
| 2704 |
|
|
| 3066 |
&pvar->ssh_state.precompress_outbuflen); |
&pvar->ssh_state.precompress_outbuflen); |
| 3067 |
buf_destroy(&pvar->ssh_state.postdecompress_inbuf, |
buf_destroy(&pvar->ssh_state.postdecompress_inbuf, |
| 3068 |
&pvar->ssh_state.postdecompress_inbuflen); |
&pvar->ssh_state.postdecompress_inbuflen); |
| 3069 |
|
pvar->agentfwd_enable = FALSE; |
| 3070 |
|
|
| 3071 |
// support of "Compression delayed" (2006.6.23 maya) |
// support of "Compression delayed" (2006.6.23 maya) |
| 3072 |
if (pvar->ssh_state.compressing || |
if (pvar->ssh_state.compressing || |
| 7560 |
return TRUE; |
return TRUE; |
| 7561 |
} |
} |
| 7562 |
|
|
| 7563 |
|
BOOL send_pty_request(PTInstVar pvar, Channel_t *c) |
| 7564 |
|
{ |
| 7565 |
|
buffer_t *msg, *ttymsg; |
| 7566 |
|
char *s = "pty-req"; // pseudo terminalのリクエスト |
| 7567 |
|
unsigned char *outmsg; |
| 7568 |
|
int len; |
| 7569 |
|
#ifdef DONT_WANTCONFIRM |
| 7570 |
|
int wantconfirm = 0; // false |
| 7571 |
|
#else |
| 7572 |
|
int wantconfirm = 1; // true |
| 7573 |
|
#endif |
| 7574 |
|
|
| 7575 |
|
// pty open |
| 7576 |
|
msg = buffer_init(); |
| 7577 |
|
if (msg == NULL) { |
| 7578 |
|
// TODO: error check |
| 7579 |
|
return FALSE; |
| 7580 |
|
} |
| 7581 |
|
ttymsg = buffer_init(); |
| 7582 |
|
if (ttymsg == NULL) { |
| 7583 |
|
// TODO: error check |
| 7584 |
|
buffer_free(msg); |
| 7585 |
|
return FALSE; |
| 7586 |
|
} |
| 7587 |
|
|
| 7588 |
|
buffer_put_int(msg, c->remote_id); |
| 7589 |
|
buffer_put_string(msg, s, strlen(s)); |
| 7590 |
|
buffer_put_char(msg, wantconfirm); // wantconfirm (disableに変更 2005/3/28 yutaka) |
| 7591 |
|
|
| 7592 |
|
s = pvar->ts->TermType; // TERM |
| 7593 |
|
buffer_put_string(msg, s, strlen(s)); |
| 7594 |
|
buffer_put_int(msg, pvar->ssh_state.win_cols); // columns |
| 7595 |
|
buffer_put_int(msg, pvar->ssh_state.win_rows); // lines |
| 7596 |
|
buffer_put_int(msg, 480); // XXX: |
| 7597 |
|
buffer_put_int(msg, 640); // XXX: |
| 7598 |
|
|
| 7599 |
|
// TTY modeはここで渡す (2005.7.17 yutaka) |
| 7600 |
|
#if 0 |
| 7601 |
|
s = ""; |
| 7602 |
|
buffer_put_string(msg, s, strlen(s)); |
| 7603 |
|
#else |
| 7604 |
|
buffer_put_char(ttymsg, 129); // TTY_OP_OSPEED_PROTO2 |
| 7605 |
|
buffer_put_int(ttymsg, 9600); // baud rate |
| 7606 |
|
buffer_put_char(ttymsg, 128); // TTY_OP_ISPEED_PROTO2 |
| 7607 |
|
buffer_put_int(ttymsg, 9600); // baud rate |
| 7608 |
|
// VERASE |
| 7609 |
|
buffer_put_char(ttymsg, 3); |
| 7610 |
|
if (pvar->ts->BSKey == IdBS) { |
| 7611 |
|
buffer_put_int(ttymsg, 0x08); // BS key |
| 7612 |
|
} else { |
| 7613 |
|
buffer_put_int(ttymsg, 0x7F); // DEL key |
| 7614 |
|
} |
| 7615 |
|
// TTY_OP_END |
| 7616 |
|
buffer_put_char(ttymsg, 0); |
| 7617 |
|
|
| 7618 |
|
// SSH2では文字列として書き込む。 |
| 7619 |
|
buffer_put_string(msg, buffer_ptr(ttymsg), buffer_len(ttymsg)); |
| 7620 |
|
#endif |
| 7621 |
|
|
| 7622 |
|
len = buffer_len(msg); |
| 7623 |
|
outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len); |
| 7624 |
|
memcpy(outmsg, buffer_ptr(msg), len); |
| 7625 |
|
finish_send_packet(pvar); |
| 7626 |
|
buffer_free(msg); |
| 7627 |
|
buffer_free(ttymsg); |
| 7628 |
|
|
| 7629 |
|
notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_REQUEST was sent at send_pty_request().", LOG_LEVEL_VERBOSE); |
| 7630 |
|
pvar->session_nego_status = 2; |
| 7631 |
|
|
| 7632 |
|
if (wantconfirm == 0) { |
| 7633 |
|
handle_SSH2_channel_success(pvar); |
| 7634 |
|
} |
| 7635 |
|
|
| 7636 |
|
return TRUE; |
| 7637 |
|
} |
| 7638 |
|
|
| 7639 |
static BOOL handle_SSH2_open_confirm(PTInstVar pvar) |
static BOOL handle_SSH2_open_confirm(PTInstVar pvar) |
| 7640 |
{ |
{ |
| 7641 |
buffer_t *msg, *ttymsg; |
buffer_t *msg; |
| 7642 |
char *s; |
char *s; |
| 7643 |
unsigned char *outmsg; |
unsigned char *outmsg; |
| 7644 |
int len; |
int len; |
| 7695 |
|
|
| 7696 |
//debug_print(100, data, len); |
//debug_print(100, data, len); |
| 7697 |
|
|
| 7698 |
// pty open |
if (c->type == TYPE_SHELL) { |
| 7699 |
|
// エージェント転送 (2008.11.25 maya) |
| 7700 |
|
if (pvar->session_settings.ForwardAgent) { |
| 7701 |
|
// pty-req より前にリクエストしないとエラーになる模様 |
| 7702 |
|
|
| 7703 |
|
msg = buffer_init(); |
| 7704 |
|
if (msg == NULL) { |
| 7705 |
|
// TODO: error check |
| 7706 |
|
return FALSE; |
| 7707 |
|
} |
| 7708 |
|
buffer_put_int(msg, c->remote_id); |
| 7709 |
|
s = "auth-agent-req@openssh.com"; |
| 7710 |
|
buffer_put_string(msg, s, strlen(s)); |
| 7711 |
|
buffer_put_char(msg, 1); // want reply |
| 7712 |
|
len = buffer_len(msg); |
| 7713 |
|
outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len); |
| 7714 |
|
memcpy(outmsg, buffer_ptr(msg), len); |
| 7715 |
|
finish_send_packet(pvar); |
| 7716 |
|
buffer_free(msg); |
| 7717 |
|
|
| 7718 |
|
notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_REQUEST was sent at handle_SSH2_channel_success().", LOG_LEVEL_VERBOSE); |
| 7719 |
|
return TRUE; |
| 7720 |
|
} |
| 7721 |
|
else { |
| 7722 |
|
return send_pty_request(pvar, c); |
| 7723 |
|
} |
| 7724 |
|
} |
| 7725 |
|
|
| 7726 |
msg = buffer_init(); |
msg = buffer_init(); |
| 7727 |
if (msg == NULL) { |
if (msg == NULL) { |
| 7728 |
// TODO: error check |
// TODO: error check |
| 7729 |
return FALSE; |
return FALSE; |
| 7730 |
} |
} |
|
ttymsg = buffer_init(); |
|
|
if (ttymsg == NULL) { |
|
|
// TODO: error check |
|
|
buffer_free(msg); |
|
|
return FALSE; |
|
|
} |
|
| 7731 |
|
|
| 7732 |
buffer_put_int(msg, remote_id); |
buffer_put_int(msg, remote_id); |
| 7733 |
if (c->type == TYPE_SCP) { |
if (c->type == TYPE_SCP) { |
| 7734 |
s = "exec"; |
s = "exec"; |
| 7735 |
} else if (c->type == TYPE_SFTP) { |
} else if (c->type == TYPE_SFTP) { |
| 7736 |
s = "subsystem"; |
s = "subsystem"; |
|
} else if (c->type == TYPE_SHELL) { |
|
|
s = "pty-req"; // pseudo terminalのリクエスト |
|
| 7737 |
} else { |
} else { |
| 7738 |
s = ""; // NOT REACHED |
s = ""; // NOT REACHED |
| 7739 |
} |
} |
| 7750 |
|
|
| 7751 |
} |
} |
| 7752 |
buffer_put_string(msg, sbuf, strlen(sbuf)); |
buffer_put_string(msg, sbuf, strlen(sbuf)); |
|
goto done; |
|
| 7753 |
} |
} |
| 7754 |
|
else if (c->type == TYPE_SFTP) { |
|
if (c->type == TYPE_SFTP) { |
|
| 7755 |
char *sbuf = "sftp"; |
char *sbuf = "sftp"; |
| 7756 |
buffer_put_string(msg, sbuf, strlen(sbuf)); |
buffer_put_string(msg, sbuf, strlen(sbuf)); |
|
goto done; |
|
| 7757 |
} |
} |
| 7758 |
|
|
|
s = pvar->ts->TermType; // TERM |
|
|
buffer_put_string(msg, s, strlen(s)); |
|
|
buffer_put_int(msg, pvar->ssh_state.win_cols); // columns |
|
|
buffer_put_int(msg, pvar->ssh_state.win_rows); // lines |
|
|
buffer_put_int(msg, 480); // XXX: |
|
|
buffer_put_int(msg, 640); // XXX: |
|
|
|
|
|
// TTY modeはここで渡す (2005.7.17 yutaka) |
|
|
#if 0 |
|
|
s = ""; |
|
|
buffer_put_string(msg, s, strlen(s)); |
|
|
#else |
|
|
buffer_put_char(ttymsg, 129); // TTY_OP_OSPEED_PROTO2 |
|
|
buffer_put_int(ttymsg, 9600); // baud rate |
|
|
buffer_put_char(ttymsg, 128); // TTY_OP_ISPEED_PROTO2 |
|
|
buffer_put_int(ttymsg, 9600); // baud rate |
|
|
// VERASE |
|
|
buffer_put_char(ttymsg, 3); |
|
|
if (pvar->ts->BSKey == IdBS) { |
|
|
buffer_put_int(ttymsg, 0x08); // BS key |
|
|
} else { |
|
|
buffer_put_int(ttymsg, 0x7F); // DEL key |
|
|
} |
|
|
// TTY_OP_END |
|
|
buffer_put_char(ttymsg, 0); |
|
|
|
|
|
// SSH2では文字列として書き込む。 |
|
|
buffer_put_string(msg, buffer_ptr(ttymsg), buffer_len(ttymsg)); |
|
|
#endif |
|
|
|
|
|
done: |
|
| 7759 |
len = buffer_len(msg); |
len = buffer_len(msg); |
| 7760 |
outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len); |
outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len); |
| 7761 |
memcpy(outmsg, buffer_ptr(msg), len); |
memcpy(outmsg, buffer_ptr(msg), len); |
| 7762 |
finish_send_packet(pvar); |
finish_send_packet(pvar); |
| 7763 |
buffer_free(msg); |
buffer_free(msg); |
|
buffer_free(ttymsg); |
|
| 7764 |
|
|
| 7765 |
notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_REQUEST was sent at handle_SSH2_open_confirm().", LOG_LEVEL_VERBOSE); |
notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_REQUEST was sent at handle_SSH2_open_confirm().", LOG_LEVEL_VERBOSE); |
| 7766 |
|
|
| 7767 |
if (c->type == TYPE_SHELL) { |
if (c->type == TYPE_SCP) { |
|
if (wantconfirm == 0) { |
|
|
handle_SSH2_channel_success(pvar); |
|
|
} |
|
|
|
|
|
} else if (c->type == TYPE_SCP) { |
|
| 7768 |
// SCPで remote-to-local の場合は、サーバからのファイル送信要求を出す。 |
// SCPで remote-to-local の場合は、サーバからのファイル送信要求を出す。 |
| 7769 |
// この時点では remote window size が"0"なので、すぐには送られないが、遅延送信処理で送られる。 |
// この時点では remote window size が"0"なので、すぐには送られないが、遅延送信処理で送られる。 |
| 7770 |
// (2007.12.27 yutaka) |
// (2007.12.27 yutaka) |
| 7866 |
unsigned char *outmsg; |
unsigned char *outmsg; |
| 7867 |
int len; |
int len; |
| 7868 |
Channel_t *c; |
Channel_t *c; |
| 7869 |
|
#ifdef DONT_WANTCONFIRM |
| 7870 |
|
int wantconfirm = 0; // false |
| 7871 |
|
#else |
| 7872 |
|
int wantconfirm = 1; // true |
| 7873 |
|
#endif |
| 7874 |
|
|
| 7875 |
{ |
{ |
| 7876 |
char buf[128]; |
char buf[128]; |
| 7881 |
} |
} |
| 7882 |
|
|
| 7883 |
if (pvar->session_nego_status == 1) { |
if (pvar->session_nego_status == 1) { |
| 7884 |
#ifdef DONT_WANTCONFIRM |
// find channel by shell id(2005.2.27 yutaka) |
| 7885 |
int wantconfirm = 0; // false |
c = ssh2_channel_lookup(pvar->shell_id); |
| 7886 |
#else |
if (c == NULL) { |
| 7887 |
int wantconfirm = 1; // true |
// TODO: error check |
| 7888 |
#endif |
return FALSE; |
| 7889 |
|
} |
| 7890 |
|
pvar->agentfwd_enable = TRUE; |
| 7891 |
|
return send_pty_request(pvar, c); |
| 7892 |
|
|
| 7893 |
pvar->session_nego_status = 2; |
} else if (pvar->session_nego_status == 2) { |
| 7894 |
|
pvar->session_nego_status = 3; |
| 7895 |
msg = buffer_init(); |
msg = buffer_init(); |
| 7896 |
if (msg == NULL) { |
if (msg == NULL) { |
| 7897 |
// TODO: error check |
// TODO: error check |
| 7922 |
handle_SSH2_channel_success(pvar); |
handle_SSH2_channel_success(pvar); |
| 7923 |
} |
} |
| 7924 |
|
|
| 7925 |
} else if (pvar->session_nego_status == 2) { |
} else if (pvar->session_nego_status == 3) { |
| 7926 |
pvar->session_nego_status = 3; |
pvar->session_nego_status = 4; |
| 7927 |
|
|
| 7928 |
} else { |
} else { |
| 7929 |
|
|
| 7932 |
return TRUE; |
return TRUE; |
| 7933 |
} |
} |
| 7934 |
|
|
| 7935 |
|
static BOOL handle_SSH2_channel_failure(PTInstVar pvar) |
| 7936 |
|
{ |
| 7937 |
|
Channel_t *c; |
| 7938 |
|
|
| 7939 |
|
notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_FAILURE was received.", LOG_LEVEL_VERBOSE); |
| 7940 |
|
|
| 7941 |
|
if (pvar->session_nego_status == 1) { |
| 7942 |
|
// リモートで auth-agent-req@openssh.com がサポートされてないので |
| 7943 |
|
// エラーは気にせず次へ進む |
| 7944 |
|
|
| 7945 |
|
// find channel by shell id(2005.2.27 yutaka) |
| 7946 |
|
c = ssh2_channel_lookup(pvar->shell_id); |
| 7947 |
|
if (c == NULL) { |
| 7948 |
|
// TODO: error check |
| 7949 |
|
return FALSE; |
| 7950 |
|
} |
| 7951 |
|
return send_pty_request(pvar, c); |
| 7952 |
|
} |
| 7953 |
|
else { |
| 7954 |
|
return FALSE; |
| 7955 |
|
} |
| 7956 |
|
|
| 7957 |
|
return TRUE; |
| 7958 |
|
} |
| 7959 |
|
|
| 7960 |
|
|
| 7961 |
|
|
| 7962 |
// クライアントのwindow sizeをサーバへ知らせる |
// クライアントのwindow sizeをサーバへ知らせる |
| 8448 |
|
|
| 8449 |
} else if (c->type == TYPE_SFTP) { // SFTP |
} else if (c->type == TYPE_SFTP) { // SFTP |
| 8450 |
|
|
| 8451 |
|
} else if (c->type == TYPE_AGENT) { // agent forward |
| 8452 |
|
if (!SSH_agent_response(pvar, c, data, str_len)) { |
| 8453 |
|
return FALSE; |
| 8454 |
|
} |
| 8455 |
} |
} |
| 8456 |
|
|
| 8457 |
//debug_print(200, data, strlen); |
//debug_print(200, data, strlen); |
| 8563 |
if (c->type == TYPE_PORTFWD) { |
if (c->type == TYPE_PORTFWD) { |
| 8564 |
FWD_channel_input_eof(pvar, c->local_num); |
FWD_channel_input_eof(pvar, c->local_num); |
| 8565 |
} |
} |
| 8566 |
|
else if (c->type == TYPE_AGENT) { |
| 8567 |
|
ssh2_channel_send_close(pvar, c); |
| 8568 |
|
} |
| 8569 |
|
|
| 8570 |
return TRUE; |
return TRUE; |
| 8571 |
} |
} |
| 8581 |
int remote_window; |
int remote_window; |
| 8582 |
int remote_maxpacket; |
int remote_maxpacket; |
| 8583 |
int chan_num = -1; |
int chan_num = -1; |
| 8584 |
|
buffer_t *msg; |
| 8585 |
|
unsigned char *outmsg; |
| 8586 |
|
|
| 8587 |
notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_OPEN was received.", LOG_LEVEL_VERBOSE); |
notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_OPEN was received.", LOG_LEVEL_VERBOSE); |
| 8588 |
|
|
| 8668 |
c->remote_window = remote_window; |
c->remote_window = remote_window; |
| 8669 |
c->remote_maxpacket = remote_maxpacket; |
c->remote_maxpacket = remote_maxpacket; |
| 8670 |
|
|
| 8671 |
|
} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { // agent forwarding |
| 8672 |
|
if (pvar->agentfwd_enable) { |
| 8673 |
|
c = ssh2_channel_new(CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, TYPE_AGENT, chan_num); |
| 8674 |
|
if (c == NULL) { |
| 8675 |
|
UTIL_get_lang_msg("MSG_SSH_NO_FREE_CHANNEL", pvar, |
| 8676 |
|
"Could not open new channel. TTSSH is already opening too many channels."); |
| 8677 |
|
notify_nonfatal_error(pvar, pvar->ts->UIMsg); |
| 8678 |
|
return FALSE; |
| 8679 |
|
} |
| 8680 |
|
c->remote_id = remote_id; |
| 8681 |
|
c->remote_window = remote_window; |
| 8682 |
|
c->remote_maxpacket = remote_maxpacket; |
| 8683 |
|
|
| 8684 |
|
msg = buffer_init(); |
| 8685 |
|
if (msg == NULL) { |
| 8686 |
|
// TODO: error check |
| 8687 |
|
return FALSE; |
| 8688 |
|
} |
| 8689 |
|
buffer_put_int(msg, c->remote_id); |
| 8690 |
|
buffer_put_int(msg, c->self_id); |
| 8691 |
|
buffer_put_int(msg, c->local_window); |
| 8692 |
|
buffer_put_int(msg, c->local_maxpacket); |
| 8693 |
|
|
| 8694 |
|
len = buffer_len(msg); |
| 8695 |
|
outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, len); |
| 8696 |
|
memcpy(outmsg, buffer_ptr(msg), len); |
| 8697 |
|
finish_send_packet(pvar); |
| 8698 |
|
buffer_free(msg); |
| 8699 |
|
|
| 8700 |
|
notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_OPEN_CONFIRMATION was sent at handle_SSH2_channel_open().", LOG_LEVEL_VERBOSE); |
| 8701 |
|
} |
| 8702 |
|
else { |
| 8703 |
|
msg = buffer_init(); |
| 8704 |
|
if (msg == NULL) { |
| 8705 |
|
// TODO: error check |
| 8706 |
|
return FALSE; |
| 8707 |
|
} |
| 8708 |
|
buffer_put_int(msg, remote_id); |
| 8709 |
|
buffer_put_int(msg, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); |
| 8710 |
|
buffer_put_string(msg, "", 0); // description |
| 8711 |
|
buffer_put_string(msg, "", 0); // language tag |
| 8712 |
|
|
| 8713 |
|
len = buffer_len(msg); |
| 8714 |
|
outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_OPEN_FAILURE, len); |
| 8715 |
|
memcpy(outmsg, buffer_ptr(msg), len); |
| 8716 |
|
finish_send_packet(pvar); |
| 8717 |
|
buffer_free(msg); |
| 8718 |
|
|
| 8719 |
|
notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_OPEN_FAILURE was sent at handle_SSH2_channel_open().", LOG_LEVEL_VERBOSE); |
| 8720 |
|
} |
| 8721 |
|
|
| 8722 |
} else { |
} else { |
| 8723 |
// unknown type(unsupported) |
// unknown type(unsupported) |
| 8724 |
|
|
| 8923 |
|
|
| 8924 |
return TRUE; |
return TRUE; |
| 8925 |
} |
} |
| 8926 |
|
|
| 8927 |
|
static BOOL SSH_agent_response(PTInstVar pvar, Channel_t *c, unsigned char *data, unsigned int buflen) |
| 8928 |
|
{ |
| 8929 |
|
int req_len, len; |
| 8930 |
|
unsigned char *keylist; |
| 8931 |
|
buffer_t *msg; |
| 8932 |
|
unsigned char cmd, res_cmd; |
| 8933 |
|
|
| 8934 |
|
req_len = get_uint32_MSBfirst(data); |
| 8935 |
|
|
| 8936 |
|
// 分割された CHANNEL_DATA の受信に対応 (2008.11.30 maya) |
| 8937 |
|
if (SSHv2(pvar)) { |
| 8938 |
|
if (c->agent_msg->len > 0 || req_len + 4 != buflen) { |
| 8939 |
|
if (c->agent_msg->len == 0) { |
| 8940 |
|
c->agent_request_len = req_len; |
| 8941 |
|
} |
| 8942 |
|
buffer_put_raw(c->agent_msg, data, buflen); |
| 8943 |
|
if (c->agent_request_len > c->agent_msg->len) { |
| 8944 |
|
return TRUE; |
| 8945 |
|
} |
| 8946 |
|
else { |
| 8947 |
|
data = c->agent_msg->buf; |
| 8948 |
|
} |
| 8949 |
|
} |
| 8950 |
|
} |
| 8951 |
|
else { |
| 8952 |
|
if (pvar->agent_channel.agent_msg->len > 0 || req_len + 4 != buflen) { |
| 8953 |
|
if (pvar->agent_channel.agent_msg->len == 0) { |
| 8954 |
|
pvar->agent_channel.agent_request_len = req_len; |
| 8955 |
|
} |
| 8956 |
|
buffer_put_raw(pvar->agent_channel.agent_msg, data, buflen); |
| 8957 |
|
if (pvar->agent_channel.agent_request_len > pvar->agent_channel.agent_msg->len) { |
| 8958 |
|
return TRUE; |
| 8959 |
|
} |
| 8960 |
|
else { |
| 8961 |
|
data = pvar->agent_channel.agent_msg->buf; |
| 8962 |
|
} |
| 8963 |
|
} |
| 8964 |
|
} |
| 8965 |
|
|
| 8966 |
|
data += 4; |
| 8967 |
|
cmd = *data; |
| 8968 |
|
|
| 8969 |
|
if (cmd == 11 || cmd == 1) { |
| 8970 |
|
// Pageant に鍵一覧を要求し、リモートに渡す |
| 8971 |
|
msg = buffer_init(); |
| 8972 |
|
if (msg == NULL) { |
| 8973 |
|
return TRUE; |
| 8974 |
|
} |
| 8975 |
|
|
| 8976 |
|
if (cmd == 11) { // SSH2_AGENTC_REQUEST_IDENTITIES |
| 8977 |
|
len = putty_get_ssh2_keylist(&keylist); |
| 8978 |
|
res_cmd = 12; // SSH2_AGENT_IDENTITIES_ANSWER |
| 8979 |
|
} |
| 8980 |
|
else { // SSH1_AGENTC_REQUEST_RSA_IDENTITIES 1 |
| 8981 |
|
len = putty_get_ssh1_keylist(&keylist); |
| 8982 |
|
res_cmd = 2; // SSH1_AGENT_RSA_IDENTITIES_ANSWER |
| 8983 |
|
} |
| 8984 |
|
|
| 8985 |
|
if (len < 5) { |
| 8986 |
|
// Pageant が起動していないか、鍵がない |
| 8987 |
|
buffer_put_int(msg, 4 + 1); |
| 8988 |
|
buffer_put_char(msg, res_cmd); |
| 8989 |
|
buffer_put_int(msg, 0); // 鍵の数 0 をセット |
| 8990 |
|
} |
| 8991 |
|
else { |
| 8992 |
|
buffer_put_int(msg, len + 1); |
| 8993 |
|
buffer_put_char(msg, res_cmd); |
| 8994 |
|
buffer_put_raw(msg, keylist, len); |
| 8995 |
|
} |
| 8996 |
|
|
| 8997 |
|
if (SSHv2(pvar)) { |
| 8998 |
|
SSH2_send_channel_data(pvar, c, msg->buf, msg->len); |
| 8999 |
|
} |
| 9000 |
|
else { |
| 9001 |
|
SSH_channel_send(pvar, pvar->agent_channel.local_id, |
| 9002 |
|
pvar->agent_channel.remote_id, |
| 9003 |
|
msg->buf, msg->len); |
| 9004 |
|
} |
| 9005 |
|
buffer_free(msg); |
| 9006 |
|
} |
| 9007 |
|
else if (cmd == 13 || cmd == 3) { |
| 9008 |
|
// Pageant に署名/ハッシュを要求し、リモートに渡す |
| 9009 |
|
msg = buffer_init(); |
| 9010 |
|
if (msg == NULL) { |
| 9011 |
|
return TRUE; |
| 9012 |
|
} |
| 9013 |
|
|
| 9014 |
|
if (cmd == 13) { // SSH2_AGENTC_SIGN_REQUEST |
| 9015 |
|
unsigned char *signedmsg; |
| 9016 |
|
int signedlen; |
| 9017 |
|
|
| 9018 |
|
data += 1; |
| 9019 |
|
len = get_uint32_MSBfirst(data); |
| 9020 |
|
signedmsg = putty_sign_ssh2_key(data, data + 4 + len, &signedlen); |
| 9021 |
|
if (signedmsg == NULL) { |
| 9022 |
|
// この channel を閉じる |
| 9023 |
|
if (SSHv2(pvar)) { |
| 9024 |
|
ssh2_channel_send_close(pvar, c); |
| 9025 |
|
} |
| 9026 |
|
else { |
| 9027 |
|
SSH_channel_input_eof(pvar, pvar->agent_channel.remote_id, |
| 9028 |
|
pvar->agent_channel.local_id); |
| 9029 |
|
} |
| 9030 |
|
return TRUE; |
| 9031 |
|
} |
| 9032 |
|
|
| 9033 |
|
buffer_put_int(msg, 1 + signedlen); |
| 9034 |
|
buffer_put_char(msg, 14); // SSH2_AGENT_SIGN_RESPONSE |
| 9035 |
|
buffer_put_raw(msg, signedmsg, signedlen); |
| 9036 |
|
|
| 9037 |
|
safefree(signedmsg); |
| 9038 |
|
} |
| 9039 |
|
else { // SSH1_AGENTC_RSA_CHALLENGE |
| 9040 |
|
unsigned char *hash; |
| 9041 |
|
int keylen, challengelen, hashlen; |
| 9042 |
|
data += 1; |
| 9043 |
|
keylen = putty_get_ssh1_keylen(data, req_len); |
| 9044 |
|
challengelen = req_len - keylen - 1 - 16 - 4; |
| 9045 |
|
hash = putty_hash_ssh1_challenge(data, keylen, |
| 9046 |
|
data + keylen, challengelen, |
| 9047 |
|
data + keylen + challengelen, |
| 9048 |
|
&hashlen); |
| 9049 |
|
if (hash == NULL) { |
| 9050 |
|
// この channel を閉じる |
| 9051 |
|
if (SSHv2(pvar)) { |
| 9052 |
|
ssh2_channel_send_close(pvar, c); |
| 9053 |
|
} |
| 9054 |
|
else { |
| 9055 |
|
SSH_channel_input_eof(pvar, pvar->agent_channel.remote_id, |
| 9056 |
|
pvar->agent_channel.local_id); |
| 9057 |
|
} |
| 9058 |
|
return TRUE; |
| 9059 |
|
} |
| 9060 |
|
|
| 9061 |
|
buffer_put_int(msg, 1 + hashlen); |
| 9062 |
|
buffer_put_char(msg, 4); // SSH1_AGENT_RSA_RESPONSE |
| 9063 |
|
buffer_put_raw(msg, hash, hashlen); |
| 9064 |
|
|
| 9065 |
|
safefree(hash); |
| 9066 |
|
} |
| 9067 |
|
|
| 9068 |
|
if (SSHv2(pvar)) { |
| 9069 |
|
SSH2_send_channel_data(pvar, c, msg->buf, msg->len); |
| 9070 |
|
} |
| 9071 |
|
else { |
| 9072 |
|
SSH_channel_send(pvar, pvar->agent_channel.local_id, |
| 9073 |
|
pvar->agent_channel.remote_id, |
| 9074 |
|
msg->buf, msg->len); |
| 9075 |
|
} |
| 9076 |
|
buffer_free(msg); |
| 9077 |
|
} |
| 9078 |
|
else { |
| 9079 |
|
// この channel を閉じる |
| 9080 |
|
if (SSHv2(pvar)) { |
| 9081 |
|
ssh2_channel_send_close(pvar, c); |
| 9082 |
|
} |
| 9083 |
|
else { |
| 9084 |
|
SSH_channel_input_eof(pvar, pvar->agent_channel.remote_id, |
| 9085 |
|
pvar->agent_channel.local_id); |
| 9086 |
|
} |
| 9087 |
|
return TRUE; |
| 9088 |
|
} |
| 9089 |
|
|
| 9090 |
|
return TRUE; |
| 9091 |
|
} |