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 3078 - (show annotations) (download) (as text)
Wed Dec 26 12:17:29 2007 UTC (16 years, 3 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 203350 byte(s)
SSHハートビートスレッドのパケット送信をモードレスダイアログ内で行うことで、
コンテキストの乱れを発生させないようにする。

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