Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/ssh.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2972 - (show annotations) (download) (as text)
Thu Apr 26 10:18:27 2007 UTC (16 years, 11 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 197785 byte(s)
port fowardingにおいて、channel close時にSSH2チャネル構造体を解放していなかったバグを修正した。

1 /*
2 Copyright (c) 1998-2001, Robert O'Callahan
3 Copyright (c) 2004-2005, Yutaka Hirata
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without modification,
7 are permitted provided that the following conditions are met:
8
9 Redistributions of source code must retain the above copyright notice, this list of
10 conditions and the following disclaimer.
11
12 Redistributions in binary form must reproduce the above copyright notice, this list
13 of conditions and the following disclaimer in the documentation and/or other materials
14 provided with the distribution.
15
16 The name of Robert O'Callahan may not be used to endorse or promote products derived from
17 this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "ttxssh.h"
31 #include "util.h"
32
33 #include <openssl/bn.h>
34 #include <openssl/evp.h>
35 #include <openssl/dh.h>
36 #include <openssl/engine.h>
37 #include <openssl/rsa.h>
38 #include <openssl/dsa.h>
39 #include <limits.h>
40 #include <malloc.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <process.h>
44 #include <time.h>
45 #include "buffer.h"
46 #include "ssh.h"
47 #include "crypt.h"
48
49 // SSH2 macro
50 #ifdef _DEBUG
51 #define SSH2_DEBUG
52 #endif
53
54 #define DONT_WANTCONFIRM 1 // (2005.3.28 yutaka)
55 #define INTBLOB_LEN 20
56 #define SIGBLOB_LEN (2*INTBLOB_LEN)
57
58 static char ssh_ttymodes[] = "\x01\x03\x02\x1c\x03\x08\x04\x15\x05\x04";
59
60 static void try_send_credentials(PTInstVar pvar);
61 static void prep_compression(PTInstVar pvar);
62
63 // �����v���g�^�C�v����
64 void SSH2_send_kexinit(PTInstVar pvar);
65 static BOOL handle_SSH2_kexinit(PTInstVar pvar);
66 static void SSH2_dh_kex_init(PTInstVar pvar);
67 static void SSH2_dh_gex_kex_init(PTInstVar pvar);
68 static BOOL handle_SSH2_dh_common_reply(PTInstVar pvar);
69 static BOOL handle_SSH2_dh_gex_reply(PTInstVar pvar);
70 static BOOL handle_SSH2_newkeys(PTInstVar pvar);
71 static BOOL handle_SSH2_authrequest(PTInstVar pvar);
72 static BOOL handle_SSH2_userauth_success(PTInstVar pvar);
73 static BOOL handle_SSH2_userauth_failure(PTInstVar pvar);
74 static BOOL handle_SSH2_userauth_banner(PTInstVar pvar);
75 static BOOL handle_SSH2_open_confirm(PTInstVar pvar);
76 static BOOL handle_SSH2_open_failure(PTInstVar pvar);
77 static BOOL handle_SSH2_request_success(PTInstVar pvar);
78 static BOOL handle_SSH2_request_failure(PTInstVar pvar);
79 static BOOL handle_SSH2_channel_success(PTInstVar pvar);
80 static BOOL handle_SSH2_channel_data(PTInstVar pvar);
81 static BOOL handle_SSH2_channel_extended_data(PTInstVar pvar);
82 static BOOL handle_SSH2_channel_eof(PTInstVar pvar);
83 static BOOL handle_SSH2_channel_close(PTInstVar pvar);
84 static BOOL handle_SSH2_channel_open(PTInstVar pvar);
85 static BOOL handle_SSH2_window_adjust(PTInstVar pvar);
86 static BOOL handle_SSH2_channel_request(PTInstVar pvar);
87 void SSH2_dispatch_init(int stage);
88 int SSH2_dispatch_enabled_check(unsigned char message);
89 void SSH2_dispatch_add_message(unsigned char message);
90 void SSH2_dispatch_add_range_message(unsigned char begin, unsigned char end);
91 int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub);
92 static void start_ssh_heartbeat_thread(PTInstVar pvar);
93
94
95 //
96 // SSH2 data structure
97 //
98
99 /* default window/packet sizes for tcp/x11-fwd-channel */
100 #define CHAN_SES_PACKET_DEFAULT (32*1024)
101 #define CHAN_SES_WINDOW_DEFAULT (2*CHAN_SES_PACKET_DEFAULT) // READAMOUNT @ pkt.c����������������
102 #define CHAN_TCP_PACKET_DEFAULT (32*1024)
103 #define CHAN_TCP_WINDOW_DEFAULT (4*CHAN_TCP_PACKET_DEFAULT)
104 #define CHAN_X11_PACKET_DEFAULT (16*1024)
105 #define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT)
106
107 // channel data structure
108 #define CHANNEL_MAX 100
109
110 enum channel_type {
111 TYPE_SHELL, TYPE_PORTFWD,
112 };
113
114 typedef struct channel {
115 int used;
116 int self_id;
117 int remote_id;
118 unsigned int local_window;
119 unsigned int local_window_max;
120 unsigned int local_consumed;
121 unsigned int local_maxpacket;
122 unsigned int remote_window;
123 unsigned int remote_maxpacket;
124 enum channel_type type;
125 int local_num;
126 } Channel_t;
127
128 static Channel_t channels[CHANNEL_MAX];
129
130 //
131 // channel function
132 //
133 static Channel_t *ssh2_channel_new(unsigned int window, unsigned int maxpack, enum confirm_type type, int local_num)
134 {
135 int i, found;
136 Channel_t *c;
137
138 found = -1;
139 for (i = 0 ; i < CHANNEL_MAX ; i++) {
140 if (channels[i].used == 0) { // free channel
141 found = i;
142 break;
143 }
144 }
145 if (found == -1) { // not free channel
146 return (NULL);
147 }
148
149 // setup
150 c = &channels[found];
151 c->used = 1;
152 c->self_id = i;
153 c->remote_id = -1;
154 c->local_window = window;
155 c->local_window_max = window;
156 c->local_consumed = 0;
157 c->local_maxpacket = maxpack;
158 c->remote_window = 0;
159 c->remote_maxpacket = 0;
160 c->type = type;
161 c->local_num = local_num; // alloc_channel()�����l��������������
162
163 return (c);
164 }
165
166
167 // channel close�����`���l���\���������X�g�����p����
168 // (2007.4.26 yutaka)
169 static void ssh2_channel_delete(Channel_t *c)
170 {
171 memset(c, 0, sizeof(Channel_t));
172 c->used = 0;
173 }
174
175
176 // connection close������������
177 void ssh2_channel_free(void)
178 {
179 int i;
180 Channel_t *c;
181
182 for (i = 0 ; i < CHANNEL_MAX ; i++) {
183 c = &channels[i];
184 memset(c, 0, sizeof(Channel_t));
185 }
186
187 }
188
189 static Channel_t *ssh2_channel_lookup(int id)
190 {
191 Channel_t *c;
192
193 if (id < 0 || id >= CHANNEL_MAX) {
194 return (NULL);
195 }
196 c = &channels[id];
197 if (c->used == 0) { // already freed
198 return (NULL);
199 }
200 return (c);
201 }
202
203 // SSH1��������������channel�\���������ASSH2������Channel_t�����������B
204 // TODO: �����I�����`���l���\������1�������������B
205 // (2005.6.12 yutaka)
206 static Channel_t *ssh2_local_channel_lookup(int local_num)
207 {
208 int i;
209 Channel_t *c;
210
211 for (i = 0 ; i < CHANNEL_MAX ; i++) {
212 c = &channels[i];
213 if (c->local_num == local_num)
214 return (c);
215 }
216 return (NULL);
217 }
218
219
220 //
221 // SSH heartbeat mutex
222 //
223 static CRITICAL_SECTION g_ssh_heartbeat_lock; /* ���b�N�p���� */
224
225 void ssh_heartbeat_lock_initialize(void)
226 {
227 InitializeCriticalSection(&g_ssh_heartbeat_lock);
228 }
229
230 void ssh_heartbeat_lock_finalize(void)
231 {
232 DeleteCriticalSection(&g_ssh_heartbeat_lock);
233 }
234
235 void ssh_heartbeat_lock(void)
236 {
237 EnterCriticalSection(&g_ssh_heartbeat_lock);
238 }
239
240 void ssh_heartbeat_unlock(void)
241 {
242 LeaveCriticalSection(&g_ssh_heartbeat_lock);
243 }
244
245
246 //
247 // SSH memory dump (for debug)
248 //
249 // (2005.3.7 yutaka)
250 //
251 #define MEMTAG_MAX 100
252 #define LOGDUMP "ssh2dump.log"
253 #define SENDTOME "Please send '"LOGDUMP"' file to TeraTerm developer team."
254
255 typedef struct memtag {
256 char *name;
257 char *desc;
258 int len;
259 char *data;
260 } memtag_t;
261
262 static memtag_t memtags[MEMTAG_MAX];
263 static int memtag_count = 0;
264 static int memtag_use = 0;
265
266 /* �_���v���C�����t�H�[�}�b�g�\������ */
267 static void displine_memdump(FILE *fp, int addr, int *bytes, int byte_cnt)
268 {
269 int i, c;
270
271 /* �������A�h���X�\�� */
272 fprintf(fp, "%08X : ", addr);
273
274 /* �o�C�i���\���i4�o�C�g�������������}���j*/
275 for (i = 0 ; i < byte_cnt ; i++) {
276 if (i > 0 && i % 4 == 0)
277 fprintf(fp, " ");
278
279 fprintf(fp, "%02X", bytes[i]);
280 }
281
282 /* ASCII�\���������������������� */
283 fprintf(fp, " %*s%*s", (16-byte_cnt)*2+1, " ", (16-byte_cnt+3)/4, " ");
284
285 /* ASCII�\�� */
286 for (i = 0 ; i < byte_cnt ; i++) {
287 c = bytes[i];
288 if (c >= 0x20 && c <= 0x7f) {
289 fprintf(fp, "%c", c);
290 } else {
291 fprintf(fp, ".");
292 }
293 }
294
295 fprintf(fp, "\n");
296 }
297
298
299 /* �_���v���[�`�� */
300 static void dump_memdump(FILE *fp, char *data, int len)
301 {
302 int c, addr;
303 int bytes[16], *ptr;
304 int byte_cnt;
305 int i;
306
307 addr = 0;
308 byte_cnt = 0;
309 ptr = bytes;
310 for (i = 0 ; i < len ; i++) {
311 c = data[i];
312 *ptr++ = c & 0xff;
313 byte_cnt++;
314
315 if (byte_cnt == 16) {
316 displine_memdump(fp, addr, bytes, byte_cnt);
317
318 addr += 16;
319 byte_cnt = 0;
320 ptr = bytes;
321 }
322 }
323
324 if (byte_cnt > 0) {
325 displine_memdump(fp, addr, bytes, byte_cnt);
326 }
327 }
328
329 void init_memdump(void)
330 {
331 int i;
332
333 for (i = 0 ; i < MEMTAG_MAX ; i++) {
334 memtags[i].name = NULL;
335 memtags[i].desc = NULL;
336 memtags[i].data = NULL;
337 memtags[i].len = 0;
338 }
339 memtag_use++;
340 }
341
342 void finish_memdump(void)
343 {
344 int i;
345
346 // initialize�������������������������������B(2005.4.3 yutaka)
347 if (memtag_use <= 0)
348 return;
349 memtag_use--;
350
351 for (i = 0 ; i < MEMTAG_MAX ; i++) {
352 free(memtags[i].name);
353 free(memtags[i].desc);
354 free(memtags[i].data);
355 memtags[i].len = 0;
356 }
357 }
358
359 void save_memdump(char *filename)
360 {
361 FILE *fp;
362 int i;
363 time_t t;
364 struct tm *tm;
365
366 fp = fopen(filename, "w");
367 if (fp == NULL)
368 return;
369
370 t = time(NULL);
371 tm = localtime(&t);
372
373 fprintf(fp, "<<< TeraTerm SSH2 log dump >>>\n");
374 fprintf(fp, "saved time: %04d/%02d/%02d %02d:%02d:%02d\n",
375 tm->tm_year + 1900,
376 tm->tm_mon + 1,
377 tm->tm_mday,
378 tm->tm_hour,
379 tm->tm_min,
380 tm->tm_sec);
381 fprintf(fp, "\n");
382
383 for (i = 0 ; i < memtag_count ; i++) {
384 fprintf(fp, "============================================\n");
385 fprintf(fp, "name: %s\n", memtags[i].name);
386 fprintf(fp, "--------------------------------------------\n");
387 fprintf(fp, "description: %s\n", memtags[i].desc);
388 fprintf(fp, "============================================\n");
389 dump_memdump(fp, memtags[i].data, memtags[i].len);
390 fprintf(fp, "\n\n\n");
391 }
392
393 fprintf(fp, "[EOF]\n");
394
395 fclose(fp);
396 }
397
398 void push_memdump(char *name, char *desc, char *data, int len)
399 {
400 memtag_t *ptr;
401 char *dp;
402
403 dp = malloc(len);
404 if (dp == NULL)
405 return;
406 memcpy(dp, data, len);
407
408 if (memtag_count >= MEMTAG_MAX)
409 return;
410
411 ptr = &memtags[memtag_count];
412 memtag_count++;
413 ptr->name = _strdup(name);
414 ptr->desc = _strdup(desc);
415 ptr->data = dp;
416 ptr->len = len;
417 }
418
419 void push_bignum_memdump(char *name, char *desc, BIGNUM *bignum)
420 {
421 int len;
422 char *buf;
423
424 len = BN_num_bytes(bignum);
425 buf = malloc(len); // allocate
426 if (buf == NULL)
427 return;
428 BN_bn2bin(bignum, buf);
429 push_memdump(name, desc, buf, len); // at push_bignum_memdump()
430 free(buf); // free
431 }
432
433
434 //
435 //
436 //
437
438
439 static int get_predecryption_amount(PTInstVar pvar)
440 {
441 static int small_block_decryption_sizes[] = { 5, 5, 6, 6, 8 };
442
443 if (SSHv1(pvar)) {
444 return 0;
445 } else {
446 int block_size = CRYPT_get_decryption_block_size(pvar);
447
448 if (block_size < 5) {
449 return small_block_decryption_sizes[block_size];
450 } else {
451 return block_size;
452 }
453 }
454 }
455
456 /* Get up to 'limit' bytes into the payload buffer.
457 'limit' is counted from the start of the payload data.
458 Returns the amount of data in the payload buffer, or
459 -1 if there is an error.
460 We can return more than limit in some cases. */
461 static int buffer_packet_data(PTInstVar pvar, int limit)
462 {
463 if (pvar->ssh_state.payloadlen >= 0) {
464 return pvar->ssh_state.payloadlen;
465 } else {
466 int cur_decompressed_bytes =
467 pvar->ssh_state.decompress_stream.next_out -
468 pvar->ssh_state.postdecompress_inbuf;
469
470 while (limit > cur_decompressed_bytes) {
471 int result;
472
473 pvar->ssh_state.payload =
474 pvar->ssh_state.postdecompress_inbuf + 1;
475 if (pvar->ssh_state.postdecompress_inbuflen ==
476 cur_decompressed_bytes) {
477 buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf,
478 &pvar->ssh_state.postdecompress_inbuflen,
479 min(limit, cur_decompressed_bytes * 2));
480 }
481
482 pvar->ssh_state.decompress_stream.next_out
483 =
484 pvar->ssh_state.postdecompress_inbuf +
485 cur_decompressed_bytes;
486 pvar->ssh_state.decompress_stream.avail_out =
487 min(limit, pvar->ssh_state.postdecompress_inbuflen)
488 - cur_decompressed_bytes;
489
490 result =
491 inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH);
492 cur_decompressed_bytes =
493 pvar->ssh_state.decompress_stream.next_out -
494 pvar->ssh_state.postdecompress_inbuf;
495
496 switch (result) {
497 case Z_OK:
498 break;
499 case Z_BUF_ERROR:
500 pvar->ssh_state.payloadlen = cur_decompressed_bytes;
501 return cur_decompressed_bytes;
502 default:
503 #ifdef I18N
504 strcpy(pvar->ts->UIMsg, "Invalid compressed data in received packet");
505 UTIL_get_lang_msg("MSG_SSH_INVALID_COMPDATA_ERROR", pvar);
506 notify_fatal_error(pvar, pvar->ts->UIMsg);
507 #else
508 notify_fatal_error(pvar,
509 "Invalid compressed data in received packet");
510 #endif
511 return -1;
512 }
513 }
514
515 return cur_decompressed_bytes;
516 }
517 }
518
519 /* For use by the protocol processing code.
520 Gets N bytes of uncompressed payload. Returns FALSE if data not available
521 and a fatal error has been signaled.
522 The data is available in the payload buffer. This buffer address
523 can change during a call to grab_payload, so take care!
524 The payload pointer is set to point to the first byte of the actual data
525 (after the packet type byte).
526 */
527 static BOOL grab_payload(PTInstVar pvar, int num_bytes)
528 {
529 /* Accept maximum of 4MB of payload data */
530 int in_buffer = buffer_packet_data(pvar, 4 * 1024 * 1024);
531
532 if (in_buffer < 0) {
533 return FALSE;
534 } else {
535 pvar->ssh_state.payload_grabbed += num_bytes;
536 if (pvar->ssh_state.payload_grabbed > in_buffer) {
537 char buf[128];
538 #ifdef I18N
539 strcpy(pvar->ts->UIMsg, "Received truncated packet (%ld > %d) @ grab_payload()");
540 UTIL_get_lang_msg("MSG_SSH_TRUNCATED_PKT_ERROR", pvar);
541 _snprintf(buf, sizeof(buf), pvar->ts->UIMsg,
542 pvar->ssh_state.payload_grabbed, in_buffer);
543 #else
544 _snprintf(buf, sizeof(buf), "Received truncated packet (%ld > %d) @ grab_payload()",
545 pvar->ssh_state.payload_grabbed, in_buffer);
546 #endif
547 notify_fatal_error(pvar, buf);
548 return FALSE;
549 } else {
550 return TRUE;
551 }
552 }
553 }
554
555 static BOOL grab_payload_limited(PTInstVar pvar, int num_bytes)
556 {
557 int in_buffer;
558
559 pvar->ssh_state.payload_grabbed += num_bytes;
560 in_buffer = buffer_packet_data(pvar, pvar->ssh_state.payload_grabbed);
561
562 if (in_buffer < 0) {
563 return FALSE;
564 } else {
565 if (pvar->ssh_state.payload_grabbed > in_buffer) {
566 char buf[128];
567 #ifdef I18N
568 strcpy(pvar->ts->UIMsg, "Received truncated packet (%ld > %d) @ grab_payload_limited()");
569 UTIL_get_lang_msg("MSG_SSH_TRUNCATED_PKT_LIM_ERROR", pvar);
570 _snprintf(buf, sizeof(buf), pvar->ts->UIMsg,
571 pvar->ssh_state.payload_grabbed, in_buffer);
572 #else
573 _snprintf(buf, sizeof(buf), "Received truncated packet (%ld > %d) @ grab_payload_limited()",
574 pvar->ssh_state.payload_grabbed, in_buffer);
575 #endif
576 notify_fatal_error(pvar, buf);
577 return FALSE;
578 } else {
579 return TRUE;
580 }
581 }
582 }
583
584 #define get_payload_uint32(pvar, offset) get_uint32_MSBfirst((pvar)->ssh_state.payload + (offset))
585 #define get_uint32(buf) get_uint32_MSBfirst((buf))
586 #define set_uint32(buf, v) set_uint32_MSBfirst((buf), (v))
587 #define get_mpint_len(pvar, offset) ((get_ushort16_MSBfirst((pvar)->ssh_state.payload + (offset)) + 7) >> 3)
588 #define get_ushort16(buf) get_ushort16_MSBfirst((buf))
589
590 #define do_crc(buf, len) (~(uint32)crc32(0xFFFFFFFF, (buf), (len)))
591
592 /* Decrypt the payload, checksum it, eat the padding, get the packet type
593 and return it.
594 'data' points to the start of the packet --- its length field.
595 'len' is the length of the
596 payload + padding (+ length of CRC for SSHv1). 'padding' is the length
597 of the padding alone. */
598 static int prep_packet(PTInstVar pvar, char FAR * data, int len,
599 int padding)
600 {
601 pvar->ssh_state.payload = data + 4;
602 pvar->ssh_state.payloadlen = len;
603
604 if (SSHv1(pvar)) {
605 if (CRYPT_detect_attack(pvar, pvar->ssh_state.payload, len)) {
606 #ifdef I18N
607 strcpy(pvar->ts->UIMsg, "'CORE insertion attack' detected. Aborting connection.");
608 UTIL_get_lang_msg("MSG_SSH_COREINS_ERROR", pvar);
609 notify_fatal_error(pvar, pvar->ts->UIMsg);
610 #else
611 notify_fatal_error(pvar,
612 "'CORE insertion attack' detected. Aborting connection.");
613 return SSH_MSG_NONE;
614 #endif
615 }
616
617 CRYPT_decrypt(pvar, pvar->ssh_state.payload, len);
618 /* PKT guarantees that the data is always 4-byte aligned */
619 if (do_crc(pvar->ssh_state.payload, len - 4) !=
620 get_uint32_MSBfirst(pvar->ssh_state.payload + len - 4)) {
621 #ifdef I18N
622 strcpy(pvar->ts->UIMsg, "Detected corrupted data; connection terminating.");
623 UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar);
624 notify_fatal_error(pvar, pvar->ts->UIMsg);
625 #else
626 notify_fatal_error(pvar,
627 "Detected corrupted data; connection terminating.");
628 #endif
629 return SSH_MSG_NONE;
630 }
631
632 pvar->ssh_state.payload += padding;
633 pvar->ssh_state.payloadlen -= padding + 4;
634 } else {
635 int already_decrypted = get_predecryption_amount(pvar);
636
637 #if 0
638 CRYPT_decrypt(pvar, data + already_decrypted,
639 len - already_decrypted);
640 #else
641 CRYPT_decrypt(pvar, data + already_decrypted,
642 (4 + len) - already_decrypted);
643 #endif
644
645 if (!CRYPT_verify_receiver_MAC
646 (pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4,
647 data + len + 4)) {
648 #ifdef I18N
649 strcpy(pvar->ts->UIMsg, "Detected corrupted data; connection terminating.");
650 UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar);
651 notify_fatal_error(pvar, pvar->ts->UIMsg);
652 #else
653 notify_fatal_error(pvar,
654 "Detected corrupted data; connection terminating.");
655 #endif
656 return SSH_MSG_NONE;
657 }
658
659 pvar->ssh_state.payload++;
660 pvar->ssh_state.payloadlen -= padding + 1;
661 }
662
663 pvar->ssh_state.payload_grabbed = 0;
664
665 if (SSHv1(pvar)) {
666 if (pvar->ssh_state.decompressing) {
667 if (pvar->ssh_state.decompress_stream.avail_in != 0) {
668 #ifdef I18N
669 strcpy(pvar->ts->UIMsg, "Internal error: a packet was not fully decompressed.\n"
670 "This is a bug, please report it.");
671 UTIL_get_lang_msg("MSG_SSH_DECOMPRESS_ERROR", pvar);
672 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
673 #else
674 notify_nonfatal_error(pvar,
675 "Internal error: a packet was not fully decompressed.\n"
676 "This is a bug, please report it.");
677 #endif
678 }
679
680 pvar->ssh_state.decompress_stream.next_in =
681 pvar->ssh_state.payload;
682 pvar->ssh_state.decompress_stream.avail_in =
683 pvar->ssh_state.payloadlen;
684 pvar->ssh_state.decompress_stream.next_out =
685 pvar->ssh_state.postdecompress_inbuf;
686 pvar->ssh_state.payloadlen = -1;
687 } else {
688 pvar->ssh_state.payload++;
689 }
690
691 if (!grab_payload_limited(pvar, 1)) {
692 return SSH_MSG_NONE;
693 }
694
695 } else {
696 // support of SSH2 packet compression (2005.7.9 yutaka)
697 // support of "Compression delayed" (2006.6.23 maya)
698 if ((pvar->stoc_compression == COMP_ZLIB ||
699 pvar->stoc_compression == COMP_DELAYED && pvar->userauth_success) &&
700 pvar->ssh2_keys[MODE_IN].comp.enabled) { // compression enabled
701 int ret;
702
703 if (pvar->decomp_buffer == NULL) {
704 pvar->decomp_buffer = buffer_init();
705 if (pvar->decomp_buffer == NULL)
706 return SSH_MSG_NONE;
707 }
708 // ���x�m�������o�b�t�@���g�������������������Y�������B
709 buffer_clear(pvar->decomp_buffer);
710
711 // packet size��padding�������������y�C���[�h�����������W�J�����B
712 ret = buffer_decompress(&pvar->ssh_state.decompress_stream,
713 pvar->ssh_state.payload, pvar->ssh_state.payloadlen, pvar->decomp_buffer);
714
715 // �|�C���^���X�V�B
716 pvar->ssh_state.payload = buffer_ptr(pvar->decomp_buffer);
717 pvar->ssh_state.payload++;
718 pvar->ssh_state.payloadlen = buffer_len(pvar->decomp_buffer);
719
720 } else {
721 pvar->ssh_state.payload++;
722 }
723
724 if (!grab_payload_limited(pvar, 1)) {
725 return SSH_MSG_NONE;
726 }
727
728 }
729
730 pvar->ssh_state.receiver_sequence_number++;
731
732 return pvar->ssh_state.payload[-1];
733 }
734
735 /* Create a packet to be sent. The SSH protocol packet type is in 'type';
736 'len' contains the length of the packet payload, in bytes (this
737 does not include the space for any of the packet headers or padding,
738 or for the packet type byte).
739 Returns a pointer to the payload data area, a region of length 'len',
740 to be filled by the caller. */
741 static unsigned char FAR *begin_send_packet(PTInstVar pvar, int type,
742 int len)
743 {
744 unsigned char FAR *buf;
745
746 pvar->ssh_state.outgoing_packet_len = len + 1;
747
748 if (pvar->ssh_state.compressing) {
749 buf_ensure_size(&pvar->ssh_state.precompress_outbuf,
750 &pvar->ssh_state.precompress_outbuflen, 1 + len);
751 buf = pvar->ssh_state.precompress_outbuf;
752 } else {
753 /* For SSHv2,
754 Encrypted_length is 4(packetlength) + 1(paddinglength) + 1(packettype)
755 + len(payload) + 4(minpadding), rounded up to nearest block_size
756 We only need a reasonable upper bound for the buffer size */
757 buf_ensure_size(&pvar->ssh_state.outbuf,
758 &pvar->ssh_state.outbuflen,
759 len + 30 + CRYPT_get_sender_MAC_size(pvar) +
760 CRYPT_get_encryption_block_size(pvar));
761 buf = pvar->ssh_state.outbuf + 12;
762 }
763
764 buf[0] = (unsigned char) type;
765 return buf + 1;
766 }
767
768 #define finish_send_packet(pvar) finish_send_packet_special((pvar), 0)
769
770 // ���M���g���C����������
771 //
772 // WinSock�� send() ���o�b�t�@�T�C�Y(len)�������������l��������������������
773 // ���������������A�����������G���[���������B
774 // �����������ATCP�R�l�N�V�������f�������o���h���B
775 // (2006.12.9 yutaka)
776 static int retry_send_packet(PTInstVar pvar, char FAR * data, int len)
777 {
778 int n;
779 int err;
780
781 while (len > 0) {
782 n = (pvar->Psend)(pvar->socket, data, len, 0);
783
784 if (n < 0) {
785 err = WSAGetLastError();
786 if (err < WSABASEERR || err == WSAEWOULDBLOCK) {
787 // send()�����l��0�������A�����G���[������ 10000 �������������A
788 // ���������������������B
789 // PuTTY 0.58���������Q�l�B
790 // (2007.2.4 yutak)
791 return 0; // success
792 }
793 return 1; // error
794 }
795
796 len -= n;
797 data += n;
798 }
799
800 return 0; // success
801 }
802
803 static BOOL send_packet_blocking(PTInstVar pvar, char FAR * data, int len)
804 {
805 u_long do_block = 0;
806
807 if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow,
808 0, 0) == SOCKET_ERROR
809 || ioctlsocket(pvar->socket, FIONBIO, &do_block) == SOCKET_ERROR
810 || retry_send_packet(pvar, data, len)
811 || (pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow,
812 pvar->notification_msg,
813 pvar->notification_events) ==
814 SOCKET_ERROR) {
815 #ifdef I18N
816 strcpy(pvar->ts->UIMsg, "A communications error occurred while sending an SSH packet.\n"
817 "The connection will close.");
818 UTIL_get_lang_msg("MSG_SSH_SEND_PKT_ERROR", pvar);
819 notify_fatal_error(pvar, pvar->ts->UIMsg);
820 #else
821 notify_fatal_error(pvar,
822 "A communications error occurred while sending an SSH packet.\n"
823 "The connection will close.");
824 #endif
825 return FALSE;
826 } else {
827 return TRUE;
828 }
829 }
830
831 /* if skip_compress is true, then the data has already been compressed
832 into outbuf + 12 */
833 static void finish_send_packet_special(PTInstVar pvar, int skip_compress)
834 {
835 int len = pvar->ssh_state.outgoing_packet_len;
836 char FAR *data;
837 int data_length;
838 buffer_t *msg = NULL; // for SSH2 packet compression
839
840 if (pvar->ssh_state.compressing) {
841 if (!skip_compress) {
842 buf_ensure_size(&pvar->ssh_state.outbuf,
843 &pvar->ssh_state.outbuflen,
844 len + (len >> 6) + 50 +
845 CRYPT_get_sender_MAC_size(pvar));
846 pvar->ssh_state.compress_stream.next_in =
847 pvar->ssh_state.precompress_outbuf;
848 pvar->ssh_state.compress_stream.avail_in = len;
849 pvar->ssh_state.compress_stream.next_out =
850 pvar->ssh_state.outbuf + 12;
851 pvar->ssh_state.compress_stream.avail_out =
852 pvar->ssh_state.outbuflen - 12;
853
854 if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
855 Z_OK) {
856 #ifdef I18N
857 strcpy(pvar->ts->UIMsg, "An error occurred while compressing packet data.\n"
858 "The connection will close.");
859 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar);
860 notify_fatal_error(pvar, pvar->ts->UIMsg);
861 #else
862 notify_fatal_error(pvar,
863 "An error occurred while compressing packet data.\n"
864 "The connection will close.");
865 #endif
866 return;
867 }
868 }
869
870 len =
871 pvar->ssh_state.outbuflen - 12 -
872 pvar->ssh_state.compress_stream.avail_out;
873 }
874
875 if (SSHv1(pvar)) {
876 int padding = 8 - ((len + 4) % 8);
877
878 data = pvar->ssh_state.outbuf + 8 - padding;
879 data_length = padding + len + 8;
880
881 set_uint32(data, len + 4);
882 if (CRYPT_get_receiver_cipher(pvar) != SSH_CIPHER_NONE) {
883 CRYPT_set_random_data(pvar, data + 4, padding);
884 } else {
885 memset(data + 4, 0, padding);
886 }
887 set_uint32(data + data_length - 4,
888 do_crc(data + 4, data_length - 8));
889 CRYPT_encrypt(pvar, data + 4, data_length - 4);
890 } else { //for SSH2(yutaka)
891 int block_size = CRYPT_get_encryption_block_size(pvar);
892 int encryption_size;
893 int padding;
894 BOOL ret;
895
896 /*
897 �f�[�^�\��
898 pvar->ssh_state.outbuf:
899 offset: 0 1 2 3 4 5 6 7 8 9 10 11 12 ... EOD
900 <--ignore---> ^^^^^^^^ <---- payload --->
901 packet length
902
903 ^^padding
904
905 <---------------------------->
906 SSH2 sending data on TCP
907
908 NOTE:
909 payload = type(1) + raw-data
910 len = ssh_state.outgoing_packet_len = payload size
911 */
912 // �p�P�b�g���k���L���������A�p�P�b�g�����k�����������M�p�P�b�g���\�z�����B(2005.7.9 yutaka)
913 // support of "Compression delayed" (2006.6.23 maya)
914 if ((pvar->ctos_compression == COMP_ZLIB ||
915 pvar->ctos_compression == COMP_DELAYED && pvar->userauth_success) &&
916 pvar->ssh2_keys[MODE_OUT].comp.enabled) {
917 // �����o�b�t�@�� packet-length(4) + padding(1) + payload(any) �������B
918 msg = buffer_init();
919 if (msg == NULL) {
920 // TODO: error check
921 return;
922 }
923
924 // ���k�������w�b�_�������y�C���[�h�����B
925 buffer_append(msg, "\0\0\0\0\0", 5); // 5 = packet-length(4) + padding(1)
926 if (buffer_compress(&pvar->ssh_state.compress_stream, pvar->ssh_state.outbuf + 12, len, msg) == -1) {
927 #ifdef I18N
928 strcpy(pvar->ts->UIMsg, "An error occurred while compressing packet data.\n"
929 "The connection will close.");
930 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar);
931 notify_fatal_error(pvar, pvar->ts->UIMsg);
932 #else
933 notify_fatal_error(pvar,
934 "An error occurred while compressing packet data.\n"
935 "The connection will close.");
936 #endif
937 return;
938 }
939 data = buffer_ptr(msg);
940 len = buffer_len(msg) - 5; // 'len' is overwritten.
941
942 } else {
943 // �����k
944 data = pvar->ssh_state.outbuf + 7;
945
946 }
947
948 // ���M�p�P�b�g�\�z(input parameter: data, len)
949 if (block_size < 8) {
950 block_size = 8;
951 }
952 encryption_size = ((len + 8) / block_size + 1) * block_size;
953 data_length = encryption_size + CRYPT_get_sender_MAC_size(pvar);
954
955 set_uint32(data, encryption_size - 4);
956 padding = encryption_size - len - 5;
957 data[4] = (unsigned char) padding;
958 CRYPT_set_random_data(pvar, data + 5 + len, padding);
959 ret = CRYPT_build_sender_MAC(pvar,
960 pvar->ssh_state.sender_sequence_number,
961 data, encryption_size,
962 data + encryption_size);
963 if (ret == FALSE) { // HMAC��������������������������
964 data_length = encryption_size;
965 }
966
967 // �p�P�b�g�������������BHMAC���~�������������O�B
968 CRYPT_encrypt(pvar, data, encryption_size);
969 }
970
971 send_packet_blocking(pvar, data, data_length);
972
973 buffer_free(msg);
974
975 pvar->ssh_state.sender_sequence_number++;
976
977 // ���M�������L�^
978 pvar->ssh_heartbeat_tick = time(NULL);
979 }
980
981 static void destroy_packet_buf(PTInstVar pvar)
982 {
983 memset(pvar->ssh_state.outbuf, 0, pvar->ssh_state.outbuflen);
984 if (pvar->ssh_state.compressing) {
985 memset(pvar->ssh_state.precompress_outbuf, 0,
986 pvar->ssh_state.precompress_outbuflen);
987 }
988 }
989
990 /* The handlers are added to the queue for each message. When one of the
991 handlers fires, if it returns FALSE, then all handlers in the set are
992 removed from their queues. */
993 static void enque_handlers(PTInstVar pvar, int num_msgs,
994 const int FAR * messages,
995 const SSHPacketHandler FAR * handlers)
996 {
997 SSHPacketHandlerItem FAR *first_item;
998 SSHPacketHandlerItem FAR *last_item = NULL;
999 int i;
1000
1001 for (i = 0; i < num_msgs; i++) {
1002 SSHPacketHandlerItem FAR *item =
1003 (SSHPacketHandlerItem FAR *)
1004 malloc(sizeof(SSHPacketHandlerItem));
1005 SSHPacketHandlerItem FAR *cur_item =
1006 pvar->ssh_state.packet_handlers[messages[i]];
1007
1008 item->handler = handlers[i];
1009
1010 if (cur_item == NULL) {
1011 pvar->ssh_state.packet_handlers[messages[i]] = item;
1012 item->next_for_message = item;
1013 item->last_for_message = item;
1014 item->active_for_message = messages[i];
1015 } else {
1016 item->next_for_message = cur_item;
1017 item->last_for_message = cur_item->last_for_message;
1018 cur_item->last_for_message->next_for_message = item;
1019 cur_item->last_for_message = item;
1020 item->active_for_message = -1;
1021 }
1022
1023 if (last_item != NULL) {
1024 last_item->next_in_set = item;
1025 } else {
1026 first_item = item;
1027 }
1028 last_item = item;
1029 }
1030
1031 if (last_item != NULL) {
1032 last_item->next_in_set = first_item;
1033 }
1034 }
1035
1036 static SSHPacketHandler get_handler(PTInstVar pvar, int message)
1037 {
1038 SSHPacketHandlerItem FAR *cur_item =
1039 pvar->ssh_state.packet_handlers[message];
1040
1041 if (cur_item == NULL) {
1042 return NULL;
1043 } else {
1044 return cur_item->handler;
1045 }
1046 }
1047
1048 /* Called only by SSH_handle_packet */
1049 static void deque_handlers(PTInstVar pvar, int message)
1050 {
1051 SSHPacketHandlerItem FAR *cur_item =
1052 pvar->ssh_state.packet_handlers[message];
1053 SSHPacketHandlerItem FAR *first_item_in_set = cur_item;
1054
1055 do {
1056 SSHPacketHandlerItem FAR *next_in_set = cur_item->next_in_set;
1057
1058 if (cur_item->active_for_message >= 0) {
1059 SSHPacketHandlerItem FAR *replacement =
1060 cur_item->next_for_message;
1061
1062 if (replacement == cur_item) {
1063 replacement = NULL;
1064 } else {
1065 replacement->active_for_message =
1066 cur_item->active_for_message;
1067 }
1068 pvar->ssh_state.packet_handlers[cur_item->active_for_message] =
1069 replacement;
1070 }
1071 cur_item->next_for_message->last_for_message =
1072 cur_item->last_for_message;
1073 cur_item->last_for_message->next_for_message =
1074 cur_item->next_for_message;
1075
1076 free(cur_item);
1077 cur_item = next_in_set;
1078 } while (cur_item != first_item_in_set);
1079 }
1080
1081 static void enque_handler(PTInstVar pvar, int message,
1082 SSHPacketHandler handler)
1083 {
1084 enque_handlers(pvar, 1, &message, &handler);
1085 }
1086
1087 static void chop_newlines(char FAR * buf)
1088 {
1089 int len = strlen(buf);
1090
1091 while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) {
1092 buf[len - 1] = 0;
1093 len--;
1094 }
1095 }
1096
1097 /********************/
1098 /* Message handlers */
1099 /********************/
1100
1101 static BOOL handle_forwarding_success(PTInstVar pvar)
1102 {
1103 return FALSE;
1104 }
1105
1106 static BOOL handle_forwarding_failure(PTInstVar pvar)
1107 {
1108 return FALSE;
1109 }
1110
1111 static void enque_forwarding_request_handlers(PTInstVar pvar)
1112 {
1113 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1114 static const SSHPacketHandler handlers[]
1115 = { handle_forwarding_success, handle_forwarding_failure };
1116
1117 enque_handlers(pvar, 2, msgs, handlers);
1118 }
1119
1120 static BOOL handle_auth_failure(PTInstVar pvar)
1121 {
1122 notify_verbose_message(pvar, "Authentication failed",
1123 LOG_LEVEL_VERBOSE);
1124
1125 // retry count������ (2005.7.15 yutaka)
1126 pvar->userauth_retry_count++;
1127
1128 AUTH_set_generic_mode(pvar);
1129 AUTH_advance_to_next_cred(pvar);
1130 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1131 try_send_credentials(pvar);
1132 return FALSE;
1133 }
1134
1135 static BOOL handle_rsa_auth_refused(PTInstVar pvar)
1136 {
1137 AUTH_destroy_cur_cred(pvar);
1138 return handle_auth_failure(pvar);
1139 }
1140
1141 static BOOL handle_TIS_challenge(PTInstVar pvar)
1142 {
1143 if (grab_payload(pvar, 4)) {
1144 int len = get_payload_uint32(pvar, 0);
1145
1146 if (grab_payload(pvar, len)) {
1147 notify_verbose_message(pvar, "Received TIS challenge",
1148 LOG_LEVEL_VERBOSE);
1149
1150 AUTH_set_TIS_mode(pvar, pvar->ssh_state.payload + 4, len);
1151 AUTH_advance_to_next_cred(pvar);
1152 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1153 try_send_credentials(pvar);
1154 }
1155 }
1156 return FALSE;
1157 }
1158
1159 static BOOL handle_auth_required(PTInstVar pvar)
1160 {
1161 notify_verbose_message(pvar, "Server requires authentication",
1162 LOG_LEVEL_VERBOSE);
1163
1164 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1165 try_send_credentials(pvar);
1166 /* the first AUTH_advance_to_next_cred is issued early by ttxssh.c */
1167
1168 return FALSE;
1169 }
1170
1171 static BOOL handle_ignore(PTInstVar pvar)
1172 {
1173 if (SSHv1(pvar)) {
1174 if (grab_payload(pvar, 4)
1175 && grab_payload(pvar, get_payload_uint32(pvar, 0))) {
1176 /* ignore it! but it must be decompressed */
1177 }
1178 }
1179 /*
1180 else {
1181 // ���b�Z�[�W�� SSH2_MSG_IGNORE ����������������
1182 // Cisco ���[�^���� (2006.11.28 maya)
1183 }
1184 */
1185 return TRUE;
1186 }
1187
1188 static BOOL handle_debug(PTInstVar pvar)
1189 {
1190 BOOL always_display;
1191 char FAR *description;
1192 int description_len;
1193 char buf[2048];
1194
1195 if (SSHv1(pvar)) {
1196 if (grab_payload(pvar, 4)
1197 && grab_payload(pvar, description_len =
1198 get_payload_uint32(pvar, 0))) {
1199 always_display = FALSE;
1200 description = pvar->ssh_state.payload + 4;
1201 description[description_len] = 0;
1202 } else {
1203 return TRUE;
1204 }
1205 } else {
1206 if (grab_payload(pvar, 5)
1207 && grab_payload(pvar,
1208 (description_len =
1209 get_payload_uint32(pvar, 1)) + 4)
1210 && grab_payload(pvar,
1211 get_payload_uint32(pvar,
1212 5 + description_len))) {
1213 always_display = pvar->ssh_state.payload[0] != 0;
1214 description = pvar->ssh_state.payload + 5;
1215 description[description_len] = 0;
1216 } else {
1217 return TRUE;
1218 }
1219 }
1220
1221 chop_newlines(description);
1222 _snprintf(buf, sizeof(buf), "DEBUG message from server: %s",
1223 description);
1224 buf[sizeof(buf) - 1] = 0;
1225 if (always_display) {
1226 notify_nonfatal_error(pvar, buf);
1227 } else {
1228 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
1229 }
1230 return TRUE;
1231 }
1232
1233 static BOOL handle_disconnect(PTInstVar pvar)
1234 {
1235 int reason_code;
1236 char FAR *description;
1237 int description_len;
1238 char buf[2048];
1239 char FAR *explanation = "";
1240 #ifdef I18N
1241 char uimsg[MAX_UIMSG];
1242 #endif
1243
1244 if (SSHv1(pvar)) {
1245 if (grab_payload(pvar, 4)
1246 && grab_payload(pvar, description_len =
1247 get_payload_uint32(pvar, 0))) {
1248 reason_code = -1;
1249 description = pvar->ssh_state.payload + 4;
1250 description[description_len] = 0;
1251 } else {
1252 return TRUE;
1253 }
1254 } else {
1255 if (grab_payload(pvar, 8)
1256 && grab_payload(pvar,
1257 (description_len =
1258 get_payload_uint32(pvar, 4)) + 4)
1259 && grab_payload(pvar,
1260 get_payload_uint32(pvar,
1261 8 + description_len))) {
1262 reason_code = get_payload_uint32(pvar, 0);
1263 description = pvar->ssh_state.payload + 8;
1264 description[description_len] = 0;
1265 } else {
1266 return TRUE;
1267 }
1268 }
1269
1270 chop_newlines(description);
1271 if (description[0] == 0) {
1272 description = NULL;
1273 }
1274
1275 if (get_handler(pvar, SSH_SMSG_FAILURE) == handle_forwarding_failure) {
1276 #ifdef I18N
1277 strcpy(pvar->ts->UIMsg, "\nIt may have disconnected because it was unable to forward a port you requested to be forwarded from the server.\n"
1278 "This often happens when someone is already forwarding that port from the server.");
1279 UTIL_get_lang_msg("MSG_SSH_UNABLE_FWD_ERROR", pvar);
1280 strcpy(uimsg, pvar->ts->UIMsg);
1281 explanation = uimsg;
1282 #else
1283 explanation =
1284 "\nIt may have disconnected because it was unable to forward a port you requested to be forwarded from the server.\n"
1285 "This often happens when someone is already forwarding that port from the server.";
1286 #endif
1287 }
1288
1289 if (description != NULL) {
1290 #ifdef I18N
1291 strcpy(pvar->ts->UIMsg, "Server disconnected with message '%s'.%s");
1292 UTIL_get_lang_msg("MSG_SSH_SERVER_DISCON_ERROR", pvar);
1293 _snprintf(buf, sizeof(buf),
1294 pvar->ts->UIMsg, description,
1295 explanation);
1296 #else
1297 _snprintf(buf, sizeof(buf),
1298 "Server disconnected with message '%s'.%s", description,
1299 explanation);
1300 #endif
1301 } else {
1302 #ifdef I18N
1303 strcpy(pvar->ts->UIMsg, "Server disconnected (no reason given).%s");
1304 UTIL_get_lang_msg("MSG_SSH_SERVER_DISCON_NORES_ERROR", pvar);
1305 _snprintf(buf, sizeof(buf),
1306 pvar->ts->UIMsg, explanation);
1307 #else
1308 _snprintf(buf, sizeof(buf),
1309 "Server disconnected (no reason given).%s", explanation);
1310 #endif
1311 }
1312 buf[sizeof(buf) - 1] = 0;
1313 notify_fatal_error(pvar, buf);
1314
1315 return TRUE;
1316 }
1317
1318 static BOOL handle_unimplemented(PTInstVar pvar)
1319 {
1320 /* Should never receive this since we only send base 2.0 protocol messages */
1321 grab_payload(pvar, 4);
1322 return TRUE;
1323 }
1324
1325 static BOOL handle_crypt_success(PTInstVar pvar)
1326 {
1327 notify_verbose_message(pvar, "Secure mode successfully achieved",
1328 LOG_LEVEL_VERBOSE);
1329 return FALSE;
1330 }
1331
1332 static BOOL handle_noauth_success(PTInstVar pvar)
1333 {
1334 notify_verbose_message(pvar, "Server does not require authentication",
1335 LOG_LEVEL_VERBOSE);
1336 prep_compression(pvar);
1337 return FALSE;
1338 }
1339
1340 static BOOL handle_auth_success(PTInstVar pvar)
1341 {
1342 notify_verbose_message(pvar, "Authentication accepted",
1343 LOG_LEVEL_VERBOSE);
1344 prep_compression(pvar);
1345
1346 // �n�[�g�r�[�g�E�X���b�h���J�n (2004.12.11 yutaka)
1347 start_ssh_heartbeat_thread(pvar);
1348
1349 return FALSE;
1350 }
1351
1352 static BOOL handle_server_public_key(PTInstVar pvar)
1353 {
1354 int server_key_public_exponent_len;
1355 int server_key_public_modulus_pos;
1356 int server_key_public_modulus_len;
1357 int host_key_bits_pos;
1358 int host_key_public_exponent_len;
1359 int host_key_public_modulus_pos;
1360 int host_key_public_modulus_len;
1361 int protocol_flags_pos;
1362 int supported_ciphers;
1363 char FAR *inmsg;
1364 Key hostkey;
1365
1366 if (!grab_payload(pvar, 14))
1367 return FALSE;
1368 server_key_public_exponent_len = get_mpint_len(pvar, 12);
1369
1370 if (!grab_payload(pvar, server_key_public_exponent_len + 2))
1371 return FALSE;
1372 server_key_public_modulus_pos = 14 + server_key_public_exponent_len;
1373 server_key_public_modulus_len =
1374 get_mpint_len(pvar, server_key_public_modulus_pos);
1375
1376 if (!grab_payload(pvar, server_key_public_modulus_len + 6))
1377 return FALSE;
1378 host_key_bits_pos =
1379 server_key_public_modulus_pos + 2 + server_key_public_modulus_len;
1380 host_key_public_exponent_len =
1381 get_mpint_len(pvar, host_key_bits_pos + 4);
1382
1383 if (!grab_payload(pvar, host_key_public_exponent_len + 2))
1384 return FALSE;
1385 host_key_public_modulus_pos =
1386 host_key_bits_pos + 6 + host_key_public_exponent_len;
1387 host_key_public_modulus_len =
1388 get_mpint_len(pvar, host_key_public_modulus_pos);
1389
1390 if (!grab_payload(pvar, host_key_public_modulus_len + 12))
1391 return FALSE;
1392 protocol_flags_pos =
1393 host_key_public_modulus_pos + 2 + host_key_public_modulus_len;
1394
1395 inmsg = pvar->ssh_state.payload;
1396
1397 CRYPT_set_server_cookie(pvar, inmsg);
1398 if (!CRYPT_set_server_RSA_key
1399 (pvar, get_uint32(inmsg + 8), pvar->ssh_state.payload + 12,
1400 inmsg + server_key_public_modulus_pos))
1401 return FALSE;
1402 if (!CRYPT_set_host_RSA_key
1403 (pvar, get_uint32(inmsg + host_key_bits_pos),
1404 inmsg + host_key_bits_pos + 4,
1405 inmsg + host_key_public_modulus_pos))
1406 return FALSE;
1407 pvar->ssh_state.server_protocol_flags =
1408 get_uint32(inmsg + protocol_flags_pos);
1409
1410 supported_ciphers = get_uint32(inmsg + protocol_flags_pos + 4);
1411 if (!CRYPT_set_supported_ciphers
1412 (pvar, supported_ciphers, supported_ciphers))
1413 return FALSE;
1414 if (!AUTH_set_supported_auth_types
1415 (pvar, get_uint32(inmsg + protocol_flags_pos + 8)))
1416 return FALSE;
1417
1418 /* this must be the LAST THING in this function, since it can cause
1419 host_is_OK to be called. */
1420 hostkey.type = KEY_RSA1;
1421 hostkey.bits = get_uint32(inmsg + host_key_bits_pos);
1422 hostkey.exp = inmsg + host_key_bits_pos + 4;
1423 hostkey.mod = inmsg + host_key_public_modulus_pos;
1424 HOSTS_check_host_key(pvar, pvar->ssh_state.hostname, &hostkey);
1425
1426 return FALSE;
1427 }
1428
1429 /*
1430 The ID must have already been found to start with "SSH-". It must
1431 be null-terminated.
1432 */
1433 static BOOL parse_protocol_ID(PTInstVar pvar, char FAR * ID)
1434 {
1435 char FAR *str;
1436
1437 for (str = ID + 4; *str >= '0' && *str <= '9'; str++) {
1438 }
1439
1440 if (*str != '.') {
1441 return FALSE;
1442 }
1443
1444 pvar->protocol_major = atoi(ID + 4);
1445 pvar->protocol_minor = atoi(str + 1);
1446
1447 // for SSH2(yutaka)
1448 // 1.99����SSH2�����������s��
1449 if (pvar->protocol_major == 1 && pvar->protocol_minor == 99) {
1450 // ���[�U�� SSH2 ���I������������������
1451 if (pvar->settings.ssh_protocol_version == 2) {
1452 pvar->protocol_major = 2;
1453 pvar->protocol_minor = 0;
1454 }
1455
1456 }
1457
1458 for (str = str + 1; *str >= '0' && *str <= '9'; str++) {
1459 }
1460
1461 return *str == '-';
1462 }
1463
1464 /*
1465 On entry, the pvar->protocol_xxx fields hold the server's advertised
1466 protocol number. We replace the fields with the protocol number we will
1467 actually use, or return FALSE if there is no usable protocol version.
1468 */
1469 static BOOL negotiate_protocol(PTInstVar pvar)
1470 {
1471 switch (pvar->protocol_major) {
1472 case 1:
1473 if (pvar->protocol_minor > 5) {
1474 pvar->protocol_minor = 5;
1475 }
1476
1477 return TRUE;
1478
1479 // for SSH2(yutaka)
1480 case 2:
1481 return TRUE; // SSH2 support
1482
1483 default:
1484 return FALSE;
1485 }
1486 }
1487
1488 static void init_protocol(PTInstVar pvar)
1489 {
1490 CRYPT_initialize_random_numbers(pvar);
1491
1492 // known_hosts�t�@�C�������z�X�g���J������������������
1493 HOSTS_prefetch_host_key(pvar, pvar->ssh_state.hostname);
1494
1495 /* while we wait for a response from the server... */
1496
1497 if (SSHv1(pvar)) {
1498 enque_handler(pvar, SSH_MSG_DISCONNECT, handle_disconnect);
1499 enque_handler(pvar, SSH_MSG_IGNORE, handle_ignore);
1500 enque_handler(pvar, SSH_MSG_DEBUG, handle_debug);
1501 enque_handler(pvar, SSH_SMSG_PUBLIC_KEY, handle_server_public_key);
1502
1503 } else { // for SSH2(yutaka)
1504 enque_handler(pvar, SSH2_MSG_DISCONNECT, handle_disconnect);
1505 enque_handler(pvar, SSH2_MSG_IGNORE, handle_ignore);
1506 enque_handler(pvar, SSH2_MSG_DEBUG, handle_debug);
1507 enque_handler(pvar, SSH2_MSG_KEXINIT, handle_SSH2_kexinit);
1508 enque_handler(pvar, SSH2_MSG_KEXDH_INIT, handle_unimplemented);
1509 enque_handler(pvar, SSH2_MSG_KEXDH_REPLY, handle_SSH2_dh_common_reply);
1510 enque_handler(pvar, SSH2_MSG_KEX_DH_GEX_REPLY, handle_SSH2_dh_gex_reply);
1511 enque_handler(pvar, SSH2_MSG_NEWKEYS, handle_SSH2_newkeys);
1512 enque_handler(pvar, SSH2_MSG_SERVICE_ACCEPT, handle_SSH2_authrequest);
1513 enque_handler(pvar, SSH2_MSG_USERAUTH_SUCCESS, handle_SSH2_userauth_success);
1514 enque_handler(pvar, SSH2_MSG_USERAUTH_FAILURE, handle_SSH2_userauth_failure);
1515 enque_handler(pvar, SSH2_MSG_USERAUTH_BANNER, handle_SSH2_userauth_banner);
1516 enque_handler(pvar, SSH2_MSG_USERAUTH_INFO_REQUEST, handle_SSH2_userauth_inforeq);
1517
1518 enque_handler(pvar, SSH2_MSG_UNIMPLEMENTED, handle_unimplemented);
1519
1520 // ���[�U�F�������f�B�X�p�b�`���[�`��
1521 enque_handler(pvar, SSH2_MSG_CHANNEL_CLOSE, handle_SSH2_channel_close);
1522 enque_handler(pvar, SSH2_MSG_CHANNEL_DATA, handle_SSH2_channel_data);
1523 enque_handler(pvar, SSH2_MSG_CHANNEL_EOF, handle_SSH2_channel_eof);
1524 enque_handler(pvar, SSH2_MSG_CHANNEL_EXTENDED_DATA, handle_SSH2_channel_extended_data);
1525 enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN, handle_SSH2_channel_open);
1526 enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, handle_SSH2_open_confirm);
1527 enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN_FAILURE, handle_SSH2_open_failure);
1528 enque_handler(pvar, SSH2_MSG_CHANNEL_REQUEST, handle_SSH2_channel_request);
1529 enque_handler(pvar, SSH2_MSG_CHANNEL_WINDOW_ADJUST, handle_SSH2_window_adjust);
1530 enque_handler(pvar, SSH2_MSG_CHANNEL_SUCCESS, handle_SSH2_channel_success);
1531 // enque_handler(pvar, SSH2_MSG_GLOBAL_REQUEST, handle_unimplemented);
1532 enque_handler(pvar, SSH2_MSG_REQUEST_FAILURE, handle_SSH2_request_failure);
1533 enque_handler(pvar, SSH2_MSG_REQUEST_SUCCESS, handle_SSH2_request_success);
1534
1535 }
1536 }
1537
1538 BOOL SSH_handle_server_ID(PTInstVar pvar, char FAR * ID, int ID_len)
1539 {
1540 static const char prefix[] = "Received server prologue string: ";
1541
1542 // initialize SSH2 memory dump (2005.3.7 yutaka)
1543 init_memdump();
1544 push_memdump("pure server ID", "start protocol version exchange", ID, ID_len);
1545
1546 if (ID_len <= 0) {
1547 return FALSE;
1548 } else {
1549 char FAR *buf = (char FAR *) malloc(ID_len + NUM_ELEM(prefix));
1550
1551 strcpy(buf, prefix);
1552 strncpy(buf + NUM_ELEM(prefix) - 1, ID, ID_len);
1553 buf[NUM_ELEM(prefix) + ID_len - 1] = 0;
1554 chop_newlines(buf);
1555
1556 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
1557
1558 free(buf);
1559
1560
1561 // ���������R�s�[������ (2005.3.9 yutaka)
1562 #if 0
1563 // for calculate SSH2 hash
1564 // �T�[�o�o�[�W�����������i���s���������������j
1565 if (ID_len >= sizeof(pvar->server_version_string))
1566 return FALSE;
1567 strncpy(pvar->server_version_string, ID, ID_len);
1568 #endif
1569
1570
1571 if (ID[ID_len - 1] != '\n') {
1572 pvar->ssh_state.status_flags |= STATUS_IN_PARTIAL_ID_STRING;
1573 return FALSE;
1574 } else
1575 if ((pvar->ssh_state.
1576 status_flags & STATUS_IN_PARTIAL_ID_STRING) != 0) {
1577 pvar->ssh_state.status_flags &= ~STATUS_IN_PARTIAL_ID_STRING;
1578 return FALSE;
1579 } else if (strncmp(ID, "SSH-", 4) != 0) {
1580 return FALSE;
1581 } else {
1582 ID[ID_len - 1] = 0;
1583
1584 if (ID_len > 1 && ID[ID_len - 2] == '\r') {
1585 ID[ID_len - 2] = 0;
1586 }
1587
1588 pvar->ssh_state.server_ID = _strdup(ID);
1589
1590 if (!parse_protocol_ID(pvar, ID) || !negotiate_protocol(pvar)) {
1591 #ifdef I18N
1592 strcpy(pvar->ts->UIMsg, "This program does not understand the server's version of the protocol.");
1593 UTIL_get_lang_msg("MSG_SSH_VERSION_ERROR", pvar);
1594 notify_fatal_error(pvar, pvar->ts->UIMsg);
1595 #else
1596 notify_fatal_error(pvar,
1597 "This program does not understand the server's version of the protocol.");
1598 #endif
1599 } else {
1600 char TTSSH_ID[1024];
1601 int TTSSH_ID_len;
1602 int a, b, c, d;
1603
1604 // �������g���o�[�W�������������� (2005.3.3 yutaka)
1605 get_file_version("ttxssh.dll", &a, &b, &c, &d);
1606
1607 _snprintf(TTSSH_ID, sizeof(TTSSH_ID),
1608 "SSH-%d.%d-TTSSH/%d.%d Win32\n",
1609 pvar->protocol_major, pvar->protocol_minor, a, b);
1610 TTSSH_ID_len = strlen(TTSSH_ID);
1611
1612 // for SSH2(yutaka)
1613 // �N���C�A���g�o�[�W�����������i���s���������������j
1614 strncpy(pvar->client_version_string, TTSSH_ID, TTSSH_ID_len);
1615
1616 // �T�[�o�o�[�W�����������i���s���������������j(2005.3.9 yutaka)
1617 _snprintf(pvar->server_version_string, sizeof(pvar->server_version_string), "%s", pvar->ssh_state.server_ID);
1618
1619 if ((pvar->Psend) (pvar->socket, TTSSH_ID, TTSSH_ID_len,
1620 0) != TTSSH_ID_len) {
1621 #ifdef I18N
1622 strcpy(pvar->ts->UIMsg, "An error occurred while sending the SSH ID string.\n"
1623 "The connection will close.");
1624 UTIL_get_lang_msg("MSG_SSH_SEND_ID_ERROR", pvar);
1625 notify_fatal_error(pvar, pvar->ts->UIMsg);
1626 #else
1627 notify_fatal_error(pvar,
1628 "An error occurred while sending the SSH ID string.\n"
1629 "The connection will close.");
1630 #endif
1631 } else {
1632 // ���s�R�[�h������ (2004.8.4 yutaka)
1633 pvar->client_version_string[--TTSSH_ID_len] = 0;
1634
1635 push_memdump("server ID", NULL, pvar->server_version_string, strlen(pvar->server_version_string));
1636 push_memdump("client ID", NULL, pvar->client_version_string, strlen(pvar->client_version_string));
1637
1638 // SSH�n���h�����o�^���s��
1639 init_protocol(pvar);
1640
1641 SSH2_dispatch_init(1);
1642 SSH2_dispatch_add_message(SSH2_MSG_KEXINIT);
1643 SSH2_dispatch_add_message(SSH2_MSG_IGNORE); // XXX: Tru64 UNIX workaround (2005.3.3 yutaka)
1644 }
1645 }
1646
1647 return TRUE;
1648 }
1649 }
1650 }
1651
1652 static BOOL handle_exit(PTInstVar pvar)
1653 {
1654 if (grab_payload(pvar, 4)) {
1655 begin_send_packet(pvar, SSH_CMSG_EXIT_CONFIRMATION, 0);
1656 finish_send_packet(pvar);
1657 notify_closed_connection(pvar);
1658 }
1659 return TRUE;
1660 }
1661
1662 static BOOL handle_data(PTInstVar pvar)
1663 {
1664 if (grab_payload_limited(pvar, 4)) {
1665 pvar->ssh_state.payload_datalen = get_payload_uint32(pvar, 0);
1666 pvar->ssh_state.payload_datastart = 4;
1667 }
1668 return TRUE;
1669 }
1670
1671 static BOOL handle_channel_open(PTInstVar pvar)
1672 {
1673 int host_len;
1674 int originator_len;
1675
1676 if ((pvar->ssh_state.
1677 server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
1678 if (grab_payload(pvar, 8)
1679 && grab_payload(pvar,
1680 8 + (host_len = get_payload_uint32(pvar, 4)))
1681 && grab_payload(pvar, originator_len =
1682 get_payload_uint32(pvar, host_len + 12))) {
1683 int local_port = get_payload_uint32(pvar, 8 + host_len);
1684
1685 pvar->ssh_state.payload[8 + host_len] = 0;
1686 FWD_open(pvar, get_payload_uint32(pvar, 0),
1687 pvar->ssh_state.payload + 8, local_port,
1688 pvar->ssh_state.payload + 16 + host_len,
1689 originator_len,
1690 NULL);
1691 }
1692 } else {
1693 if (grab_payload(pvar, 8)
1694 && grab_payload(pvar,
1695 4 + (host_len =
1696 get_payload_uint32(pvar, 4)))) {
1697 int local_port = get_payload_uint32(pvar, 8 + host_len);
1698
1699 pvar->ssh_state.payload[8 + host_len] = 0;
1700 FWD_open(pvar, get_payload_uint32(pvar, 0),
1701 pvar->ssh_state.payload + 8, local_port, NULL, 0,
1702 NULL);
1703 }
1704 }
1705
1706 return TRUE;
1707 }
1708
1709 static BOOL handle_X11_channel_open(PTInstVar pvar)
1710 {
1711 int originator_len;
1712
1713 if ((pvar->ssh_state.
1714 server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
1715 if (grab_payload(pvar, 8)
1716 && grab_payload(pvar, originator_len =
1717 get_payload_uint32(pvar, 4))) {
1718 FWD_X11_open(pvar, get_payload_uint32(pvar, 0),
1719 pvar->ssh_state.payload + 8, originator_len, NULL);
1720 }
1721 } else {
1722 if (grab_payload(pvar, 4)) {
1723 FWD_X11_open(pvar, get_payload_uint32(pvar, 0), NULL, 0, NULL);
1724 }
1725 }
1726
1727 return TRUE;
1728 }
1729
1730 static BOOL handle_channel_open_confirmation(PTInstVar pvar)
1731 {
1732 if (grab_payload(pvar, 8)) {
1733 FWD_confirmed_open(pvar, get_payload_uint32(pvar, 0),
1734 get_payload_uint32(pvar, 4));
1735 }
1736 return FALSE;
1737 }
1738
1739 static BOOL handle_channel_open_failure(PTInstVar pvar)
1740 {
1741 if (grab_payload(pvar, 4)) {
1742 FWD_failed_open(pvar, get_payload_uint32(pvar, 0));
1743 }
1744 return FALSE;
1745 }
1746
1747 static BOOL handle_channel_data(PTInstVar pvar)
1748 {
1749 int len;
1750
1751 if (grab_payload(pvar, 8)
1752 && grab_payload(pvar, len = get_payload_uint32(pvar, 4))) {
1753 FWD_received_data(pvar, get_payload_uint32(pvar, 0),
1754 pvar->ssh_state.payload + 8, len);
1755 }
1756 return TRUE;
1757 }
1758
1759 static BOOL handle_channel_input_eof(PTInstVar pvar)
1760 {
1761 if (grab_payload(pvar, 4)) {
1762 FWD_channel_input_eof(pvar, get_payload_uint32(pvar, 0));
1763 }
1764 return TRUE;
1765 }
1766
1767 static BOOL handle_channel_output_eof(PTInstVar pvar)
1768 {
1769 if (grab_payload(pvar, 4)) {
1770 FWD_channel_output_eof(pvar, get_payload_uint32(pvar, 0));
1771 }
1772 return TRUE;
1773 }
1774
1775
1776
1777 // �n���h�����O�������b�Z�[�W����������
1778
1779 #define HANDLE_MESSAGE_MAX 30
1780 static unsigned char handle_messages[HANDLE_MESSAGE_MAX];
1781 static int handle_message_count = 0;
1782 static int handle_message_stage = 0;
1783
1784 void SSH2_dispatch_init(int stage)
1785 {
1786 handle_message_count = 0;
1787 handle_message_stage = stage;
1788 }
1789
1790 int SSH2_dispatch_enabled_check(unsigned char message)
1791 {
1792 int i;
1793
1794 for (i = 0 ; i < handle_message_count ; i++) {
1795 if (handle_messages[i] == message)
1796 return 1;
1797 }
1798 return 0;
1799 }
1800
1801 void SSH2_dispatch_add_message(unsigned char message)
1802 {
1803
1804 if (handle_message_count >= HANDLE_MESSAGE_MAX) {
1805 // TODO: error check
1806 return;
1807 }
1808
1809 handle_messages[handle_message_count++] = message;
1810 }
1811
1812 void SSH2_dispatch_add_range_message(unsigned char begin, unsigned char end)
1813 {
1814 unsigned char c;
1815
1816 for (c = begin ; c <= end ; c++) {
1817 SSH2_dispatch_add_message(c);
1818 }
1819 }
1820
1821
1822 void SSH_handle_packet(PTInstVar pvar, char FAR * data, int len,
1823 int padding)
1824 {
1825 unsigned char message = prep_packet(pvar, data, len, padding);
1826
1827
1828 #ifdef SSH2_DEBUG
1829 // for SSH2(yutaka)
1830 if (SSHv2(pvar)) {
1831 if (pvar->key_done) {
1832 message = message;
1833 }
1834
1835 if (pvar->userauth_success) {
1836 message = message;
1837 }
1838
1839 if (pvar->rekeying) {
1840 message = message;
1841 }
1842 }
1843 #endif
1844
1845 // SSH�����b�Z�[�W�^�C�v���`�F�b�N
1846 if (message != SSH_MSG_NONE) {
1847 // ���b�Z�[�W�^�C�v���������n���h�����N��
1848 SSHPacketHandler handler = get_handler(pvar, message);
1849
1850 // for SSH2(yutaka)
1851 if (SSHv2(pvar)) {
1852 // �z���O�����b�Z�[�W�^�C�v�������������A�{�[�g�������B
1853 if (!SSH2_dispatch_enabled_check(message) || handler == NULL) {
1854 char buf[1024];
1855
1856 #ifdef I18N
1857 strcpy(pvar->ts->UIMsg, "Unexpected SSH2 message(%d) on current stage(%d)");
1858 UTIL_get_lang_msg("MSG_SSH_UNEXP_MSG2_ERROR", pvar);
1859 _snprintf(buf, sizeof(buf),
1860 pvar->ts->UIMsg, message, handle_message_stage);
1861 #else
1862 _snprintf(buf, sizeof(buf),
1863 "Unexpected SSH2 message(%d) on current stage(%d)", message, handle_message_stage);
1864 #endif
1865 notify_fatal_error(pvar, buf);
1866 // abort
1867 }
1868 }
1869
1870 if (handler == NULL) {
1871 if (SSHv1(pvar)) {
1872 char buf[1024];
1873
1874 #ifdef I18N
1875 strcpy(pvar->ts->UIMsg, "Unexpected packet type received: %d");
1876 UTIL_get_lang_msg("MSG_SSH_UNEXP_MSG_ERROR", pvar);
1877 _snprintf(buf, sizeof(buf),
1878 pvar->ts->UIMsg, message, handle_message_stage);
1879 #else
1880 _snprintf(buf, sizeof(buf),
1881 "Unexpected packet type received: %d", message);
1882 #endif
1883 buf[sizeof(buf) - 1] = 0;
1884 notify_fatal_error(pvar, buf);
1885 } else {
1886 unsigned char FAR *outmsg =
1887 begin_send_packet(pvar, SSH2_MSG_UNIMPLEMENTED, 4);
1888
1889 set_uint32(outmsg,
1890 pvar->ssh_state.receiver_sequence_number - 1);
1891 finish_send_packet(pvar);
1892 /* XXX need to decompress incoming packet, but how? */
1893 }
1894 } else {
1895 if (!handler(pvar)) {
1896 deque_handlers(pvar, message);
1897 }
1898 }
1899 }
1900 }
1901
1902 static BOOL handle_pty_success(PTInstVar pvar)
1903 {
1904 FWD_enter_interactive_mode(pvar);
1905 enque_handler(pvar, SSH_SMSG_EXITSTATUS, handle_exit);
1906 enque_handler(pvar, SSH_SMSG_STDOUT_DATA, handle_data);
1907 enque_handler(pvar, SSH_SMSG_STDERR_DATA, handle_data);
1908 enque_handler(pvar, SSH_MSG_CHANNEL_DATA, handle_channel_data);
1909 enque_handler(pvar, SSH_MSG_CHANNEL_INPUT_EOF,
1910 handle_channel_input_eof);
1911 enque_handler(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED,
1912 handle_channel_output_eof);
1913 enque_handler(pvar, SSH_MSG_PORT_OPEN, handle_channel_open);
1914 enque_handler(pvar, SSH_SMSG_X11_OPEN, handle_X11_channel_open);
1915 return FALSE;
1916 }
1917
1918 static BOOL handle_pty_failure(PTInstVar pvar)
1919 {
1920 #ifdef I18N
1921 strcpy(pvar->ts->UIMsg, "The server cannot allocate a pseudo-terminal. "
1922 "You may encounter some problems with the terminal.");
1923 UTIL_get_lang_msg("MSG_SSH_ALLOC_TERMINAL_ERROR", pvar);
1924 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1925 #else
1926 notify_nonfatal_error(pvar,
1927 "The server cannot allocate a pseudo-terminal. "
1928 "You may encounter some problems with the terminal.");
1929 #endif
1930 return handle_pty_success(pvar);
1931 }
1932
1933 static void prep_pty(PTInstVar pvar)
1934 {
1935 int len = strlen(pvar->ts->TermType);
1936 unsigned char FAR *outmsg =
1937 begin_send_packet(pvar, SSH_CMSG_REQUEST_PTY,
1938 4 + len + 16 + sizeof(ssh_ttymodes));
1939 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1940 static const SSHPacketHandler handlers[]
1941 = { handle_pty_success, handle_pty_failure };
1942
1943 set_uint32(outmsg, len);
1944 memcpy(outmsg + 4, pvar->ts->TermType, len);
1945 set_uint32(outmsg + 4 + len, pvar->ssh_state.win_rows);
1946 set_uint32(outmsg + 4 + len + 4, pvar->ssh_state.win_cols);
1947 set_uint32(outmsg + 4 + len + 8, 0);
1948 set_uint32(outmsg + 4 + len + 12, 0);
1949 memcpy(outmsg + 4 + len + 16, ssh_ttymodes, sizeof(ssh_ttymodes));
1950 finish_send_packet(pvar);
1951
1952 enque_handlers(pvar, 2, msgs, handlers);
1953
1954 begin_send_packet(pvar, SSH_CMSG_EXEC_SHELL, 0);
1955 finish_send_packet(pvar);
1956 }
1957
1958 static void prep_forwarding(PTInstVar pvar)
1959 {
1960 FWD_prep_forwarding(pvar);
1961 prep_pty(pvar);
1962 }
1963
1964
1965 //
1966 //
1967 // (2005.7.10 yutaka)
1968 static void enable_send_compression(PTInstVar pvar)
1969 {
1970 static int initialize = 0;
1971
1972 if (initialize) {
1973 deflateEnd(&pvar->ssh_state.compress_stream);
1974 }
1975 initialize = 1;
1976
1977 pvar->ssh_state.compress_stream.zalloc = NULL;
1978 pvar->ssh_state.compress_stream.zfree = NULL;
1979 pvar->ssh_state.compress_stream.opaque = NULL;
1980 if (deflateInit
1981 (&pvar->ssh_state.compress_stream,
1982 pvar->ssh_state.compression_level) != Z_OK) {
1983 #ifdef I18N
1984 strcpy(pvar->ts->UIMsg, "An error occurred while setting up compression.\n"
1985 "The connection will close.");
1986 UTIL_get_lang_msg("MSG_SSH_SETUP_COMP_ERROR", pvar);
1987 notify_fatal_error(pvar, pvar->ts->UIMsg);
1988 #else
1989 notify_fatal_error(pvar,
1990 "An error occurred while setting up compression.\n"
1991 "The connection will close.");
1992 #endif
1993 return;
1994 } else {
1995 // SSH2�������k�E�W�J������SSH1���������s�������A���L�t���O���������������B(2005.7.9 yutaka)
1996 if (SSHv2(pvar)) {
1997 pvar->ssh_state.compressing = FALSE;
1998 } else {
1999 pvar->ssh_state.compressing = TRUE;
2000 }
2001 }
2002 }
2003
2004 static void enable_recv_compression(PTInstVar pvar)
2005 {
2006 static int initialize = 0;
2007
2008 if (initialize) {
2009 deflateEnd(&pvar->ssh_state.decompress_stream);
2010 }
2011 initialize = 1;
2012
2013 pvar->ssh_state.decompress_stream.zalloc = NULL;
2014 pvar->ssh_state.decompress_stream.zfree = NULL;
2015 pvar->ssh_state.decompress_stream.opaque = NULL;
2016 if (inflateInit(&pvar->ssh_state.decompress_stream) != Z_OK) {
2017 deflateEnd(&pvar->ssh_state.compress_stream);
2018 #ifdef I18N
2019 strcpy(pvar->ts->UIMsg, "An error occurred while setting up compression.\n"
2020 "The connection will close.");
2021 UTIL_get_lang_msg("MSG_SSH_SETUP_COMP_ERROR", pvar);
2022 notify_fatal_error(pvar, pvar->ts->UIMsg);
2023 #else
2024 notify_fatal_error(pvar,
2025 "An error occurred while setting up compression.\n"
2026 "The connection will close.");
2027 #endif
2028 return;
2029 } else {
2030 // SSH2�������k�E�W�J������SSH1���������s�������A���L�t���O���������������B(2005.7.9 yutaka)
2031 if (SSHv2(pvar)) {
2032 pvar->ssh_state.decompressing = FALSE;
2033 } else {
2034 pvar->ssh_state.decompressing = TRUE;
2035 }
2036
2037 buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf,
2038 &pvar->ssh_state.postdecompress_inbuflen, 1000);
2039 }
2040 }
2041
2042 static void enable_compression(PTInstVar pvar)
2043 {
2044 enable_send_compression(pvar);
2045 enable_recv_compression(pvar);
2046
2047 // SSH2�������k�E�W�J������SSH1���������s�������A���L�t���O���������������B(2005.7.9 yutaka)
2048 if (SSHv2(pvar)) {
2049 pvar->ssh_state.compressing = FALSE;
2050 pvar->ssh_state.decompressing = FALSE;
2051 }
2052
2053 }
2054
2055 static BOOL handle_enable_compression(PTInstVar pvar)
2056 {
2057 enable_compression(pvar);
2058 prep_forwarding(pvar);
2059 return FALSE;
2060 }
2061
2062 static BOOL handle_disable_compression(PTInstVar pvar)
2063 {
2064 prep_forwarding(pvar);
2065 return FALSE;
2066 }
2067
2068 static void prep_compression(PTInstVar pvar)
2069 {
2070 if (pvar->session_settings.CompressionLevel > 0) {
2071 // added if statement (2005.7.10 yutaka)
2072 if (SSHv1(pvar)) {
2073 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
2074 static const SSHPacketHandler handlers[]
2075 = { handle_enable_compression, handle_disable_compression };
2076
2077 unsigned char FAR *outmsg =
2078 begin_send_packet(pvar, SSH_CMSG_REQUEST_COMPRESSION, 4);
2079
2080 set_uint32(outmsg, pvar->session_settings.CompressionLevel);
2081 finish_send_packet(pvar);
2082
2083 enque_handlers(pvar, 2, msgs, handlers);
2084 }
2085
2086 pvar->ssh_state.compression_level =
2087 pvar->session_settings.CompressionLevel;
2088
2089 } else {
2090 // added if statement (2005.7.10 yutaka)
2091 if (SSHv1(pvar)) {
2092 prep_forwarding(pvar);
2093 }
2094 }
2095 }
2096
2097 static void enque_simple_auth_handlers(PTInstVar pvar)
2098 {
2099 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
2100 static const SSHPacketHandler handlers[]
2101 = { handle_auth_success, handle_auth_failure };
2102
2103 enque_handlers(pvar, 2, msgs, handlers);
2104 }
2105
2106 static BOOL handle_rsa_challenge(PTInstVar pvar)
2107 {
2108 int challenge_bytes;
2109
2110 if (!grab_payload(pvar, 2)) {
2111 return FALSE;
2112 }
2113
2114 challenge_bytes = get_mpint_len(pvar, 0);
2115
2116 if (grab_payload(pvar, challenge_bytes)) {
2117 unsigned char FAR *outmsg =
2118 begin_send_packet(pvar, SSH_CMSG_AUTH_RSA_RESPONSE, 16);
2119
2120 if (CRYPT_generate_RSA_challenge_response
2121 (pvar, pvar->ssh_state.payload + 2, challenge_bytes, outmsg)) {
2122
2123 // �Z�b�V�������������p�X���[�h���g���������������A�����������\�[�X�������������B
2124 // socket close���������������������������������A���������������B(2005.4.8 yutaka)
2125 #if 0
2126 //AUTH_destroy_cur_cred(pvar);
2127 #endif
2128
2129 finish_send_packet(pvar);
2130
2131 enque_simple_auth_handlers(pvar);
2132 } else {
2133 #ifdef I18N
2134 strcpy(pvar->ts->UIMsg, "An error occurred while decrypting the RSA challenge.\n"
2135 "Perhaps the key file is corrupted.");
2136 UTIL_get_lang_msg("MSG_SSH_DECRYPT_RSA_ERROR", pvar);
2137 notify_fatal_error(pvar, pvar->ts->UIMsg);
2138 #else
2139 notify_fatal_error(pvar,
2140 "An error occurred while decrypting the RSA challenge.\n"
2141 "Perhaps the key file is corrupted.");
2142 #endif
2143 }
2144 }
2145
2146 return FALSE;
2147 }
2148
2149 #define OBFUSCATING_ROUND_TO 32
2150
2151 static int obfuscating_round_up(PTInstVar pvar, int size)
2152 {
2153 return (size + OBFUSCATING_ROUND_TO - 1) & ~(OBFUSCATING_ROUND_TO - 1);
2154 }
2155
2156 static void try_send_credentials(PTInstVar pvar)
2157 {
2158 if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_CREDENTIALS) == 0) {
2159 AUTHCred FAR *cred = AUTH_get_cur_cred(pvar);
2160 static const int RSA_msgs[] =
2161 { SSH_SMSG_AUTH_RSA_CHALLENGE, SSH_SMSG_FAILURE };
2162 static const SSHPacketHandler RSA_handlers[]
2163 = { handle_rsa_challenge, handle_rsa_auth_refused };
2164 static const int TIS_msgs[] =
2165 { SSH_SMSG_AUTH_TIS_CHALLENGE, SSH_SMSG_FAILURE };
2166 static const SSHPacketHandler TIS_handlers[]
2167 = { handle_TIS_challenge, handle_auth_failure };
2168
2169 // SSH2���������������������X�L�b�v
2170 if (SSHv2(pvar))
2171 goto skip_ssh2;
2172
2173 switch (cred->method) {
2174 case SSH_AUTH_NONE:
2175 return;
2176 case SSH_AUTH_PASSWORD:{
2177 int len = strlen(cred->password);
2178 // Round up password length to discourage traffic analysis
2179 int obfuscated_len = obfuscating_round_up(pvar, len);
2180 unsigned char FAR *outmsg =
2181 begin_send_packet(pvar, SSH_CMSG_AUTH_PASSWORD,
2182 4 + obfuscated_len);
2183
2184 notify_verbose_message(pvar,
2185 "Trying PASSWORD authentication...",
2186 LOG_LEVEL_VERBOSE);
2187
2188 set_uint32(outmsg, obfuscated_len);
2189 memcpy(outmsg + 4, cred->password, len);
2190 memset(outmsg + 4 + len, 0, obfuscated_len - len);
2191
2192 // �Z�b�V�������������p�X���[�h���g���������������A�����������\�[�X�������������B
2193 // socket close���������������������������������A���������������B(2005.4.8 yutaka)
2194 #if 0
2195 //AUTH_destroy_cur_cred(pvar);
2196 #endif
2197
2198 enque_simple_auth_handlers(pvar);
2199 break;
2200 }
2201 case SSH_AUTH_RHOSTS:{
2202 int len = strlen(cred->rhosts_client_user);
2203 unsigned char FAR *outmsg =
2204 begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS, 4 + len);
2205
2206 notify_verbose_message(pvar,
2207 "Trying RHOSTS authentication...",
2208 LOG_LEVEL_VERBOSE);
2209
2210 set_uint32(outmsg, len);
2211 memcpy(outmsg + 4, cred->rhosts_client_user, len);
2212 AUTH_destroy_cur_cred(pvar);
2213 enque_simple_auth_handlers(pvar);
2214 break;
2215 }
2216 case SSH_AUTH_RSA:{
2217 int len = BN_num_bytes(cred->key_pair->RSA_key->n);
2218 unsigned char FAR *outmsg =
2219 begin_send_packet(pvar, SSH_CMSG_AUTH_RSA, 2 + len);
2220
2221 notify_verbose_message(pvar,
2222 "Trying RSA authentication...",
2223 LOG_LEVEL_VERBOSE);
2224
2225 set_ushort16_MSBfirst(outmsg, len * 8);
2226 BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + 2);
2227 /* don't destroy the current credentials yet */
2228 enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
2229 break;
2230 }
2231 case SSH_AUTH_RHOSTS_RSA:{
2232 int mod_len = BN_num_bytes(cred->key_pair->RSA_key->n);
2233 int name_len = strlen(cred->rhosts_client_user);
2234 int exp_len = BN_num_bytes(cred->key_pair->RSA_key->e);
2235 int index;
2236 unsigned char FAR *outmsg =
2237 begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS_RSA,
2238 12 + mod_len + name_len + exp_len);
2239
2240 notify_verbose_message(pvar,
2241 "Trying RHOSTS+RSA authentication...",
2242 LOG_LEVEL_VERBOSE);
2243
2244 set_uint32(outmsg, name_len);
2245 memcpy(outmsg + 4, cred->rhosts_client_user, name_len);
2246 index = 4 + name_len;
2247
2248 set_uint32(outmsg + index, 8 * mod_len);
2249 set_ushort16_MSBfirst(outmsg + index + 4, 8 * exp_len);
2250 BN_bn2bin(cred->key_pair->RSA_key->e, outmsg + index + 6);
2251 index += 6 + exp_len;
2252
2253 set_ushort16_MSBfirst(outmsg + index, 8 * mod_len);
2254 BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + index + 2);
2255 /* don't destroy the current credentials yet */
2256 enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
2257 break;
2258 }
2259 case SSH_AUTH_TIS:{
2260 if (cred->password == NULL) {
2261 unsigned char FAR *outmsg =
2262 begin_send_packet(pvar, SSH_CMSG_AUTH_TIS, 0);
2263
2264 notify_verbose_message(pvar,
2265 "Trying TIS authentication...",
2266 LOG_LEVEL_VERBOSE);
2267 enque_handlers(pvar, 2, TIS_msgs, TIS_handlers);
2268 } else {
2269 int len = strlen(cred->password);
2270 int obfuscated_len = obfuscating_round_up(pvar, len);
2271 unsigned char FAR *outmsg =
2272 begin_send_packet(pvar, SSH_CMSG_AUTH_TIS_RESPONSE,
2273 4 + obfuscated_len);
2274
2275 notify_verbose_message(pvar, "Sending TIS response",
2276 LOG_LEVEL_VERBOSE);
2277
2278 set_uint32(outmsg, obfuscated_len);
2279 memcpy(outmsg + 4, cred->password, len);
2280 memset(outmsg + 4 + len, 0, obfuscated_len - len);
2281 enque_simple_auth_handlers(pvar);
2282 }
2283
2284 AUTH_destroy_cur_cred(pvar);
2285 break;
2286 }
2287 default:
2288 #ifdef I18N
2289 strcpy(pvar->ts->UIMsg, "Internal error: unsupported authentication method");
2290 UTIL_get_lang_msg("MSG_SSH_UNSUPPORT_AUTH_METHOD_ERROR", pvar);
2291 notify_fatal_error(pvar, pvar->ts->UIMsg);
2292 #else
2293 notify_fatal_error(pvar,
2294 "Internal error: unsupported authentication method");
2295 #endif
2296 return;
2297 }
2298
2299 finish_send_packet(pvar);
2300
2301 skip_ssh2:;
2302 destroy_packet_buf(pvar);
2303
2304 pvar->ssh_state.status_flags |= STATUS_DONT_SEND_CREDENTIALS;
2305 }
2306 }
2307
2308 static void try_send_user_name(PTInstVar pvar)
2309 {
2310 if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_USER_NAME) == 0) {
2311 char FAR *username = AUTH_get_user_name(pvar);
2312
2313 if (username != NULL) {
2314 int len = strlen(username);
2315 int obfuscated_len = obfuscating_round_up(pvar, len);
2316 unsigned char FAR *outmsg =
2317 begin_send_packet(pvar, SSH_CMSG_USER, 4 + obfuscated_len);
2318 char buf[1024] = "Sending user name: ";
2319 static const int msgs[] =
2320 { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
2321 static const SSHPacketHandler handlers[]
2322 = { handle_noauth_success, handle_auth_required };
2323
2324 set_uint32(outmsg, obfuscated_len);
2325 memcpy(outmsg + 4, username, len);
2326 memset(outmsg + 4 + len, 0, obfuscated_len - len);
2327 finish_send_packet(pvar);
2328
2329 pvar->ssh_state.status_flags |= STATUS_DONT_SEND_USER_NAME;
2330
2331 strncpy(buf + strlen(buf), username,
2332 sizeof(buf) - strlen(buf) - 2);
2333 buf[sizeof(buf) - 1] = 0;
2334 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
2335
2336 enque_handlers(pvar, 2, msgs, handlers);
2337 }
2338 }
2339 }
2340
2341 static void send_session_key(PTInstVar pvar)
2342 {
2343 int encrypted_session_key_len;
2344 unsigned char FAR *outmsg;
2345
2346 if (SSHv1(pvar)) {
2347 encrypted_session_key_len =
2348 CRYPT_get_encrypted_session_key_len(pvar);
2349 }
2350
2351 if (!CRYPT_choose_ciphers(pvar))
2352 return;
2353
2354 if (SSHv1(pvar)) {
2355 outmsg =
2356 begin_send_packet(pvar, SSH_CMSG_SESSION_KEY,
2357 15 + encrypted_session_key_len);
2358 outmsg[0] = (unsigned char) CRYPT_get_sender_cipher(pvar);
2359 memcpy(outmsg + 1, CRYPT_get_server_cookie(pvar), 8); /* antispoofing cookie */
2360 outmsg[9] = (unsigned char) (encrypted_session_key_len >> 5);
2361 outmsg[10] = (unsigned char) (encrypted_session_key_len << 3);
2362 if (!CRYPT_choose_session_key(pvar, outmsg + 11))
2363 return;
2364 set_uint32(outmsg + 11 + encrypted_session_key_len,
2365 SSH_PROTOFLAG_SCREEN_NUMBER |
2366 SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
2367 finish_send_packet(pvar);
2368 }
2369
2370 if (!CRYPT_start_encryption(pvar, 1, 1))
2371 return;
2372 notify_established_secure_connection(pvar);
2373
2374 if (SSHv1(pvar)) {
2375 enque_handler(pvar, SSH_SMSG_SUCCESS, handle_crypt_success);
2376 }
2377
2378 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_USER_NAME;
2379
2380 if (SSHv1(pvar)) {
2381 try_send_user_name(pvar);
2382 }
2383 }
2384
2385 /*************************
2386 END of message handlers
2387 ************************/
2388
2389 void SSH_init(PTInstVar pvar)
2390 {
2391 int i;
2392
2393 buf_create(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
2394 buf_create(&pvar->ssh_state.precompress_outbuf,
2395 &pvar->ssh_state.precompress_outbuflen);
2396 buf_create(&pvar->ssh_state.postdecompress_inbuf,
2397 &pvar->ssh_state.postdecompress_inbuflen);
2398 pvar->ssh_state.payload = NULL;
2399 pvar->ssh_state.compressing = FALSE;
2400 pvar->ssh_state.decompressing = FALSE;
2401 pvar->ssh_state.status_flags =
2402 STATUS_DONT_SEND_USER_NAME | STATUS_DONT_SEND_CREDENTIALS;
2403 pvar->ssh_state.payload_datalen = 0;
2404 pvar->ssh_state.hostname = NULL;
2405 pvar->ssh_state.server_ID = NULL;
2406 pvar->ssh_state.receiver_sequence_number = 0;
2407 pvar->ssh_state.sender_sequence_number = 0;
2408 for (i = 0; i < NUM_ELEM(pvar->ssh_state.packet_handlers); i++) {
2409 pvar->ssh_state.packet_handlers[i] = NULL;
2410 }
2411
2412 // for SSH2(yutaka)
2413 memset(pvar->ssh2_keys, 0, sizeof(pvar->ssh2_keys));
2414 pvar->userauth_success = 0;
2415 pvar->session_nego_status = 0;
2416 pvar->settings.ssh_protocol_version = 2; // SSH2(default)
2417 pvar->rekeying = 0;
2418 pvar->key_done = 0;
2419 pvar->ssh2_autologin = 0; // autologin disabled(default)
2420 pvar->ask4passwd = 0; // disabled(default) (2006.9.18 maya)
2421 pvar->userauth_retry_count = 0;
2422 pvar->decomp_buffer = NULL;
2423
2424 }
2425
2426 void SSH_open(PTInstVar pvar)
2427 {
2428 pvar->ssh_state.hostname = _strdup(pvar->ts->HostName);
2429 pvar->ssh_state.win_cols = pvar->ts->TerminalWidth;
2430 pvar->ssh_state.win_rows = pvar->ts->TerminalHeight;
2431 }
2432
2433 void SSH_notify_disconnecting(PTInstVar pvar, char FAR * reason)
2434 {
2435 if (SSHv1(pvar)) {
2436 int len = reason == NULL ? 0 : strlen(reason);
2437 unsigned char FAR *outmsg =
2438 begin_send_packet(pvar, SSH_MSG_DISCONNECT, len + 4);
2439
2440 set_uint32(outmsg, len);
2441 if (reason != NULL) {
2442 memcpy(outmsg + 4, reason, len);
2443 }
2444 finish_send_packet(pvar);
2445
2446 } else { // for SSH2(yutaka)
2447 buffer_t *msg;
2448 unsigned char *outmsg;
2449 int len;
2450 Channel_t *c;
2451
2452 c = ssh2_channel_lookup(pvar->shell_id);
2453 if (c == NULL)
2454 return;
2455
2456 // SSH2 server��channel close���`����
2457 msg = buffer_init();
2458 if (msg == NULL) {
2459 // TODO: error check
2460 return;
2461 }
2462 buffer_put_int(msg, c->remote_id);
2463
2464 len = buffer_len(msg);
2465 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_CLOSE, len);
2466 memcpy(outmsg, buffer_ptr(msg), len);
2467 finish_send_packet(pvar);
2468 buffer_free(msg);
2469
2470 }
2471
2472 }
2473
2474 void SSH_notify_host_OK(PTInstVar pvar)
2475 {
2476 if ((pvar->ssh_state.status_flags & STATUS_HOST_OK) == 0) {
2477 pvar->ssh_state.status_flags |= STATUS_HOST_OK;
2478 send_session_key(pvar);
2479 }
2480 }
2481
2482 void SSH_notify_win_size(PTInstVar pvar, int cols, int rows)
2483 {
2484 pvar->ssh_state.win_cols = cols;
2485 pvar->ssh_state.win_rows = rows;
2486
2487 if (SSHv1(pvar)) {
2488 if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) == handle_data) {
2489 unsigned char FAR *outmsg =
2490 begin_send_packet(pvar, SSH_CMSG_WINDOW_SIZE, 16);
2491
2492 set_uint32(outmsg, rows);
2493 set_uint32(outmsg + 4, cols);
2494 set_uint32(outmsg + 8, 0);
2495 set_uint32(outmsg + 12, 0);
2496 finish_send_packet(pvar);
2497 }
2498
2499 } else if (SSHv2(pvar)) { // �^�[�~�i���T�C�Y���X���m������ (2005.1.4 yutaka)
2500 // SSH2�����������`�F�b�N���s���B(2005.1.5 yutaka)
2501 buffer_t *msg;
2502 char *s;
2503 unsigned char *outmsg;
2504 int len;
2505 Channel_t *c;
2506
2507 c = ssh2_channel_lookup(pvar->shell_id);
2508 if (c == NULL)
2509 return;
2510
2511 msg = buffer_init();
2512 if (msg == NULL) {
2513 // TODO: error check
2514 return;
2515 }
2516 buffer_put_int(msg, c->remote_id);
2517 s = "window-change";
2518 buffer_put_string(msg, s, strlen(s));
2519 buffer_put_char(msg, 0); // wantconfirm
2520 buffer_put_int(msg, pvar->ssh_state.win_cols); // columns
2521 buffer_put_int(msg, pvar->ssh_state.win_rows); // lines
2522 buffer_put_int(msg, 480); // XXX:
2523 buffer_put_int(msg, 640); // XXX:
2524 len = buffer_len(msg);
2525 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len);
2526 memcpy(outmsg, buffer_ptr(msg), len);
2527 finish_send_packet(pvar);
2528 buffer_free(msg);
2529
2530 notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_REQUEST was sent at SSH_notify_win_size().", LOG_LEVEL_VERBOSE);
2531
2532 } else {
2533 // SSH�����������������������B
2534
2535 }
2536
2537 }
2538
2539 int SSH_get_min_packet_size(PTInstVar pvar)
2540 {
2541 if (SSHv1(pvar)) {
2542 return 12;
2543 } else {
2544 int block_size = CRYPT_get_decryption_block_size(pvar);
2545
2546 return max(16, block_size);
2547 }
2548 }
2549
2550 /* data is guaranteed to be at least SSH_get_min_packet_size bytes long
2551 at least 5 bytes must be decrypted */
2552 void SSH_predecrpyt_packet(PTInstVar pvar, char FAR * data)
2553 {
2554 if (SSHv2(pvar)) {
2555 CRYPT_decrypt(pvar, data, get_predecryption_amount(pvar));
2556 }
2557 }
2558
2559 int SSH_get_clear_MAC_size(PTInstVar pvar)
2560 {
2561 if (SSHv1(pvar)) {
2562 return 0;
2563 } else {
2564 return CRYPT_get_receiver_MAC_size(pvar);
2565 }
2566 }
2567
2568 void SSH_notify_user_name(PTInstVar pvar)
2569 {
2570 try_send_user_name(pvar);
2571 }
2572
2573 void SSH_notify_cred(PTInstVar pvar)
2574 {
2575 try_send_credentials(pvar);
2576 }
2577
2578 void SSH_send(PTInstVar pvar, unsigned char const FAR * buf, int buflen)
2579 {
2580 if (SSHv1(pvar)) {
2581 if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) != handle_data) {
2582 return;
2583 }
2584
2585 while (buflen > 0) {
2586 int len =
2587 buflen >
2588 SSH_MAX_SEND_PACKET_SIZE ? SSH_MAX_SEND_PACKET_SIZE : buflen;
2589 unsigned char FAR *outmsg =
2590 begin_send_packet(pvar, SSH_CMSG_STDIN_DATA, 4 + len);
2591
2592 set_uint32(outmsg, len);
2593
2594 if (pvar->ssh_state.compressing) {
2595 buf_ensure_size(&pvar->ssh_state.outbuf,
2596 &pvar->ssh_state.outbuflen,
2597 len + (len >> 6) + 50);
2598 pvar->ssh_state.compress_stream.next_in =
2599 pvar->ssh_state.precompress_outbuf;
2600 pvar->ssh_state.compress_stream.avail_in = 5;
2601 pvar->ssh_state.compress_stream.next_out =
2602 pvar->ssh_state.outbuf + 12;
2603 pvar->ssh_state.compress_stream.avail_out =
2604 pvar->ssh_state.outbuflen - 12;
2605
2606 if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) !=
2607 Z_OK) {
2608 #ifdef I18N
2609 strcpy(pvar->ts->UIMsg, "Error compressing packet data");
2610 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar);
2611 notify_fatal_error(pvar, pvar->ts->UIMsg);
2612 #else
2613 notify_fatal_error(pvar, "Error compressing packet data");
2614 #endif
2615 return;
2616 }
2617
2618 pvar->ssh_state.compress_stream.next_in =
2619 (unsigned char FAR *) buf;
2620 pvar->ssh_state.compress_stream.avail_in = len;
2621
2622 if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2623 Z_OK) {
2624 #ifdef I18N
2625 strcpy(pvar->ts->UIMsg, "Error compressing packet data");
2626 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar);
2627 notify_fatal_error(pvar, pvar->ts->UIMsg);
2628 #else
2629 notify_fatal_error(pvar, "Error compressing packet data");
2630 #endif
2631 return;
2632 }
2633 } else {
2634 memcpy(outmsg + 4, buf, len);
2635 }
2636
2637 finish_send_packet_special(pvar, 1);
2638
2639 buflen -= len;
2640 buf += len;
2641 }
2642
2643 } else { // for SSH2(yutaka)
2644 buffer_t *msg;
2645 unsigned char *outmsg;
2646 int len;
2647 Channel_t *c;
2648
2649 // SSH2���������������A�p�P�b�g���������B(2005.6.19 yutaka)
2650 if (pvar->rekeying) {
2651 // TODO: ���z���������p�P�b�g�j�����������A�p�P�b�g���������x���������������������A
2652 // �������������������B
2653 c = NULL;
2654
2655 return;
2656 }
2657
2658 c = ssh2_channel_lookup(pvar->shell_id);
2659 if (c == NULL)
2660 return;
2661
2662 msg = buffer_init();
2663 if (msg == NULL) {
2664 // TODO: error check
2665 return;
2666 }
2667 buffer_put_int(msg, c->remote_id);
2668 buffer_put_string(msg, (char *)buf, buflen);
2669
2670 len = buffer_len(msg);
2671 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_DATA, len);
2672 memcpy(outmsg, buffer_ptr(msg), len);
2673 finish_send_packet(pvar);
2674 buffer_free(msg);
2675
2676 // remote window size������
2677 c->remote_window -= len;
2678
2679 }
2680
2681 }
2682
2683 int SSH_extract_payload(PTInstVar pvar, unsigned char FAR * dest, int len)
2684 {
2685 int num_bytes = pvar->ssh_state.payload_datalen;
2686
2687 if (num_bytes > len) {
2688 num_bytes = len;
2689 }
2690
2691 if (!pvar->ssh_state.decompressing) {
2692 memcpy(dest,
2693 pvar->ssh_state.payload + pvar->ssh_state.payload_datastart,
2694 num_bytes);
2695 pvar->ssh_state.payload_datastart += num_bytes;
2696 } else if (num_bytes > 0) {
2697 pvar->ssh_state.decompress_stream.next_out = dest;
2698 pvar->ssh_state.decompress_stream.avail_out = num_bytes;
2699
2700 if (inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH) !=
2701 Z_OK) {
2702 #ifdef I18N
2703 strcpy(pvar->ts->UIMsg, "Invalid compressed data in received packet");
2704 UTIL_get_lang_msg("MSG_SSH_INVALID_COMPDATA_ERROR", pvar);
2705 notify_fatal_error(pvar, pvar->ts->UIMsg);
2706 #else
2707 notify_fatal_error(pvar,
2708 "Invalid compressed data in received packet");
2709 #endif
2710 return 0;
2711 }
2712 }
2713
2714 pvar->ssh_state.payload_datalen -= num_bytes;
2715
2716 return num_bytes;
2717 }
2718
2719 void SSH_get_compression_info(PTInstVar pvar, char FAR * dest, int len)
2720 {
2721 char buf[1024];
2722 char buf2[1024];
2723
2724 // added support of SSH2 packet compression (2005.7.10 yutaka)
2725 // support of "Compression delayed" (2006.6.23 maya)
2726 if (pvar->ssh_state.compressing ||
2727 pvar->ctos_compression == COMP_ZLIB ||
2728 pvar->ctos_compression == COMP_DELAYED && pvar->userauth_success) {
2729 unsigned long total_in = pvar->ssh_state.compress_stream.total_in;
2730 unsigned long total_out =
2731 pvar->ssh_state.compress_stream.total_out;
2732
2733 if (total_out > 0) {
2734 #ifdef I18N
2735 strcpy(pvar->ts->UIMsg, "level %d; ratio %.1f (%ld:%ld)");
2736 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO", pvar);
2737 _snprintf(buf, sizeof(buf), pvar->ts->UIMsg,
2738 pvar->ssh_state.compression_level,
2739 ((double) total_in) / total_out, total_in,
2740 total_out);
2741 #else
2742 _snprintf(buf, sizeof(buf), "level %d; ratio %.1f (%ld:%ld)",
2743 pvar->ssh_state.compression_level,
2744 ((double) total_in) / total_out, total_in,
2745 total_out);
2746 #endif
2747 } else {
2748 #ifdef I18N
2749 strcpy(pvar->ts->UIMsg, "level %d");
2750 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO2", pvar);
2751 _snprintf(buf, sizeof(buf), pvar->ts->UIMsg,
2752 pvar->ssh_state.compression_level);
2753 #else
2754 _snprintf(buf, sizeof(buf), "level %d",
2755 pvar->ssh_state.compression_level);
2756 #endif
2757 }
2758 } else {
2759 #ifdef I18N
2760 strcpy(pvar->ts->UIMsg, "none");
2761 UTIL_get_lang_msg("DLG_ABOUT_COMP_NONE", pvar);
2762 strcpy(buf, pvar->ts->UIMsg);
2763 #else
2764 strcpy(buf, "none");
2765 #endif
2766 }
2767 buf[sizeof(buf) - 1] = 0;
2768
2769 // support of "Compression delayed" (2006.6.23 maya)
2770 if (pvar->ssh_state.decompressing ||
2771 pvar->stoc_compression == COMP_ZLIB ||
2772 pvar->stoc_compression == COMP_DELAYED && pvar->userauth_success) {
2773 unsigned long total_in =
2774 pvar->ssh_state.decompress_stream.total_in;
2775 unsigned long total_out =
2776 pvar->ssh_state.decompress_stream.total_out;
2777
2778 if (total_in > 0) {
2779 #ifdef I18N
2780 strcpy(pvar->ts->UIMsg, "level %d; ratio %.1f (%ld:%ld)");
2781 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO", pvar);
2782 _snprintf(buf2, sizeof(buf2), pvar->ts->UIMsg,
2783 pvar->ssh_state.compression_level,
2784 ((double) total_out) / total_in, total_out,
2785 total_in);
2786 #else
2787 _snprintf(buf2, sizeof(buf2), "level %d; ratio %.1f (%ld:%ld)",
2788 pvar->ssh_state.compression_level,
2789 ((double) total_out) / total_in, total_out,
2790 total_in);
2791 #endif
2792 } else {
2793 #ifdef I18N
2794 strcpy(pvar->ts->UIMsg, "level %d");
2795 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO2", pvar);
2796 _snprintf(buf2, sizeof(buf2), pvar->ts->UIMsg,
2797 pvar->ssh_state.compression_level);
2798 #else
2799 _snprintf(buf2, sizeof(buf2), "level %d",
2800 pvar->ssh_state.compression_level);
2801 #endif
2802 }
2803 } else {
2804 #ifdef I18N
2805 strcpy(pvar->ts->UIMsg, "none");
2806 UTIL_get_lang_msg("DLG_ABOUT_COMP_NONE", pvar);
2807 strcpy(buf2, pvar->ts->UIMsg);
2808 #else
2809 strcpy(buf2, "none");
2810 #endif
2811 }
2812 buf2[sizeof(buf2) - 1] = 0;
2813
2814 #ifdef I18N
2815 strcpy(pvar->ts->UIMsg, "Upstream %s; Downstream %s");
2816 UTIL_get_lang_msg("DLG_ABOUT_COMP_UPDOWN", pvar);
2817 _snprintf(dest, len, pvar->ts->UIMsg, buf, buf2);
2818 #else
2819 _snprintf(dest, len, "Upstream %s; Downstream %s", buf, buf2);
2820 #endif
2821 dest[len - 1] = 0;
2822 }
2823
2824 void SSH_get_server_ID_info(PTInstVar pvar, char FAR * dest, int len)
2825 {
2826 strncpy(dest, pvar->ssh_state.server_ID == NULL ? "Unknown"
2827 : pvar->ssh_state.server_ID, len);
2828 dest[len - 1] = 0;
2829 }
2830
2831 void SSH_get_protocol_version_info(PTInstVar pvar, char FAR * dest,
2832 int len)
2833 {
2834 if (pvar->protocol_major == 0) {
2835 strncpy(dest, "Unknown", len);
2836 } else {
2837 _snprintf(dest, len, "%d.%d", pvar->protocol_major,
2838 pvar->protocol_minor);
2839 }
2840 dest[len - 1] = 0;
2841 }
2842
2843 void SSH_end(PTInstVar pvar)
2844 {
2845 int i;
2846
2847 for (i = 0; i < 256; i++) {
2848 SSHPacketHandlerItem FAR *first_item =
2849 pvar->ssh_state.packet_handlers[i];
2850
2851 if (first_item != NULL) {
2852 SSHPacketHandlerItem FAR *item = first_item;
2853
2854 do {
2855 SSHPacketHandlerItem FAR *cur_item = item;
2856
2857 item = item->next_for_message;
2858 free(cur_item);
2859 } while (item != first_item);
2860 }
2861 pvar->ssh_state.packet_handlers[i] = NULL;
2862 }
2863
2864 free(pvar->ssh_state.hostname);
2865 pvar->ssh_state.hostname = NULL;
2866 free(pvar->ssh_state.server_ID);
2867 pvar->ssh_state.server_ID = NULL;
2868 buf_destroy(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
2869 buf_destroy(&pvar->ssh_state.precompress_outbuf,
2870 &pvar->ssh_state.precompress_outbuflen);
2871 buf_destroy(&pvar->ssh_state.postdecompress_inbuf,
2872 &pvar->ssh_state.postdecompress_inbuflen);
2873
2874 // support of "Compression delayed" (2006.6.23 maya)
2875 if (pvar->ssh_state.compressing ||
2876 pvar->ctos_compression == COMP_ZLIB || // add SSH2 flag (2005.7.10 yutaka)
2877 pvar->ctos_compression == COMP_DELAYED && pvar->userauth_success) {
2878 deflateEnd(&pvar->ssh_state.compress_stream);
2879 pvar->ssh_state.compressing = FALSE;
2880 }
2881 // support of "Compression delayed" (2006.6.23 maya)
2882 if (pvar->ssh_state.decompressing ||
2883 pvar->stoc_compression == COMP_ZLIB || // add SSH2 flag (2005.7.10 yutaka)
2884 pvar->stoc_compression == COMP_DELAYED && pvar->userauth_success) {
2885 inflateEnd(&pvar->ssh_state.decompress_stream);
2886 pvar->ssh_state.decompressing = FALSE;
2887 }
2888
2889 #if 1
2890 // SSH2���f�[�^���������� (2004.12.27 yutaka)
2891 if (SSHv2(pvar)) {
2892 if (pvar->kexdh) {
2893 DH_free(pvar->kexdh);
2894 pvar->kexdh = NULL;
2895 }
2896 memset(pvar->server_version_string, 0, sizeof(pvar->server_version_string));
2897 memset(pvar->client_version_string, 0, sizeof(pvar->client_version_string));
2898
2899 if (pvar->my_kex != NULL) {
2900 buffer_free(pvar->my_kex);
2901 pvar->my_kex = NULL;
2902 }
2903 if (pvar->peer_kex != NULL) {
2904 buffer_free(pvar->peer_kex);
2905 pvar->peer_kex = NULL;
2906 }
2907
2908 pvar->we_need = 0;
2909 pvar->key_done = 0;
2910 pvar->rekeying = 0;
2911
2912 if (pvar->session_id != NULL) {
2913 free(pvar->session_id);
2914 pvar->session_id = NULL;
2915 }
2916 pvar->session_id_len = 0;
2917
2918 pvar->userauth_success = 0;
2919 //pvar->remote_id = 0;
2920 pvar->shell_id = 0;
2921 pvar->session_nego_status = 0;
2922
2923 pvar->ssh_heartbeat_tick = 0;
2924
2925 if (pvar->decomp_buffer != NULL) {
2926 buffer_free(pvar->decomp_buffer);
2927 pvar->decomp_buffer = NULL;
2928 }
2929 }
2930 #endif
2931
2932 }
2933
2934 /* support for port forwarding */
2935 void SSH_channel_send(PTInstVar pvar, int channel_num,
2936 uint32 remote_channel_num,
2937 unsigned char FAR * buf, int len)
2938 {
2939 int buflen = len;
2940
2941 if (SSHv1(pvar)) {
2942 unsigned char FAR *outmsg =
2943 begin_send_packet(pvar, SSH_MSG_CHANNEL_DATA, 8 + len);
2944
2945 set_uint32(outmsg, remote_channel_num);
2946 set_uint32(outmsg + 4, len);
2947
2948 if (pvar->ssh_state.compressing) {
2949 buf_ensure_size(&pvar->ssh_state.outbuf,
2950 &pvar->ssh_state.outbuflen, len + (len >> 6) + 50);
2951 pvar->ssh_state.compress_stream.next_in =
2952 pvar->ssh_state.precompress_outbuf;
2953 pvar->ssh_state.compress_stream.avail_in = 9;
2954 pvar->ssh_state.compress_stream.next_out =
2955 pvar->ssh_state.outbuf + 12;
2956 pvar->ssh_state.compress_stream.avail_out =
2957 pvar->ssh_state.outbuflen - 12;
2958
2959 if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) != Z_OK) {
2960 #ifdef I18N
2961 strcpy(pvar->ts->UIMsg, "Error compressing packet data");
2962 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar);
2963 notify_fatal_error(pvar, pvar->ts->UIMsg);
2964 #else
2965 notify_fatal_error(pvar, "Error compressing packet data");
2966 #endif
2967 return;
2968 }
2969
2970 pvar->ssh_state.compress_stream.next_in =
2971 (unsigned char FAR *) buf;
2972 pvar->ssh_state.compress_stream.avail_in = len;
2973
2974 if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2975 Z_OK) {
2976 #ifdef I18N
2977 strcpy(pvar->ts->UIMsg, "Error compressing packet data");
2978 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar);
2979 notify_fatal_error(pvar, pvar->ts->UIMsg);
2980 #else
2981 notify_fatal_error(pvar, "Error compressing packet data");
2982 #endif
2983 return;
2984 }
2985 } else {
2986 memcpy(outmsg + 8, buf, len);
2987 }
2988
2989 finish_send_packet_special(pvar, 1);
2990
2991 } else {
2992 // �|�[�g�t�H���[�f�B���O���������N���C�A���g���������M�v�����ASSH���M���������T�[�o���������������B
2993 buffer_t *msg;
2994 unsigned char *outmsg;
2995 int len;
2996 Channel_t *c;
2997
2998 // SSH2���������������A�p�P�b�g���������B(2005.6.19 yutaka)
2999 if (pvar->rekeying) {
3000 // TODO: ���z���������p�P�b�g�j�����������A�p�P�b�g���������x���������������������A
3001 // �������������������B
3002 c = NULL;
3003
3004 return;
3005 }
3006
3007 c = ssh2_local_channel_lookup(channel_num);
3008 if (c == NULL)
3009 return;
3010
3011 msg = buffer_init();
3012 if (msg == NULL) {
3013 // TODO: error check
3014 return;
3015 }
3016 buffer_put_int(msg, c->remote_id);
3017 buffer_put_string(msg, (char *)buf, buflen);
3018
3019 len = buffer_len(msg);
3020 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_DATA, len);
3021 memcpy(outmsg, buffer_ptr(msg), len);
3022 finish_send_packet(pvar);
3023 buffer_free(msg);
3024
3025 // remote window size������
3026 c->remote_window -= len;
3027 }
3028
3029 }
3030
3031 void SSH_fail_channel_open(PTInstVar pvar, uint32 remote_channel_num)
3032 {
3033 if (SSHv1(pvar)) {
3034 unsigned char FAR *outmsg =
3035 begin_send_packet(pvar, SSH_MSG_CHANNEL_OPEN_FAILURE, 4);
3036
3037 set_uint32(outmsg, remote_channel_num);
3038 finish_send_packet(pvar);
3039
3040 } else { // SSH2 (2005.6.26 yutaka)
3041 int len;
3042 Channel_t *c = NULL;
3043 buffer_t *msg;
3044 unsigned char *outmsg;
3045
3046 msg = buffer_init();
3047 if (msg == NULL) {
3048 // TODO: error check
3049 return;
3050 }
3051 buffer_put_int(msg, remote_channel_num);
3052 buffer_put_int(msg, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
3053
3054 len = buffer_len(msg);
3055 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_OPEN_FAILURE, len);
3056 memcpy(outmsg, buffer_ptr(msg), len);
3057 finish_send_packet(pvar);
3058 buffer_free(msg);
3059
3060 }
3061 }
3062
3063 void SSH_confirm_channel_open(PTInstVar pvar, uint32 remote_channel_num,
3064 uint32 local_channel_num)
3065 {
3066 if (SSHv1(pvar)) {
3067 unsigned char FAR *outmsg =
3068 begin_send_packet(pvar, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 8);
3069
3070 set_uint32(outmsg, remote_channel_num);
3071 set_uint32(outmsg + 4, local_channel_num);
3072 finish_send_packet(pvar);
3073
3074 } else {
3075 buffer_t *msg;
3076 unsigned char *outmsg;
3077 int len;
3078 Channel_t *c;
3079
3080 // port-forwarding(remote to local)�����[�J�����������������T�[�o�������B(2005.7.2 yutaka)
3081 c = ssh2_local_channel_lookup(local_channel_num);
3082 if (c == NULL) {
3083 // It is sure to be successful as long as it's not a program bug either.
3084 return;
3085 }
3086
3087 msg = buffer_init();
3088 if (msg == NULL) {
3089 // TODO: error check
3090 return;
3091 }
3092 buffer_put_int(msg, c->remote_id);
3093 buffer_put_int(msg, c->self_id);
3094 buffer_put_int(msg, c->local_window);
3095 buffer_put_int(msg, c->local_maxpacket);
3096
3097 len = buffer_len(msg);
3098 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, len);
3099 memcpy(outmsg, buffer_ptr(msg), len);
3100 finish_send_packet(pvar);
3101 buffer_free(msg);
3102
3103 }
3104 }
3105
3106 void SSH_channel_output_eof(PTInstVar pvar, uint32 remote_channel_num)
3107 {
3108 if (SSHv1(pvar)){
3109 unsigned char FAR *outmsg =
3110 begin_send_packet(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4);
3111
3112 set_uint32(outmsg, remote_channel_num);
3113 finish_send_packet(pvar);
3114
3115 } else {
3116 // SSH2: ���������B
3117
3118 }
3119 }
3120
3121 void SSH_channel_input_eof(PTInstVar pvar, uint32 remote_channel_num, uint32 local_channel_num)
3122 {
3123 if (SSHv1(pvar)){
3124 unsigned char FAR *outmsg =
3125 begin_send_packet(pvar, SSH_MSG_CHANNEL_INPUT_EOF, 4);
3126
3127 set_uint32(outmsg, remote_channel_num);
3128 finish_send_packet(pvar);
3129
3130 } else {
3131 // SSH2: �`���l���N���[�Y���T�[�o�����m
3132 buffer_t *msg;
3133 unsigned char *outmsg;
3134 int len;
3135 Channel_t *c;
3136
3137 // SSH2���������������A�p�P�b�g���������B(2005.6.21 yutaka)
3138 if (pvar->rekeying) {
3139 // TODO: ���z���������p�P�b�g�j�����������A�p�P�b�g���������x���������������������A
3140 // �������������������B
3141 c = NULL;
3142
3143 return;
3144 }
3145
3146 c = ssh2_local_channel_lookup(local_channel_num);
3147 if (c == NULL)
3148 return;
3149
3150 msg = buffer_init();
3151 if (msg == NULL) {
3152 // TODO: error check
3153 return;
3154 }
3155 buffer_put_int(msg, c->remote_id); // remote ID
3156
3157 len = buffer_len(msg);
3158 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_EOF, len);
3159 memcpy(outmsg, buffer_ptr(msg), len);
3160 finish_send_packet(pvar);
3161 buffer_free(msg);
3162 }
3163
3164 }
3165
3166 void SSH_request_forwarding(PTInstVar pvar, int from_server_port,
3167 char FAR * to_local_host, int to_local_port)
3168 {
3169 if (SSHv1(pvar)) {
3170 int host_len = strlen(to_local_host);
3171 unsigned char FAR *outmsg =
3172 begin_send_packet(pvar, SSH_CMSG_PORT_FORWARD_REQUEST,
3173 12 + host_len);
3174
3175 set_uint32(outmsg, from_server_port);
3176 set_uint32(outmsg + 4, host_len);
3177 memcpy(outmsg + 8, to_local_host, host_len);
3178 set_uint32(outmsg + 8 + host_len, to_local_port);
3179 finish_send_packet(pvar);
3180
3181 enque_forwarding_request_handlers(pvar);
3182
3183 } else {
3184 // SSH2 port-forwading remote to local (2005.6.21 yutaka)
3185 buffer_t *msg;
3186 char *s;
3187 unsigned char *outmsg;
3188 int len;
3189
3190 msg = buffer_init();
3191 if (msg == NULL) {
3192 // TODO: error check
3193 return;
3194 }
3195 s = "tcpip-forward";
3196 buffer_put_string(msg, s, strlen(s)); // ctype
3197 buffer_put_char(msg, 1); // want reply
3198 s = "0.0.0.0";
3199 buffer_put_string(msg, s, strlen(s));
3200
3201 buffer_put_int(msg, from_server_port); // listening port
3202
3203 len = buffer_len(msg);
3204 outmsg = begin_send_packet(pvar, SSH2_MSG_GLOBAL_REQUEST, len);
3205 memcpy(outmsg, buffer_ptr(msg), len);
3206 finish_send_packet(pvar);
3207 buffer_free(msg);
3208
3209 }
3210 }
3211
3212 void SSH_request_X11_forwarding(PTInstVar pvar,
3213 char FAR * auth_protocol,
3214 unsigned char FAR * auth_data,
3215 int auth_data_len, int screen_num)
3216 {
3217 if (SSHv1(pvar)) {
3218 int protocol_len = strlen(auth_protocol);
3219 int data_len = auth_data_len * 2;
3220 unsigned char FAR *outmsg =
3221 begin_send_packet(pvar, SSH_CMSG_X11_REQUEST_FORWARDING,
3222 12 + protocol_len + data_len);
3223 int i;
3224 char FAR *auth_data_ptr;
3225
3226 set_uint32(outmsg, protocol_len);
3227 memcpy(outmsg + 4, auth_protocol, protocol_len);
3228 set_uint32(outmsg + 4 + protocol_len, data_len);
3229 auth_data_ptr = outmsg + 8 + protocol_len;
3230 for (i = 0; i < auth_data_len; i++) {
3231 sprintf(auth_data_ptr + i * 2, "%.2x", auth_data[i]);
3232 }
3233 set_uint32(outmsg + 8 + protocol_len + data_len, screen_num);
3234
3235 finish_send_packet(pvar);
3236
3237 enque_forwarding_request_handlers