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 2993 - (show annotations) (download) (as text)
Wed Aug 8 16:25:10 2007 UTC (16 years, 8 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 206399 byte(s)
no message

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