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 8233 - (show annotations) (download) (as text)
Fri Sep 27 10:16:12 2019 UTC (4 years, 6 months ago) by doda
Original Path: trunk/ttssh2/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 286815 byte(s)
コメント修正
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 = BN_num_bits(pvar->crypt_state.server_key.RSA_key->n);
2588 int host_key_bits = BN_num_bits(pvar->crypt_state.host_key.RSA_key->n);
2589 int server_key_bytes = (server_key_bits + 7) / 8;
2590 int host_key_bytes = (host_key_bits + 7) / 8;
2591 int session_buf_len = server_key_bytes + host_key_bytes + 8;
2592 char *session_buf = (char *) malloc(session_buf_len);
2593 unsigned char session_id[16];
2594
2595 unsigned char *hash;
2596 int pubkeylen, hashlen;
2597
2598 /* Pageant ���n�b�V�����v�Z���������� */
2599 // ���J��������
2600 pubkeylen = putty_get_ssh1_keylen(pvar->pageant_curkey, pvar->pageant_keylistlen);
2601 // �Z�b�V����ID������
2602 BN_bn2bin(pvar->crypt_state.host_key.RSA_key->n, session_buf);
2603 BN_bn2bin(pvar->crypt_state.server_key.RSA_key->n, session_buf + host_key_bytes);
2604 memcpy(session_buf + server_key_bytes + host_key_bytes, pvar->crypt_state.server_cookie, 8);
2605 MD5(session_buf, session_buf_len, session_id);
2606 // �n�b�V������������
2607 hash = putty_hash_ssh1_challenge(pvar->pageant_curkey,
2608 pubkeylen,
2609 pvar->ssh_state.payload,
2610 challenge_bytes + 2,
2611 session_id,
2612 &hashlen);
2613
2614 // �n�b�V�������M
2615 memcpy(outmsg, hash, 16);
2616 free(hash);
2617
2618 finish_send_packet(pvar);
2619
2620 enque_simple_auth_handlers(pvar);
2621 }
2622 }
2623
2624 return FALSE;
2625 }
2626
2627 static void try_send_credentials(PTInstVar pvar)
2628 {
2629 if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_CREDENTIALS) == 0) {
2630 AUTHCred *cred = AUTH_get_cur_cred(pvar);
2631 static const int RSA_msgs[] =
2632 { SSH_SMSG_AUTH_RSA_CHALLENGE, SSH_SMSG_FAILURE };
2633 static const SSHPacketHandler RSA_handlers[]
2634 = { handle_rsa_challenge, handle_rsa_auth_refused };
2635 static const int TIS_msgs[] =
2636 { SSH_SMSG_AUTH_TIS_CHALLENGE, SSH_SMSG_FAILURE };
2637 static const SSHPacketHandler TIS_handlers[]
2638 = { handle_TIS_challenge, handle_auth_failure };
2639
2640 // SSH2���������������������X�L�b�v
2641 if (SSHv2(pvar))
2642 goto skip_ssh2;
2643
2644 switch (cred->method) {
2645 case SSH_AUTH_NONE:
2646 return;
2647 case SSH_AUTH_PASSWORD:{
2648 int len = strlen(cred->password);
2649 unsigned char *outmsg =
2650 begin_send_packet(pvar, SSH_CMSG_AUTH_PASSWORD,
2651 4 + len);
2652
2653 logputs(LOG_LEVEL_VERBOSE, "Trying PASSWORD authentication...");
2654
2655 set_uint32(outmsg, len);
2656 memcpy(outmsg + 4, cred->password, len);
2657
2658 // �Z�b�V�������������p�X���[�h���g���������������A�����������\�[�X�������������B
2659 // socket close���������������������������������A���������������B(2005.4.8 yutaka)
2660 //AUTH_destroy_cur_cred(pvar);
2661
2662 enque_simple_auth_handlers(pvar);
2663 break;
2664 }
2665 case SSH_AUTH_RHOSTS:{
2666 int len = strlen(cred->rhosts_client_user);
2667 unsigned char *outmsg =
2668 begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS, 4 + len);
2669
2670 logputs(LOG_LEVEL_VERBOSE, "Trying RHOSTS authentication...");
2671
2672 set_uint32(outmsg, len);
2673 memcpy(outmsg + 4, cred->rhosts_client_user, len);
2674 AUTH_destroy_cur_cred(pvar);
2675 enque_simple_auth_handlers(pvar);
2676 break;
2677 }
2678 case SSH_AUTH_RSA:{
2679 int len = BN_num_bytes(cred->key_pair->rsa->n);
2680 unsigned char *outmsg =
2681 begin_send_packet(pvar, SSH_CMSG_AUTH_RSA, 2 + len);
2682
2683 logputs(LOG_LEVEL_VERBOSE, "Trying RSA authentication...");
2684
2685 set_ushort16_MSBfirst(outmsg, len * 8);
2686 BN_bn2bin(cred->key_pair->rsa->n, outmsg + 2);
2687 /* don't destroy the current credentials yet */
2688 enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
2689 break;
2690 }
2691 case SSH_AUTH_RHOSTS_RSA:{
2692 int mod_len = BN_num_bytes(cred->key_pair->rsa->n);
2693 int name_len = strlen(cred->rhosts_client_user);
2694 int exp_len = BN_num_bytes(cred->key_pair->rsa->e);
2695 int index;
2696 unsigned char *outmsg =
2697 begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS_RSA,
2698 12 + mod_len + name_len + exp_len);
2699
2700 logputs(LOG_LEVEL_VERBOSE, "Trying RHOSTS+RSA authentication...");
2701
2702 set_uint32(outmsg, name_len);
2703 memcpy(outmsg + 4, cred->rhosts_client_user, name_len);
2704 index = 4 + name_len;
2705
2706 set_uint32(outmsg + index, 8 * mod_len);
2707 set_ushort16_MSBfirst(outmsg + index + 4, 8 * exp_len);
2708 BN_bn2bin(cred->key_pair->rsa->e, outmsg + index + 6);
2709 index += 6 + exp_len;
2710
2711 set_ushort16_MSBfirst(outmsg + index, 8 * mod_len);
2712 BN_bn2bin(cred->key_pair->rsa->n, outmsg + index + 2);
2713 /* don't destroy the current credentials yet */
2714 enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
2715 break;
2716 }
2717 case SSH_AUTH_PAGEANT:{
2718 unsigned char *outmsg;
2719 unsigned char *pubkey;
2720 int len, bn_bytes;
2721
2722 if (pvar->pageant_keycurrent != 0) {
2723 // ���O�������X�L�b�v
2724 pvar->pageant_curkey += 4;
2725 len = get_ushort16_MSBfirst(pvar->pageant_curkey);
2726 bn_bytes = (len + 7) / 8;
2727 pvar->pageant_curkey += 2 + bn_bytes;
2728 len = get_ushort16_MSBfirst(pvar->pageant_curkey);
2729 bn_bytes = (len + 7) / 8;
2730 pvar->pageant_curkey += 2 + bn_bytes;
2731 // ���O�������R�����g���X�L�b�v
2732 len = get_uint32_MSBfirst(pvar->pageant_curkey);
2733 pvar->pageant_curkey += 4 + len;
2734 // �����������u������
2735 }
2736 pubkey = pvar->pageant_curkey + 4;
2737 len = get_ushort16_MSBfirst(pubkey);
2738 bn_bytes = (len + 7) / 8;
2739 pubkey += 2 + bn_bytes;
2740 len = get_ushort16_MSBfirst(pubkey);
2741 bn_bytes = (len + 7) / 8;
2742 pubkey += 2;
2743 outmsg = begin_send_packet(pvar, SSH_CMSG_AUTH_RSA, 2 + bn_bytes);
2744
2745 logputs(LOG_LEVEL_VERBOSE, "Trying RSA authentication...");
2746
2747 set_ushort16_MSBfirst(outmsg, bn_bytes * 8);
2748 memcpy(outmsg + 2, pubkey, bn_bytes);
2749 /* don't destroy the current credentials yet */
2750
2751 pvar->pageant_keycurrent++;
2752
2753 enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
2754 break;
2755 }
2756 case SSH_AUTH_TIS:{
2757 if (cred->password == NULL) {
2758 unsigned char *outmsg =
2759 begin_send_packet(pvar, SSH_CMSG_AUTH_TIS, 0);
2760
2761 logputs(LOG_LEVEL_VERBOSE, "Trying TIS authentication...");
2762 enque_handlers(pvar, 2, TIS_msgs, TIS_handlers);
2763 } else {
2764 int len = strlen(cred->password);
2765 unsigned char *outmsg =
2766 begin_send_packet(pvar, SSH_CMSG_AUTH_TIS_RESPONSE,
2767 4 + len);
2768
2769 logputs(LOG_LEVEL_VERBOSE, "Sending TIS response");
2770
2771 set_uint32(outmsg, len);
2772 memcpy(outmsg + 4, cred->password, len);
2773 enque_simple_auth_handlers(pvar);
2774 }
2775
2776 AUTH_destroy_cur_cred(pvar);
2777 break;
2778 }
2779 default:
2780 UTIL_get_lang_msg("MSG_SSH_UNSUPPORT_AUTH_METHOD_ERROR", pvar,
2781 "Internal error: unsupported authentication method");
2782 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
2783 return;
2784 }
2785
2786 finish_send_packet(pvar);
2787
2788 skip_ssh2:;
2789 destroy_packet_buf(pvar);
2790
2791 pvar->ssh_state.status_flags |= STATUS_DONT_SEND_CREDENTIALS;
2792 }
2793 }
2794
2795 static void try_send_user_name(PTInstVar pvar)
2796 {
2797 if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_USER_NAME) == 0) {
2798 char *username = AUTH_get_user_name(pvar);
2799
2800 if (username != NULL) {
2801 int len = strlen(username);
2802 unsigned char *outmsg =
2803 begin_send_packet(pvar, SSH_CMSG_USER, 4 + len);
2804 static const int msgs[] =
2805 { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
2806 static const SSHPacketHandler handlers[]
2807 = { handle_noauth_success, handle_auth_required };
2808
2809 set_uint32(outmsg, len);
2810 memcpy(outmsg + 4, username, len);
2811 finish_send_packet(pvar);
2812
2813 pvar->ssh_state.status_flags |= STATUS_DONT_SEND_USER_NAME;
2814
2815 logprintf(LOG_LEVEL_VERBOSE, "Sending user name: %s", username);
2816
2817 enque_handlers(pvar, 2, msgs, handlers);
2818 }
2819 }
2820 }
2821
2822 static void send_session_key(PTInstVar pvar)
2823 {
2824 int encrypted_session_key_len;
2825 unsigned char *outmsg;
2826
2827 if (SSHv1(pvar)) {
2828 encrypted_session_key_len =
2829 CRYPT_get_encrypted_session_key_len(pvar);
2830 }
2831
2832 if (!CRYPT_choose_ciphers(pvar))
2833 return;
2834
2835 if (SSHv1(pvar)) {
2836 outmsg =
2837 begin_send_packet(pvar, SSH_CMSG_SESSION_KEY,
2838 15 + encrypted_session_key_len);
2839 outmsg[0] = (unsigned char) CRYPT_get_sender_cipher(pvar);
2840 memcpy(outmsg + 1, CRYPT_get_server_cookie(pvar), 8); /* antispoofing cookie */
2841 outmsg[9] = (unsigned char) (encrypted_session_key_len >> 5);
2842 outmsg[10] = (unsigned char) (encrypted_session_key_len << 3);
2843 if (!CRYPT_choose_session_key(pvar, outmsg + 11))
2844 return;
2845 set_uint32(outmsg + 11 + encrypted_session_key_len,
2846 SSH_PROTOFLAG_SCREEN_NUMBER |
2847 SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
2848 finish_send_packet(pvar);
2849 }
2850
2851 if (!CRYPT_start_encryption(pvar, 1, 1))
2852 return;
2853 notify_established_secure_connection(pvar);
2854
2855 if (SSHv1(pvar)) {
2856 enque_handler(pvar, SSH_SMSG_SUCCESS, handle_crypt_success);
2857 }
2858
2859 pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_USER_NAME;
2860
2861 if (SSHv1(pvar)) {
2862 try_send_user_name(pvar);
2863 }
2864 }
2865
2866 /*************************
2867 END of message handlers
2868 ************************/
2869
2870 void SSH_init(PTInstVar pvar)
2871 {
2872 int i;
2873
2874 buf_create(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
2875 buf_create(&pvar->ssh_state.precompress_outbuf,
2876 &pvar->ssh_state.precompress_outbuflen);
2877 buf_create(&pvar->ssh_state.postdecompress_inbuf,
2878 &pvar->ssh_state.postdecompress_inbuflen);
2879 pvar->ssh_state.payload = NULL;
2880 pvar->ssh_state.compressing = FALSE;
2881 pvar->ssh_state.decompressing = FALSE;
2882 pvar->ssh_state.status_flags =
2883 STATUS_DONT_SEND_USER_NAME | STATUS_DONT_SEND_CREDENTIALS;
2884 pvar->ssh_state.payload_datalen = 0;
2885 pvar->ssh_state.hostname = NULL;
2886 pvar->ssh_state.server_ID = NULL;
2887 pvar->ssh_state.receiver_sequence_number = 0;
2888 pvar->ssh_state.sender_sequence_number = 0;
2889 for (i = 0; i < NUM_ELEM(pvar->ssh_state.packet_handlers); i++) {
2890 pvar->ssh_state.packet_handlers[i] = NULL;
2891 }
2892
2893 // for SSH2(yutaka)
2894 memset(pvar->ssh2_keys, 0, sizeof(pvar->ssh2_keys));
2895 pvar->userauth_success = 0;
2896 pvar->shell_id = SSH_CHANNEL_INVALID;
2897 pvar->session_nego_status = 0;
2898 pvar->settings.ssh_protocol_version = 2; // SSH2(default)
2899 pvar->rekeying = 0;
2900 pvar->key_done = 0;
2901 pvar->ssh2_autologin = 0; // autologin disabled(default)
2902 pvar->ask4passwd = 0; // disabled(default) (2006.9.18 maya)
2903 pvar->userauth_retry_count = 0;
2904 pvar->decomp_buffer = NULL;
2905 pvar->authbanner_buffer = NULL;
2906 pvar->ssh2_authlist = NULL; // (2007.4.27 yutaka)
2907 pvar->tryed_ssh2_authlist = FALSE;
2908 pvar->agentfwd_enable = FALSE;
2909 pvar->use_subsystem = FALSE;
2910 pvar->nosession = FALSE;
2911
2912 }
2913
2914 void SSH_open(PTInstVar pvar)
2915 {
2916 pvar->ssh_state.hostname = _strdup(pvar->ts->HostName);
2917 pvar->ssh_state.tcpport = pvar->ts->TCPPort;
2918 pvar->ssh_state.win_cols = pvar->ts->TerminalWidth;
2919 pvar->ssh_state.win_rows = pvar->ts->TerminalHeight;
2920 }
2921
2922 void SSH_notify_disconnecting(PTInstVar pvar, char *reason)
2923 {
2924 if (SSHv1(pvar)) {
2925 int len = reason == NULL ? 0 : strlen(reason);
2926 unsigned char *outmsg =
2927 begin_send_packet(pvar, SSH_MSG_DISCONNECT, len + 4);
2928
2929 set_uint32(outmsg, len);
2930 if (reason != NULL) {
2931 memcpy(outmsg + 4, reason, len);
2932 }
2933 finish_send_packet(pvar);
2934
2935 } else { // for SSH2(yutaka)
2936 buffer_t *msg;
2937 unsigned char *outmsg;
2938 char *s;
2939 int len;
2940
2941 // SSH2 server��disconnect���`����
2942 msg = buffer_init();
2943 if (msg == NULL) {
2944 // TODO: error check
2945 logprintf(LOG_LEVEL_ERROR, "%s: buffer_init returns NULL.", __FUNCTION__);
2946 return;
2947 }
2948 buffer_put_int(msg, SSH2_DISCONNECT_BY_APPLICATION);
2949 buffer_put_string(msg, reason, strlen(reason));
2950 s = "";
2951 buffer_put_string(msg, s, strlen(s));
2952
2953 len = buffer_len(msg);
2954 outmsg = begin_send_packet(pvar, SSH2_MSG_DISCONNECT, len);
2955 memcpy(outmsg, buffer_ptr(msg), len);
2956 finish_send_packet(pvar);
2957 buffer_free(msg);
2958
2959 logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_DISCONNECT was sent at SSH_notify_disconnecting().");
2960 }
2961 }
2962
2963 void SSH_notify_host_OK(PTInstVar pvar)
2964 {
2965 if ((pvar->ssh_state.status_flags & STATUS_HOST_OK) == 0) {
2966 pvar->ssh_state.status_flags |= STATUS_HOST_OK;
2967 send_session_key(pvar);
2968 // ���[�U�F�����s���������^�C�~���O�������������A�F���_�C�A���O���o���������B
2969 // STATUS_HOST_OK�������ASTATUS_DONT_SEND_USER_NAME�����������������A
2970 // �F���_�C�A���O�������g�����������A�����^�C�~���O�����������B
2971 AUTH_advance_to_next_cred(pvar);
2972 }
2973 }
2974
2975 static void get_window_pixel_size(PTInstVar pvar, int *x, int *y)
2976 {
2977 RECT r;
2978
2979 if (pvar->cv->HWin && GetWindowRect(pvar->cv->HWin, &r)) {
2980 *x = r.right - r.left;
2981 *y = r.bottom - r.top;
2982 }
2983 else {
2984 *x = 0;
2985 *y = 0;
2986 }
2987
2988 return;
2989 }
2990
2991 void SSH_notify_win_size(PTInstVar pvar, int cols, int rows)
2992 {
2993 int x, y;
2994
2995 pvar->ssh_state.win_cols = cols;
2996 pvar->ssh_state.win_rows = rows;
2997
2998 get_window_pixel_size(pvar, &x, &y);
2999
3000 if (SSHv1(pvar)) {
3001 if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) == handle_data) {
3002 unsigned char *outmsg =
3003 begin_send_packet(pvar, SSH_CMSG_WINDOW_SIZE, 16);
3004
3005 set_uint32(outmsg, rows); // window height (characters)
3006 set_uint32(outmsg + 4, cols); // window width (characters)
3007 set_uint32(outmsg + 8, x); // window width (pixels)
3008 set_uint32(outmsg + 12, y); // window height (pixels)
3009 finish_send_packet(pvar);
3010 logprintf(LOG_LEVEL_VERBOSE, "%s: sending SSH_CMSG_WINDOW_SIZE. "
3011 "cols: %d, rows: %d, x: %d, y: %d", __FUNCTION__, cols, rows, x, y);
3012 }
3013
3014 } else if (SSHv2(pvar)) {
3015 // �^�[�~�i���T�C�Y���X���m������ (2005.1.4 yutaka)
3016 // SSH2�����������`�F�b�N���s���B(2005.1.5 yutaka)
3017 buffer_t *msg;
3018 char *req_type = "window-change";
3019 unsigned char *outmsg;
3020 int len;
3021 Channel_t *c;
3022
3023 c = ssh2_channel_lookup(pvar->shell_id);
3024 if (c == NULL) {
3025 logprintf(LOG_LEVEL_ERROR, "%s: shell channel not found.", __FUNCTION__);
3026 return;
3027 }
3028
3029
3030 msg = buffer_init();
3031 if (msg == NULL) {
3032 // TODO: error check
3033 logprintf(LOG_LEVEL_ERROR, "%s: buffer_init returns NULL.", __FUNCTION__);
3034 return;
3035 }
3036 buffer_put_int(msg, c->remote_id);
3037 buffer_put_string(msg, req_type, strlen(req_type));
3038 buffer_put_char(msg, 0); // want_reply
3039 buffer_put_int(msg, cols); // columns
3040 buffer_put_int(msg, rows); // lines
3041 buffer_put_int(msg, x); // window width (pixel):
3042 buffer_put_int(msg, y); // window height (pixel):
3043 len = buffer_len(msg);
3044 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len);
3045 memcpy(outmsg, buffer_ptr(msg), len);
3046 finish_send_packet(pvar);
3047 buffer_free(msg);
3048
3049 logprintf(LOG_LEVEL_VERBOSE, "%s: sending SSH2_MSG_CHANNEL_REQUEST. "
3050 "local: %d, remote: %d, request-type: %s, cols: %d, rows: %d, x: %d, y: %d", __FUNCTION__,
3051 c->self_id, c->remote_id, req_type, cols, rows, x, y);
3052
3053 } else {
3054 // SSH�����������������������B
3055 }
3056 }
3057
3058 // �u���[�N�M�������� -- RFC 4335
3059 // OpenSSH ��"~B"�����������B
3060 // (2010.9.27 yutaka)
3061 int SSH_notify_break_signal(PTInstVar pvar)
3062 {
3063 int ret = 0;
3064
3065 if (SSHv2(pvar)) { // SSH2 ��������
3066 buffer_t *msg;
3067 char *req_type = "break";
3068 unsigned char *outmsg;
3069 int len;
3070 Channel_t *c;
3071
3072 c = ssh2_channel_lookup(pvar->shell_id);
3073 if (c == NULL) {
3074 logprintf(LOG_LEVEL_ERROR, "%s: shell channel not found.", __FUNCTION__);
3075 goto error;
3076 }
3077
3078 msg = buffer_init();
3079 if (msg == NULL) {
3080 logprintf(LOG_LEVEL_ERROR, "%s: buffer_init returns NULL.", __FUNCTION__);
3081 goto error;
3082 }
3083 buffer_put_int(msg, c->remote_id);
3084 buffer_put_string(msg, req_type, strlen(req_type));
3085 buffer_put_char(msg, 0); // want_reply
3086 buffer_put_int(msg, 1000); // break-length (msec)
3087 len = buffer_len(msg);
3088 outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len);
3089 memcpy(outmsg, buffer_ptr(msg), len);
3090 finish_send_packet(pvar);
3091 buffer_free(msg);
3092
3093 logprintf(LOG_LEVEL_VERBOSE, "%s: sending SSH2_MSG_CHANNEL_REQUEST. "
3094 "local: %d, remote: %d, request-type: %s, break-length: %d", __FUNCTION__,
3095 c->self_id, c->remote_id, req_type, 1000);
3096
3097 ret = 1;
3098 }
3099
3100 error:
3101 return (ret);
3102 }
3103
3104 unsigned int SSH_get_min_packet_size(PTInstVar pvar)
3105 {
3106 if (SSHv1(pvar)) {
3107 return 12;
3108 } else {
3109 return max(16, CRYPT_get_decryption_block_size(pvar));
3110 }
3111 }
3112
3113 /* data is guaranteed to be at least SSH_get_min_packet_size bytes long
3114 at least 5 bytes must be decrypted */
3115 void SSH_predecrypt_packet(PTInstVar pvar, char *data)
3116 {
3117 if (SSHv2(pvar)) {
3118 CRYPT_decrypt(pvar, data, get_predecryption_amount(pvar));
3119 }
3120 }
3121
3122 unsigned int SSH_get_clear_MAC_size(PTInstVar pvar)
3123 {
3124 if (SSHv1(pvar)) {
3125 return 0;
3126 } else {
3127 return CRYPT_get_receiver_MAC_size(pvar);
3128 }
3129 }
3130
3131 unsigned int SSH_get_authdata_size(PTInstVar pvar, int direction)
3132 {
3133 if (SSHv1(pvar)) {
3134 return 0;
3135 }
3136 else {
3137 struct Mac *mac = &pvar->ssh2_keys[direction].mac;
3138 struct Enc *enc = &pvar->ssh2_keys[direction].enc;
3139
3140 if (enc && enc->auth_len > 0) {
3141 // AEAD
3142 return enc->auth_len;
3143 }
3144 else if (mac && mac->enabled) {
3145 return mac->mac_len;
3146 }
3147 else {
3148 return 0;
3149 }
3150 }
3151 }
3152
3153 void SSH_notify_user_name(PTInstVar pvar)
3154 {
3155 try_send_user_name(pvar);
3156 }
3157
3158 void SSH_notify_cred(PTInstVar pvar)
3159 {
3160 try_send_credentials(pvar);
3161 }
3162
3163 void SSH_send(PTInstVar pvar, unsigned char const *buf, unsigned int buflen)
3164 {
3165 // RAW�p�P�b�g�_���v������ (2008.8.15 yutaka)
3166 if (LogLevel(pvar, LOG_LEVEL_SSHDUMP)) {
3167 init_memdump();
3168 push_memdump("SSH sending packet", "SSH_send", (char *)buf, buflen);
3169 }
3170
3171 if (SSHv1(pvar)) {
3172 if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) != handle_data) {
3173 return;
3174 }
3175
3176 while (buflen > 0) {
3177 int len =
3178 buflen >
3179 SSH_MAX_SEND_PACKET_SIZE ? SSH_MAX_SEND_PACKET_SIZE : buflen;
3180 unsigned char *outmsg