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 3057 - (show annotations) (download) (as text)
Sun Oct 28 15:55:48 2007 UTC (16 years, 5 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 192696 byte(s)
local_window の計算を調整した。

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