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 7008 - (show annotations) (download) (as text)
Mon Dec 18 11:06:16 2017 UTC (6 years, 3 months ago) by doda
Original Path: trunk/ttssh2/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 268531 byte(s)
AEAD 暗号使用時は MAC Negotiation の結果を無視するようにした #37750

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