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 3056 - (show annotations) (download) (as text)
Sun Oct 28 15:36:45 2007 UTC (16 years, 5 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 192847 byte(s)
ポート転送において、remote_window未転送分の再送処理を追加。ただし、未完。

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