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 3082 - (show annotations) (download) (as text)
Thu Dec 27 15:11:09 2007 UTC (16 years, 3 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 205102 byte(s)
SCPファイル送信ウィンドウのキャンセルボタンのスペルミス修正。
2GB以上のファイルを送信しようとしたあとに、SSH2_MSG_CHANNEL_EOFの受信処理で
port-forwarding用関数をコールしないようにした。
ファイル受信処理は実装途中(影響なし)。

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