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