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 3073 - (show annotations) (download) (as text)
Tue Dec 11 19:33:02 2007 UTC (16 years, 4 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 193869 byte(s)
デフォルトユーザ名を指定しておらず、認証方式を challenge にしており、/ask4passwd を指定している場合、SSH2_MSG_SERVICE_REQUESTを2回送信してしまう問題を修正した。
認証方式を challenge にしており、CheckAuthListFirst が off で、/ask4passwd を指定している場合、TIS 認証ダイアログが自動的に出現しない問題を修正した。
CheckAuthListFirst が on で、ユーザ名を送信できる状態になる前にユーザ名を入力してフォーカスを外した場合、OKボタンを押したあとに認証が行われない問題を修正した。

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 //
60 // SSH2 data structure
61 //
62
63 // channel data structure
64 #define CHANNEL_MAX 100
65
66 enum channel_type {
67 TYPE_SHELL, TYPE_PORTFWD,
68 };
69
70 typedef struct bufchain {
71 buffer_t *msg;
72 struct bufchain *next;
73 } bufchain_t;
74
75 typedef struct channel {
76 int used;
77 int self_id;
78 int remote_id;
79 unsigned int local_window;
80 unsigned int local_window_max;
81 unsigned int local_consumed;
82 unsigned int local_maxpacket;
83 unsigned int remote_window;
84 unsigned int remote_maxpacket;
85 enum channel_type type;
86 int local_num;
87 bufchain_t *bufchain;
88 } Channel_t;
89
90 static Channel_t channels[CHANNEL_MAX];
91
92 static char ssh_ttymodes[] = "\x01\x03\x02\x1c\x03\x08\x04\x15\x05\x04";
93
94 static void try_send_credentials(PTInstVar pvar);
95 static void prep_compression(PTInstVar pvar);
96
97 // �����v���g�^�C�v����
98 void SSH2_send_kexinit(PTInstVar pvar);
99 static BOOL handle_SSH2_kexinit(PTInstVar pvar);
100 static void SSH2_dh_kex_init(PTInstVar pvar);
101 static void SSH2_dh_gex_kex_init(PTInstVar pvar);
102 static BOOL handle_SSH2_dh_common_reply(PTInstVar pvar);
103 static BOOL handle_SSH2_dh_gex_reply(PTInstVar pvar);
104 static BOOL handle_SSH2_newkeys(PTInstVar pvar);
105 static BOOL handle_SSH2_authrequest(PTInstVar pvar);
106 static BOOL handle_SSH2_userauth_success(PTInstVar pvar);
107 static BOOL handle_SSH2_userauth_failure(PTInstVar pvar);
108 static BOOL handle_SSH2_userauth_banner(PTInstVar pvar);
109 static BOOL handle_SSH2_open_confirm(PTInstVar pvar);
110 static BOOL handle_SSH2_open_failure(PTInstVar pvar);
111 static BOOL handle_SSH2_request_success(PTInstVar pvar);
112 static BOOL handle_SSH2_request_failure(PTInstVar pvar);
113 static BOOL handle_SSH2_channel_success(PTInstVar pvar);
114 static BOOL handle_SSH2_channel_data(PTInstVar pvar);
115 static BOOL handle_SSH2_channel_extended_data(PTInstVar pvar);
116 static BOOL handle_SSH2_channel_eof(PTInstVar pvar);
117 static BOOL handle_SSH2_channel_close(PTInstVar pvar);
118 static BOOL handle_SSH2_channel_open(PTInstVar pvar);
119 static BOOL handle_SSH2_window_adjust(PTInstVar pvar);
120 static BOOL handle_SSH2_channel_request(PTInstVar pvar);
121 void SSH2_dispatch_init(int stage);
122 int SSH2_dispatch_enabled_check(unsigned char message);
123 void SSH2_dispatch_add_message(unsigned char message);
124 void SSH2_dispatch_add_range_message(unsigned char begin, unsigned char end);
125 int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub);
126 static void start_ssh_heartbeat_thread(PTInstVar pvar);
127 static void SSH2_send_channel_data(PTInstVar pvar, Channel_t *c, unsigned char FAR * buf, unsigned int buflen);
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 int code = 0;
835 char *kind = NULL, buf[256];
836
837 #if 0
838 if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow,
839 0, 0) == SOCKET_ERROR
840 || ioctlsocket(pvar->socket, FIONBIO, &do_block) == SOCKET_ERROR
841 || retry_send_packet(pvar, data, len)
842 || (pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow,
843 pvar->notification_msg,
844 pvar->notification_events) ==
845 SOCKET_ERROR) {
846 UTIL_get_lang_msg("MSG_SSH_SEND_PKT_ERROR", pvar,
847 "A communications error occurred while sending an SSH packet.\n"
848 "The connection will close.");
849 notify_fatal_error(pvar, pvar->ts->UIMsg);
850 return FALSE;
851 } else {
852 return TRUE;
853 }
854 #else
855 if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow,
856 0, 0) == SOCKET_ERROR) {
857 code = WSAGetLastError();
858 kind = "WSAAsyncSelect1";
859 goto error;
860 }
861 if (ioctlsocket(pvar->socket, FIONBIO, &do_block) == SOCKET_ERROR) {
862 code = WSAGetLastError();
863 kind = "ioctlsocket";
864 goto error;
865 }
866 if (retry_send_packet(pvar, data, len) != 0) {
867 code = WSAGetLastError();
868 kind = "retry_send_packet";
869 goto error;
870 }
871 if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow,
872 pvar->notification_msg,
873 pvar->notification_events) ==
874 SOCKET_ERROR) {
875 code = WSAGetLastError();
876 kind = "WSAAsyncSelect2";
877 goto error;
878 }
879
880 return TRUE;
881
882 error:
883 UTIL_get_lang_msg("MSG_SSH_SEND_PKT_ERROR", pvar,
884 "A communications error occurred while sending an SSH packet.\n"
885 "The connection will close. (%s:%d)");
886 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg,
887 kind, code);
888 notify_fatal_error(pvar, buf);
889 return FALSE;
890 #endif
891 }
892
893 /* if skip_compress is true, then the data has already been compressed
894 into outbuf + 12 */
895 static void finish_send_packet_special(PTInstVar pvar, int skip_compress)
896 {
897 unsigned int len = pvar->ssh_state.outgoing_packet_len;
898 unsigned char FAR *data;
899 unsigned int data_length;
900 buffer_t *msg = NULL; // for SSH2 packet compression
901
902 if (pvar->ssh_state.compressing) {
903 if (!skip_compress) {
904 buf_ensure_size(&pvar->ssh_state.outbuf,
905 &pvar->ssh_state.outbuflen,
906 (int)(len + (len >> 6) + 50 +
907 CRYPT_get_sender_MAC_size(pvar)));
908 pvar->ssh_state.compress_stream.next_in =
909 pvar->ssh_state.precompress_outbuf;
910 pvar->ssh_state.compress_stream.avail_in = len;
911 pvar->ssh_state.compress_stream.next_out =
912 pvar->ssh_state.outbuf + 12;
913 pvar->ssh_state.compress_stream.avail_out =
914 pvar->ssh_state.outbuflen - 12;
915
916 if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) != Z_OK) {
917 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar,
918 "An error occurred while compressing packet data.\n"
919 "The connection will close.");
920 notify_fatal_error(pvar, pvar->ts->UIMsg);
921 return;
922 }
923 }
924
925 len =
926 pvar->ssh_state.outbuflen - 12 -
927 pvar->ssh_state.compress_stream.avail_out;
928 }
929
930 if (SSHv1(pvar)) {
931 int padding = 8 - ((len + 4) % 8);
932
933 data = pvar->ssh_state.outbuf + 8 - padding;
934 data_length = padding + len + 8;
935
936 set_uint32(data, len + 4);
937 if (CRYPT_get_receiver_cipher(pvar) != SSH_CIPHER_NONE) {
938 CRYPT_set_random_data(pvar, data + 4, padding);
939 } else {
940 memset(data + 4, 0, padding);
941 }
942 set_uint32(data + data_length - 4,
943 do_crc(data + 4, data_length - 8));
944 CRYPT_encrypt(pvar, data + 4, data_length - 4);
945 } else { //for SSH2(yutaka)
946 int block_size = CRYPT_get_encryption_block_size(pvar);
947 unsigned int encryption_size;
948 unsigned int padding;
949 BOOL ret;
950
951 /*
952 �f�[�^�\��
953 pvar->ssh_state.outbuf:
954 offset: 0 1 2 3 4 5 6 7 8 9 10 11 12 ... EOD
955 <--ignore---> ^^^^^^^^ <---- payload --->
956 packet length
957
958 ^^padding
959
960 <---------------------------->
961 SSH2 sending data on TCP
962
963 NOTE:
964 payload = type(1) + raw-data
965 len = ssh_state.outgoing_packet_len = payload size
966 */
967 // �p�P�b�g���k���L���������A�p�P�b�g�����k�����������M�p�P�b�g���\�z�����B(2005.7.9 yutaka)
968 // support of "Compression delayed" (2006.6.23 maya)
969 if ((pvar->ctos_compression == COMP_ZLIB ||
970 pvar->ctos_compression == COMP_DELAYED && pvar->userauth_success) &&
971 pvar->ssh2_keys[MODE_OUT].comp.enabled) {
972 // �����o�b�t�@�� packet-length(4) + padding(1) + payload(any) �������B
973 msg = buffer_init();
974 if (msg == NULL) {
975 // TODO: error check
976 return;
977 }
978
979 // ���k�������w�b�_�������y�C���[�h�����B
980 buffer_append(msg, "\0\0\0\0\0", 5); // 5 = packet-length(4) + padding(1)
981 if (buffer_compress(&pvar->ssh_state.compress_stream, pvar->ssh_state.outbuf + 12, len, msg) == -1) {
982 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar,
983 "An error occurred while compressing packet data.\n"
984 "The connection will close.");
985 notify_fatal_error(pvar, pvar->ts->UIMsg);
986 return;
987 }
988 data = buffer_ptr(msg);
989 len = buffer_len(msg) - 5; // 'len' is overwritten.
990
991 } else {
992 // �����k
993 data = pvar->ssh_state.outbuf + 7;
994
995 }
996
997 // ���M�p�P�b�g�\�z(input parameter: data, len)
998 if (block_size < 8) {
999 block_size = 8;
1000 }
1001 #if 0
1002 encryption_size = ((len + 8) / block_size + 1) * block_size;
1003 data_length = encryption_size + CRYPT_get_sender_MAC_size(pvar);
1004
1005 set_uint32(data, encryption_size - 4);
1006 padding = encryption_size - len - 5;
1007 data[4] = (unsigned char) padding;
1008 #else
1009 // �������p�P�b�g�����������������A�T�[�o����"Bad packet length"���������������������������B
1010 // (2007.10.29 yutaka)
1011 encryption_size = 4 + 1 + len;
1012 padding = block_size - (encryption_size % block_size);
1013 if (padding < 4)
1014 padding += block_size;
1015 encryption_size += padding;
1016 set_uint32(data, encryption_size - 4);
1017 data[4] = (unsigned char) padding;
1018 data_length = encryption_size + CRYPT_get_sender_MAC_size(pvar);
1019 #endif
1020 //if (pvar->ssh_state.outbuflen <= 7 + data_length) *(int *)0 = 0;
1021 CRYPT_set_random_data(pvar, data + 5 + len, padding);
1022 ret = CRYPT_build_sender_MAC(pvar,
1023 pvar->ssh_state.sender_sequence_number,
1024 data, encryption_size,
1025 data + encryption_size);
1026 if (ret == FALSE) { // HMAC��������������������������
1027 data_length = encryption_size;
1028 }
1029
1030 // �p�P�b�g�������������BHMAC���~�������������O�B
1031 CRYPT_encrypt(pvar, data, encryption_size);
1032 }
1033
1034 send_packet_blocking(pvar, data, data_length);
1035
1036 buffer_free(msg);
1037
1038 pvar->ssh_state.sender_sequence_number++;
1039
1040 // ���M�������L�^
1041 pvar->ssh_heartbeat_tick = time(NULL);
1042 }
1043
1044 static void destroy_packet_buf(PTInstVar pvar)
1045 {
1046 memset(pvar->ssh_state.outbuf, 0, pvar->ssh_state.outbuflen);
1047 if (pvar->ssh_state.compressing) {
1048 memset(pvar->ssh_state.precompress_outbuf, 0,
1049 pvar->ssh_state.precompress_outbuflen);
1050 }
1051 }
1052
1053 /* The handlers are added to the queue for each message. When one of the
1054 handlers fires, if it returns FALSE, then all handlers in the set are
1055 removed from their queues. */
1056 static void enque_handlers(PTInstVar pvar, int num_msgs,
1057 const int FAR * messages,
1058 const SSHPacketHandler FAR * handlers)
1059 {
1060 SSHPacketHandlerItem FAR *first_item;
1061 SSHPacketHandlerItem FAR *last_item = NULL;
1062 int i;
1063
1064 for (i = 0; i < num_msgs; i++) {
1065 SSHPacketHandlerItem FAR *item =
1066 (SSHPacketHandlerItem FAR *)
1067 malloc(sizeof(SSHPacketHandlerItem));
1068 SSHPacketHandlerItem FAR *cur_item =
1069 pvar->ssh_state.packet_handlers[messages[i]];
1070
1071 item->handler = handlers[i];
1072
1073 if (cur_item == NULL) {
1074 pvar->ssh_state.packet_handlers[messages[i]] = item;
1075 item->next_for_message = item;
1076 item->last_for_message = item;
1077 item->active_for_message = messages[i];
1078 } else {
1079 item->next_for_message = cur_item;
1080 item->last_for_message = cur_item->last_for_message;
1081 cur_item->last_for_message->next_for_message = item;
1082 cur_item->last_for_message = item;
1083 item->active_for_message = -1;
1084 }
1085
1086 if (last_item != NULL) {
1087 last_item->next_in_set = item;
1088 } else {
1089 first_item = item;
1090 }
1091 last_item = item;
1092 }
1093
1094 if (last_item != NULL) {
1095 last_item->next_in_set = first_item;
1096 }
1097 }
1098
1099 static SSHPacketHandler get_handler(PTInstVar pvar, int message)
1100 {
1101 SSHPacketHandlerItem FAR *cur_item =
1102 pvar->ssh_state.packet_handlers[message];
1103
1104 if (cur_item == NULL) {
1105 return NULL;
1106 } else {
1107 return cur_item->handler;
1108 }
1109 }
1110
1111 /* Called only by SSH_handle_packet */
1112 static void deque_handlers(PTInstVar pvar, int message)
1113 {
1114 SSHPacketHandlerItem FAR *cur_item =
1115 pvar->ssh_state.packet_handlers[message];
1116 SSHPacketHandlerItem FAR *first_item_in_set = cur_item;
1117
1118 do {
1119 SSHPacketHandlerItem FAR *next_in_set = cur_item->next_in_set;
1120
1121 if (cur_item->active_for_message >= 0) {
1122 SSHPacketHandlerItem FAR *replacement =
1123 cur_item->next_for_message;
1124
1125 if (replacement == cur_item) {
1126 replacement = NULL;
1127 } else {
1128 replacement->active_for_message =
1129 cur_item->active_for_message;
1130 }
1131 pvar->ssh_state.packet_handlers[cur_item->active_for_message] =
1132 replacement;
1133 }
1134 cur_item->next_for_message->last_for_message =
1135 cur_item->last_for_message;
1136 cur_item->last_for_message->next_for_message =
1137 cur_item->next_for_message;
1138
1139 free(cur_item);
1140 cur_item = next_in_set;
1141 } while (cur_item != first_item_in_set);
1142 }
1143
1144 static void enque_handler(PTInstVar pvar, int message,
1145 SSHPacketHandler handler)
1146 {
1147 enque_handlers(pvar, 1, &message, &handler);
1148 }
1149
1150 static void chop_newlines(char FAR * buf)
1151 {
1152 int len = strlen(buf);
1153
1154 while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) {
1155 buf[len - 1] = 0;
1156 len--;
1157 }
1158 }
1159
1160 /********************/
1161 /* Message handlers */
1162 /********************/
1163
1164 static BOOL handle_forwarding_success(PTInstVar pvar)
1165 {
1166 return FALSE;
1167 }
1168
1169 static BOOL handle_forwarding_failure(PTInstVar pvar)
1170 {
1171 return FALSE;
1172 }
1173
1174 static void enque_forwarding_request_handlers(PTInstVar pvar)
1175 {
1176 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1177 static const SSHPacketHandler handlers[]
1178 = { handle_forwarding_success, handle_forwarding_failure };
1179
1180 enque_handlers(pvar, 2, msgs, handlers);
1181 }
1182
1183 static BOOL handle_auth_failure(PTInstVar pvar)
1184 {
1185 notify_verbose_message(pvar, "Authentication failed",
1186 LOG_LEVEL_VERBOSE);
1187
1188 // retry count������ (2005.7.15 yutaka)
1189 pvar->userauth_retry_count++;
1190
1191 AUTH_set_generic_mode(pvar);
1192 AUTH_advance_to_next_cred(pvar);
1193 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1194 try_send_credentials(pvar);
1195 return FALSE;
1196 }
1197
1198 static BOOL handle_rsa_auth_refused(PTInstVar pvar)
1199 {
1200 AUTH_destroy_cur_cred(pvar);
1201 return handle_auth_failure(pvar);
1202 }
1203
1204 static BOOL handle_TIS_challenge(PTInstVar pvar)
1205 {
1206 if (grab_payload(pvar, 4)) {
1207 int len = get_payload_uint32(pvar, 0);
1208
1209 if (grab_payload(pvar, len)) {
1210 notify_verbose_message(pvar, "Received TIS challenge",
1211 LOG_LEVEL_VERBOSE);
1212
1213 AUTH_set_TIS_mode(pvar, pvar->ssh_state.payload + 4, len);
1214 AUTH_advance_to_next_cred(pvar);
1215 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1216 try_send_credentials(pvar);
1217 }
1218 }
1219 return FALSE;
1220 }
1221
1222 static BOOL handle_auth_required(PTInstVar pvar)
1223 {
1224 notify_verbose_message(pvar, "Server requires authentication",
1225 LOG_LEVEL_VERBOSE);
1226
1227 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1228 try_send_credentials(pvar);
1229 /* the first AUTH_advance_to_next_cred is issued early by ttxssh.c */
1230
1231 return FALSE;
1232 }
1233
1234 static BOOL handle_ignore(PTInstVar pvar)
1235 {
1236 if (SSHv1(pvar)) {
1237 if (grab_payload(pvar, 4)
1238 && grab_payload(pvar, get_payload_uint32(pvar, 0))) {
1239 /* ignore it! but it must be decompressed */
1240 }
1241 }
1242 /*
1243 else {
1244 // ���b�Z�[�W�� SSH2_MSG_IGNORE ����������������
1245 // Cisco ���[�^���� (2006.11.28 maya)
1246 }
1247 */
1248 return TRUE;
1249 }
1250
1251 static BOOL handle_debug(PTInstVar pvar)
1252 {
1253 BOOL always_display;
1254 char FAR *description;
1255 int description_len;
1256 char buf[2048];
1257
1258 if (SSHv1(pvar)) {
1259 if (grab_payload(pvar, 4)
1260 && grab_payload(pvar, description_len =
1261 get_payload_uint32(pvar, 0))) {
1262 always_display = FALSE;
1263 description = pvar->ssh_state.payload + 4;
1264 description[description_len] = 0;
1265 } else {
1266 return TRUE;
1267 }
1268 } else {
1269 if (grab_payload(pvar, 5)
1270 && grab_payload(pvar,
1271 (description_len = get_payload_uint32(pvar, 1)) + 4)
1272 && grab_payload(pvar,
1273 get_payload_uint32(pvar, 5 + description_len))) {
1274 always_display = pvar->ssh_state.payload[0] != 0;
1275 description = pvar->ssh_state.payload + 5;
1276 description[description_len] = 0;
1277 } else {
1278 return TRUE;
1279 }
1280 }
1281
1282 chop_newlines(description);
1283 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "DEBUG message from server: %s",
1284 description);
1285 if (always_display) {
1286 notify_nonfatal_error(pvar, buf);
1287 } else {
1288 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
1289 }
1290 return TRUE;
1291 }
1292
1293 static BOOL handle_disconnect(PTInstVar pvar)
1294 {
1295 int reason_code;
1296 char FAR *description;
1297 int description_len;
1298 char buf[2048];
1299 char FAR *explanation = "";
1300 char uimsg[MAX_UIMSG];
1301
1302 if (SSHv1(pvar)) {
1303 if (grab_payload(pvar, 4)
1304 && grab_payload(pvar, description_len = get_payload_uint32(pvar, 0))) {
1305 reason_code = -1;
1306 description = pvar->ssh_state.payload + 4;
1307 description[description_len] = 0;
1308 } else {
1309 return TRUE;
1310 }
1311 } else {
1312 if (grab_payload(pvar, 8)
1313 && grab_payload(pvar,
1314 (description_len = get_payload_uint32(pvar, 4)) + 4)
1315 && grab_payload(pvar,
1316 get_payload_uint32(pvar, 8 + description_len))) {
1317 reason_code = get_payload_uint32(pvar, 0);
1318 description = pvar->ssh_state.payload + 8;
1319 description[description_len] = 0;
1320 } else {
1321 return TRUE;
1322 }
1323 }
1324
1325 chop_newlines(description);
1326 if (description[0] == 0) {
1327 description = NULL;
1328 }
1329
1330 if (get_handler(pvar, SSH_SMSG_FAILURE) == handle_forwarding_failure) {
1331 UTIL_get_lang_msg("MSG_SSH_UNABLE_FWD_ERROR", pvar,
1332 "\nIt may have disconnected because it was unable to forward a port you requested to be forwarded from the server.\n"
1333 "This often happens when someone is already forwarding that port from the server.");
1334 strncpy_s(uimsg, sizeof(uimsg), pvar->ts->UIMsg, _TRUNCATE);
1335 explanation = uimsg;
1336 }
1337
1338 if (description != NULL) {
1339 UTIL_get_lang_msg("MSG_SSH_SERVER_DISCON_ERROR", pvar,
1340 "Server disconnected with message '%s'%s");
1341 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1342 pvar->ts->UIMsg, description,
1343 explanation);
1344 } else {
1345 UTIL_get_lang_msg("MSG_SSH_SERVER_DISCON_NORES_ERROR", pvar,
1346 "Server disconnected (no reason given).%s");
1347 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1348 pvar->ts->UIMsg, explanation);
1349 }
1350 notify_fatal_error(pvar, buf);
1351
1352 return TRUE;
1353 }
1354
1355 static BOOL handle_unimplemented(PTInstVar pvar)
1356 {
1357 /* Should never receive this since we only send base 2.0 protocol messages */
1358 grab_payload(pvar, 4);
1359 return TRUE;
1360 }
1361
1362 static BOOL handle_crypt_success(PTInstVar pvar)
1363 {
1364 notify_verbose_message(pvar, "Secure mode successfully achieved",
1365 LOG_LEVEL_VERBOSE);
1366 return FALSE;
1367 }
1368
1369 static BOOL handle_noauth_success(PTInstVar pvar)
1370 {
1371 notify_verbose_message(pvar, "Server does not require authentication",
1372 LOG_LEVEL_VERBOSE);
1373 prep_compression(pvar);
1374 return FALSE;
1375 }
1376
1377 static BOOL handle_auth_success(PTInstVar pvar)
1378 {
1379 notify_verbose_message(pvar, "Authentication accepted",
1380 LOG_LEVEL_VERBOSE);
1381 prep_compression(pvar);
1382
1383 // �n�[�g�r�[�g�E�X���b�h���J�n (2004.12.11 yutaka)
1384 start_ssh_heartbeat_thread(pvar);
1385
1386 return FALSE;
1387 }
1388
1389 static BOOL handle_server_public_key(PTInstVar pvar)
1390 {
1391 int server_key_public_exponent_len;
1392 int server_key_public_modulus_pos;
1393 int server_key_public_modulus_len;
1394 int host_key_bits_pos;
1395 int host_key_public_exponent_len;
1396 int host_key_public_modulus_pos;
1397 int host_key_public_modulus_len;
1398 int protocol_flags_pos;
1399 int supported_ciphers;
1400 char FAR *inmsg;
1401 Key hostkey;
1402
1403 if (!grab_payload(pvar, 14))
1404 return FALSE;
1405 server_key_public_exponent_len = get_mpint_len(pvar, 12);
1406
1407 if (!grab_payload(pvar, server_key_public_exponent_len + 2))
1408 return FALSE;
1409 server_key_public_modulus_pos = 14 + server_key_public_exponent_len;
1410 server_key_public_modulus_len =
1411 get_mpint_len(pvar, server_key_public_modulus_pos);
1412
1413 if (!grab_payload(pvar, server_key_public_modulus_len + 6))
1414 return FALSE;
1415 host_key_bits_pos =
1416 server_key_public_modulus_pos + 2 + server_key_public_modulus_len;
1417 host_key_public_exponent_len =
1418 get_mpint_len(pvar, host_key_bits_pos + 4);
1419
1420 if (!grab_payload(pvar, host_key_public_exponent_len + 2))
1421 return FALSE;
1422 host_key_public_modulus_pos =
1423 host_key_bits_pos + 6 + host_key_public_exponent_len;
1424 host_key_public_modulus_len =
1425 get_mpint_len(pvar, host_key_public_modulus_pos);
1426
1427 if (!grab_payload(pvar, host_key_public_modulus_len + 12))
1428 return FALSE;
1429 protocol_flags_pos =
1430 host_key_public_modulus_pos + 2 + host_key_public_modulus_len;
1431
1432 inmsg = pvar->ssh_state.payload;
1433
1434 CRYPT_set_server_cookie(pvar, inmsg);
1435 if (!CRYPT_set_server_RSA_key(pvar,
1436 get_uint32(inmsg + 8),
1437 pvar->ssh_state.payload + 12,
1438 inmsg + server_key_public_modulus_pos))
1439 return FALSE;
1440 if (!CRYPT_set_host_RSA_key(pvar,
1441 get_uint32(inmsg + host_key_bits_pos),
1442 inmsg + host_key_bits_pos + 4,
1443 inmsg + host_key_public_modulus_pos))
1444 return FALSE;
1445 pvar->ssh_state.server_protocol_flags =
1446 get_uint32(inmsg + protocol_flags_pos);
1447
1448 supported_ciphers = get_uint32(inmsg + protocol_flags_pos + 4);
1449 if (!CRYPT_set_supported_ciphers(pvar,
1450 supported_ciphers,
1451 supported_ciphers))
1452 return FALSE;
1453 if (!AUTH_set_supported_auth_types(pvar,
1454 get_uint32(inmsg + protocol_flags_pos + 8)))
1455 return FALSE;
1456
1457 /* this must be the LAST THING in this function, since it can cause
1458 host_is_OK to be called. */
1459 hostkey.type = KEY_RSA1;
1460 hostkey.bits = get_uint32(inmsg + host_key_bits_pos);
1461 hostkey.exp = inmsg + host_key_bits_pos + 4;
1462 hostkey.mod = inmsg + host_key_public_modulus_pos;
1463 HOSTS_check_host_key(pvar, pvar->ssh_state.hostname, &hostkey);
1464
1465 return FALSE;
1466 }
1467
1468 /*
1469 The ID must have already been found to start with "SSH-". It must
1470 be null-terminated.
1471 */
1472 static BOOL parse_protocol_ID(PTInstVar pvar, char FAR * ID)
1473 {
1474 char FAR *str;
1475
1476 for (str = ID + 4; *str >= '0' && *str <= '9'; str++) {
1477 }
1478
1479 if (*str != '.') {
1480 return FALSE;
1481 }
1482
1483 pvar->protocol_major = atoi(ID + 4);
1484 pvar->protocol_minor = atoi(str + 1);
1485
1486 // for SSH2(yutaka)
1487 // 1.99����SSH2�����������s��
1488 if (pvar->protocol_major == 1 && pvar->protocol_minor == 99) {
1489 // ���[�U�� SSH2 ���I������������������
1490 if (pvar->settings.ssh_protocol_version == 2) {
1491 pvar->protocol_major = 2;
1492 pvar->protocol_minor = 0;
1493 }
1494
1495 }
1496
1497 for (str = str + 1; *str >= '0' && *str <= '9'; str++) {
1498 }
1499
1500 return *str == '-';
1501 }
1502
1503 /*
1504 On entry, the pvar->protocol_xxx fields hold the server's advertised
1505 protocol number. We replace the fields with the protocol number we will
1506 actually use, or return FALSE if there is no usable protocol version.
1507 */
1508 static BOOL negotiate_protocol(PTInstVar pvar)
1509 {
1510 switch (pvar->protocol_major) {
1511 case 1:
1512 if (pvar->protocol_minor > 5) {
1513 pvar->protocol_minor = 5;
1514 }
1515
1516 return TRUE;
1517
1518 // for SSH2(yutaka)
1519 case 2:
1520 return TRUE; // SSH2 support
1521
1522 default:
1523 return FALSE;
1524 }
1525 }
1526
1527 static void init_protocol(PTInstVar pvar)
1528 {
1529 CRYPT_initialize_random_numbers(pvar);
1530
1531 // known_hosts�t�@�C�������z�X�g���J������������������
1532 HOSTS_prefetch_host_key(pvar, pvar->ssh_state.hostname);
1533
1534 /* while we wait for a response from the server... */
1535
1536 if (SSHv1(pvar)) {
1537 enque_handler(pvar, SSH_MSG_DISCONNECT, handle_disconnect);
1538 enque_handler(pvar, SSH_MSG_IGNORE, handle_ignore);
1539 enque_handler(pvar, SSH_MSG_DEBUG, handle_debug);
1540 enque_handler(pvar, SSH_SMSG_PUBLIC_KEY, handle_server_public_key);
1541
1542 } else { // for SSH2(yutaka)
1543 enque_handler(pvar, SSH2_MSG_DISCONNECT, handle_disconnect);
1544 enque_handler(pvar, SSH2_MSG_IGNORE, handle_ignore);
1545 enque_handler(pvar, SSH2_MSG_DEBUG, handle_debug);
1546 enque_handler(pvar, SSH2_MSG_KEXINIT, handle_SSH2_kexinit);
1547 enque_handler(pvar, SSH2_MSG_KEXDH_INIT, handle_unimplemented);
1548 enque_handler(pvar, SSH2_MSG_KEXDH_REPLY, handle_SSH2_dh_common_reply);
1549 enque_handler(pvar, SSH2_MSG_KEX_DH_GEX_REPLY, handle_SSH2_dh_gex_reply);
1550 enque_handler(pvar, SSH2_MSG_NEWKEYS, handle_SSH2_newkeys);
1551 enque_handler(pvar, SSH2_MSG_SERVICE_ACCEPT, handle_SSH2_authrequest);
1552 enque_handler(pvar, SSH2_MSG_USERAUTH_SUCCESS, handle_SSH2_userauth_success);
1553 enque_handler(pvar, SSH2_MSG_USERAUTH_FAILURE, handle_SSH2_userauth_failure);
1554 enque_handler(pvar, SSH2_MSG_USERAUTH_BANNER, handle_SSH2_userauth_banner);
1555 enque_handler(pvar, SSH2_MSG_USERAUTH_INFO_REQUEST, handle_SSH2_userauth_inforeq);
1556
1557 enque_handler(pvar, SSH2_MSG_UNIMPLEMENTED, handle_unimplemented);
1558
1559 // ���[�U�F�������f�B�X�p�b�`���[�`��
1560 enque_handler(pvar, SSH2_MSG_CHANNEL_CLOSE, handle_SSH2_channel_close);
1561 enque_handler(pvar, SSH2_MSG_CHANNEL_DATA, handle_SSH2_channel_data);
1562 enque_handler(pvar, SSH2_MSG_CHANNEL_EOF, handle_SSH2_channel_eof);
1563 enque_handler(pvar, SSH2_MSG_CHANNEL_EXTENDED_DATA, handle_SSH2_channel_extended_data);
1564 enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN, handle_SSH2_channel_open);
1565 enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, handle_SSH2_open_confirm);
1566 enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN_FAILURE, handle_SSH2_open_failure);
1567 enque_handler(pvar, SSH2_MSG_CHANNEL_REQUEST, handle_SSH2_channel_request);
1568 enque_handler(pvar, SSH2_MSG_CHANNEL_WINDOW_ADJUST, handle_SSH2_window_adjust);
1569 enque_handler(pvar, SSH2_MSG_CHANNEL_SUCCESS, handle_SSH2_channel_success);
1570 // enque_handler(pvar, SSH2_MSG_GLOBAL_REQUEST, handle_unimplemented);
1571 enque_handler(pvar, SSH2_MSG_REQUEST_FAILURE, handle_SSH2_request_failure);
1572 enque_handler(pvar, SSH2_MSG_REQUEST_SUCCESS, handle_SSH2_request_success);
1573
1574 }
1575 }
1576
1577 BOOL SSH_handle_server_ID(PTInstVar pvar, char FAR * ID, int ID_len)
1578 {
1579 static const char prefix[] = "Received server prologue string: ";
1580
1581 // initialize SSH2 memory dump (2005.3.7 yutaka)
1582 init_memdump();
1583 push_memdump("pure server ID", "start protocol version exchange", ID, ID_len);
1584
1585 if (ID_len <= 0) {
1586 return FALSE;
1587 } else {
1588 int buf_len = ID_len + NUM_ELEM(prefix);
1589 char FAR *buf = (char FAR *) malloc(buf_len);
1590
1591 strncpy_s(buf, buf_len, prefix, _TRUNCATE);
1592 strncat_s(buf, buf_len, ID, _TRUNCATE);
1593 chop_newlines(buf);
1594
1595 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
1596
1597 free(buf);
1598
1599
1600 // ���������R�s�[������ (2005.3.9 yutaka)
1601 #if 0
1602 // for calculate SSH2 hash
1603 // �T�[�o�o�[�W�����������i���s���������������j
1604 if (ID_len >= sizeof(pvar->server_version_string))
1605 return FALSE;
1606 strncpy(pvar->server_version_string, ID, ID_len);
1607 #endif
1608
1609
1610 if (ID[ID_len - 1] != '\n') {
1611 pvar->ssh_state.status_flags |= STATUS_IN_PARTIAL_ID_STRING;
1612 return FALSE;
1613 } else if ((pvar->ssh_state.status_flags & STATUS_IN_PARTIAL_ID_STRING) != 0) {
1614 pvar->ssh_state.status_flags &= ~STATUS_IN_PARTIAL_ID_STRING;
1615 return FALSE;
1616 } else if (strncmp(ID, "SSH-", 4) != 0) {
1617 return FALSE;
1618 } else {
1619 ID[ID_len - 1] = 0;
1620
1621 if (ID_len > 1 && ID[ID_len - 2] == '\r') {
1622 ID[ID_len - 2] = 0;
1623 }
1624
1625 pvar->ssh_state.server_ID = _strdup(ID);
1626
1627 if (!parse_protocol_ID(pvar, ID) || !negotiate_protocol(pvar)) {
1628 UTIL_get_lang_msg("MSG_SSH_VERSION_ERROR", pvar,
1629 "This program does not understand the server's version of the protocol.");
1630 notify_fatal_error(pvar, pvar->ts->UIMsg);
1631 } else {
1632 char TTSSH_ID[1024];
1633 int TTSSH_ID_len;
1634 int a, b, c, d;
1635
1636 // �������g���o�[�W�������������� (2005.3.3 yutaka)
1637 get_file_version("ttxssh.dll", &a, &b, &c, &d);
1638
1639 _snprintf_s(TTSSH_ID, sizeof(TTSSH_ID), _TRUNCATE,
1640 "SSH-%d.%d-TTSSH/%d.%d Win32\n",
1641 pvar->protocol_major, pvar->protocol_minor, a, b);
1642 TTSSH_ID_len = strlen(TTSSH_ID);
1643
1644 // for SSH2(yutaka)
1645 // �N���C�A���g�o�[�W�����������i���s���������������j
1646 strncpy_s(pvar->client_version_string, sizeof(pvar->client_version_string),
1647 TTSSH_ID, _TRUNCATE);
1648
1649 // �T�[�o�o�[�W�����������i���s���������������j(2005.3.9 yutaka)
1650 _snprintf_s(pvar->server_version_string,
1651 sizeof(pvar->server_version_string), _TRUNCATE,
1652 "%s", pvar->ssh_state.server_ID);
1653
1654 if ((pvar->Psend) (pvar->socket, TTSSH_ID, TTSSH_ID_len,
1655 0) != TTSSH_ID_len) {
1656 UTIL_get_lang_msg("MSG_SSH_SEND_ID_ERROR", pvar,
1657 "An error occurred while sending the SSH ID string.\n"
1658 "The connection will close.");
1659 notify_fatal_error(pvar, pvar->ts->UIMsg);
1660 } else {
1661 // ���s�R�[�h������ (2004.8.4 yutaka)
1662 pvar->client_version_string[--TTSSH_ID_len] = 0;
1663
1664 push_memdump("server ID", NULL, pvar->server_version_string, strlen(pvar->server_version_string));
1665 push_memdump("client ID", NULL, pvar->client_version_string, strlen(pvar->client_version_string));
1666
1667 // SSH�n���h�����o�^���s��
1668 init_protocol(pvar);
1669
1670 SSH2_dispatch_init(1);
1671 SSH2_dispatch_add_message(SSH2_MSG_KEXINIT);
1672 SSH2_dispatch_add_message(SSH2_MSG_IGNORE); // XXX: Tru64 UNIX workaround (2005.3.3 yutaka)
1673 }
1674 }
1675
1676 return TRUE;
1677 }
1678 }
1679 }
1680
1681 static BOOL handle_exit(PTInstVar pvar)
1682 {
1683 if (grab_payload(pvar, 4)) {
1684 begin_send_packet(pvar, SSH_CMSG_EXIT_CONFIRMATION, 0);
1685 finish_send_packet(pvar);
1686 notify_closed_connection(pvar);
1687 }
1688 return TRUE;
1689 }
1690
1691 static BOOL handle_data(PTInstVar pvar)
1692 {
1693 if (grab_payload_limited(pvar, 4)) {
1694 pvar->ssh_state.payload_datalen = get_payload_uint32(pvar, 0);
1695 pvar->ssh_state.payload_datastart = 4;
1696 }
1697 return TRUE;
1698 }
1699
1700 static BOOL handle_channel_open(PTInstVar pvar)
1701 {
1702 int host_len;
1703 int originator_len;
1704
1705 if ((pvar->ssh_state.
1706 server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
1707 if (grab_payload(pvar, 8)
1708 && grab_payload(pvar,
1709 8 + (host_len = get_payload_uint32(pvar, 4)))
1710 && grab_payload(pvar, originator_len =
1711 get_payload_uint32(pvar, host_len + 12))) {
1712 int local_port = get_payload_uint32(pvar, 8 + host_len);
1713
1714 pvar->ssh_state.payload[8 + host_len] = 0;
1715 FWD_open(pvar, get_payload_uint32(pvar, 0),
1716 pvar->ssh_state.payload + 8, local_port,
1717 pvar->ssh_state.payload + 16 + host_len,
1718 originator_len,
1719 NULL);
1720 }
1721 } else {
1722 if (grab_payload(pvar, 8)
1723 && grab_payload(pvar,
1724 4 + (host_len = get_payload_uint32(pvar, 4)))) {
1725 int local_port = get_payload_uint32(pvar, 8 + host_len);
1726
1727 pvar->ssh_state.payload[8 + host_len] = 0;
1728 FWD_open(pvar, get_payload_uint32(pvar, 0),
1729 pvar->ssh_state.payload + 8, local_port, NULL, 0,
1730 NULL);
1731 }
1732 }
1733
1734 return TRUE;
1735 }
1736
1737 static BOOL handle_X11_channel_open(PTInstVar pvar)
1738 {
1739 int originator_len;
1740
1741 if ((pvar->ssh_state.server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
1742 if (grab_payload(pvar, 8)
1743 && grab_payload(pvar, originator_len = get_payload_uint32(pvar, 4))) {
1744 FWD_X11_open(pvar, get_payload_uint32(pvar, 0),
1745 pvar->ssh_state.payload + 8, originator_len, NULL);
1746 }
1747 } else {
1748 if (grab_payload(pvar, 4)) {
1749 FWD_X11_open(pvar, get_payload_uint32(pvar, 0), NULL, 0, NULL);
1750 }
1751 }
1752
1753 return TRUE;
1754 }
1755
1756 static BOOL handle_channel_open_confirmation(PTInstVar pvar)
1757 {
1758 if (grab_payload(pvar, 8)) {
1759 FWD_confirmed_open(pvar, get_payload_uint32(pvar, 0),
1760 get_payload_uint32(pvar, 4));
1761 }
1762 return FALSE;
1763 }
1764
1765 static BOOL handle_channel_open_failure(PTInstVar pvar)
1766 {
1767 if (grab_payload(pvar, 4)) {
1768 FWD_failed_open(pvar, get_payload_uint32(pvar, 0));
1769 }
1770 return FALSE;
1771 }
1772
1773 static BOOL handle_channel_data(PTInstVar pvar)
1774 {
1775 int len;
1776
1777 if (grab_payload(pvar, 8)
1778 && grab_payload(pvar, len = get_payload_uint32(pvar, 4))) {
1779 FWD_received_data(pvar, get_payload_uint32(pvar, 0),
1780 pvar->ssh_state.payload + 8, len);
1781 }
1782 return TRUE;
1783 }
1784
1785 static BOOL handle_channel_input_eof(PTInstVar pvar)
1786 {
1787 if (grab_payload(pvar, 4)) {
1788 FWD_channel_input_eof(pvar, get_payload_uint32(pvar, 0));
1789 }
1790 return TRUE;
1791 }
1792
1793 static BOOL handle_channel_output_eof(PTInstVar pvar)
1794 {
1795 if (grab_payload(pvar, 4)) {
1796 FWD_channel_output_eof(pvar, get_payload_uint32(pvar, 0));
1797 }
1798 return TRUE;
1799 }
1800
1801
1802
1803 // �n���h�����O�������b�Z�[�W����������
1804
1805 #define HANDLE_MESSAGE_MAX 30
1806 static unsigned char handle_messages[HANDLE_MESSAGE_MAX];
1807 static int handle_message_count = 0;
1808 static int handle_message_stage = 0;
1809
1810 void SSH2_dispatch_init(int stage)
1811 {
1812 handle_message_count = 0;
1813 handle_message_stage = stage;
1814 }
1815
1816 int SSH2_dispatch_enabled_check(unsigned char message)
1817 {
1818 int i;
1819
1820 for (i = 0 ; i < handle_message_count ; i++) {
1821 if (handle_messages[i] == message)
1822 return 1;
1823 }
1824 return 0;
1825 }
1826
1827 void SSH2_dispatch_add_message(unsigned char message)
1828 {
1829
1830 if (handle_message_count >= HANDLE_MESSAGE_MAX) {
1831 // TODO: error check
1832 return;
1833 }
1834
1835 handle_messages[handle_message_count++] = message;
1836 }
1837
1838 void SSH2_dispatch_add_range_message(unsigned char begin, unsigned char end)
1839 {
1840 unsigned char c;
1841
1842 for (c = begin ; c <= end ; c++) {
1843 SSH2_dispatch_add_message(c);
1844 }
1845 }
1846
1847
1848 void SSH_handle_packet(PTInstVar pvar, char FAR * data, int len,
1849 int padding)
1850 {
1851 unsigned char message = prep_packet(pvar, data, len, padding);
1852
1853
1854 #ifdef SSH2_DEBUG
1855 // for SSH2(yutaka)
1856 if (SSHv2(pvar)) {
1857 if (pvar->key_done) {
1858 message = message;
1859 }
1860
1861 if (pvar->userauth_success) {
1862 message = message;
1863 }
1864
1865 if (pvar->rekeying) {
1866 message = message;
1867 }
1868 }
1869 #endif
1870
1871 // SSH�����b�Z�[�W�^�C�v���`�F�b�N
1872 if (message != SSH_MSG_NONE) {
1873 // ���b�Z�[�W�^�C�v���������n���h�����N��
1874 SSHPacketHandler handler = get_handler(pvar, message);
1875
1876 // for SSH2(yutaka)
1877 if (SSHv2(pvar)) {
1878 // �z���O�����b�Z�[�W�^�C�v�������������A�{�[�g�������B
1879 if (!SSH2_dispatch_enabled_check(message) || handler == NULL) {
1880 char buf[1024];
1881
1882 UTIL_get_lang_msg("MSG_SSH_UNEXP_MSG2_ERROR", pvar,
1883 "Unexpected SSH2 message(%d) on current stage(%d)");
1884 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1885 pvar->ts->UIMsg, message, handle_message_stage);
1886 notify_fatal_error(pvar, buf);
1887 // abort
1888 }
1889 }
1890
1891 if (handler == NULL) {
1892 if (SSHv1(pvar)) {
1893 char buf[1024];
1894
1895 UTIL_get_lang_msg("MSG_SSH_UNEXP_MSG_ERROR", pvar,
1896 "Unexpected packet type received: %d");
1897 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1898 pvar->ts->UIMsg, message, handle_message_stage);
1899 notify_fatal_error(pvar, buf);
1900 } else {
1901 unsigned char FAR *outmsg =
1902 begin_send_packet(pvar, SSH2_MSG_UNIMPLEMENTED, 4);
1903
1904 set_uint32(outmsg,
1905 pvar->ssh_state.receiver_sequence_number - 1);
1906 finish_send_packet(pvar);
1907 /* XXX need to decompress incoming packet, but how? */
1908 }
1909 } else {
1910 if (!handler(pvar)) {
1911 deque_handlers(pvar, message);
1912 }
1913 }
1914 }
1915 }
1916
1917 static BOOL handle_pty_success(PTInstVar pvar)
1918 {
1919 FWD_enter_interactive_mode(pvar);
1920 enque_handler(pvar, SSH_SMSG_EXITSTATUS, handle_exit);
1921 enque_handler(pvar, SSH_SMSG_STDOUT_DATA, handle_data);
1922 enque_handler(pvar, SSH_SMSG_STDERR_DATA, handle_data);
1923 enque_handler(pvar, SSH_MSG_CHANNEL_DATA, handle_channel_data);
1924 enque_handler(pvar, SSH_MSG_CHANNEL_INPUT_EOF,
1925 handle_channel_input_eof);
1926 enque_handler(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED,
1927 handle_channel_output_eof);
1928 enque_handler(pvar, SSH_MSG_PORT_OPEN, handle_channel_open);
1929 enque_handler(pvar, SSH_SMSG_X11_OPEN, handle_X11_channel_open);
1930 return FALSE;
1931 }
1932
1933 static BOOL handle_pty_failure(PTInstVar pvar)
1934 {
1935 UTIL_get_lang_msg("MSG_SSH_ALLOC_TERMINAL_ERROR", pvar,
1936 "The server cannot allocate a pseudo-terminal. "
1937 "You may encounter some problems with the terminal.");
1938 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1939 return handle_pty_success(pvar);
1940 }
1941
1942 static void prep_pty(PTInstVar pvar)
1943 {
1944 int len = strlen(pvar->ts->TermType);
1945 unsigned char FAR *outmsg =
1946 begin_send_packet(pvar, SSH_CMSG_REQUEST_PTY,
1947 4 + len + 16 + sizeof(ssh_ttymodes));
1948 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1949 static const SSHPacketHandler handlers[]
1950 = { handle_pty_success, handle_pty_failure };
1951
1952 set_uint32(outmsg, len);
1953 memcpy(outmsg + 4, pvar->ts->TermType, len);
1954 set_uint32(outmsg + 4 + len, pvar->ssh_state.win_rows);
1955 set_uint32(outmsg + 4 + len + 4, pvar->ssh_state.win_cols);
1956 set_uint32(outmsg + 4 + len + 8, 0);
1957 set_uint32(outmsg + 4 + len + 12, 0);
1958 memcpy(outmsg + 4 + len + 16, ssh_ttymodes, sizeof(ssh_ttymodes));
1959 finish_send_packet(pvar);
1960
1961 enque_handlers(pvar, 2, msgs, handlers);
1962
1963 begin_send_packet(pvar, SSH_CMSG_EXEC_SHELL, 0);
1964 finish_send_packet(pvar);
1965 }
1966
1967 static void prep_forwarding(PTInstVar pvar)
1968 {
1969 FWD_prep_forwarding(pvar);
1970 prep_pty(pvar);
1971 }
1972
1973
1974 //
1975 //
1976 // (2005.7.10 yutaka)
1977 static void enable_send_compression(PTInstVar pvar)
1978 {
1979 static int initialize = 0;
1980
1981 if (initialize) {
1982 deflateEnd(&pvar->ssh_state.compress_stream);
1983 }
1984 initialize = 1;
1985
1986 pvar->ssh_state.compress_stream.zalloc = NULL;
1987 pvar->ssh_state.compress_stream.zfree = NULL;
1988 pvar->ssh_state.compress_stream.opaque = NULL;
1989 if (deflateInit
1990 (&pvar->ssh_state.compress_stream,
1991 pvar->ssh_state.compression_level) != Z_OK) {
1992 UTIL_get_lang_msg("MSG_SSH_SETUP_COMP_ERROR", pvar,
1993 "An error occurred while setting up compression.\n"
1994 "The connection will close.");
1995 notify_fatal_error(pvar, pvar->ts->UIMsg);
1996 return;
1997 } else {
1998 // SSH2�������k�E�W�J������SSH1���������s�������A���L�t���O���������������B(2005.7.9 yutaka)
1999 if (SSHv2(pvar)) {
2000 pvar->ssh_state.compressing = FALSE;
2001 } else {
2002 pvar->ssh_state.compressing = TRUE;
2003 }
2004 }
2005 }
2006
2007 static void enable_recv_compression(PTInstVar pvar)
2008 {
2009 static int initialize = 0;
2010
2011 if (initialize) {
2012 deflateEnd(&pvar->ssh_state.decompress_stream);
2013 }
2014 initialize = 1;
2015
2016 pvar->ssh_state.decompress_stream.zalloc = NULL;
2017 pvar->ssh_state.decompress_stream.zfree = NULL;
2018 pvar->ssh_state.decompress_stream.opaque = NULL;
2019 if (inflateInit(&pvar->ssh_state.decompress_stream) != Z_OK) {
2020 deflateEnd(&pvar->ssh_state.compress_stream);
2021 UTIL_get_lang_msg("MSG_SSH_SETUP_COMP_ERROR", pvar,
2022 "An error occurred while setting up compression.\n"
2023 "The connection will close.");
2024 notify_fatal_error(pvar, pvar->ts->UIMsg);
2025 return;
2026 } else {
2027 // SSH2�������k�E�W�J������SSH1���������s�������A���L�t���O���������������B(2005.7.9 yutaka)
2028 if (SSHv2(pvar)) {
2029 pvar->ssh_state.decompressing = FALSE;
2030 } else {
2031 pvar->ssh_state.decompressing = TRUE;
2032 }
2033
2034 buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf,
2035 &pvar->ssh_state.postdecompress_inbuflen, 1000);
2036 }
2037 }
2038
2039 static void enable_compression(PTInstVar pvar)
2040 {
2041 enable_send_compression(pvar);
2042 enable_recv_compression(pvar);
2043
2044 // SSH2�������k�E�W�J������SSH1���������s�������A���L�t���O���������������B(2005.7.9 yutaka)
2045 if (SSHv2(pvar)) {
2046 pvar->ssh_state.compressing = FALSE;
2047 pvar->ssh_state.decompressing = FALSE;
2048 }
2049
2050 }
2051
2052 static BOOL handle_enable_compression(PTInstVar pvar)
2053 {
2054 enable_compression(pvar);
2055 prep_forwarding(pvar);
2056 return FALSE;
2057 }
2058
2059 static BOOL handle_disable_compression(PTInstVar pvar)
2060 {
2061 prep_forwarding(pvar);
2062 return FALSE;
2063 }
2064
2065 static void prep_compression(PTInstVar pvar)
2066 {
2067 if (pvar->session_settings.CompressionLevel > 0) {
2068 // added if statement (2005.7.10 yutaka)
2069 if (SSHv1(pvar)) {
2070 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
2071 static const SSHPacketHandler handlers[]
2072 = { handle_enable_compression, handle_disable_compression };
2073
2074 unsigned char FAR *outmsg =
2075 begin_send_packet(pvar, SSH_CMSG_REQUEST_COMPRESSION, 4);
2076
2077 set_uint32(outmsg, pvar->session_settings.CompressionLevel);
2078 finish_send_packet(pvar);
2079
2080 enque_handlers(pvar, 2, msgs, handlers);
2081 }
2082
2083 pvar->ssh_state.compression_level =
2084 pvar->session_settings.CompressionLevel;
2085
2086 } else {
2087 // added if statement (2005.7.10 yutaka)
2088 if (SSHv1(pvar)) {
2089 prep_forwarding(pvar);
2090 }
2091 }
2092 }
2093
2094 static void enque_simple_auth_handlers(PTInstVar pvar)
2095 {
2096 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
2097 static const SSHPacketHandler handlers[]
2098 = { handle_auth_success, handle_auth_failure };
2099
2100 enque_handlers(pvar, 2, msgs, handlers);
2101 }
2102
2103 static BOOL handle_rsa_challenge(PTInstVar pvar)
2104 {
2105 int challenge_bytes;
2106
2107 if (!grab_payload(pvar, 2)) {
2108 return FALSE;
2109 }
2110
2111 challenge_bytes = get_mpint_len(pvar, 0);
2112
2113 if (grab_payload(pvar, challenge_bytes)) {
2114 unsigned char FAR *outmsg =
2115 begin_send_packet(pvar, SSH_CMSG_AUTH_RSA_RESPONSE, 16);
2116
2117 if (CRYPT_generate_RSA_challenge_response
2118 (pvar, pvar->ssh_state.payload + 2, challenge_bytes, outmsg)) {
2119
2120 // �Z�b�V�������������p�X���[�h���g���������������A�����������\�[�X�������������B
2121 // socket close���������������������������������A���������������B(2005.4.8 yutaka)
2122 #if 0
2123 //AUTH_destroy_cur_cred(pvar);
2124 #endif
2125
2126 finish_send_packet(pvar);
2127
2128 enque_simple_auth_handlers(pvar);
2129 } else {
2130 UTIL_get_lang_msg("MSG_SSH_DECRYPT_RSA_ERROR", pvar,
2131 "An error occurred while decrypting the RSA challenge.\n"
2132 "Perhaps the key file is corrupted.");
2133 notify_fatal_error(pvar, pvar->ts->UIMsg);
2134 }
2135 }
2136
2137 return FALSE;
2138 }
2139
2140 #define OBFUSCATING_ROUND_TO 32
2141
2142 static int obfuscating_round_up(PTInstVar pvar, int size)
2143 {
2144 return (size + OBFUSCATING_ROUND_TO - 1) & ~(OBFUSCATING_ROUND_TO - 1);
2145 }
2146
2147 static void try_send_credentials(PTInstVar pvar)
2148 {
2149 if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_CREDENTIALS) == 0) {
2150 AUTHCred FAR *cred = AUTH_get_cur_cred(pvar);
2151 static const int RSA_msgs[] =
2152 { SSH_SMSG_AUTH_RSA_CHALLENGE, SSH_SMSG_FAILURE };
2153 static const SSHPacketHandler RSA_handlers[]
2154 = { handle_rsa_challenge, handle_rsa_auth_refused };
2155 static const int TIS_msgs[] =
2156 { SSH_SMSG_AUTH_TIS_CHALLENGE, SSH_SMSG_FAILURE };
2157 static const SSHPacketHandler TIS_handlers[]
2158 = { handle_TIS_challenge, handle_auth_failure };
2159
2160 // SSH2���������������������X�L�b�v
2161 if (SSHv2(pvar))
2162 goto skip_ssh2;
2163
2164 switch (cred->method) {
2165 case SSH_AUTH_NONE:
2166 return;
2167 case SSH_AUTH_PASSWORD:{
2168 int len = strlen(cred->password);
2169 // Round up password length to discourage traffic analysis
2170 int obfuscated_len = obfuscating_round_up(pvar, len);
2171 unsigned char FAR *outmsg =
2172 begin_send_packet(pvar, SSH_CMSG_AUTH_PASSWORD,
2173 4 + obfuscated_len);
2174
2175 notify_verbose_message(pvar,
2176 "Trying PASSWORD authentication...",
2177 LOG_LEVEL_VERBOSE);
2178
2179 set_uint32(outmsg, obfuscated_len);
2180 memcpy(outmsg + 4, cred->password, len);
2181 memset(outmsg + 4 + len, 0, obfuscated_len - len);
2182
2183 // �Z�b�V�������������p�X���[�h���g���������������A�����������\�[�X�������������B
2184 // socket close���������������������������������A���������������B(2005.4.8 yutaka)
2185 #if 0
2186 //AUTH_destroy_cur_cred(pvar);
2187 #endif
2188
2189 enque_simple_auth_handlers(pvar);
2190 break;
2191 }
2192 case SSH_AUTH_RHOSTS:{
2193 int len = strlen(cred->rhosts_client_user);
2194 unsigned char FAR *outmsg =
2195 begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS, 4 + len);
2196
2197 notify_verbose_message(pvar,
2198 "Trying RHOSTS authentication...",
2199 LOG_LEVEL_VERBOSE);
2200
2201 set_uint32(outmsg, len);
2202 memcpy(outmsg + 4, cred->rhosts_client_user, len);
2203 AUTH_destroy_cur_cred(pvar);
2204 enque_simple_auth_handlers(pvar);
2205 break;
2206 }
2207 case SSH_AUTH_RSA:{
2208 int len = BN_num_bytes(cred->key_pair->RSA_key->n);
2209 unsigned char FAR *outmsg =
2210 begin_send_packet(pvar, SSH_CMSG_AUTH_RSA, 2 + len);
2211
2212 notify_verbose_message(pvar,
2213 "Trying RSA authentication...",
2214 LOG_LEVEL_VERBOSE);
2215
2216 set_ushort16_MSBfirst(outmsg, len * 8);
2217 BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + 2);
2218 /* don't destroy the current credentials yet */
2219 enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
2220 break;
2221 }
2222 case SSH_AUTH_RHOSTS_RSA:{
2223 int mod_len = BN_num_bytes(cred->key_pair->RSA_key->n);
2224 int name_len = strlen(cred->rhosts_client_user);
2225 int exp_len = BN_num_bytes(cred->key_pair->RSA_key->e);
2226 int index;
2227 unsigned char FAR *outmsg =
2228 begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS_RSA,
2229 12 + mod_len + name_len + exp_len);
2230
2231 notify_verbose_message(pvar,
2232 "Trying RHOSTS+RSA authentication...",
2233 LOG_LEVEL_VERBOSE);
2234
2235 set_uint32(outmsg, name_len);
2236 memcpy(outmsg + 4, cred->rhosts_client_user, name_len);
2237 index = 4 + name_len;
2238
2239 set_uint32(outmsg + index, 8 * mod_len);
2240 set_ushort16_MSBfirst(outmsg + index + 4, 8 * exp_len);
2241 BN_bn2bin(cred->key_pair->RSA_key->e, outmsg + index + 6);
2242 index += 6 + exp_len;
2243
2244 set_ushort16_MSBfirst(outmsg + index, 8 * mod_len);
2245 BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + index + 2);
2246 /* don't destroy the current credentials yet */
2247 enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
2248 break;
2249 }
2250 case SSH_AUTH_TIS:{
2251 if (cred->password == NULL) {
2252 unsigned char FAR *outmsg =
2253 begin_send_packet(pvar, SSH_CMSG_AUTH_TIS, 0);
2254
2255 notify_verbose_message(pvar,
2256 "Trying TIS authentication...",
2257 LOG_LEVEL_VERBOSE);
2258 enque_handlers(pvar, 2, TIS_msgs, TIS_handlers);
2259 } else {
2260 int len = strlen(cred->password);
2261 int obfuscated_len = obfuscating_round_up(pvar, len);
2262 unsigned char FAR *outmsg =
2263 begin_send_packet(pvar, SSH_CMSG_AUTH_TIS_RESPONSE,
2264 4 + obfuscated_len);
2265
2266 notify_verbose_message(pvar, "Sending TIS response",
2267 LOG_LEVEL_VERBOSE);
2268
2269 set_uint32(outmsg, obfuscated_len);
2270 memcpy(outmsg + 4, cred->password, len);
2271 memset(outmsg + 4 + len, 0, obfuscated_len - len);
2272 enque_simple_auth_handlers(pvar);
2273 }
2274
2275 AUTH_destroy_cur_cred(pvar);
2276 break;
2277 }
2278 default:
2279 UTIL_get_lang_msg("MSG_SSH_UNSUPPORT_AUTH_METHOD_ERROR", pvar,
2280 "Internal error: unsupported authentication method");
2281 notify_fatal_error(pvar, pvar->ts->UIMsg);
2282 return;
2283 }
2284
2285 finish_send_packet(pvar);
2286
2287 skip_ssh2:;
2288 destroy_packet_buf(pvar);
2289
2290 pvar->ssh_state.status_flags |= STATUS_DONT_SEND_CREDENTIALS;
2291 }
2292 }
2293
2294 static void try_send_user_name(PTInstVar pvar)
2295 {
2296 if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_USER_NAME) == 0) {
2297 char FAR *username = AUTH_get_user_name(pvar);
2298
2299 if (username != NULL) {
2300 int len = strlen(username);
2301 int obfuscated_len = obfuscating_round_up(pvar, len);
2302 unsigned char FAR *outmsg =
2303 begin_send_packet(pvar, SSH_CMSG_USER, 4 + obfuscated_len);
2304 char buf[1024] = "Sending user name: ";
2305 static const int msgs[] =
2306 { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
2307 static const SSHPacketHandler handlers[]
2308 = { handle_noauth_success, handle_auth_required };
2309
2310 set_uint32(outmsg, obfuscated_len);
2311 memcpy(outmsg + 4, username, len);
2312 memset(outmsg + 4 + len, 0, obfuscated_len - len);
2313 finish_send_packet(pvar);
2314
2315 pvar->ssh_state.status_flags |= STATUS_DONT_SEND_USER_NAME;
2316
2317 strncat_s(buf, sizeof(buf), username, _TRUNCATE);
2318 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
2319
2320 enque_handlers(pvar, 2, msgs, handlers);
2321 }
2322 }
2323 }
2324
2325 static void send_session_key(PTInstVar pvar)
2326 {
2327 int encrypted_session_key_len;
2328 unsigned char FAR *outmsg;
2329
2330 if (SSHv1(pvar)) {
2331 encrypted_session_key_len =
2332 CRYPT_get_encrypted_session_key_len(pvar);
2333 }
2334
2335 if (!CRYPT_choose_ciphers(pvar))
2336 return;
2337
2338 if (SSHv1(pvar)) {
2339 outmsg =
2340 begin_send_packet(pvar, SSH_CMSG_SESSION_KEY,
2341 15 + encrypted_session_key_len);
2342 outmsg[0] = (unsigned char) CRYPT_get_sender_cipher(pvar);
2343 memcpy(outmsg + 1, CRYPT_get_server_cookie(pvar), 8); /* antispoofing cookie */
2344 outmsg[9] = (unsigned char) (encrypted_session_key_len >> 5);
2345 outmsg[10] = (unsigned char) (encrypted_session_key_len << 3);
2346 if (!CRYPT_choose_session_key(pvar, outmsg + 11))
2347 return;
2348 set_uint32(outmsg + 11 + encrypted_session_key_len,
2349 SSH_PROTOFLAG_SCREEN_NUMBER |
2350 SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
2351 finish_send_packet(pvar);
2352 }
2353
2354 if (!CRYPT_start_encryption(pvar, 1, 1))
2355 return;
2356 notify_established_secure_connection(pvar);
2357
2358 if (SSHv1(pvar)) {
2359 enque_handler(pvar, SSH_SMSG_SUCCESS, handle_crypt_success);
2360 }
2361
2362 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_USER_NAME;
2363
2364 if (SSHv1(pvar)) {
2365 try_send_user_name(pvar);
2366 }
2367 }
2368
2369 /*************************
2370 END of message handlers
2371 ************************/
2372
2373 void SSH_init(PTInstVar pvar)
2374 {
2375 int i;
2376
2377 buf_create(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
2378 buf_create(&pvar->ssh_state.precompress_outbuf,
2379 &pvar->ssh_state.precompress_outbuflen);
2380 buf_create(&pvar->ssh_state.postdecompress_inbuf,
2381 &pvar->ssh_state.postdecompress_inbuflen);
2382 pvar->ssh_state.payload = NULL;
2383 pvar->ssh_state.compressing = FALSE;
2384 pvar->ssh_state.decompressing = FALSE;
2385 pvar->ssh_state.status_flags =
2386 STATUS_DONT_SEND_USER_NAME | STATUS_DONT_SEND_CREDENTIALS;
2387 pvar->ssh_state.payload_datalen = 0;
2388 pvar->ssh_state.hostname = NULL;
2389 pvar->ssh_state.server_ID = NULL;
2390 pvar->ssh_state.receiver_sequence_number = 0;
2391 pvar->ssh_state.sender_sequence_number = 0;
2392 for (i = 0; i < NUM_ELEM(pvar->ssh_state.packet_handlers); i++) {
2393 pvar->ssh_state.packet_handlers[i] = NULL;
2394 }
2395
2396 // for SSH2(yutaka)
2397 memset(pvar->ssh2_keys, 0, sizeof(pvar->ssh2_keys));
2398 pvar->userauth_success = 0;
2399 pvar->session_nego_status = 0;
2400 pvar->settings.ssh_protocol_version = 2; // SSH2(default)
2401 pvar->rekeying = 0;
2402 pvar->key_done = 0;
2403 pvar->ssh2_autologin = 0; // autologin disabled(default)
2404 pvar->ask4passwd = 0; // disabled(default) (2006.9.18 maya)
2405 pvar->userauth_retry_count = 0;
2406 pvar->decomp_buffer = NULL;
2407 pvar->ssh2_authlist = NULL; // (2007.4.27 yutaka)
2408 pvar->tryed_ssh2_authlist = FALSE;
2409
2410 }
2411
2412 void SSH_open(PTInstVar pvar)
2413 {
2414 pvar->ssh_state.hostname = _strdup(pvar->ts->HostName);
2415 pvar->ssh_state.win_cols = pvar->ts->TerminalWidth;
2416 pvar->ssh_state.win_rows = pvar->ts->TerminalHeight;
2417 }
2418
2419 void SSH_notify_disconnecting(PTInstVar pvar, char FAR * reason)
2420 {
2421 if (SSHv1(pvar)) {
2422 int len = reason == NULL ? 0 : strlen(reason);
2423 unsigned char FAR *outmsg =
2424 begin_send_packet(pvar, SSH_MSG_DISCONNECT, len + 4);
2425
2426 set_uint32(outmsg, len);
2427 if (reason != NULL) {
2428 memcpy(outmsg + 4, reason, len);
2429 }
2430 finish_send_packet(pvar);
2431
2432 } else { // for SSH2(yutaka)
2433 buffer_t *msg;
2434 unsigned char *outmsg;
2435 int len;
2436 Channel_t *c;
2437
2438 c = ssh2_channel_lookup(pvar->shell_id);
2439 if (c == NULL)
2440 return;
2441
2442 // SSH2 server��channel close���`����
2443 msg = buffer_init();
2444 if (msg == NULL) {
2445 // TODO: error check
2446 return;
2447 }
2448 buffer_put_int(msg, c->remote_id);
2449
2450 len = buffer_len(msg);
2451 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_CLOSE, len);
2452 memcpy(outmsg, buffer_ptr(msg), len);
2453 finish_send_packet(pvar);
2454 buffer_free(msg);
2455
2456 }
2457
2458 }
2459
2460 void SSH_notify_host_OK(PTInstVar pvar)
2461 {
2462 if ((pvar->ssh_state.status_flags & STATUS_HOST_OK) == 0) {
2463 pvar->ssh_state.status_flags |= STATUS_HOST_OK;
2464 send_session_key(pvar);
2465 }
2466 }
2467
2468 void SSH_notify_win_size(PTInstVar pvar, int cols, int rows)
2469 {
2470 pvar->ssh_state.win_cols = cols;
2471 pvar->ssh_state.win_rows = rows;
2472
2473 if (SSHv1(pvar)) {
2474 if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) == handle_data) {
2475 unsigned char FAR *outmsg =
2476 begin_send_packet(pvar, SSH_CMSG_WINDOW_SIZE, 16);
2477
2478 set_uint32(outmsg, rows);
2479 set_uint32(outmsg + 4, cols);
2480 set_uint32(outmsg + 8, 0);
2481 set_uint32(outmsg + 12, 0);
2482 finish_send_packet(pvar);
2483 }
2484
2485 } else if (SSHv2(pvar)) { // �^�[�~�i���T�C�Y���X���m������ (2005.1.4 yutaka)
2486 // SSH2�����������`�F�b�N���s���B(2005.1.5 yutaka)
2487 buffer_t *msg;
2488 char *s;
2489 unsigned char *outmsg;
2490 int len;
2491 Channel_t *c;
2492
2493 c = ssh2_channel_lookup(pvar->shell_id);
2494 if (c == NULL)
2495 return;
2496
2497 msg = buffer_init();
2498 if (msg == NULL) {
2499 // TODO: error check
2500 return;
2501 }
2502 buffer_put_int(msg, c->remote_id);
2503 s = "window-change";
2504 buffer_put_string(msg, s, strlen(s));
2505 buffer_put_char(msg, 0); // wantconfirm
2506 buffer_put_int(msg, pvar->ssh_state.win_cols); // columns
2507 buffer_put_int(msg, pvar->ssh_state.win_rows); // lines
2508 buffer_put_int(msg, 480); // XXX:
2509 buffer_put_int(msg, 640); // XXX:
2510 len = buffer_len(msg);
2511 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len);
2512 memcpy(outmsg, buffer_ptr(msg), len);
2513 finish_send_packet(pvar);
2514 buffer_free(msg);
2515
2516 notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_REQUEST was sent at SSH_notify_win_size().", LOG_LEVEL_VERBOSE);
2517
2518 } else {
2519 // SSH�����������������������B
2520
2521 }
2522
2523 }
2524
2525 int SSH_get_min_packet_size(PTInstVar pvar)
2526 {
2527 if (SSHv1(pvar)) {
2528 return 12;
2529 } else {
2530 int block_size = CRYPT_get_decryption_block_size(pvar);
2531
2532 return max(16, block_size);
2533 }
2534 }
2535
2536 /* data is guaranteed to be at least SSH_get_min_packet_size bytes long
2537 at least 5 bytes must be decrypted */
2538 void SSH_predecrpyt_packet(PTInstVar pvar, char FAR * data)
2539 {
2540 if (SSHv2(pvar)) {
2541 CRYPT_decrypt(pvar, data, get_predecryption_amount(pvar));
2542 }
2543 }
2544
2545 int SSH_get_clear_MAC_size(PTInstVar pvar)
2546 {
2547 if (SSHv1(pvar)) {
2548 return 0;
2549 } else {
2550 return CRYPT_get_receiver_MAC_size(pvar);
2551 }
2552 }
2553
2554 void SSH_notify_user_name(PTInstVar pvar)
2555 {
2556 try_send_user_name(pvar);
2557 }
2558
2559 void SSH_notify_cred(PTInstVar pvar)
2560 {
2561 try_send_credentials(pvar);
2562 }
2563
2564 void SSH_send(PTInstVar pvar, unsigned char const FAR * buf, unsigned int buflen)
2565 {
2566 if (SSHv1(pvar)) {
2567 if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) != handle_data) {
2568 return;
2569 }
2570
2571 while (buflen > 0) {
2572 int len =
2573 buflen >
2574 SSH_MAX_SEND_PACKET_SIZE ? SSH_MAX_SEND_PACKET_SIZE : buflen;
2575 unsigned char FAR *outmsg =
2576 begin_send_packet(pvar, SSH_CMSG_STDIN_DATA, 4 + len);
2577
2578 set_uint32(outmsg, len);
2579
2580 if (pvar->ssh_state.compressing) {
2581 buf_ensure_size(&pvar->ssh_state.outbuf,
2582 &pvar->ssh_state.outbuflen,
2583 len + (len >> 6) + 50);
2584 pvar->ssh_state.compress_stream.next_in =
2585 pvar->ssh_state.precompress_outbuf;
2586 pvar->ssh_state.compress_stream.avail_in = 5;
2587 pvar->ssh_state.compress_stream.next_out =
2588 pvar->ssh_state.outbuf + 12;
2589 pvar->ssh_state.compress_stream.avail_out =
2590 pvar->ssh_state.outbuflen - 12;
2591
2592 if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) != Z_OK) {
2593 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar,
2594 "Error compressing packet data");
2595 notify_fatal_error(pvar, pvar->ts->UIMsg);
2596 return;
2597 }
2598
2599 pvar->ssh_state.compress_stream.next_in =
2600 (unsigned char FAR *) buf;
2601 pvar->ssh_state.compress_stream.avail_in = len;
2602
2603 if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) != Z_OK) {
2604 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar,
2605 "Error compressing packet data");
2606 notify_fatal_error(pvar, pvar->ts->UIMsg);
2607 return;
2608 }
2609 } else {
2610 memcpy(outmsg + 4, buf, len);
2611 }
2612
2613 finish_send_packet_special(pvar, 1);
2614
2615 buflen -= len;
2616 buf += len;
2617 }
2618
2619 } else { // for SSH2(yutaka)
2620 Channel_t *c = ssh2_channel_lookup(pvar->shell_id);
2621 SSH2_send_channel_data(pvar, c, (unsigned char *)buf, buflen);
2622 }
2623
2624 }
2625
2626 int SSH_extract_payload(PTInstVar pvar, unsigned char FAR * dest, int len)
2627 {
2628 int num_bytes = pvar->ssh_state.payload_datalen;
2629
2630 if (num_bytes > len) {
2631 num_bytes = len;
2632 }
2633
2634 if (!pvar->ssh_state.decompressing) {
2635 memcpy(dest,
2636 pvar->ssh_state.payload + pvar->ssh_state.payload_datastart,
2637 num_bytes);
2638 pvar->ssh_state.payload_datastart += num_bytes;
2639 } else if (num_bytes > 0) {
2640 pvar->ssh_state.decompress_stream.next_out = dest;
2641 pvar->ssh_state.decompress_stream.avail_out = num_bytes;
2642
2643 if (inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH) != Z_OK) {
2644 UTIL_get_lang_msg("MSG_SSH_INVALID_COMPDATA_ERROR", pvar,
2645 "Invalid compressed data in received packet");
2646 notify_fatal_error(pvar, pvar->ts->UIMsg);
2647 return 0;
2648 }
2649 }
2650
2651 pvar->ssh_state.payload_datalen -= num_bytes;
2652
2653 return num_bytes;
2654 }
2655
2656 void SSH_get_compression_info(PTInstVar pvar, char FAR * dest, int len)
2657 {
2658 char buf[1024];
2659 char buf2[1024];
2660
2661 // added support of SSH2 packet compression (2005.7.10 yutaka)
2662 // support of "Compression delayed" (2006.6.23 maya)
2663 if (pvar->ssh_state.compressing ||
2664 pvar->ctos_compression == COMP_ZLIB ||
2665 pvar->ctos_compression == COMP_DELAYED && pvar->userauth_success) {
2666 unsigned long total_in = pvar->ssh_state.compress_stream.total_in;
2667 unsigned long total_out =
2668 pvar->ssh_state.compress_stream.total_out;
2669
2670 if (total_out > 0) {
2671 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO", pvar,
2672 "level %d; ratio %.1f (%ld:%ld)");
2673 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg,
2674 pvar->ssh_state.compression_level,
2675 ((double) total_in) / total_out, total_in,
2676 total_out);
2677 } else {
2678 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO2", pvar, "level %d");
2679 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg,
2680 pvar->ssh_state.compression_level);
2681 }
2682 } else {
2683 UTIL_get_lang_msg("DLG_ABOUT_COMP_NONE", pvar, "none");
2684 strncpy_s(buf, sizeof(buf), pvar->ts->UIMsg, _TRUNCATE);
2685 }
2686
2687 // support of "Compression delayed" (2006.6.23 maya)
2688 if (pvar->ssh_state.decompressing ||
2689 pvar->stoc_compression == COMP_ZLIB ||
2690 pvar->stoc_compression == COMP_DELAYED && pvar->userauth_success) {
2691 unsigned long total_in =
2692 pvar->ssh_state.decompress_stream.total_in;
2693 unsigned long total_out =
2694 pvar->ssh_state.decompress_stream.total_out;
2695
2696 if (total_in > 0) {
2697 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO", pvar,
2698 "level %d; ratio %.1f (%ld:%ld)");
2699 _snprintf_s(buf2, sizeof(buf2), _TRUNCATE, pvar->ts->UIMsg,
2700 pvar->ssh_state.compression_level,
2701 ((double) total_out) / total_in, total_out,
2702 total_in);
2703 } else {
2704 UTIL_get_lang_msg("DLG_ABOUT_COMP_INFO2", pvar, "level %d");
2705 _snprintf_s(buf2, sizeof(buf2), _TRUNCATE, pvar->ts->UIMsg,
2706 pvar->ssh_state.compression_level);
2707 }
2708 } else {
2709 UTIL_get_lang_msg("DLG_ABOUT_COMP_NONE", pvar, "none");
2710 strncpy_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2711 }
2712
2713 UTIL_get_lang_msg("DLG_ABOUT_COMP_UPDOWN", pvar,
2714 "Upstream %s; Downstream %s");
2715 _snprintf_s(dest, len, _TRUNCATE, pvar->ts->UIMsg, buf, buf2);
2716 }
2717
2718 void SSH_get_server_ID_info(PTInstVar pvar, char FAR * dest, int len)
2719 {
2720 strncpy_s(dest, len,
2721 pvar->ssh_state.server_ID == NULL ? "Unknown"
2722 : pvar->ssh_state.server_ID,
2723 _TRUNCATE);
2724 }
2725
2726 void SSH_get_protocol_version_info(PTInstVar pvar, char FAR * dest,
2727 int len)
2728 {
2729 if (pvar->protocol_major == 0) {
2730 strncpy_s(dest, len, "Unknown", _TRUNCATE);
2731 } else {
2732 _snprintf_s(dest, len, _TRUNCATE, "%d.%d", pvar->protocol_major,
2733 pvar->protocol_minor);
2734 }
2735 }
2736
2737 void SSH_end(PTInstVar pvar)
2738 {
2739 int i;
2740
2741 for (i = 0; i < 256; i++) {
2742 SSHPacketHandlerItem FAR *first_item =
2743 pvar->ssh_state.packet_handlers[i];
2744
2745 if (first_item != NULL) {
2746 SSHPacketHandlerItem FAR *item = first_item;
2747
2748 do {
2749 SSHPacketHandlerItem FAR *cur_item = item;
2750
2751 item = item->next_for_message;
2752 free(cur_item);
2753 } while (item != first_item);
2754 }
2755 pvar->ssh_state.packet_handlers[i] = NULL;
2756 }
2757
2758 free(pvar->ssh_state.hostname);
2759 pvar->ssh_state.hostname = NULL;
2760 free(pvar->ssh_state.server_ID);
2761 pvar->ssh_state.server_ID = NULL;
2762 buf_destroy(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
2763 buf_destroy(&pvar->ssh_state.precompress_outbuf,
2764 &pvar->ssh_state.precompress_outbuflen);
2765 buf_destroy(&pvar->ssh_state.postdecompress_inbuf,
2766 &pvar->ssh_state.postdecompress_inbuflen);
2767
2768 // support of "Compression delayed" (2006.6.23 maya)
2769 if (pvar->ssh_state.compressing ||
2770 pvar->ctos_compression == COMP_ZLIB || // add SSH2 flag (2005.7.10 yutaka)
2771 pvar->ctos_compression == COMP_DELAYED && pvar->userauth_success) {
2772 deflateEnd(&pvar->ssh_state.compress_stream);
2773 pvar->ssh_state.compressing = FALSE;
2774 }
2775 // support of "Compression delayed" (2006.6.23 maya)
2776 if (pvar->ssh_state.decompressing ||
2777 pvar->stoc_compression == COMP_ZLIB || // add SSH2 flag (2005.7.10 yutaka)
2778 pvar->stoc_compression == COMP_DELAYED && pvar->userauth_success) {
2779 inflateEnd(&pvar->ssh_state.decompress_stream);
2780 pvar->ssh_state.decompressing = FALSE;
2781 }
2782
2783 #if 1
2784 // SSH2���f�[�^���������� (2004.12.27 yutaka)
2785 if (SSHv2(pvar)) {
2786 if (pvar->kexdh) {
2787 DH_free(pvar->kexdh);
2788 pvar->kexdh = NULL;
2789 }
2790 memset(pvar->server_version_string, 0, sizeof(pvar->server_version_string));
2791 memset(pvar->client_version_string, 0, sizeof(pvar->client_version_string));
2792
2793 if (pvar->my_kex != NULL) {
2794 buffer_free(pvar->my_kex);
2795 pvar->my_kex = NULL;
2796 }
2797 if (pvar->peer_kex != NULL) {
2798 buffer_free(pvar->peer_kex);
2799 pvar->peer_kex = NULL;
2800 }
2801
2802 pvar->we_need = 0;
2803 pvar->key_done = 0;
2804 pvar->rekeying = 0;
2805
2806 if (pvar->session_id != NULL) {
2807 free(pvar->session_id);
2808 pvar->session_id = NULL;
2809 }
2810 pvar->session_id_len = 0;
2811
2812 pvar->userauth_success = 0;
2813 //pvar->remote_id = 0;
2814 pvar->shell_id = 0;
2815 pvar->session_nego_status = 0;
2816
2817 pvar->ssh_heartbeat_tick = 0;
2818
2819 if (pvar->decomp_buffer != NULL) {
2820 buffer_free(pvar->decomp_buffer);
2821 pvar->decomp_buffer = NULL;
2822 }
2823
2824 if (pvar->ssh2_authlist != NULL) { // (2007.4.27 yutaka)
2825 free(pvar->ssh2_authlist);
2826 pvar->ssh2_authlist = NULL;
2827 }
2828
2829 pvar->tryed_ssh2_authlist = FALSE;
2830 }
2831 #endif
2832
2833 }
2834
2835 static void SSH2_send_channel_data(PTInstVar pvar, Channel_t *c, unsigned char FAR * buf, unsigned int buflen)
2836 {
2837 buffer_t *msg;
2838 unsigned char *outmsg;
2839 unsigned int len;
2840
2841 // SSH2���������������A�p�P�b�g���������B(2005.6.19 yutaka)
2842 if (pvar->rekeying) {
2843 // TODO: ���z���������p�P�b�g�j�����������A�p�P�b�g���������x���������������������A
2844 // �������������������B
2845 c = NULL;
2846
2847 return;
2848 }
2849
2850 if (c == NULL)
2851 return;
2852
2853 if ((unsigned int)buflen > c->remote_window) {
2854 unsigned int offset = c->remote_window;
2855 // ���������f�[�^����������������������
2856 ssh2_channel_add_bufchain(c, buf + offset, buflen - offset);
2857 buflen = offset;
2858 }
2859 if (buflen > 0) {
2860 msg = buffer_init();
2861 if (msg == NULL) {
2862 // TODO: error check
2863 return;
2864 }
2865 buffer_put_int(msg, c->remote_id);
2866 buffer_put_string(msg, (char *)buf, buflen);
2867
2868 len = buffer_len(msg);
2869 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_DATA, len);
2870 //if (len + 12 >= pvar->ssh_state.outbuflen) *(int *)0 = 0;
2871 memcpy(outmsg, buffer_ptr(msg), len);
2872 finish_send_packet(pvar);
2873 buffer_free(msg);
2874 //debug_print(1, pvar->ssh_state.outbuf, 7 + 4 + 1 + 1 + len);
2875
2876 // remote window size������
2877 if (buflen <= c->remote_window) {
2878 c->remote_window -= buflen;
2879 }
2880 else {
2881 c->remote_window = 0;
2882 }
2883 }
2884 }
2885
2886 /* support for port forwarding */
2887 void SSH_channel_send(PTInstVar pvar, int channel_num,
2888 uint32 remote_channel_num,
2889 unsigned char FAR * buf, int len)
2890 {
2891 if (SSHv1(pvar)) {
2892 unsigned char FAR *outmsg =
2893 begin_send_packet(pvar, SSH_MSG_CHANNEL_DATA, 8 + len);
2894
2895 set_uint32(outmsg, remote_channel_num);
2896 set_uint32(outmsg + 4, len);
2897
2898 if (pvar->ssh_state.compressing) {
2899 buf_ensure_size(&pvar->ssh_state.outbuf,
2900 &pvar->ssh_state.outbuflen, len + (len >> 6) + 50);
2901 pvar->ssh_state.compress_stream.next_in =
2902 pvar->ssh_state.precompress_outbuf;
2903 pvar->ssh_state.compress_stream.avail_in = 9;
2904 pvar->ssh_state.compress_stream.next_out =
2905 pvar->ssh_state.outbuf + 12;
2906 pvar->ssh_state.compress_stream.avail_out =
2907 pvar->ssh_state.outbuflen - 12;
2908
2909 if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) != Z_OK) {
2910 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar,
2911 "Error compressing packet data");
2912 notify_fatal_error(pvar, pvar->ts->UIMsg);
2913 return;
2914 }
2915
2916 pvar->ssh_state.compress_stream.next_in =
2917 (unsigned char FAR *) buf;
2918 pvar->ssh_state.compress_stream.avail_in = len;
2919
2920 if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2921 Z_OK) {
2922 UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar,
2923 "Error compressing packet data");
2924 notify_fatal_error(pvar, pvar->ts->UIMsg);
2925 return;
2926 }
2927 } else {
2928 memcpy(outmsg + 8, buf, len);
2929 }
2930
2931 finish_send_packet_special(pvar, 1);
2932
2933 } else {
2934 // �|�[�g�t�H���[�f�B���O���������N���C�A���g���������M�v�����ASSH���M���������T�[�o���������������B
2935 Channel_t *c = ssh2_local_channel_lookup(channel_num);
2936 SSH2_send_channel_data(pvar, c, buf, len);
2937 }
2938
2939 }
2940
2941 void SSH_fail_channel_open(PTInstVar pvar, uint32 remote_channel_num)
2942 {
2943 if (SSHv1(pvar)) {
2944 unsigned char FAR *outmsg =
2945 begin_send_packet(pvar, SSH_MSG_CHANNEL_OPEN_FAILURE, 4);
2946
2947 set_uint32(outmsg, remote_channel_num);
2948 finish_send_packet(pvar);
2949
2950 } else { // SSH2 (2005.6.26 yutaka)
2951 int len;
2952 Channel_t *c = NULL;
2953 buffer_t *msg;
2954 unsigned char *outmsg;
2955
2956 msg = buffer_init();
2957 if (msg == NULL) {
2958 // TODO: error check
2959 return;
2960 }
2961 buffer_put_int(msg, remote_channel_num);
2962 buffer_put_int(msg, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
2963 buffer_put_string(msg, "", 0); // description
2964 buffer_put_string(msg, "", 0); // language tag
2965
2966 len = buffer_len(msg);
2967 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_OPEN_FAILURE, len);
2968 memcpy(outmsg, buffer_ptr(msg), len);
2969 finish_send_packet(pvar);
2970 buffer_free(msg);
2971
2972 }
2973 }
2974
2975 void SSH_confirm_channel_open(PTInstVar pvar, uint32 remote_channel_num,
2976 uint32 local_channel_num)
2977 {
2978 if (SSHv1(pvar)) {
2979 unsigned char FAR *outmsg =
2980 begin_send_packet(pvar, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 8);
2981
2982 set_uint32(outmsg, remote_channel_num);
2983 set_uint32(outmsg + 4, local_channel_num);
2984 finish_send_packet(pvar);
2985
2986 } else {
2987 buffer_t *msg;
2988 unsigned char *outmsg;
2989 int len;
2990 Channel_t *c;
2991
2992 // port-forwarding(remote to local)�����[�J�����������������T�[�o�������B(2005.7.2 yutaka)
2993 c = ssh2_local_channel_lookup(local_channel_num);
2994 if (c == NULL) {
2995 // It is sure to be successful as long as it's not a program bug either.
2996 return;
2997 }
2998
2999 msg = buffer_init();
3000 if (msg == NULL) {
3001 // TODO: error check
3002 return;
3003 }
3004 buffer_put_int(msg, c->remote_id);
3005 buffer_put_int(msg, c->self_id);
3006 buffer_put_int(msg, c->local_window);
3007 buffer_put_int(msg, c->local_maxpacket);
3008
3009 len = buffer_len(msg);
3010 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, len);
3011 memcpy(outmsg, buffer_ptr(msg), len);
3012 finish_send_packet(pvar);
3013 buffer_free(msg);
3014
3015 }
3016 }
3017
3018 void SSH_channel_output_eof(PTInstVar pvar, uint32 remote_channel_num)
3019 {
3020 if (SSHv1(pvar)){
3021 unsigned char FAR *outmsg =
3022 begin_send_packet(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED, 4);
3023
3024 set_uint32(outmsg, remote_channel_num);
3025 finish_send_packet(pvar);
3026
3027 } else {
3028 // SSH2: ���������B
3029
3030 }
3031 }
3032
3033 void SSH_channel_input_eof(PTInstVar pvar, uint32 remote_channel_num, uint32 local_channel_num)
3034 {
3035 if (SSHv1(pvar)){
3036 unsigned char FAR *outmsg =
3037 begin_send_packet(pvar, SSH_MSG_CHANNEL_INPUT_EOF, 4);
3038
3039 set_uint32(outmsg, remote_channel_num);
3040 finish_send_packet(pvar);
3041
3042 } else {
3043 // SSH2: �`���l���N���[�Y���T�[�o�����m
3044 buffer_t *msg;
3045 unsigned char *outmsg;
3046 int len;
3047 Channel_t *c;
3048
3049 // SSH2���������������A�p�P�b�g���������B(2005.6.21 yutaka)
3050 if (pvar->rekeying) {
3051 // TODO: ���z���������p�P�b�g�j�����������A�p�P�b�g���������x���������������������A
3052 // �������������������B
3053 c = NULL;
3054
3055 return;
3056 }
3057
3058 c = ssh2_local_channel_lookup(local_channel_num);
3059 if (c == NULL)
3060 return;
3061
3062 msg = buffer_init();
3063 if (msg == NULL) {
3064 // TODO: error check
3065 return;
3066 }
3067 buffer_put_int(msg, c->remote_id); // remote ID
3068
3069 len = buffer_len(msg);
3070 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_EOF, len);
3071 memcpy(outmsg, buffer_ptr(msg), len);
3072 finish_send_packet(pvar);
3073 buffer_free(msg);
3074 }
3075
3076 }
3077
3078 void SSH_request_forwarding(PTInstVar pvar, int from_server_port,
3079 char FAR * to_local_host, int to_local_port)
3080 {
3081 if (SSHv1(pvar)) {
3082 int host_len = strlen(to_local_host);
3083 unsigned char FAR *outmsg =
3084 begin_send_packet(pvar, SSH_CMSG_PORT_FORWARD_REQUEST,
3085 12 + host_len);
3086
3087 set_uint32(outmsg, from_server_port);
3088 set_uint32(outmsg + 4, host_len);
3089 memcpy(outmsg + 8, to_local_host, host_len);
3090 set_uint32(outmsg + 8 + host_len, to_local_port);
3091 finish_send_packet(pvar);
3092
3093 enque_forwarding_request_handlers(pvar);
3094
3095 } else {
3096 // SSH2 port-forwading remote to local (2005.6.21 yutaka)
3097 buffer_t *msg;
3098 char *s;
3099 unsigned char *outmsg;
3100 int len;
3101
3102 msg = buffer_init();
3103 if (msg == NULL) {
3104 // TODO: error check
3105 return;
3106 }
3107 s = "tcpip-forward";
3108 buffer_put_string(msg, s, strlen(s)); // ctype
3109 buffer_put_char(msg, 1); // want reply
3110 s = "0.0.0.0";
3111 buffer_put_string(msg, s, strlen(s));
3112
3113 buffer_put_int(msg, from_server_port); // listening port
3114
3115 len = buffer_len(msg);
3116 outmsg = begin_send_packet(pvar, SSH2_MSG_GLOBAL_REQUEST, len);
3117 memcpy(outmsg, buffer_ptr(msg), len);
3118 finish_send_packet(pvar);
3119 buffer_free(msg);
3120
3121 }
3122 }
3123
3124 void SSH_request_X11_forwarding(PTInstVar pvar,
3125 char FAR * auth_protocol,
3126 unsigned char FAR * auth_data,
3127 int auth_data_len, int screen_num)
3128 {
3129 if (SSHv1(pvar)) {
3130 int protocol_len = strlen(auth_protocol);
3131 int data_len = auth_data_len * 2;
3132 int outmsg_len = 12 + protocol_len + data_len;
3133 unsigned char FAR *outmsg =
3134 begin_send_packet(pvar, SSH_CMSG_X11_REQUEST_FORWARDING, outmsg_len);
3135 int i;
3136 char FAR *auth_data_ptr;
3137
3138 set_uint32(outmsg, protocol_len);
3139 memcpy(outmsg + 4, auth_protocol, protocol_len);
3140 set_uint32(outmsg + 4 + protocol_len, data_len);
3141 auth_data_ptr = outmsg + 8 + protocol_len;
3142 for (i = 0; i < auth_data_len; i++) {
3143 _snprintf_s(auth_data_ptr + i * 2,
3144 outmsg_len - (auth_data_ptr - outmsg) - i * 2,
3145 _TRUNCATE, "%.2x", auth_data[i]);
3146 }
3147 set_uint32(outmsg + 8 + protocol_len + data_len, screen_num);
3148
3149 finish_send_packet(pvar);
3150
3151 enque_forwarding_request_handlers(pvar);
3152
3153 } else {
3154 // SSH2: X11 port-forwarding (2005.7.2 yutaka)
3155 buffer_t *msg;
3156 char *s;
3157 unsigned char *outmsg;
3158 int len;
3159 Channel_t *c;
3160 int newlen;
3161 char *newdata;
3162 int i;
3163
3164 msg = buffer_init();
3165 if (msg == NULL) {
3166 // TODO: error check
3167 return;
3168 }
3169
3170 c = ssh2_channel_lookup(pvar->shell_id);
3171 if (c == NULL)
3172 return;
3173
3174 // making the fake data
3175 newlen = 2 * auth_data_len + 1;
3176 newdata = malloc(newlen);
3177 if (newdata == NULL)
3178 return;
3179 for (i = 0 ; i < auth_data_len ; i++) {
3180 _snprintf_s(newdata + i*2, newlen - i*2, _TRUNCATE, "%02x", auth_data[i]);
3181 }
3182 newdata[newlen - 1] = '\0';
3183
3184 buffer_put_int(msg, c->remote_id);
3185 s = "x11-req";
3186 buffer_put_string(msg, s, strlen(s)); // service name
3187 buffer_put_char(msg, 0); // want confirm (false)
3188 buffer_put_char(msg, 0); // XXX bool single connection
3189
3190 s = auth_protocol; // MIT-MAGIC-COOKIE-1
3191 buffer_put_string(msg, s, strlen(s));
3192 s = newdata;
3193 buffer_put_string(msg, s, strlen(s));
3194
3195 buffer_put_int(msg, screen_num);
3196
3197 len = buffer_len(msg);
3198 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len);
3199 memcpy(outmsg, buffer_ptr(msg), len);
3200 finish_send_packet(pvar);
3201 buffer_free(msg);
3202
3203 free(newdata);
3204 }
3205
3206 }
3207
3208 void SSH_open_channel(PTInstVar pvar, uint32 local_channel_num,
3209 char FAR * to_remote_host, int to_remote_port,
3210 char FAR * originator, unsigned short originator_port)
3211 {
3212 static const int msgs[]
3213 = { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, SSH_MSG_CHANNEL_OPEN_FAILURE };
3214 static const SSHPacketHandler handlers[]
3215 = { handle_channel_open_confirmation, handle_channel_open_failure };
3216
3217 int host_len = strlen(to_remote_host);
3218
3219 if ((pvar->ssh_state.
3220 server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
3221 int originator_len = strlen(originator);
3222 unsigned char FAR *outmsg =
3223 begin_send_packet(pvar, SSH_MSG_PORT_OPEN,
3224