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 8316 - (show annotations) (download) (as text)
Wed Oct 16 13:19:25 2019 UTC (4 years, 5 months ago) by yutakapon
Original Path: trunk/ttssh2/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 287891 byte(s)
- TTSSHとTTProxyを OpenSSL 1.1.1 に対応した。
  ※OpenSSL 1.0.2ではビルドできません
- Win32 APIのWindows依存チェックツール(installer/checksymbol)を追加した。

branches/openssl_1_1_1_v3からリビジョン8258をマージ:
/branches/openssl_1_1_1_v2 ブランチの r7785 - r8256 をマージした。


........

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