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 8425 - (show annotations) (download) (as text)
Fri Nov 29 10:08:55 2019 UTC (4 years, 4 months ago) by doda
Original Path: trunk/ttssh2/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 288974 byte(s)
codeconv周り修正 [Ttssh2-devel 4404]

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