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