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 5853 - (show annotations) (download) (as text)
Thu May 7 16:38:03 2015 UTC (8 years, 11 months ago) by yutakapon
Original Path: trunk/ttssh2/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 254937 byte(s)
チケット #35047 SSH サーバホスト公開鍵の自動更新

known_hosts ファイルを更新する際の問い合わせダイアログにおいて、
 ・デフォルトボタンを"NO"にした。
 ・英文メッセージを変更した。
※I18N対応は未。

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