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 2976 - (show annotations) (download) (as text)
Fri Apr 27 12:56:47 2007 UTC (16 years, 11 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 201366 byte(s)
ユーザ認証リストをもらったら、認証ダイアログのラジオボタンを更新するようにした。

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 pvar->ssh2_authlist = NULL; // (2007.4.27 yutaka)
2424
2425 }
2426
2427 void SSH_open(PTInstVar pvar)
2428 {
2429 pvar->ssh_state.hostname = _strdup(pvar->ts->HostName);
2430 pvar->ssh_state.win_cols = pvar->ts->TerminalWidth;
2431 pvar->ssh_state.win_rows = pvar->ts->TerminalHeight;
2432 }
2433
2434 void SSH_notify_disconnecting(PTInstVar pvar, char FAR * reason)
2435 {
2436 if (SSHv1(pvar)) {
2437 int len = reason == NULL ? 0 : strlen(reason);
2438 unsigned char FAR *outmsg =
2439 begin_send_packet(pvar, SSH_MSG_DISCONNECT, len + 4);
2440
2441 set_uint32(outmsg, len);
2442 if (reason != NULL) {
2443 memcpy(outmsg + 4, reason, len);
2444 }
2445 finish_send_packet(pvar);
2446
2447 } else { // for SSH2(yutaka)
2448 buffer_t *msg;
2449 unsigned char *outmsg;
2450 int len;
2451 Channel_t *c;
2452
2453 c = ssh2_channel_lookup(pvar->shell_id);
2454 if (c == NULL)
2455 return;
2456
2457 // SSH2 server��channel close���`����
2458 msg = buffer_init();
2459 if (msg == NULL) {
2460 // TODO: error check
2461 return;
2462 }
2463 buffer_put_int(msg, c->remote_id);
2464
2465 len = buffer_len(msg);
2466 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_CLOSE, len);
2467 memcpy(outmsg, buffer_ptr(msg), len);
2468 finish_send_packet(pvar);
2469 buffer_free(msg);
2470
2471 }
2472
2473 }
2474
2475 void SSH_notify_host_OK(PTInstVar pvar)
2476 {
2477 if ((pvar->ssh_state.status_flags & STATUS_HOST_OK) == 0) {
2478 pvar->ssh_state.status_flags |= STATUS_HOST_OK;
2479 send_session_key(pvar);
2480 }
2481 }
2482
2483 void SSH_notify_win_size(PTInstVar pvar, int cols, int rows)
2484 {
2485 pvar->ssh_state.win_cols = cols;
2486 pvar->ssh_state.win_rows = rows;
2487
2488 if (SSHv1(pvar)) {
2489 if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) == handle_data) {
2490 unsigned char FAR *outmsg =
2491 begin_send_packet(pvar, SSH_CMSG_WINDOW_SIZE, 16);
2492
2493 set_uint32(outmsg, rows);
2494 set_uint32(outmsg + 4, cols);
2495 set_uint32(outmsg + 8, 0);
2496 set_uint32(outmsg + 12, 0);
2497 finish_send_packet(pvar);
2498 }
2499
2500 } else if (SSHv2(pvar)) { // �^�[�~�i���T�C�Y���X���m������ (2005.1.4 yutaka)
2501 // SSH2�����������`�F�b�N���s���B(2005.1.5 yutaka)
2502 buffer_t *msg;
2503 char *s;
2504 unsigned char *outmsg;
2505 int len;
2506 Channel_t *c;
2507
2508 c = ssh2_channel_lookup(pvar->shell_id);
2509 if (c == NULL)
2510 return;
2511
2512 msg = buffer_init();
2513 if (msg == NULL) {
2514 // TODO: error check
2515 return;
2516 }
2517 buffer_put_int(msg, c->remote_id);
2518 s = "window-change";
2519 buffer_put_string(msg, s, strlen(s));
2520 buffer_put_char(msg, 0); // wantconfirm
2521 buffer_put_int(msg, pvar->ssh_state.win_cols); // columns
2522 buffer_put_int(msg, pvar->ssh_state.win_rows); // lines
2523 buffer_put_int(msg, 480); // XXX:
2524 buffer_put_int(msg, 640); // XXX:
2525 len = buffer_len(msg);
2526 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len);
2527 memcpy(outmsg, buffer_ptr(msg), len);
2528 finish_send_packet(pvar);
2529 buffer_free(msg);
2530
2531 notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_REQUEST was sent at SSH_notify_win_size().", LOG_LEVEL_VERBOSE);
2532
2533 } else {
2534 // SSH�����������������������B
2535
2536 }
2537
2538 }
2539
2540 int SSH_get_min_packet_size(PTInstVar pvar)
2541 {
2542 if (SSHv1(pvar)) {
2543 return 12;
2544 } else {
2545 int block_size = CRYPT_get_decryption_block_size(pvar);
2546
2547 return max(16, block_size);
2548 }
2549 }
2550
2551 /* data is guaranteed to be at least SSH_get_min_packet_size bytes long
2552 at least 5 bytes must be decrypted */
2553 void SSH_predecrpyt_packet(PTInstVar pvar, char FAR * data)
2554 {
2555 if (SSHv2(pvar)) {
2556 CRYPT_decrypt(pvar, data, get_predecryption_amount(pvar));
2557 }
2558 }
2559
2560 int SSH_get_clear_MAC_size(PTInstVar pvar)
2561 {
2562 if (SSHv1(pvar)) {
2563 return 0;
2564 } else {
2565 return CRYPT_get_receiver_MAC_size(pvar);
2566 }
2567 }
2568
2569 void SSH_notify_user_name(PTInstVar pvar)
2570 {
2571 try_send_user_name(pvar);
2572 }
2573
2574 void SSH_notify_cred(PTInstVar pvar)
2575 {
2576 try_send_credentials(pvar);
2577 }
2578
2579 void SSH_send(PTInstVar pvar, unsigned char const FAR * buf, int buflen)
2580 {
2581 if (SSHv1(pvar)) {
2582 if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) != handle_data) {
2583 return;
2584 }
2585
2586 while (buflen > 0) {
2587 int len =
2588 buflen >
2589 SSH_MAX_SEND_PACKET_SIZE ? SSH_MAX_SEND_PACKET_SIZE : buflen;
2590 unsigned char FAR *outmsg =
2591 begin_send_packet(pvar, SSH_CMSG_STDIN_DATA, 4 + len);
2592
2593 set_uint32(outmsg, len);
2594
2595 if (pvar->ssh_state.compressing) {
2596 buf_ensure_size(&pvar->ssh_state.outbuf,
2597 &pvar->ssh_state.outbuflen,
2598 len + (len >> 6) + 50);
2599 pvar->ssh_state.compress_stream.next_in =
2600 pvar->ssh_state.precompress_outbuf;
2601 pvar->ssh_state.compress_stream.avail_in = 5;
2602 pvar->ssh_state.compress_stream.next_out =
2603 pvar->ssh_state.outbuf + 12;
2604 pvar->ssh_state.compress_stream.avail_out =
2605 pvar->ssh_state.outbuflen - 12;
2606
2607 if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) !=
2608 Z_OK) {
2609 #ifdef I18N
2610 strcpy(pvar->ts->UIMsg, "Error compressing packet data");
2611 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar);
2612 notify_fatal_error(pvar, pvar->ts->UIMsg);
2613 #else
2614 notify_fatal_error(pvar, "Error compressing packet data");
2615 #endif
2616 return;
2617 }
2618
2619 pvar->ssh_state.compress_stream.next_in =
2620 (unsigned char FAR *) buf;
2621 pvar->ssh_state.compress_stream.avail_in = len;
2622
2623 if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2624 Z_OK) {
2625 #ifdef I18N
2626 strcpy(pvar->ts->UIMsg, "Error compressing packet data");
2627 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar);
2628 notify_fatal_error(pvar, pvar->ts->UIMsg);
2629 #else
2630 notify_fatal_error(pvar, "Error compressing packet data");
2631 #endif
2632 return;
2633 }
2634 } else {
2635 memcpy(outmsg + 4, buf, len);
2636 }
2637
2638 finish_send_packet_special(pvar, 1);
2639
2640 buflen -= len;
2641 buf += len;
2642 }
2643
2644 } else { // for SSH2(yutaka)
2645 buffer_t *msg;
2646 unsigned char *outmsg;
2647 int len;
2648 Channel_t *c;
2649
2650 // SSH2���������������A�p�P�b�g���������B(2005.6.19 yutaka)
2651 if (pvar->rekeying) {
2652 // TODO: ���z���������p�P�b�g�j�����������A�p�P�b�g���������x���������������������A
2653 // �������������������B
2654 c = NULL;
2655
2656 return;
2657 }
2658
2659 c = ssh2_channel_lookup(pvar->shell_id);
2660 if (c == NULL)
2661 return;
2662
2663 msg = buffer_init();
2664 if (msg == NULL) {
2665 // TODO: error check
2666 return;
2667 }
2668 buffer_put_int(msg, c->remote_id);
2669 buffer_put_string(msg, (char *)buf, buflen);
2670
2671 len = buffer_len(msg);
2672 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_DATA, len);
2673 memcpy(outmsg, buffer_ptr(msg), len);
2674 finish_send_packet(pvar);
2675 buffer_free(msg);
2676
2677 // remote window size������
2678 c->remote_window -= len;
2679
2680 }
2681
2682 }
2683
2684 int SSH_extract_payload(PTInstVar pvar, unsigned char FAR * dest, int len)
2685 {
2686 int num_bytes = pvar->ssh_state.payload_datalen;
2687
2688 if (num_bytes > len) {
2689 num_bytes = len;
2690 }
2691
2692 if (!pvar->ssh_state.decompressing) {
2693 memcpy(dest,
2694 pvar->ssh_state.payload + pvar->ssh_state.payload_datastart,
2695 num_bytes);
2696 pvar->ssh_state.payload_datastart += num_bytes;
2697 } else if (num_bytes > 0) {
2698 pvar->ssh_state.decompress_stream.next_out = dest;
2699 pvar->ssh_state.decompress_stream.avail_out = num_bytes;
2700
2701 if (inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH) !=
2702 Z_OK) {
2703 #ifdef I18N
2704 strcpy(pvar->ts->UIMsg, "Invalid compressed data in received packet");
2705 UTIL_get_lang_msg("MSG_SSH_INVALID_COMPDATA_ERROR", pvar);
2706 notify_fatal_error(pvar, pvar->ts->UIMsg);
2707 #else
2708 notify_fatal_error(pvar,
2709 "Invalid compressed data in received packet");
2710 #endif
2711 return 0;
2712 }
2713 }
2714
2715 pvar->ssh_state.payload_datalen -= num_bytes;
2716
2717 return num_bytes;
2718 }
2719
2720 void SSH_get_compression_info(PTInstVar pvar, char FAR * dest, int len)
2721 {
2722 char buf[1024];
2723 char buf2[1024];
2724
2725 // added support of SSH2 packet compression (2005.7.10 yutaka)
2726 // support of "Compression delayed" (2006.6.23 maya)
2727 if (pvar->ssh_state.compressing ||
2728 pvar->ctos_compression == COMP_ZLIB ||
2729 pvar->ctos_compression == COMP_DELAYED && pvar->userauth_success) {
2730 unsigned long total_in = pvar->ssh_state.compress_stream.total_in;
2731 unsigned long total_out =
2732 pvar->ssh_state.compress_stream.total_out;
2733
2734 if (total_out > 0) {
2735 #ifdef I18N
2736 strcpy(pvar->ts->UIMsg, "level %d; ratio %.1f (%ld:%ld)");
2737 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO", pvar);
2738 _snprintf(buf, sizeof(buf), pvar->ts->UIMsg,
2739 pvar->ssh_state.compression_level,
2740 ((double) total_in) / total_out, total_in,
2741 total_out);
2742 #else
2743 _snprintf(buf, sizeof(buf), "level %d; ratio %.1f (%ld:%ld)",
2744 pvar->ssh_state.compression_level,
2745 ((double) total_in) / total_out, total_in,
2746 total_out);
2747 #endif
2748 } else {
2749 #ifdef I18N
2750 strcpy(pvar->ts->UIMsg, "level %d");
2751 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO2", pvar);
2752 _snprintf(buf, sizeof(buf), pvar->ts->UIMsg,
2753 pvar->ssh_state.compression_level);
2754 #else
2755 _snprintf(buf, sizeof(buf), "level %d",
2756 pvar->ssh_state.compression_level);
2757 #endif
2758 }
2759 } else {
2760 #ifdef I18N
2761 strcpy(pvar->ts->UIMsg, "none");
2762 UTIL_get_lang_msg("DLG_ABOUT_COMP_NONE", pvar);
2763 strcpy(buf, pvar->ts->UIMsg);
2764 #else
2765 strcpy(buf, "none");
2766 #endif
2767 }
2768 buf[sizeof(buf) - 1] = 0;
2769
2770 // support of "Compression delayed" (2006.6.23 maya)
2771 if (pvar->ssh_state.decompressing ||
2772 pvar->stoc_compression == COMP_ZLIB ||
2773 pvar->stoc_compression == COMP_DELAYED && pvar->userauth_success) {
2774 unsigned long total_in =
2775 pvar->ssh_state.decompress_stream.total_in;
2776 unsigned long total_out =
2777 pvar->ssh_state.decompress_stream.total_out;
2778
2779 if (total_in > 0) {
2780 #ifdef I18N
2781 strcpy(pvar->ts->UIMsg, "level %d; ratio %.1f (%ld:%ld)");
2782 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO", pvar);
2783 _snprintf(buf2, sizeof(buf2), pvar->ts->UIMsg,
2784 pvar->ssh_state.compression_level,
2785 ((double) total_out) / total_in, total_out,
2786 total_in);
2787 #else
2788 _snprintf(buf2, sizeof(buf2), "level %d; ratio %.1f (%ld:%ld)",
2789 pvar->ssh_state.compression_level,
2790 ((double) total_out) / total_in, total_out,
2791 total_in);
2792 #endif
2793 } else {
2794 #ifdef I18N
2795 strcpy(pvar->ts->UIMsg, "level %d");
2796 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO2", pvar);
2797 _snprintf(buf2, sizeof(buf2), pvar->ts->UIMsg,
2798 pvar->ssh_state.compression_level);
2799 #else
2800 _snprintf(buf2, sizeof(buf2), "level %d",
2801 pvar->ssh_state.compression_level);
2802 #endif
2803 }
2804 } else {
2805 #ifdef I18N
2806 strcpy(pvar->ts->UIMsg, "none");
2807 UTIL_get_lang_msg("DLG_ABOUT_COMP_NONE", pvar);
2808 strcpy(buf2, pvar->ts->UIMsg);
2809 #else
2810 strcpy(buf2, "none");
2811 #endif
2812 }
2813 buf2[sizeof(buf2) - 1] = 0;
2814
2815 #ifdef I18N
2816 strcpy(pvar->ts->UIMsg, "Upstream %s; Downstream %s");
2817 UTIL_get_lang_msg("DLG_ABOUT_COMP_UPDOWN", pvar);
2818 _snprintf(dest, len, pvar->ts->UIMsg, buf, buf2);
2819 #else
2820 _snprintf(dest, len, "Upstream %s; Downstream %s", buf, buf2);
2821 #endif
2822 dest[len - 1] = 0;
2823 }
2824
2825 void SSH_get_server_ID_info(PTInstVar pvar, char FAR * dest, int len)
2826 {
2827 strncpy(dest, pvar->ssh_state.server_ID == NULL ? "Unknown"
2828 : pvar->ssh_state.server_ID, len);
2829 dest[len - 1] = 0;
2830 }
2831
2832 void SSH_get_protocol_version_info(PTInstVar pvar, char FAR * dest,
2833 int len)
2834 {
2835 if (pvar->protocol_major == 0) {
2836 strncpy(dest, "Unknown", len);
2837 } else {
2838 _snprintf(dest, len, "%d.%d", pvar->protocol_major,
2839 pvar->protocol_minor);
2840 }
2841 dest[len - 1] = 0;
2842 }
2843
2844 void SSH_end(PTInstVar pvar)
2845 {
2846 int i;
2847
2848 for (i = 0; i < 256; i++) {
2849 SSHPacketHandlerItem FAR *first_item =
2850 pvar->ssh_state.packet_handlers[i];
2851
2852 if (first_item != NULL) {
2853 SSHPacketHandlerItem FAR *item = first_item;
2854
2855 do {
2856 SSHPacketHandlerItem FAR *cur_item = item;
2857
2858 item = item->next_for_message;
2859 free(cur_item);
2860 } while (item != first_item);
2861 }
2862 pvar->ssh_state.packet_handlers[i] = NULL;
2863 }
2864
2865 free(pvar->ssh_state.hostname);
2866 pvar->ssh_state.hostname = NULL;
2867 free(pvar->ssh_state.server_ID);
2868 pvar->ssh_state.server_ID = NULL;
2869 buf_destroy(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
2870 buf_destroy(&pvar->ssh_state.precompress_outbuf,
2871 &pvar->ssh_state.precompress_outbuflen);
2872 buf_destroy(&pvar->ssh_state.postdecompress_inbuf,
2873 &pvar->ssh_state.postdecompress_inbuflen);
2874
2875 // support of "Compression delayed" (2006.6.23 maya)
2876 if (pvar->ssh_state.compressing ||
2877 pvar->ctos_compression == COMP_ZLIB || // add SSH2 flag (2005.7.10 yutaka)
2878 pvar->ctos_compression == COMP_DELAYED && pvar->userauth_success) {
2879 deflateEnd(&pvar->ssh_state.compress_stream);
2880 pvar->ssh_state.compressing = FALSE;
2881 }
2882 // support of "Compression delayed" (2006.6.23 maya)
2883 if (pvar->ssh_state.decompressing ||
2884 pvar->stoc_compression == COMP_ZLIB || // add SSH2 flag (2005.7.10 yutaka)
2885 pvar->stoc_compression == COMP_DELAYED && pvar->userauth_success) {
2886 inflateEnd(&pvar->ssh_state.decompress_stream);
2887 pvar->ssh_state.decompressing = FALSE;
2888 }
2889
2890 #if 1
2891 // SSH2���f�[�^���������� (2004.12.27 yutaka)
2892 if (SSHv2(pvar)) {
2893 if (pvar->kexdh) {
2894 DH_free(pvar->kexdh);
2895 pvar->kexdh = NULL;
2896 }
2897 memset(pvar->server_version_string, 0, sizeof(pvar->server_version_string));
2898 memset(pvar->client_version_string, 0, sizeof(pvar->client_version_string));
2899
2900 if (pvar->my_kex != NULL) {
2901 buffer_free(pvar->my_kex);
2902 pvar->my_kex = NULL;
2903 }
2904 if (pvar->peer_kex != NULL) {
2905 buffer_free(pvar->peer_kex);
2906 pvar->peer_kex = NULL;
2907 }
2908
2909 pvar->we_need = 0;
2910 pvar->key_done = 0;
2911 pvar->rekeying = 0;
2912
2913 if (pvar->session_id != NULL) {
2914 free(pvar->session_id);
2915 pvar->session_id = NULL;
2916 }
2917 pvar->session_id_len = 0;
2918
2919 pvar->userauth_success = 0;
2920 //pvar->remote_id = 0;
2921 pvar->shell_id = 0;
2922 pvar->session_nego_status = 0;
2923
2924 pvar->ssh_heartbeat_tick = 0;
2925
2926 if (pvar->decomp_buffer != NULL) {
2927 buffer_free(pvar->decomp_buffer);
2928 pvar->decomp_buffer = NULL;
2929 }
2930
2931 if (pvar->ssh2_authlist != NULL) { // (2007.4.27 yutaka)
2932 free(pvar->ssh2_authlist);
2933 pvar->ssh2_authlist = NULL;
2934 }
2935 }
2936 #endif
2937
2938 }
2939
2940 /* support for port forwarding */
2941 void SSH_channel_send(PTInstVar pvar, int channel_num,
2942 uint32 remote_channel_num,
2943 unsigned char FAR * buf, int len)
2944 {
2945 int buflen = len;
2946
2947 if (SSHv1(pvar)) {
2948 unsigned char FAR *outmsg =
2949 begin_send_packet(pvar, SSH_MSG_CHANNEL_DATA, 8 + len);
2950
2951 set_uint32(outmsg, remote_channel_num);
2952 set_uint32(outmsg + 4, len);
2953
2954 if (pvar->ssh_state.compressing) {
2955 buf_ensure_size(&pvar->ssh_state.outbuf,
2956 &pvar->ssh_state.outbuflen, len + (len >> 6) + 50);
2957 pvar->ssh_state.compress_stream.next_in =
2958 pvar->ssh_state.precompress_outbuf;
2959 pvar->ssh_state.compress_stream.avail_in = 9;
2960 pvar->ssh_state.compress_stream.next_out =
2961 pvar->ssh_state.outbuf + 12;
2962 pvar->ssh_state.compress_stream.avail_out =
2963 pvar->ssh_state.outbuflen - 12;
2964
2965 if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) != Z_OK) {
2966 #ifdef I18N
2967 strcpy(pvar->ts->UIMsg, "Error compressing packet data");
2968 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar);
2969 notify_fatal_error(pvar, pvar->ts->UIMsg);
2970 #else
2971 notify_fatal_error(pvar, "Error compressing packet data");
2972 #endif
2973 return;
2974 }
2975
2976 pvar->ssh_state.compress_stream.next_in =
2977 (unsigned char FAR *) buf;
2978 pvar->ssh_state.compress_stream.avail_in = len;
2979
2980 if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2981 Z_OK) {
2982 #ifdef I18N
2983 strcpy(pvar->ts->UIMsg, "Error compressing packet data");
2984 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar);
2985 notify_fatal_error(pvar, pvar->ts->UIMsg);
2986 #else
2987 notify_fatal_error(pvar, "Error compressing packet data");
2988 #endif
2989 return;
2990 }
2991 } else {
2992 memcpy(outmsg + 8, buf, len);
2993 }
2994
2995 finish_send_packet_special(pvar, 1);
2996
2997 } else {
2998 // �|�[�g�t�H���[�f�B���O���������N���C�A���g���������M�v�����ASSH���M���������T�[�o���������������B
2999 buffer_t *msg;
3000 unsigned char *outmsg;
3001 int len;
3002 Channel_t *c;
3003
3004 // SSH2���������������A�p�P�b�g���������B(2005.6.19 yutaka)
3005 if (pvar->rekeying) {
3006 // TODO: ���z���������p�P�b�g�j�����������A�p�P�b�g���������x���������������������A
3007 // �������������������B
3008 c = NULL;
3009
3010 return;
3011 }
3012
3013 c = ssh2_local_channel_lookup(channel_num);
3014 if (c == NULL)
3015 return;
3016
3017 msg = buffer_init();
3018 if (msg == NULL) {
3019 // TODO: error check
3020 return;
3021 }
3022 buffer_put_int(msg, c->remote_id);
3023 buffer_put_string(msg, (char *)buf, buflen);
3024
3025 len = buffer_len(msg);
3026 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_DATA, len);
3027 memcpy(outmsg, buffer_ptr(msg), len);
3028 finish_send_packet(pvar);
3029 buffer_free(msg);
3030
3031 // remote window size������
3032 c->remote_window -= len;
3033 }
3034
3035 }
3036
3037 void SSH_fail_channel_open(PTInstVar pvar, uint32 remote_channel_num)
3038 {
3039 if (SSHv1(pvar)) {
3040 unsigned char FAR *outmsg =
3041 begin_send_packet(pvar, SSH_MSG_CHANNEL_OPEN_FAILURE, 4);
3042
3043 set_uint32(outmsg, remote_channel_num);
3044 finish_send_packet(pvar);
3045
3046 } else { // SSH2 (2005.6.26 yutaka)
3047 int len;
3048 Channel_t *c = NULL;
3049 buffer_t *msg;
3050 unsigned char *outmsg;
3051
3052 msg = buffer_init();
3053 if (msg == NULL) {
3054 // TODO: error check
3055 return;
3056 }
3057 buffer_put_int(msg, remote_channel_num);
3058 buffer_put_int(msg, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
3059
3060 len = buffer_len(msg);
3061 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_OPEN_FAILURE, len);
3062 memcpy(outmsg, buffer_ptr(msg), len);
3063 finish_send_packet(pvar);
3064 buffer_free(msg);
3065
3066 }
3067 }
3068
3069 void SSH_confirm_channel_open(PTInstVar pvar, uint32 remote_channel_num,
3070 uint32 local_channel_num)
3071 {
3072 if (SSHv1(pvar)) {
3073 unsigned char FAR *outmsg =
3074 begin_send_packet(pvar, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 8);
3075
3076 set_uint32(outmsg, remote_channel_num);
3077 set_uint32(outmsg + 4, local_channel_num);
3078 finish_send_packet(pvar);
3079
3080 } else {
3081 buffer_t *msg;
3082 unsigned char *outmsg;
3083 int len;
3084 Channel_t *c;
3085
3086 // port-forwarding(remote to local)�����[�J�����������������T�[�o�������B(2005.7.2 yutaka)
3087 c = ssh2_local_channel_lookup(local_channel_num);
3088 if (c == NULL) {
3089 // It is sure to be successful as long as it's not a program bug either.
3090 return;
3091 }
3092
3093 msg = buffer_init();
3094 if (msg == NULL) {
3095 // TODO: error check
3096 return;
3097 }
3098 buffer_put_int(msg, c->remote_id);
3099 buffer_put_int(msg, c->self_id);
3100 buffer_put_int(msg, c->local_window);
3101 buffer_put_int(msg, c->local_maxpacket);
3102
3103 len = buffer_len(msg);
3104 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, len);
3105 memcpy(outmsg, buffer_ptr(msg), len);
3106 finish_send_packet(pvar);
3107 buffer_free(msg);
3108
3109 }
3110 }
3111
3112 void SSH_channel_output_eof(PTInstVar pvar, uint32 remote_channel_num)
3113 {
3114 if (SSHv1(pvar)){
3115 unsigned char FAR *outmsg =
3116 begin_send_packet(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4);
3117
3118 set_uint32(outmsg, remote_channel_num);
3119 finish_send_packet(pvar);
3120
3121 } else {
3122 // SSH2: ���������B
3123
3124 }
3125 }
3126
3127 void SSH_channel_input_eof(PTInstVar pvar, uint32 remote_channel_num, uint32 local_channel_num)
3128 {
3129 if (SSHv1(pvar)){
3130 unsigned char FAR *outmsg =
3131 begin_send_packet(pvar, SSH_MSG_CHANNEL_INPUT_EOF, 4);
3132
3133 set_uint32(outmsg, remote_channel_num);
3134 finish_send_packet(pvar);
3135
3136 } else {
3137 // SSH2: �`���l���N���[�Y���T�[�o�����m
3138 buffer_t *msg;
3139 unsigned char *outmsg;
3140 int len;
3141 Channel_t *c;
3142
3143 // SSH2���������������A�p�P�b�g���������B(2005.6.21 yutaka)
3144 if (pvar->rekeying) {
3145 // TODO: ���z���������p�P�b�g�j�����������A�p�P�b�g���������x���������������������A
3146 // �������������������B
3147 c = NULL;
3148
3149 return;
3150 }
3151
3152 c = ssh2_local_channel_lookup(local_channel_num);
3153 if (c == NULL)
3154 return;
3155
3156 msg = buffer_init();
3157 if (msg == NULL) {
3158 // TODO: error check
3159 return;
3160 }
3161 buffer_put_int(msg, c->remote_id); // remote ID
3162
3163 len = buffer_len(msg);
3164 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_EOF, len);
3165 memcpy(outmsg, buffer_ptr(msg), len);
3166 finish_send_packet(pvar);
3167 buffer_free(msg);
3168 }
3169
3170 }
3171
3172 void SSH_request_forwarding(PTInstVar pvar, int from_server_port,
3173 char FAR * to_local_host, int to_local_port)
3174 {
3175 if (SSHv1(pvar)) {
3176 int host_len = strlen(to_local_host);
3177 unsigned char FAR *outmsg =
3178 begin_send_packet(pvar, SSH_CMSG_PORT_FORWARD_REQUEST,
3179 12 + host_len);
3180
3181 set_uint32(outmsg, from_server_port);
3182 set_uint32(outmsg + 4, host_len);
3183 memcpy(outmsg + 8, to_local_host, host_len);
3184 set_uint32(outmsg + 8 + host_len, to_local_port);
3185 finish_send_packet(pvar);
3186
3187 enque_forwarding_request_handlers(pvar);
3188
3189 } else {
3190 // SSH2 port-forwading remote to local (2005.6.21 yutaka)
3191 buffer_t *msg;
3192 char *s;
3193 unsigned char *outmsg;
3194 int len;
3195
3196 msg = buffer_init();
3197 if (msg == NULL) {
3198 // TODO: error check
3199 return;
3200 }
3201 s = "tcpip-forward";
3202 buffer_put_string(msg, s, strlen(s)); // ctype
3203 buffer_put_char(msg, 1); // want reply
3204 s = "0.0.0.0";
3205 buffer_put_string(msg, s, strlen(s));
3206
3207 buffer_put_int(msg, from_server_port); // listening port
3208
3209 len = buffer_len(msg);
3210 outmsg = begin_send_packet(pvar, SSH2_MSG_GLOBAL_REQUEST, len);
3211 memcpy(outmsg, buffer_ptr(msg), len);
3212 finish_send_packet(pvar);
3213 buffer_free(msg);
3214
3215 }
3216 }
3217
3218 void SSH_request_X11_forwarding(PTInstVar pvar,
3219 char FAR * auth_protocol,
3220 unsigned char FAR * auth_data,
3221 int auth_data_len, int screen_num)
3222 {
3223 if (SSHv1(pvar)) {
3224 int protocol_len = strlen(auth_protocol);
3225 int data_len = auth_data_len * 2;
3226 unsigned char FAR *outmsg =
3227 begin_send_packet(pvar, SSH_CMSG_X11_REQUEST_FORWARDING,
3228 12 + protocol_len + data_len);
3229 int i;
3230 char FAR *auth_data_ptr;
3231
3232 set_uint32(outmsg, protocol_len);
3233 memcpy(outmsg + 4, auth_protocol, protocol_len);
3234 set_uint32(outmsg + 4 + protocol_len, data_len);
3235 auth_data_ptr = outmsg + 8 + protocol_len;
3236 for (i = 0; i < auth_data_len; i++) {
3237 sprintf