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