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 7771 - (show annotations) (download) (as text)
Sat Jun 15 06:42:23 2019 UTC (4 years, 9 months ago) by yutakapon
Original Path: trunk/ttssh2/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 274200 byte(s)
ポート転送でSSH通信が遅い場合において、Tera Term(TTSSH)の消費メモリが
肥大化して、アプリが落ちる問題を修正した。
チケット #39297

local channelからのパケット読み込み時、SSHサーバへの送信でremote_windowに
空きがない場合は、バッファにパケットを記録するが、フロー制御を追加して際限なく
バッファに溜め込まないようにした。

branches/portfwd_memleak ブランチからのマージ。

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