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 5640 - (show annotations) (download) (as text)
Sun Jul 13 08:47:03 2014 UTC (9 years, 9 months ago) by yutakapon
Original Path: trunk/ttssh2/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 251941 byte(s)
#34039: スペースを含むファイルをSCP受信できない

SCP受信時、サーバから不定なデータ列が送られてきた場合、エラーメッセージを出すようにした。

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