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 3058 - (show annotations) (download) (as text)
Tue Oct 30 15:01:43 2007 UTC (16 years, 5 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 194131 byte(s)
ウインドウサイズ計算のバグを修正した
送れなかったバッファの処理を改善した

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