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 5545 - (show annotations) (download) (as text)
Mon Mar 17 16:06:58 2014 UTC (10 years ago) by yutakapon
Original Path: trunk/ttssh2/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 250595 byte(s)
チケット #33263
Curve25519楕円曲線DH(Diffe Hellman)アルゴリズムを使った鍵交換をサポートした。

svn+ssh://svn.sourceforge.jp/svnroot/ttssh2/branches/ssh_ed25519
ブランチからマージ。

現時点でサポートしている機能は下記の通り。

 ・Key Generatorで ED25519 鍵の作成
 ・Key Generatorで RSA/DSA/ECDSA 秘密鍵ファイルに bcrypt KDF を選択可能。
 ・ED25519 による公開鍵認証ログイン
 ・RSA(bcrypt KDF) による公開鍵認証ログイン
 ・DSA(bcrypt KDF) による公開鍵認証ログイン
 ・ECDSA(bcrypt KDF) による公開鍵認証ログイン
 ・Host Keyに ssh-ed25519 のサポート

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