Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/ssh.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9217 - (hide annotations) (download) (as text)
Sun Apr 25 02:18:41 2021 UTC (2 years, 11 months ago) by nmaya
File MIME type: text/x-csrc
File size: 280942 byte(s)
SSH2 暗号化方式 chacha20-poly1305@openssh.com をサポート
1 maya 3227 /*
2 doda 6841 * Copyright (c) 1998-2001, Robert O'Callahan
3 nmaya 9049 * (C) 2004- TeraTerm Project
4 doda 6841 * 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 maya 3227
30     #include "ttxssh.h"
31     #include "util.h"
32     #include "resource.h"
33     #include "libputty.h"
34 maya 4304 #include "key.h"
35 doda 6779 #include "ttcommon.h"
36 doda 8397 #include "codeconv.h"
37 maya 3227
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 doda 4379 #include <commctrl.h>
52 maya 3227 #include "buffer.h"
53     #include "ssh.h"
54     #include "crypt.h"
55     #include "fwd.h"
56     #include "sftp.h"
57 maya 4304 #include "kex.h"
58 zmatsuo 7560 #include "dlglib.h"
59 maya 3227
60     #include <sys/types.h>
61     #include <sys/stat.h>
62 maya 5607 #include <sys/utime.h>
63 maya 3227 #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 doda 6812 //
84     // msg �� NULL �����������������BNULL �������� "(null)" �������B
85     //
86     #define NonNull(msg) ((msg)?(msg):"(null)")
87 maya 3227
88 doda 7024 typedef enum {
89     GetPayloadError = 0,
90     GetPayloadOK = 1,
91     GetPayloadTruncate = 2
92     } PayloadStat;
93    
94 yutakapon 5850 static struct global_confirm global_confirms;
95    
96 maya 3227 static Channel_t channels[CHANNEL_MAX];
97    
98     static char ssh_ttymodes[] = "\x01\x03\x02\x1c\x03\x08\x04\x15\x05\x04";
99    
100 yutakapon 6528 static CRITICAL_SECTION g_ssh_scp_lock; /* SCP���M�p���b�N */
101    
102 youlab 8924 static int g_scp_sending; /* SCP���M����? */
103    
104 maya 3227 static void try_send_credentials(PTInstVar pvar);
105     static void prep_compression(PTInstVar pvar);
106    
107     // �����v���g�^�C�v����
108     void SSH2_send_kexinit(PTInstVar pvar);
109     static BOOL handle_SSH2_kexinit(PTInstVar pvar);
110     static void SSH2_dh_kex_init(PTInstVar pvar);
111     static void SSH2_dh_gex_kex_init(PTInstVar pvar);
112 maya 4314 static void SSH2_ecdh_kex_init(PTInstVar pvar);
113 maya 3227 static BOOL handle_SSH2_dh_common_reply(PTInstVar pvar);
114     static BOOL handle_SSH2_dh_gex_reply(PTInstVar pvar);
115     static BOOL handle_SSH2_newkeys(PTInstVar pvar);
116     static BOOL handle_SSH2_service_accept(PTInstVar pvar);
117     static BOOL handle_SSH2_userauth_success(PTInstVar pvar);
118     static BOOL handle_SSH2_userauth_failure(PTInstVar pvar);
119     static BOOL handle_SSH2_userauth_banner(PTInstVar pvar);
120     static BOOL handle_SSH2_open_confirm(PTInstVar pvar);
121     static BOOL handle_SSH2_open_failure(PTInstVar pvar);
122 yutakapon 5829 static BOOL handle_SSH2_client_global_request(PTInstVar pvar);
123 maya 3227 static BOOL handle_SSH2_request_success(PTInstVar pvar);
124     static BOOL handle_SSH2_request_failure(PTInstVar pvar);
125     static BOOL handle_SSH2_channel_success(PTInstVar pvar);
126     static BOOL handle_SSH2_channel_failure(PTInstVar pvar);
127     static BOOL handle_SSH2_channel_data(PTInstVar pvar);
128     static BOOL handle_SSH2_channel_extended_data(PTInstVar pvar);
129     static BOOL handle_SSH2_channel_eof(PTInstVar pvar);
130     static BOOL handle_SSH2_channel_close(PTInstVar pvar);
131     static BOOL handle_SSH2_channel_open(PTInstVar pvar);
132     static BOOL handle_SSH2_window_adjust(PTInstVar pvar);
133     static BOOL handle_SSH2_channel_request(PTInstVar pvar);
134     void SSH2_dispatch_init(int stage);
135     int SSH2_dispatch_enabled_check(unsigned char message);
136     void SSH2_dispatch_add_message(unsigned char message);
137     void SSH2_dispatch_add_range_message(unsigned char begin, unsigned char end);
138     int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub);
139     static void start_ssh_heartbeat_thread(PTInstVar pvar);
140     void ssh2_channel_send_close(PTInstVar pvar, Channel_t *c);
141     static BOOL SSH_agent_response(PTInstVar pvar, Channel_t *c, int local_channel_num, unsigned char *data, unsigned int buflen);
142 yutakapon 6528 static void ssh2_scp_get_packetlist(Channel_t *c, unsigned char **buf, unsigned int *buflen);
143     static void ssh2_scp_free_packetlist(Channel_t *c);
144 doda 6799 static void get_window_pixel_size(PTInstVar pvar, int *x, int *y);
145 yutakapon 8093 static BOOL store_contents_for_known_hosts(PTInstVar pvar, enum ssh_kex_known_hosts kex_type, UINT_PTR offset);
146 maya 3227
147 doda 7019 // �}�N��
148     #define remained_payload(pvar) ((pvar)->ssh_state.payload + payload_current_offset(pvar))
149     #define remained_payloadlen(pvar) ((pvar)->ssh_state.payloadlen - (pvar)->ssh_state.payload_grabbed)
150     #define payload_current_offset(pvar) ((pvar)->ssh_state.payload_grabbed - 1)
151    
152 maya 3227 //
153 yutakapon 5850 // Global request confirm
154     //
155     static void client_init_global_confirm(void)
156     {
157     memset(&global_confirms, 0, sizeof(global_confirms));
158     global_confirms.ref_count = 0;
159     }
160    
161 yutakapon 5853 void client_register_global_confirm(global_confirm_cb *cb, void *ctx)
162 yutakapon 5850 {
163     struct global_confirm *gc = &global_confirms;
164    
165     if (gc->ref_count == 0) {
166     gc->cb = cb;
167     gc->ctx = ctx;
168     gc->ref_count = 1;
169     }
170     }
171    
172 yutakapon 5853 static int client_global_request_reply(PTInstVar pvar, int type, unsigned int seq, void *ctxt)
173     {
174 yutakapon 5850 struct global_confirm *gc = &global_confirms;
175    
176     if (gc->ref_count >= 1) {
177     if (gc->cb)
178     gc->cb(pvar, type, seq, gc->ctx);
179     gc->ref_count = 0;
180     }
181    
182     return 0;
183 yutakapon 5853 }
184 yutakapon 5850
185     //
186 maya 3227 // channel function
187     //
188     static Channel_t *ssh2_channel_new(unsigned int window, unsigned int maxpack,
189 zmatsuo 7536 enum channel_type type, int local_num)
190 maya 3227 {
191     int i, found;
192     Channel_t *c;
193    
194     found = -1;
195     for (i = 0 ; i < CHANNEL_MAX ; i++) {
196     if (channels[i].used == 0) { // free channel
197     found = i;
198     break;
199     }
200     }
201     if (found == -1) { // not free channel
202     return (NULL);
203     }
204    
205     // setup
206     c = &channels[found];
207     memset(c, 0, sizeof(Channel_t));
208     c->used = 1;
209     c->self_id = i;
210 doda 8600 c->remote_id = SSH_CHANNEL_INVALID;
211 maya 3227 c->local_window = window;
212     c->local_window_max = window;
213     c->local_consumed = 0;
214     c->local_maxpacket = maxpack;
215     c->remote_window = 0;
216     c->remote_maxpacket = 0;
217     c->type = type;
218     c->local_num = local_num; // alloc_channel()�����l��������������
219     c->bufchain = NULL;
220 yutakapon 7771 c->bufchain_amount = 0;
221     c->bufchain_recv_suspended = FALSE;
222 maya 3227 if (type == TYPE_SCP) {
223     c->scp.state = SCP_INIT;
224     c->scp.progress_window = NULL;
225 zmatsuo 7930 c->scp.thread = INVALID_HANDLE_VALUE;
226 maya 3227 c->scp.localfp = NULL;
227 maya 5607 c->scp.filemtime = 0;
228     c->scp.fileatime = 0;
229 maya 3227 }
230     if (type == TYPE_AGENT) {
231     c->agent_msg = buffer_init();
232     c->agent_request_len = 0;
233     }
234 maya 5422 c->state = 0;
235 maya 3227
236     return (c);
237     }
238    
239     // remote_window�������������������A�������������o�b�t�@�����X�g�i�������j���������������B
240 yutakapon 7771 // �������m�������������� ssh2_channel_retry_send_bufchain() �����������B
241     static void ssh2_channel_add_bufchain(PTInstVar pvar, Channel_t *c, unsigned char *buf, unsigned int buflen)
242 maya 3227 {
243     bufchain_t *p, *old;
244    
245     // allocate new buffer
246     p = malloc(sizeof(bufchain_t));
247     if (p == NULL)
248     return;
249     p->msg = buffer_init();
250     if (p == NULL) {
251     free(p);
252     return;
253     }
254     buffer_put_raw(p->msg, buf, buflen);
255     p->next = NULL;
256    
257     if (c->bufchain == NULL) {
258     c->bufchain = p;
259     } else {
260     old = c->bufchain;
261     while (old->next)
262     old = old->next;
263     old->next = p;
264     }
265 yutakapon 7771
266     // �o�b�t�@�T�C�Y�����v���X�V����(�L�^�p)
267     c->bufchain_amount += buflen;
268    
269     // remote_window�����������������Alocal connection�������p�P�b�g���M��
270     // ���~�w�����o���B���������m���~�����������������B
271     FWD_suspend_resume_local_connection(pvar, c, FALSE);
272 maya 3227 }
273    
274 yutakapon 7771 // remote_window�����������������A���X�g���c���������f�[�^�������������B
275     // ���M���������������������������B
276 maya 3227 static void ssh2_channel_retry_send_bufchain(PTInstVar pvar, Channel_t *c)
277     {
278     bufchain_t *ch;
279     unsigned int size;
280 yutakapon 7771 bufchain_t* ch_origin = c->bufchain;
281 maya 3227
282     while (c->bufchain) {
283     // ����������������
284     ch = c->bufchain;
285     size = buffer_len(ch->msg);
286     if (size >= c->remote_window)
287     break;
288    
289     if (c->local_num == -1) { // shell or SCP
290 yutakapon 5039 SSH2_send_channel_data(pvar, c, buffer_ptr(ch->msg), size, TRUE);
291 maya 3227 } else { // port-forwarding
292 yutakapon 5039 SSH_channel_send(pvar, c->local_num, -1, buffer_ptr(ch->msg), size, TRUE);
293 maya 3227 }
294    
295     c->bufchain = ch->next;
296    
297     buffer_free(ch->msg);
298     free(ch);
299 yutakapon 7771
300     // �o�b�t�@�T�C�Y�����v���X�V����(�L�^�p)
301     c->bufchain_amount -= size;
302 maya 3227 }
303 yutakapon 7771
304     // ���X���������X�g���������������A
305     // local connection�������p�P�b�g���m�����J�����B
306     if (ch_origin && c->bufchain == NULL) {
307     FWD_suspend_resume_local_connection(pvar, c, TRUE);
308     }
309 maya 3227 }
310    
311     // channel close�����`���l���\���������X�g�����p����
312     // (2007.4.26 yutaka)
313     static void ssh2_channel_delete(Channel_t *c)
314     {
315     bufchain_t *ch, *ptr;
316 yutakapon 6586 enum scp_state prev_state;
317 maya 3227
318     ch = c->bufchain;
319     while (ch) {
320     if (ch->msg)
321     buffer_free(ch->msg);
322     ptr = ch;
323     ch = ch->next;
324     free(ptr);
325     }
326    
327     if (c->type == TYPE_SCP) {
328 yutakapon 6586 // SCP���������������������������B
329     prev_state = c->scp.state;
330    
331 maya 3227 c->scp.state = SCP_CLOSING;
332 maya 5607 if (c->scp.localfp != NULL) {
333 maya 3227 fclose(c->scp.localfp);
334 maya 5607 if (c->scp.dir == FROMREMOTE) {
335     if (c->scp.fileatime > 0 && c->scp.filemtime > 0) {
336     struct _utimbuf filetime;
337     filetime.actime = c->scp.fileatime;
338     filetime.modtime = c->scp.filemtime;
339     _utime(c->scp.localfilefull, &filetime);
340     }
341 yutakapon 6586
342     // SCP���M���������������������A���[�J�����������t�@�C�����c�[�����������B
343     // (2017.2.12 yutaka)
344     if (prev_state != SCP_CLOSING)
345     remove(c->scp.localfilefull);
346 maya 5607 }
347     }
348 maya 3227 if (c->scp.progress_window != NULL) {
349     DestroyWindow(c->scp.progress_window);
350     c->scp.progress_window = NULL;
351     }
352 zmatsuo 7930 if (c->scp.thread != INVALID_HANDLE_VALUE) {
353 maya 3227 WaitForSingleObject(c->scp.thread, INFINITE);
354     CloseHandle(c->scp.thread);
355 zmatsuo 7930 c->scp.thread = INVALID_HANDLE_VALUE;
356 maya 3227 }
357 yutakapon 6528
358 yutakapon 8031 // SCP���M�����������ASCP�p���X�g���J�����s���B
359     // Windows9x���������������C�������B
360     if (c->scp.dir == FROMREMOTE)
361     ssh2_scp_free_packetlist(c);
362 youlab 8924
363     g_scp_sending = FALSE;
364 maya 3227 }
365     if (c->type == TYPE_AGENT) {
366     buffer_free(c->agent_msg);
367     }
368    
369     memset(c, 0, sizeof(Channel_t));
370     c->used = 0;
371     }
372    
373     // connection close������������
374     void ssh2_channel_free(void)
375     {
376     int i;
377     Channel_t *c;
378    
379     for (i = 0 ; i < CHANNEL_MAX ; i++) {
380     c = &channels[i];
381     ssh2_channel_delete(c);
382     }
383     }
384    
385     static Channel_t *ssh2_channel_lookup(int id)
386     {
387     Channel_t *c;
388    
389     if (id < 0 || id >= CHANNEL_MAX) {
390 zmatsuo 7649 logprintf(LOG_LEVEL_VERBOSE, "%s: invalid channel id. (%d)", __FUNCTION__, id);
391 maya 3227 return (NULL);
392     }
393     c = &channels[id];
394     if (c->used == 0) { // already freed
395 zmatsuo 7649 logprintf(LOG_LEVEL_VERBOSE, "%s: channel was already freed. id:%d", __FUNCTION__, id);
396 maya 3227 return (NULL);
397     }
398     return (c);
399     }
400    
401     // SSH1��������������channel�\���������ASSH2������Channel_t�����������B
402     // TODO: �����I�����`���l���\������1�������������B
403     // (2005.6.12 yutaka)
404 yutakapon 7771 Channel_t *ssh2_local_channel_lookup(int local_num)
405 maya 3227 {
406     int i;
407     Channel_t *c;
408    
409     for (i = 0 ; i < CHANNEL_MAX ; i++) {
410     c = &channels[i];
411     if (c->local_num == local_num)
412     return (c);
413     }
414     return (NULL);
415     }
416    
417     //
418     // SSH heartbeat mutex
419     //
420     // TTSSH�� thread-safe �������������A�}���`�X���b�h�������p�P�b�g���M�����������B
421     // �V���O���X���b�h�����R���e�L�X�g�X�C�b�`�������������������������A
422     // ���b�N�������K�v�����������A���������B(2007.12.26 yutaka)
423     //
424     static CRITICAL_SECTION g_ssh_heartbeat_lock; /* �����M�p���b�N */
425    
426     void ssh_heartbeat_lock_initialize(void)
427     {
428     //InitializeCriticalSection(&g_ssh_heartbeat_lock);
429     }
430    
431     void ssh_heartbeat_lock_finalize(void)
432     {
433     //DeleteCriticalSection(&g_ssh_heartbeat_lock);
434     }
435    
436     void ssh_heartbeat_lock(void)
437     {
438     //EnterCriticalSection(&g_ssh_heartbeat_lock);
439     }
440    
441     void ssh_heartbeat_unlock(void)
442     {
443     //LeaveCriticalSection(&g_ssh_heartbeat_lock);
444     }
445    
446     //
447     // SSH memory dump (for debug)
448     //
449     // (2005.3.7 yutaka)
450     //
451     #define MEMTAG_MAX 300
452     #define LOGDUMP "ssh2connect.log"
453     #define LOG_PACKET_DUMP "ssh2packet.log"
454     #define SENDTOME "Please send '"LOGDUMP"' file to Tera Term developer team."
455    
456     typedef struct memtag {
457     char *name;
458     char *desc;
459     time_t time;
460     int len;
461     char *data;
462     } memtag_t;
463    
464     static memtag_t memtags[MEMTAG_MAX];
465     static int memtag_count = 0;
466     static int memtag_use = 0;
467    
468     /* �_���v���C�����t�H�[�}�b�g�\������ */
469     static void displine_memdump(FILE *fp, int addr, int *bytes, int byte_cnt)
470     {
471     int i, c;
472    
473     /* �������A�h���X�\�� */
474     fprintf(fp, "%08X : ", addr);
475    
476     /* �o�C�i���\���i4�o�C�g�������������}���j*/
477     for (i = 0 ; i < byte_cnt ; i++) {
478     if (i > 0 && i % 4 == 0)
479     fprintf(fp, " ");
480    
481     fprintf(fp, "%02X", bytes[i]);
482     }
483    
484     /* ASCII�\���������������������� */
485     fprintf(fp, " %*s%*s", (16-byte_cnt)*2+1, " ", (16-byte_cnt+3)/4, " ");
486    
487     /* ASCII�\�� */
488     for (i = 0 ; i < byte_cnt ; i++) {
489     c = bytes[i];
490     if (isprint(c)) {
491     fprintf(fp, "%c", c);
492     } else {
493     fprintf(fp, ".");
494     }
495     }
496    
497     fprintf(fp, "\n");
498     }
499    
500    
501     /* �_���v���[�`�� */
502     static void dump_memdump(FILE *fp, char *data, int len)
503     {
504     int c, addr;
505     int bytes[16], *ptr;
506     int byte_cnt;
507     int i;
508    
509     addr = 0;
510     byte_cnt = 0;
511     ptr = bytes;
512     for (i = 0 ; i < len ; i++) {
513     c = data[i];
514     *ptr++ = c & 0xff;
515     byte_cnt++;
516    
517     if (byte_cnt == 16) {
518     displine_memdump(fp, addr, bytes, byte_cnt);
519    
520     addr += 16;
521     byte_cnt = 0;
522     ptr = bytes;
523     }
524     }
525    
526     if (byte_cnt > 0) {
527     displine_memdump(fp, addr, bytes, byte_cnt);
528     }
529     }
530    
531     void init_memdump(void)
532     {
533     int i;
534    
535     if (memtag_use > 0)
536     return;
537    
538     for (i = 0 ; i < MEMTAG_MAX ; i++) {
539     memtags[i].name = NULL;
540     memtags[i].desc = NULL;
541     memtags[i].data = NULL;
542     memtags[i].len = 0;
543     }
544     memtag_use++;
545     }
546    
547     void finish_memdump(void)
548     {
549     int i;
550    
551     // initialize�������������������������������B(2005.4.3 yutaka)
552     if (memtag_use <= 0)
553     return;
554     memtag_use--;
555    
556     for (i = 0 ; i < MEMTAG_MAX ; i++) {
557     free(memtags[i].name);
558     free(memtags[i].desc);
559     free(memtags[i].data);
560     memtags[i].len = 0;
561     }
562     memtag_count = 0;
563     }
564    
565     void save_memdump(char *filename)
566     {
567     FILE *fp;
568     int i;
569     time_t t;
570     struct tm *tm;
571    
572     fp = fopen(filename, "w");
573     if (fp == NULL)
574     return;
575    
576     t = time(NULL);
577     tm = localtime(&t);
578    
579     fprintf(fp, "<<< Tera Term SSH2 log dump >>>\n");
580     fprintf(fp, "saved time: %04d/%02d/%02d %02d:%02d:%02d\n",
581     tm->tm_year + 1900,
582     tm->tm_mon + 1,
583     tm->tm_mday,
584     tm->tm_hour,
585     tm->tm_min,
586     tm->tm_sec);
587     fprintf(fp, "\n");
588    
589     for (i = 0 ; i < memtag_count ; i++) {
590     fprintf(fp, "============================================\n");
591     fprintf(fp, "name: %s\n", memtags[i].name);
592     fprintf(fp, "--------------------------------------------\n");
593     fprintf(fp, "description: %s\n", memtags[i].desc);
594     fprintf(fp, "--------------------------------------------\n");
595     fprintf(fp, "time: %s", ctime(&memtags[i].time));
596     fprintf(fp, "============================================\n");
597     dump_memdump(fp, memtags[i].data, memtags[i].len);
598     fprintf(fp, "\n\n\n");
599     }
600    
601     fprintf(fp, "[EOF]\n");
602    
603     fclose(fp);
604     }
605    
606     void push_memdump(char *name, char *desc, char *data, int len)
607     {
608     memtag_t *ptr;
609     char *dp;
610    
611     dp = malloc(len);
612     if (dp == NULL)
613     return;
614     memcpy(dp, data, len);
615    
616     if (memtag_count >= MEMTAG_MAX)
617     return;
618    
619     ptr = &memtags[memtag_count];
620     memtag_count++;
621     ptr->name = _strdup(name);
622     ptr->desc = _strdup(desc);
623     ptr->time = time(NULL);
624     ptr->data = dp;
625     ptr->len = len;
626     }
627    
628     void push_bignum_memdump(char *name, char *desc, BIGNUM *bignum)
629     {
630     int len;
631     char *buf;
632    
633     len = BN_num_bytes(bignum);
634     buf = malloc(len); // allocate
635     if (buf == NULL)
636     return;
637     BN_bn2bin(bignum, buf);
638     push_memdump(name, desc, buf, len); // at push_bignum_memdump()
639     free(buf); // free
640     }
641    
642 doda 6982 static unsigned int get_predecryption_amount(PTInstVar pvar)
643 maya 3227 {
644     static int small_block_decryption_sizes[] = { 5, 5, 6, 6, 8 };
645    
646     if (SSHv1(pvar)) {
647     return 0;
648     } else {
649 doda 6982 unsigned int block_size = CRYPT_get_decryption_block_size(pvar);
650 maya 3227
651     if (block_size < 5) {
652     return small_block_decryption_sizes[block_size];
653     } else {
654     return block_size;
655     }
656     }
657     }
658    
659     /* Get up to 'limit' bytes into the payload buffer.
660     'limit' is counted from the start of the payload data.
661     Returns the amount of data in the payload buffer, or
662     -1 if there is an error.
663     We can return more than limit in some cases. */
664     static int buffer_packet_data(PTInstVar pvar, int limit)
665     {
666     if (pvar->ssh_state.payloadlen >= 0) {
667     return pvar->ssh_state.payloadlen;
668     } else {
669     int cur_decompressed_bytes =
670 doda 6967 pvar->ssh_state.decompress_stream.next_out - pvar->ssh_state.postdecompress_inbuf;
671 maya 3227
672     while (limit > cur_decompressed_bytes) {
673     int result;
674    
675 doda 6967 pvar->ssh_state.payload = pvar->ssh_state.postdecompress_inbuf + 1;
676 maya 3227 if (pvar->ssh_state.postdecompress_inbuflen == cur_decompressed_bytes) {
677     buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf,
678     &pvar->ssh_state.postdecompress_inbuflen,
679     min(limit, cur_decompressed_bytes * 2));
680     }
681    
682     pvar->ssh_state.decompress_stream.next_out =
683 doda 6967 pvar->ssh_state.postdecompress_inbuf + cur_decompressed_bytes;
684 maya 3227 pvar->ssh_state.decompress_stream.avail_out =
685 doda 6967 min(limit, pvar->ssh_state.postdecompress_inbuflen) - cur_decompressed_bytes;
686 maya 3227
687 doda 6967 result = inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH);
688 maya 3227 cur_decompressed_bytes =
689 doda 6967 pvar->ssh_state.decompress_stream.next_out - pvar->ssh_state.postdecompress_inbuf;
690 maya 3227
691     switch (result) {
692     case Z_OK:
693     break;
694     case Z_BUF_ERROR:
695     pvar->ssh_state.payloadlen = cur_decompressed_bytes;
696     return cur_decompressed_bytes;
697     default:
698     UTIL_get_lang_msg("MSG_SSH_INVALID_COMPDATA_ERROR", pvar,
699     "Invalid compressed data in received packet");
700 maya 5678 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
701 maya 3227 return -1;
702     }
703     }
704    
705     return cur_decompressed_bytes;
706     }
707     }
708    
709     /* For use by the protocol processing code.
710     Gets N bytes of uncompressed payload. Returns FALSE if data not available
711     and a fatal error has been signaled.
712     The data is available in the payload buffer. This buffer address
713     can change during a call to grab_payload, so take care!
714     The payload pointer is set to point to the first byte of the actual data
715     (after the packet type byte).
716     */
717     static BOOL grab_payload(PTInstVar pvar, int num_bytes)
718     {
719     /* Accept maximum of 4MB of payload data */
720     int in_buffer = buffer_packet_data(pvar, PACKET_MAX_SIZE);
721    
722     if (in_buffer < 0) {
723     return FALSE;
724     } else {
725     pvar->ssh_state.payload_grabbed += num_bytes;
726     if (pvar->ssh_state.payload_grabbed > in_buffer) {
727     char buf[128];
728     UTIL_get_lang_msg("MSG_SSH_TRUNCATED_PKT_ERROR", pvar,
729     "Received truncated packet (%ld > %d) @ grab_payload()");
730     _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg,
731     pvar->ssh_state.payload_grabbed, in_buffer);
732 maya 5678 notify_fatal_error(pvar, buf, TRUE);
733 maya 3227 return FALSE;
734     } else {
735     return TRUE;
736     }
737     }
738     }
739    
740     static BOOL grab_payload_limited(PTInstVar pvar, int num_bytes)
741     {
742     int in_buffer;
743    
744     pvar->ssh_state.payload_grabbed += num_bytes;
745     in_buffer = buffer_packet_data(pvar, pvar->ssh_state.payload_grabbed);
746    
747     if (in_buffer < 0) {
748     return FALSE;
749     } else {
750     if (pvar->ssh_state.payload_grabbed > in_buffer) {
751     char buf[128];
752     UTIL_get_lang_msg("MSG_SSH_TRUNCATED_PKT_LIM_ERROR", pvar,
753     "Received truncated packet (%ld > %d) @ grab_payload_limited()");
754     _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg,
755     pvar->ssh_state.payload_grabbed, in_buffer);
756 maya 5678 notify_fatal_error(pvar, buf, TRUE);
757 maya 3227 return FALSE;
758     } else {
759     return TRUE;
760     }
761     }
762     }
763    
764 doda 7024 static PayloadStat get_byte_from_payload(PTInstVar pvar, unsigned char *val)
765     {
766     unsigned char *data;
767    
768     data = remained_payload(pvar);
769     if (!grab_payload(pvar, 1)) {
770     return GetPayloadError;
771     }
772    
773     *val = *data;
774     return GetPayloadOK;
775     }
776     #define get_boolean_from_payload(pvar, val) get_byte_from_payload(pvar, val)
777    
778     static PayloadStat get_bytearray_from_payload(PTInstVar pvar, unsigned char *buff, unsigned int len)
779     {
780     unsigned char *data;
781    
782     data = remained_payload(pvar);
783     if (!grab_payload(pvar, len)) {
784     return GetPayloadError;
785     }
786    
787     memcpy_s(buff, len, data, len);
788     return GetPayloadOK;
789     }
790    
791     static PayloadStat get_uint32_from_payload(PTInstVar pvar, unsigned int *val)
792     {
793     unsigned char *data;
794    
795     data = remained_payload(pvar);
796     if (!grab_payload(pvar, 4)) {
797     return GetPayloadError;
798     }
799    
800     *val = get_uint32(data);
801     return GetPayloadOK;
802     }
803    
804     static PayloadStat get_string_from_payload(
805     PTInstVar pvar, unsigned char *buff, unsigned int bufflen, unsigned int *len, BOOL null_terminate)
806     {
807     unsigned int size;
808     unsigned char *data;
809    
810     if (!get_uint32_from_payload(pvar, &size)) {
811     return GetPayloadError;
812     }
813    
814     data = remained_payload(pvar);
815     if (!grab_payload(pvar, size)) {
816     return GetPayloadError;
817     }
818    
819     *len = size;
820    
821     if (size < bufflen) {
822     memcpy_s(buff, bufflen, data, size);
823     if (null_terminate) {
824     buff[size] = 0;
825     }
826     return GetPayloadOK;
827     }
828     else if (size == bufflen) {
829     memcpy_s(buff, bufflen, data, bufflen);
830     if (null_terminate) {
831     buff[bufflen-1] = 0;
832     return GetPayloadTruncate;
833     }
834     else {
835     return GetPayloadOK;
836     }
837     }
838     else {
839     memcpy_s(buff, bufflen, data, bufflen);
840     if (null_terminate) {
841     buff[bufflen-1] = 0;
842     }
843     return GetPayloadTruncate;
844     }
845     }
846     #define get_namelist_from_payload(pvar, buff, bufflen, size) get_string_from_payload(pvar, buff, bufflen, size, TRUE)
847    
848     static PayloadStat get_mpint_from_payload(PTInstVar pvar, BIGNUM *bn)
849     {
850     unsigned int len;
851     unsigned char *data;
852    
853     if (!get_uint32_from_payload(pvar, &len)) {
854     return GetPayloadError;
855     }
856    
857     data = remained_payload(pvar);
858     if (!grab_payload(pvar, len)) {
859     return GetPayloadError;
860     }
861    
862     BN_bin2bn(data, len, bn);
863    
864     return GetPayloadOK;
865     }
866    
867 maya 3227 #define do_crc(buf, len) (~(uint32)crc32(0xFFFFFFFF, (buf), (len)))
868    
869 doda 6967 /*
870     * Decrypt the payload, checksum it, eat the padding, get the packet type and return it.
871     * 'data' points to the start of the packet --- its length field.
872     * 'len' is the length of the * payload + padding (+ length of CRC for SSHv1).
873     * 'padding' is the length of the padding alone.
874     */
875 doda 6982 static int prep_packet_ssh1(PTInstVar pvar, char *data, unsigned int len, unsigned int padding)
876 maya 3227 {
877     pvar->ssh_state.payload = data + 4;
878     pvar->ssh_state.payloadlen = len;
879    
880 doda 6968 if (CRYPT_detect_attack(pvar, pvar->ssh_state.payload, len)) {
881     UTIL_get_lang_msg("MSG_SSH_COREINS_ERROR", pvar, "'CORE insertion attack' detected. Aborting connection.");
882     notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
883     }
884 maya 3227
885 doda 6968 CRYPT_decrypt(pvar, pvar->ssh_state.payload, len);
886     /* PKT guarantees that the data is always 4-byte aligned */
887     if (do_crc(pvar->ssh_state.payload, len - 4) != get_uint32_MSBfirst(pvar->ssh_state.payload + len - 4)) {
888     UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, "Detected corrupted data; connection terminating.");
889     notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
890     return SSH_MSG_NONE;
891     }
892 maya 3227
893 doda 6968 pvar->ssh_state.payload += padding;
894     pvar->ssh_state.payloadlen -= padding + 4;
895 maya 3227
896 doda 6968 pvar->ssh_state.payload_grabbed = 0;
897 maya 3227
898 doda 6968 if (pvar->ssh_state.decompressing) {
899     if (pvar->ssh_state.decompress_stream.avail_in != 0) {
900     UTIL_get_lang_msg("MSG_SSH_DECOMPRESS_ERROR", pvar,
901     "Internal error: a packet was not fully decompressed.\n"
902     "This is a bug, please report it.");
903     notify_nonfatal_error(pvar, pvar->ts->UIMsg);
904 maya 3227 }
905    
906 doda 6968 pvar->ssh_state.decompress_stream.next_in = pvar->ssh_state.payload;
907     pvar->ssh_state.decompress_stream.avail_in = pvar->ssh_state.payloadlen;
908     pvar->ssh_state.decompress_stream.next_out = pvar->ssh_state.postdecompress_inbuf;
909     pvar->ssh_state.payloadlen = -1;
910     } else {
911 maya 3227 pvar->ssh_state.payload++;
912     }
913    
914 doda 6968 if (!grab_payload_limited(pvar, 1)) {
915     return SSH_MSG_NONE;
916     }
917 maya 3227
918 doda 6968 pvar->ssh_state.receiver_sequence_number++;
919 maya 3227
920 doda 6968 return pvar->ssh_state.payload[-1];
921     }
922 maya 3227
923 doda 6972 /*
924     * �p�P�b�g�����������������������s���B(SSHv2�p)
925     * �E�f�[�^����
926     * �EMAC ������
927     * �Epadding ����������
928     * �E���b�Z�[�W�^�C�v��������������
929     *
930     * ����:
931     * data - ssh �p�P�b�g���������w���|�C���^
932     * len - �p�P�b�g�� (�������p�P�b�g������(4�o�C�g)���������l)
933 doda 6985 * aadlen - ���������������������F���������������������f�[�^������
934 nmaya 9217 * chacha20-poly1305 �����������������p�P�b�g������������
935 doda 6985 * authlen - �F���f�[�^(AEAD tag)��
936 doda 6972 */
937    
938 doda 6985 static int prep_packet_ssh2(PTInstVar pvar, char *data, unsigned int len, unsigned int aadlen, unsigned int authlen)
939 doda 6968 {
940 doda 6983 unsigned int padding;
941    
942 doda 6985 if (authlen > 0) {
943     if (!CRYPT_decrypt_aead(pvar, data, len, aadlen, authlen)) {
944     UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, "Detected corrupted data; connection terminating.");
945     notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
946     return SSH_MSG_NONE;
947     }
948     }
949     else if (aadlen > 0) {
950 doda 6972 // EtM ������������ MAC ���������s��
951 doda 6969 if (!CRYPT_verify_receiver_MAC(pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4, data + len + 4)) {
952     UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, "Detected corrupted data; connection terminating.");
953     notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
954     return SSH_MSG_NONE;
955     }
956 maya 3227
957 doda 6972 // �p�P�b�g������(����4�o�C�g)�������������������������A�������X�L�b�v�������������B
958 doda 6969 CRYPT_decrypt(pvar, data + 4, len);
959 doda 6968 }
960 doda 6969 else {
961 doda 6972 // E&M �����������������O���������������B
962     // ���O�������������������������B
963 doda 6982 unsigned int already_decrypted = get_predecryption_amount(pvar);
964 maya 3227
965 doda 6972 // ���O�����������������X�L�b�v�����A�c�������������������B
966 doda 6969 CRYPT_decrypt(pvar, data + already_decrypted, (4 + len) - already_decrypted);
967    
968 doda 6972 // E&M ������������ MAC ���������s���B
969 doda 6969 if (!CRYPT_verify_receiver_MAC(pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4, data + len + 4)) {
970     UTIL_get_lang_msg("MSG_SSH_CORRUPTDATA_ERROR", pvar, "Detected corrupted data; connection terminating.");
971     notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
972     return SSH_MSG_NONE;
973     }
974     }
975    
976 doda 6983 // �p�f�B���O��������
977     padding = (unsigned int) data[4];
978    
979 doda 6972 // �p�P�b�g��(4�o�C�g) �������p�f�B���O��(1�o�C�g)�������X�L�b�v���� SSH �y�C���[�h������
980     pvar->ssh_state.payload = data + 4 + 1;
981 maya 3227
982 doda 6972 // �p�f�B���O������(1�o�C�g)���p�f�B���O���������������y�C���[�h��
983     pvar->ssh_state.payloadlen = len - 1 - padding;
984    
985 doda 6968 pvar->ssh_state.payload_grabbed = 0;
986 maya 3227
987 doda 6968 // data compression
988     if (pvar->ssh2_keys[MODE_IN].comp.enabled &&
989     (pvar->stoc_compression == COMP_ZLIB ||
990     pvar->stoc_compression == COMP_DELAYED && pvar->userauth_success)) {
991    
992     if (pvar->decomp_buffer == NULL) {
993     pvar->decomp_buffer = buffer_init();
994     if (pvar->decomp_buffer == NULL)
995     return SSH_MSG_NONE;
996 maya 3227 }
997 doda 6968 // ���x�m�������o�b�t�@���g�������������������Y�������B
998     buffer_clear(pvar->decomp_buffer);
999 maya 3227
1000 doda 6968 // packet size��padding�������������y�C���[�h�����������W�J�����B
1001     buffer_decompress(&pvar->ssh_state.decompress_stream,
1002     pvar->ssh_state.payload,
1003     pvar->ssh_state.payloadlen,
1004     pvar->decomp_buffer);
1005    
1006     // �|�C���^���X�V�B
1007     pvar->ssh_state.payload = buffer_ptr(pvar->decomp_buffer);
1008     pvar->ssh_state.payload++;
1009     pvar->ssh_state.payloadlen = buffer_len(pvar->decomp_buffer);
1010     } else {
1011     pvar->ssh_state.payload++;
1012 maya 3227 }
1013    
1014 doda 6968 if (!grab_payload_limited(pvar, 1)) {
1015     return SSH_MSG_NONE;
1016     }
1017    
1018 maya 3227 pvar->ssh_state.receiver_sequence_number++;
1019    
1020     return pvar->ssh_state.payload[-1];
1021     }
1022    
1023     /* Create a packet to be sent. The SSH protocol packet type is in 'type';
1024     'len' contains the length of the packet payload, in bytes (this
1025     does not include the space for any of the packet headers or padding,
1026     or for the packet type byte).
1027     Returns a pointer to the payload data area, a region of length 'len',
1028     to be filled by the caller. */
1029 doda 6801 unsigned char *begin_send_packet(PTInstVar pvar, int type, int len)
1030 maya 3227 {
1031 doda 6801 unsigned char *buf;
1032 maya 3227
1033     pvar->ssh_state.outgoing_packet_len = len + 1;
1034    
1035     if (pvar->ssh_state.compressing) {
1036     buf_ensure_size(&pvar->ssh_state.precompress_outbuf,
1037     &pvar->ssh_state.precompress_outbuflen, 1 + len);
1038     buf = pvar->ssh_state.precompress_outbuf;
1039     } else {
1040     /* For SSHv2,
1041     Encrypted_length is 4(packetlength) + 1(paddinglength) + 1(packettype)
1042     + len(payload) + 4(minpadding), rounded up to nearest block_size
1043     We only need a reasonable upper bound for the buffer size */
1044     buf_ensure_size(&pvar->ssh_state.outbuf,
1045     &pvar->ssh_state.outbuflen,
1046 doda 6982 (int)(len + 30 + CRYPT_get_sender_MAC_size(pvar) +
1047     CRYPT_get_encryption_block_size(pvar)));
1048 maya 3227 buf = pvar->ssh_state.outbuf + 12;
1049     }
1050    
1051     buf[0] = (unsigned char) type;
1052     return buf + 1;
1053     }
1054    
1055    
1056     // ���M���g���C����������
1057     //
1058     // WinSock�� send() ���o�b�t�@�T�C�Y(len)�������������l��������������������
1059     // ���������������A�����������G���[���������B
1060     // �����������ATCP�R�l�N�V�������f�������o���h���B
1061     // (2006.12.9 yutaka)
1062 doda 6801 static int retry_send_packet(PTInstVar pvar, char *data, int len)
1063 maya 3227 {
1064     int n;
1065     int err;
1066    
1067     while (len > 0) {
1068     n = (pvar->Psend)(pvar->socket, data, len, 0);
1069    
1070     if (n < 0) {
1071     err = WSAGetLastError();
1072     if (err < WSABASEERR || err == WSAEWOULDBLOCK) {
1073     // send()�����l��0�������A�����G���[������ 10000 �������������A
1074     // ���������������������B
1075     // PuTTY 0.58���������Q�l�B
1076     // (2007.2.4 yutak)
1077     return 0; // success
1078     }
1079     return 1; // error
1080     }
1081    
1082     len -= n;
1083     data += n;
1084     }
1085    
1086     return 0; // success
1087     }
1088    
1089 doda 6801 static BOOL send_packet_blocking(PTInstVar pvar, char *data, int len)
1090 maya 3227 {
1091     // �p�P�b�g���M�����o�b�t�@���g�������������A�u���b�L���O�����M�����������K�v�������B
1092     // �m���u���b�L���O�����M����WSAEWOULDBLOCK�����������������A�����o�b�t�@�����M��������
1093     // ���������������������������������B(2007.10.30 yutaka)
1094     u_long do_block = 0;
1095     int code = 0;
1096     char *kind = NULL, buf[256];
1097    
1098 doda 6967 if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow, 0, 0) == SOCKET_ERROR) {
1099     code = WSAGetLastError();
1100     kind = "WSAAsyncSelect1";
1101     goto error;
1102 maya 3227 }
1103     if (ioctlsocket(pvar->socket, FIONBIO, &do_block) == SOCKET_ERROR) {
1104 doda 6967 code = WSAGetLastError();
1105     kind = "ioctlsocket";
1106     goto error;
1107 maya 3227 }
1108     if (retry_send_packet(pvar, data, len) != 0) {
1109 doda 6967 code = WSAGetLastError();
1110     kind = "retry_send_packet";
1111     goto error;
1112 maya 3227 }
1113     if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow,
1114     pvar->notification_msg,
1115 doda 6967 pvar->notification_events) == SOCKET_ERROR) {
1116     code = WSAGetLastError();
1117     kind = "WSAAsyncSelect2";
1118     goto error;
1119 maya 3227 }
1120     return TRUE;
1121    
1122     error:
1123     UTIL_get_lang_msg("MSG_SSH_SEND_PKT_ERROR", pvar,
1124     "A communications error occurred while sending an SSH packet.\n"
1125     "The connection will close. (%s:%d)");
1126     _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg,
1127     kind, code);
1128 maya 5678 notify_fatal_error(pvar, buf, TRUE);
1129 maya 3227 return FALSE;
1130     }
1131    
1132     /* if skip_compress is true, then the data has already been compressed
1133     into outbuf + 12 */
1134 yutakapon 4926 void finish_send_packet_special(PTInstVar pvar, int skip_compress)
1135 maya 3227 {
1136     unsigned int len = pvar->ssh_state.outgoing_packet_len;
1137 doda 6801 unsigned char *data;
1138 maya 3227 unsigned int data_length;
1139     buffer_t *msg = NULL; // for SSH2 packet compression
1140    
1141     if (pvar->ssh_state.compressing) {
1142     if (!skip_compress) {
1143     buf_ensure_size(&pvar->ssh_state.outbuf,
1144     &pvar->ssh_state.outbuflen,
1145 doda 6967 (int)(len + (len >> 6) + 50 + CRYPT_get_sender_MAC_size(pvar)));
1146     pvar->ssh_state.compress_stream.next_in = pvar->ssh_state.precompress_outbuf;
1147 maya 3227 pvar->ssh_state.compress_stream.avail_in = len;
1148 doda 6967 pvar->ssh_state.compress_stream.next_out = pvar->ssh_state.outbuf + 12;
1149     pvar->ssh_state.compress_stream.avail_out = pvar->ssh_state.outbuflen - 12;
1150 maya 3227
1151     if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) != Z_OK) {
1152     UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar,
1153     "An error occurred while compressing packet data.\n"
1154     "The connection will close.");
1155 maya 5678 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
1156 maya 3227 return;
1157     }
1158     }
1159    
1160 doda 6967 len = pvar->ssh_state.outbuflen - 12 - pvar->ssh_state.compress_stream.avail_out;
1161 maya 3227 }
1162    
1163     if (SSHv1(pvar)) {
1164 maya 7774 unsigned int padding = 8 - ((len + 4) % 8);
1165 maya 3227
1166     data = pvar->ssh_state.outbuf + 8 - padding;
1167     data_length = padding + len + 8;
1168    
1169     set_uint32(data, len + 4);
1170     if (CRYPT_get_receiver_cipher(pvar) != SSH_CIPHER_NONE) {
1171     CRYPT_set_random_data(pvar, data + 4, padding);
1172     } else {
1173     memset(data + 4, 0, padding);
1174     }
1175 doda 6967 set_uint32(data + data_length - 4, do_crc(data + 4, data_length - 8));
1176 maya 3227 CRYPT_encrypt(pvar, data + 4, data_length - 4);
1177     } else { //for SSH2(yutaka)
1178 doda 6982 unsigned int block_size = CRYPT_get_encryption_block_size(pvar);
1179 nmaya 9217 unsigned int packet_length;
1180 maya 3227 unsigned int encryption_size;
1181 nmaya 9217 unsigned int padding_size;
1182 maya 3227 BOOL ret;
1183 doda 6969 struct Mac *mac = &pvar->ssh2_keys[MODE_OUT].mac;
1184 doda 6985 struct Enc *enc = &pvar->ssh2_keys[MODE_OUT].enc;
1185     unsigned int aadlen = 0, maclen = 0, authlen = 0;
1186 maya 3227
1187     /*
1188     �f�[�^�\��
1189     pvar->ssh_state.outbuf:
1190     offset: 0 1 2 3 4 5 6 7 8 9 10 11 12 ... EOD
1191     <--ignore---> ^^^^^^^^ <---- payload --->
1192 doda 6967 packet length
1193 maya 3227
1194 nmaya 9217 ^^padding_size
1195 maya 3227
1196 doda 6967 <---------------------------->
1197     SSH2 sending data on TCP
1198 maya 3227
1199     NOTE:
1200     payload = type(1) + raw-data
1201     len = ssh_state.outgoing_packet_len = payload size
1202     */
1203     // �p�P�b�g���k���L���������A�p�P�b�g�����k�����������M�p�P�b�g���\�z�����B(2005.7.9 yutaka)
1204     // support of "Compression delayed" (2006.6.23 maya)
1205     if ((pvar->ctos_compression == COMP_ZLIB ||
1206     pvar->ctos_compression == COMP_DELAYED && pvar->userauth_success) &&
1207     pvar->ssh2_keys[MODE_OUT].comp.enabled) {
1208     // �����o�b�t�@�� packet-length(4) + padding(1) + payload(any) �������B
1209     msg = buffer_init();
1210     if (msg == NULL) {
1211     // TODO: error check
1212 zmatsuo 7649 logprintf(LOG_LEVEL_ERROR, "%s: buffer_init returns NULL.", __FUNCTION__);
1213 maya 3227 return;
1214     }
1215    
1216     // ���k�������w�b�_�������y�C���[�h�����B
1217     buffer_append(msg, "\0\0\0\0\0", 5); // 5 = packet-length(4) + padding(1)
1218     if (buffer_compress(&pvar->ssh_state.compress_stream, pvar->ssh_state.outbuf + 12, len, msg) == -1) {
1219     UTIL_get_lang_msg("MSG_SSH_COMP_ERROR", pvar,
1220     "An error occurred while compressing packet data.\n"
1221     "The connection will close.");
1222 maya 5678 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
1223 maya 3227 return;
1224     }
1225     data = buffer_ptr(msg);
1226     len = buffer_len(msg) - 5; // 'len' is overwritten.
1227    
1228     } else {
1229     // �����k
1230     data = pvar->ssh_state.outbuf + 7;
1231     }
1232    
1233     // ���M�p�P�b�g�\�z(input parameter: data, len)
1234     if (block_size < 8) {
1235     block_size = 8;
1236     }
1237    
1238 doda 6985 if (enc) {
1239     authlen = enc->auth_len;
1240     }
1241    
1242     if (mac && mac->etm || authlen > 0) {
1243 nmaya 9217 // ���������������������AMAC �������������p�P�b�g������������
1244     // ������ chacha20-poly1305 ���������������p�P�b�g������������
1245     // cf. PKT_recv �����R�����g
1246 doda 6969 aadlen = 4;
1247     }
1248    
1249 nmaya 9217 packet_length = 1 + len; // �p�f�B���O�����T�C�Y + �y�C���[�h��
1250     encryption_size = 4 + packet_length - aadlen; // �p�P�b�g�����T�C�Y + packet_length - addlen
1251     padding_size = block_size - (encryption_size % block_size);
1252     if (padding_size < 4)
1253     padding_size += block_size;
1254     packet_length += padding_size;
1255     encryption_size += padding_size;
1256     set_uint32(data, packet_length);
1257     data[4] = (unsigned char) padding_size;
1258 yutakapon 4492 if (msg) {
1259     // �p�P�b�g���k�������A�o�b�t�@���g�������B(2011.6.10 yutaka)
1260 nmaya 9217 buffer_append_space(msg, padding_size + EVP_MAX_MD_SIZE);
1261 yutakapon 4495 // realloc()���������A�|�C���^�����������\�������������A���x���������B
1262     data = buffer_ptr(msg);
1263 yutakapon 4492 }
1264 doda 6967
1265 nmaya 9217 CRYPT_set_random_data(pvar, data + 5 + len, padding_size);
1266 doda 6969
1267 doda 6985 if (authlen > 0) {
1268 nmaya 9217 // �p�P�b�g�������� MAC ���v�Z
1269 doda 6985 CRYPT_encrypt_aead(pvar, data, encryption_size, aadlen, authlen);
1270     maclen = authlen;
1271     }
1272     else if (aadlen) {
1273 nmaya 9217 // �p�P�b�g�������iaadlen�������������j
1274 doda 6985 CRYPT_encrypt(pvar, data + aadlen, encryption_size);
1275    
1276     // EtM �������������� MAC ���v�Z����
1277 doda 6969 ret = CRYPT_build_sender_MAC(pvar, pvar->ssh_state.sender_sequence_number,
1278 doda 6985 data, aadlen + encryption_size, data + aadlen + encryption_size);
1279 doda 6969 if (ret) {
1280 doda 6972 maclen = CRYPT_get_sender_MAC_size(pvar);
1281 doda 6969 }
1282 maya 3227 }
1283 doda 6985 else {
1284 nmaya 9217 // E&M �����������O�� MAC ���v�Z����
1285 doda 6969 ret = CRYPT_build_sender_MAC(pvar, pvar->ssh_state.sender_sequence_number,
1286 doda 6985 data, encryption_size, data + encryption_size);
1287 doda 6969 if (ret) {
1288     maclen = CRYPT_get_sender_MAC_size(pvar);
1289     }
1290 doda 6985
1291     // �p�P�b�g������
1292     CRYPT_encrypt(pvar, data, encryption_size);
1293 doda 6969 }
1294    
1295 doda 6972 data_length = encryption_size + aadlen + maclen;
1296    
1297 zmatsuo 7649 logprintf(150,
1298 nmaya 9217 "%s: built packet info: "
1299     "aadlen:%d, enclen:%d, padlen:%d, datalen:%d, maclen:%d, "
1300     "Encrypt Mode:%s, MAC mode:%s",
1301     __FUNCTION__,
1302     aadlen, encryption_size, padding_size, data_length, maclen,
1303     authlen ? "AEAD" : "not AEAD", aadlen ? "EtM" : "E&M");
1304 maya 3227 }
1305    
1306     send_packet_blocking(pvar, data, data_length);
1307    
1308     buffer_free(msg);
1309    
1310     pvar->ssh_state.sender_sequence_number++;
1311    
1312     // ���M�������L�^
1313     pvar->ssh_heartbeat_tick = time(NULL);
1314     }
1315    
1316     static void destroy_packet_buf(PTInstVar pvar)
1317     {
1318     memset(pvar->ssh_state.outbuf, 0, pvar->ssh_state.outbuflen);
1319     if (pvar->ssh_state.compressing) {
1320     memset(pvar->ssh_state.precompress_outbuf, 0,
1321     pvar->ssh_state.precompress_outbuflen);
1322     }
1323     }
1324    
1325     /* The handlers are added to the queue for each message. When one of the
1326     handlers fires, if it returns FALSE, then all handlers in the set are
1327     removed from their queues. */
1328     static void enque_handlers(PTInstVar pvar, int num_msgs,
1329 doda 6801 const int *messages,
1330     const SSHPacketHandler *handlers)
1331 maya 3227 {
1332 doda 6801 SSHPacketHandlerItem *first_item;
1333     SSHPacketHandlerItem *last_item = NULL;
1334 maya 3227 int i;
1335    
1336     for (i = 0; i < num_msgs; i++) {
1337 doda 6801 SSHPacketHandlerItem *item =
1338     (SSHPacketHandlerItem *)
1339 maya 3227 malloc(sizeof(SSHPacketHandlerItem));
1340 doda 6801 SSHPacketHandlerItem *cur_item =
1341 maya 3227 pvar->ssh_state.packet_handlers[messages[i]];
1342    
1343     item->handler = handlers[i];
1344    
1345     if (cur_item == NULL) {
1346     pvar->ssh_state.packet_handlers[messages[i]] = item;
1347     item->next_for_message = item;
1348     item->last_for_message = item;
1349     item->active_for_message = messages[i];
1350     } else {
1351     item->next_for_message = cur_item;
1352     item->last_for_message = cur_item->last_for_message;
1353     cur_item->last_for_message->next_for_message = item;
1354     cur_item->last_for_message = item;
1355     item->active_for_message = -1;
1356     }
1357    
1358     if (last_item != NULL) {
1359     last_item->next_in_set = item;
1360     } else {
1361     first_item = item;
1362     }
1363     last_item = item;
1364     }
1365    
1366     if (last_item != NULL) {
1367     last_item->next_in_set = first_item;
1368     }
1369     }
1370    
1371     static SSHPacketHandler get_handler(PTInstVar pvar, int message)
1372     {
1373 doda 6801 SSHPacketHandlerItem *cur_item =
1374 maya 3227 pvar->ssh_state.packet_handlers[message];
1375    
1376     if (cur_item == NULL) {
1377     return NULL;
1378     } else {
1379     return cur_item->handler;
1380     }
1381     }
1382    
1383     /* Called only by SSH_handle_packet */
1384     static void deque_handlers(PTInstVar pvar, int message)
1385     {
1386 doda 6801 SSHPacketHandlerItem *cur_item =
1387 maya 3227 pvar->ssh_state.packet_handlers[message];
1388 doda 6801 SSHPacketHandlerItem *first_item_in_set = cur_item;
1389 maya 3227
1390     if (cur_item == NULL)
1391     return;
1392    
1393     do {
1394 doda 6801 SSHPacketHandlerItem *next_in_set = cur_item->next_in_set;
1395 maya 3227
1396     if (cur_item->active_for_message >= 0) {
1397 doda 6801 SSHPacketHandlerItem *replacement =
1398 maya 3227 cur_item->next_for_message;
1399    
1400     if (replacement == cur_item) {
1401     replacement = NULL;
1402     } else {
1403     replacement->active_for_message =
1404     cur_item->active_for_message;
1405     }
1406     pvar->ssh_state.packet_handlers[cur_item->active_for_message] =
1407     replacement;
1408     }
1409     cur_item->next_for_message->last_for_message =
1410     cur_item->last_for_message;
1411     cur_item->last_for_message->next_for_message =
1412     cur_item->next_for_message;
1413    
1414     free(cur_item);
1415     cur_item = next_in_set;
1416     } while (cur_item != first_item_in_set);
1417     }
1418    
1419     static void enque_handler(PTInstVar pvar, int message,
1420     SSHPacketHandler handler)
1421     {
1422     enque_handlers(pvar, 1, &message, &handler);
1423     }
1424    
1425 doda 6801 static void chop_newlines(char *buf)
1426 maya 3227 {
1427     int len = strlen(buf);
1428    
1429     while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) {
1430     buf[len - 1] = 0;
1431     len--;
1432     }
1433     }
1434    
1435     /********************/
1436     /* Message handlers */
1437     /********************/
1438    
1439     static BOOL handle_forwarding_success(PTInstVar pvar)
1440     {
1441     return FALSE;
1442     }
1443    
1444     static BOOL handle_forwarding_failure(PTInstVar pvar)
1445     {
1446     return FALSE;
1447     }
1448    
1449     static void enque_forwarding_request_handlers(PTInstVar pvar)
1450     {
1451     static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1452     static const SSHPacketHandler handlers[]
1453     = { handle_forwarding_success, handle_forwarding_failure };
1454    
1455     enque_handlers(pvar, 2, msgs, handlers);
1456     }
1457    
1458     static BOOL handle_auth_failure(PTInstVar pvar)
1459     {
1460 doda 6809 logputs(LOG_LEVEL_VERBOSE, "Authentication failed");
1461 maya 3227
1462     // retry count������ (2005.7.15 yutaka)
1463     pvar->userauth_retry_count++;
1464    
1465     AUTH_set_generic_mode(pvar);
1466     AUTH_advance_to_next_cred(pvar);
1467     pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1468     try_send_credentials(pvar);
1469     return FALSE;
1470     }
1471    
1472     static BOOL handle_rsa_auth_refused(PTInstVar pvar)
1473     {
1474     if (pvar->auth_state.cur_cred.method == SSH_AUTH_PAGEANT) {
1475     if (pvar->pageant_keycount <= pvar->pageant_keycurrent) {
1476     // �S�������������I������
1477     safefree(pvar->pageant_key);
1478     }
1479     else {
1480     // ������������
1481     pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1482     try_send_credentials(pvar);
1483     return TRUE;
1484     }
1485     }
1486     AUTH_destroy_cur_cred(pvar);
1487     return handle_auth_failure(pvar);
1488     }
1489    
1490     static BOOL handle_TIS_challenge(PTInstVar pvar)
1491     {
1492     if (grab_payload(pvar, 4)) {
1493     int len = get_payload_uint32(pvar, 0);
1494    
1495     if (grab_payload(pvar, len)) {
1496 doda 6809 logputs(LOG_LEVEL_VERBOSE, "Received TIS challenge");
1497 maya 3227
1498 doda 7477 AUTH_set_TIS_mode(pvar, pvar->ssh_state.payload + 4, len, 0);
1499 maya 3227 AUTH_advance_to_next_cred(pvar);
1500     pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1501     try_send_credentials(pvar);
1502     }
1503     }
1504     return FALSE;
1505     }
1506    
1507     static BOOL handle_auth_required(PTInstVar pvar)
1508     {
1509 doda 6809 logputs(LOG_LEVEL_VERBOSE, "Server requires authentication");
1510 maya 3227
1511     pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1512     try_send_credentials(pvar);
1513     /* the first AUTH_advance_to_next_cred is issued early by ttxssh.c */
1514    
1515     return FALSE;
1516     }
1517    
1518     static BOOL handle_ignore(PTInstVar pvar)
1519     {
1520     if (SSHv1(pvar)) {
1521 doda 6809 logputs(LOG_LEVEL_VERBOSE, "SSH_MSG_IGNORE was received.");
1522 maya 3227
1523     if (grab_payload(pvar, 4)
1524     && grab_payload(pvar, get_payload_uint32(pvar, 0))) {
1525     /* ignore it! but it must be decompressed */
1526     }
1527     }
1528     else {
1529 doda 6809 logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_IGNORE was received.");
1530 maya 3227
1531     // ���b�Z�[�W�� SSH2_MSG_IGNORE ����������������
1532     // Cisco ���[�^���� (2006.11.28 maya)
1533     }
1534     return TRUE;
1535     }
1536    
1537     static BOOL handle_debug(PTInstVar pvar)
1538     {
1539     BOOL always_display;
1540 doda 6801 char *description;
1541 maya 3227 int description_len;
1542     char buf[2048];
1543    
1544     if (SSHv1(pvar)) {
1545 doda 6809 logputs(LOG_LEVEL_VERBOSE, "SSH_MSG_DEBUG was received.");
1546 maya 3227
1547     if (grab_payload(pvar, 4)
1548     && grab_payload(pvar, description_len =
1549     get_payload_uint32(pvar, 0))) {
1550     always_display = FALSE;
1551     description = pvar->ssh_state.payload + 4;
1552     description[description_len] = 0;
1553     } else {
1554     return TRUE;
1555     }
1556     } else {
1557 doda 6809 logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_DEBUG was received.");
1558 maya 3227
1559     if (grab_payload(pvar, 5)
1560     && grab_payload(pvar,
1561     (description_len = get_payload_uint32(pvar, 1)) + 4)
1562     && grab_payload(pvar,
1563     get_payload_uint32(pvar, 5 + description_len))) {
1564     always_display = pvar->ssh_state.payload[0] != 0;
1565     description = pvar->ssh_state.payload + 5;
1566     description[description_len] = 0;
1567     } else {
1568     return TRUE;
1569     }
1570     }
1571    
1572     chop_newlines(description);
1573     _snprintf_s(buf, sizeof(buf), _TRUNCATE, "DEBUG message from server: %s",
1574     description);
1575     if (always_display) {
1576     notify_nonfatal_error(pvar, buf);
1577     } else {
1578 doda 6809 logputs(LOG_LEVEL_VERBOSE, buf);
1579 maya 3227 }
1580     return TRUE;
1581     }
1582    
1583     static BOOL handle_disconnect(PTInstVar pvar)
1584     {
1585     int reason_code;
1586 doda 6801 char *description;
1587 maya 3227 int description_len;
1588     char buf[2048];
1589 doda 6801 char *explanation = "";
1590 maya 3227 char uimsg[MAX_UIMSG];
1591    
1592     if (SSHv1(pvar)) {
1593 doda 6809 logputs(LOG_LEVEL_VERBOSE, "SSH_MSG_DISCONNECT was received.");
1594 maya 3227
1595     if (grab_payload(pvar, 4)
1596     && grab_payload(pvar, description_len = get_payload_uint32(pvar, 0))) {
1597     reason_code = -1;
1598     description = pvar->ssh_state.payload + 4;
1599     description[description_len] = 0;
1600     } else {
1601     return TRUE;
1602     }
1603     } else {
1604 doda 6809 logputs(LOG_LEVEL_VERBOSE, "SSH2_MSG_DISCONNECT was received.");
1605 maya 3227
1606     if (grab_payload(pvar, 8)
1607     && grab_payload(pvar,
1608     (description_len = get_payload_uint32(pvar, 4)) + 4)
1609     && grab_payload(pvar,
1610     get_payload_uint32(pvar, 8 + description_len))) {
1611     reason_code = get_payload_uint32(pvar, 0);
1612     description = pvar->ssh_state.payload + 8;
1613     description[description_len] = 0;
1614     } else {
1615     return TRUE;
1616     }
1617     }
1618    
1619     chop_newlines(description);
1620     if (description[0] == 0) {
1621     description = NULL;
1622     }
1623    
1624     if (get_handler(pvar, SSH_SMSG_FAILURE) == handle_forwarding_failure) {
1625     UTIL_get_lang_msg("MSG_SSH_UNABLE_FWD_ERROR", pvar,
1626     "\nIt may have disconnected because it was unable to forward a port you requested to be forwarded from the server.\n"
1627     "This often happens when someone is already forwarding that port from the server.");
1628     strncpy_s(uimsg, sizeof(uimsg), pvar->ts->UIMsg, _TRUNCATE);
1629     explanation = uimsg;
1630     }
1631    
1632     if (description != NULL) {
1633     UTIL_get_lang_msg("MSG_SSH_SERVER_DISCON_ERROR", pvar,
1634     "Server disconnected with message '%s'%s");
1635     _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1636     pvar->ts->UIMsg, description,
1637     explanation);
1638     } else {
1639     UTIL_get_lang_msg("MSG_SSH_SERVER_DISCON_NORES_ERROR", pvar,
1640     "Server disconnected (no reason given).%s");
1641     _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1642     pvar->ts->UIMsg, explanation);
1643     }
1644    
1645 maya 5678 if (SSHv2(pvar)) {
1646     // SSH2_MSG_DISCONNECT �������������������������M��������������
1647     notify_fatal_error(pvar, buf, FALSE);
1648     }
1649     else {
1650     // SSH1 ���������d�l�����������������A���O����������������
1651     notify_fatal_error(pvar, buf, TRUE);
1652     }
1653    
1654 maya 3227 return TRUE;
1655     }
1656    
1657     static BOOL handle_unimplemented(PTInstVar pvar)
1658     {
1659     /* Should never receive this since we only send base 2.0 protocol messages */
1660     grab_payload(pvar, 4);
1661     return TRUE;
1662     }
1663    
1664     static BOOL handle_crypt_success(PTInstVar pvar)
1665     {
1666 doda 6809 logputs(LOG_LEVEL_VERBOSE, "Secure mode successfully achieved");
1667 maya 3227 return FALSE;
1668     }
1669    
1670     static BOOL handle_noauth_success(PTInstVar pvar)
1671     {
1672 doda 6809 logputs(LOG_LEVEL_VERBOSE, "Server does not require authentication");
1673 maya 3227 prep_compression(pvar);
1674     return FALSE;
1675     }
1676    
1677     static BOOL handle_auth_success(PTInstVar pvar)
1678     {
1679 doda 6809 logputs(LOG_LEVEL_VERBOSE, "Authentication accepted");
1680 maya 3227 prep_compression(pvar);
1681    
1682     // �n�[�g�r�[�g�E�X���b�h���J�n (2004.12.11 yutaka)
1683     start_ssh_heartbeat_thread(pvar);
1684    
1685     return FALSE;
1686     }
1687    
1688 yutakapon 8093 /*
1689     * SSH1�T�[�o���������������������`�F�b�N�����A������known_hosts�_�C�A���O���\�������B
1690     */
1691 maya 3227 static BOOL handle_server_public_key(PTInstVar pvar)
1692     {
1693     int server_key_public_exponent_len;
1694     int server_key_public_modulus_pos;
1695     int server_key_public_modulus_len;
1696     int host_key_bits_pos;
1697     int host_key_public_exponent_len;
1698     int host_key_public_modulus_pos;
1699     int host_key_public_modulus_len;
1700     int protocol_flags_pos;
1701     int supported_ciphers;
1702 doda 6801 char *inmsg;
1703 maya 3227 Key hostkey;
1704     int supported_types;
1705 yutakapon 8093 int ret;
1706 maya 3227
1707 doda 6809 logputs(LOG_LEVEL_VERBOSE, "SSH_SMSG_PUBLIC_KEY was received.");
1708 maya 3227
1709     if (!grab_payload(pvar, 14))
1710     return FALSE;
1711     server_key_public_exponent_len = get_mpint_len(pvar, 12);
1712    
1713     if (!grab_payload(pvar, server_key_public_exponent_len + 2))
1714     return FALSE;
1715     server_key_public_modulus_pos = 14 + server_key_public_exponent_len;
1716     server_key_public_modulus_len =
1717     get_mpint_len(pvar, server_key_public_modulus_pos);
1718    
1719     if (!grab_payload(pvar, server_key_public_modulus_len + 6))
1720     return FALSE;
1721     host_key_bits_pos =
1722     server_key_public_modulus_pos + 2 + server_key_public_modulus_len;
1723     host_key_public_exponent_len =
1724     get_mpint_len(pvar, host_key_bits_pos + 4);
1725    
1726     if (!grab_payload(pvar, host_key_public_exponent_len + 2))
1727     return FALSE;
1728     host_key_public_modulus_pos =
1729     host_key_bits_pos + 6 + host_key_public_exponent_len;
1730     host_key_public_modulus_len =
1731     get_mpint_len(pvar, host_key_public_modulus_pos);
1732    
1733     if (!grab_payload(pvar, host_key_public_modulus_len + 12))
1734     return FALSE;
1735     protocol_flags_pos =
1736     host_key_public_modulus_pos + 2 + host_key_public_modulus_len;
1737    
1738     inmsg = pvar->ssh_state.payload;
1739    
1740     CRYPT_set_server_cookie(pvar, inmsg);
1741     if (!CRYPT_set_server_RSA_key(pvar,
1742     get_uint32(inmsg + 8),
1743     pvar->ssh_state.payload + 12,
1744     inmsg + server_key_public_modulus_pos))
1745     return FALSE;
1746     if (!CRYPT_set_host_RSA_key(pvar,
1747     get_uint32(inmsg + host_key_bits_pos),
1748     inmsg + host_key_bits_pos + 4,
1749     inmsg + host_key_public_modulus_pos))
1750     return FALSE;
1751     pvar->ssh_state.server_protocol_flags =
1752     get_uint32(inmsg + protocol_flags_pos);
1753    
1754     supported_ciphers = get_uint32(inmsg + protocol_flags_pos + 4);
1755     if (!CRYPT_set_supported_ciphers(pvar,
1756     supported_ciphers,
1757     supported_ciphers))
1758     return FALSE;
1759    
1760     // SSH1 �T�[�o���A�T�|�[�g�����������F������������������
1761     // RSA ���L������ PAGEANT ���L��������
1762     supported_types = get_uint32(inmsg + protocol_flags_pos + 8);
1763     if ((supported_types & (1 << SSH_AUTH_RSA)) > 0) {
1764     supported_types |= (1 << SSH_AUTH_PAGEANT);
1765     }
1766     if (!AUTH_set_supported_auth_types(pvar,
1767     supported_types))
1768     return FALSE;
1769    
1770 yutakapon 8093 // ���������p���f�[�^��������������
1771     if (store_contents_for_known_hosts(pvar, SSH1_PUBLIC_KEY_KNOWN_HOSTS, 0) == FALSE)
1772     return FALSE;
1773    
1774 maya 3227 /* this must be the LAST THING in this function, since it can cause
1775     host_is_OK to be called. */
1776     hostkey.type = KEY_RSA1;
1777     hostkey.bits = get_uint32(inmsg + host_key_bits_pos);
1778     hostkey.exp = inmsg + host_key_bits_pos + 4;
1779     hostkey.mod = inmsg + host_key_public_modulus_pos;
1780    
1781 yutakapon 8093 ret = HOSTS_check_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport, &hostkey);
1782     if (ret == TRUE) {
1783     /* known_hosts�_�C�A���O�������o�����s�v�������A
1784     * ���������������s�����B
1785     */
1786     ret = handle_server_public_key_after_known_hosts(pvar);
1787    
1788     } else {
1789     /* known_hosts�_�C�A���O�������o���������A
1790     * ���~�A�����������B
1791     */
1792    
1793     }
1794    
1795 maya 3227 return FALSE;
1796     }
1797    
1798 yutakapon 8093 BOOL handle_server_public_key_after_known_hosts(PTInstVar pvar)
1799     {
1800     SSH_notify_host_OK(pvar);
1801    
1802     return TRUE;
1803     }
1804    
1805 maya 3227 /*
1806     The ID must have already been found to start with "SSH-". It must
1807     be null-terminated.
1808     */
1809 doda 6801 static BOOL parse_protocol_ID(PTInstVar pvar, char *ID)
1810 maya 3227 {
1811 doda 6801 char *str;
1812 maya 3227
1813     for (str = ID + 4; *str >= '0' && *str <= '9'; str++) {
1814     }
1815    
1816     if (*str != '.') {
1817     return FALSE;
1818     }
1819    
1820     pvar->protocol_major = atoi(ID + 4);
1821     pvar->protocol_minor = atoi(str + 1);
1822    
1823     for (str = str + 1; *str >= '0' && *str <= '9'; str++) {
1824     }
1825    
1826     return *str == '-';
1827     }
1828    
1829     /*
1830     On entry, the pvar->protocol_xxx fields hold the server's advertised
1831     protocol number. We replace the fields with the protocol number we will
1832     actually use, or return FALSE if there is no usable protocol version.
1833     */
1834 maya 4682 static int negotiate_protocol(PTInstVar pvar)
1835 maya 3227 {
1836     switch (pvar->protocol_major) {
1837     case 1:
1838 maya 4682 if (pvar->protocol_minor == 99 &&
1839     pvar->settings.ssh_protocol_version == 2) {
1840     // �T�[�o�� 1.99 �����[�U�� SSH2 ���I������������������
1841     // 2.0 ����������
1842     pvar->protocol_major = 2;
1843     pvar->protocol_minor = 0;
1844     return 0;
1845     }
1846    
1847     if (pvar->settings.ssh_protocol_version == 2) {
1848     // �o�[�W��������
1849     return -1;
1850     }
1851    
1852 maya 3227 if (pvar->protocol_minor > 5) {
1853     pvar->protocol_minor = 5;
1854     }
1855    
1856 maya 4682 return 0;
1857 maya 3227
1858     // for SSH2(yutaka)
1859     case 2:
1860 maya 4682 if (pvar->settings.ssh_protocol_version == 1) {
1861     // �o�[�W��������
1862     return -1;
1863     }
1864 maya 3227
1865 maya 4682 return 0; // SSH2 support
1866    
1867 maya 3227 default:
1868 maya 4682 return 1;
1869 maya 3227 }
1870     }
1871    
1872     static void init_protocol(PTInstVar pvar)
1873     {
1874     CRYPT_initialize_random_numbers(pvar);
1875    
1876     // known_hosts�t�@�C�������z�X�g���J������������������
1877     HOSTS_prefetch_host_key(pvar, pvar->ssh_state.hostname, pvar->ssh_state.tcpport);
1878    
1879     /* while we wait for a response from the server... */
1880    
1881     if (SSHv1(pvar)) {
1882     enque_handler(pvar, SSH_MSG_DISCONNECT, handle_disconnect);
1883     enque_handler(pvar, SSH_MSG_IGNORE, handle_ignore);
1884     enque_handler(pvar, SSH_MSG_DEBUG, handle_debug);
1885     enque_handler(pvar, SSH_SMSG_PUBLIC_KEY, handle_server_public_key);
1886    
1887     } else { // for SSH2(yutaka)
1888     enque_handler(pvar, SSH2_MSG_DISCONNECT, handle_disconnect);
1889     enque_handler(pvar, SSH2_MSG_IGNORE, handle_ignore);
1890     enque_handler(pvar, SSH2_MSG_DEBUG, handle_debug);
1891     enque_handler(pvar, SSH2_MSG_KEXINIT, handle_SSH2_kexinit);
1892     enque_handler(pvar, SSH2_MSG_KEXDH_INIT, handle_unimplemented);
1893     enque_handler(pvar, SSH2_MSG_KEXDH_REPLY, handle_SSH2_dh_common_reply);
1894     enque_handler(pvar, SSH2_MSG_KEX_DH_GEX_REPLY, handle_SSH2_dh_gex_reply);
1895     enque_handler(pvar, SSH2_MSG_NEWKEYS, handle_SSH2_newkeys);
1896     enque_handler(pvar, SSH2_MSG_SERVICE_ACCEPT, handle_SSH2_service_accept);
1897     enque_handler(pvar, SSH2_MSG_USERAUTH_SUCCESS, handle_SSH2_userauth_success);
1898     enque_handler(pvar, SSH2_MSG_USERAUTH_FAILURE, handle_SSH2_userauth_failure);
1899     enque_handler(pvar, SSH2_MSG_USERAUTH_BANNER, handle_SSH2_userauth_banner);
1900 doda 6657 enque_handler(pvar, SSH2_MSG_USERAUTH_INFO_REQUEST, handle_SSH2_userauth_msg60);
1901 maya 3227
1902     enque_handler(pvar, SSH2_MSG_UNIMPLEMENTED, handle_unimplemented);
1903    
1904     // ���[�U�F�������f�B�X�p�b�`���[�`��
1905     enque_handler(pvar, SSH2_MSG_CHANNEL_CLOSE, handle_SSH2_channel_close);
1906     enque_handler(pvar, SSH2_MSG_CHANNEL_DATA, handle_SSH2_channel_data);
1907     enque_handler(pvar, SSH2_MSG_CHANNEL_EOF, handle_SSH2_channel_eof);
1908     enque_handler(pvar, SSH2_MSG_CHANNEL_EXTENDED_DATA, handle_SSH2_channel_extended_data);
1909     enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN, handle_SSH2_channel_open);
1910     enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, handle_SSH2_open_confirm);
1911     enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN_FAILURE, handle_SSH2_open_failure);
1912     enque_handler(pvar, SSH2_MSG_CHANNEL_REQUEST, handle_SSH2_channel_request);
1913     enque_handler(pvar, SSH2_MSG_CHANNEL_WINDOW_ADJUST, handle_SSH2_window_adjust);
1914     enque_handler(pvar, SSH2_MSG_CHANNEL_SUCCESS, handle_SSH2_channel_success);
1915     enque_handler(pvar, SSH2_MSG_CHANNEL_FAILURE, handle_SSH2_channel_failure);
1916 yutakapon 5829 enque_handler(pvar, SSH2_MSG_GLOBAL_REQUEST, handle_SSH2_client_global_request);
1917 maya 3227 enque_handler(pvar, SSH2_MSG_REQUEST_FAILURE, handle_SSH2_request_failure);
1918     enque_handler(pvar, SSH2_MSG_REQUEST_SUCCESS, handle_SSH2_request_success);
1919    
1920 yutakapon 5850 client_init_global_confirm();
1921    
1922 maya 3227 }
1923     }
1924    
1925 doda 5928 void server_version_check(PTInstVar pvar)
1926     {
1927     char *server_swver;
1928    
1929     pvar->server_compat_flag = 0;
1930    
1931     if ((server_swver = strchr(pvar->server_version_string+4, '-')) == NULL) {
1932 doda 6809 logputs(LOG_LEVEL_WARNING, "Can't get server software version string.");
1933 doda 5928 return;
1934     }
1935     server_swver++;
1936    
1937     if (strncmp(server_swver, "Cisco-1", 7) == 0) {
1938     pvar->server_compat_flag |= SSH_BUG_DHGEX_LARGE;
1939 doda 6809 logputs(LOG_LEVEL_INFO, "Server version string is matched to \"Cisco-1\", compatibility flag SSH_BUG_DHGEX_LARGE is enabled.");
1940 doda 5928 }
1941     }
1942    
1943 doda 6801 BOOL SSH_handle_server_ID(PTInstVar pvar, char *ID, int ID_len)
1944 maya 3227 {
1945 maya 4546 static char prefix[64];
1946 maya 4682 int negotiate;
1947     char uimsg[MAX_UIMSG];
1948 maya 3227
1949     // initialize SSH2 memory dump (2005.3.7 yutaka)
1950     init_memdump();
1951     push_memdump("pure server ID", "start protocol version exchange", ID, ID_len);
1952    
1953     if (ID_len <= 0) {
1954     return FALSE;
1955     } else {
1956 maya 4546 int buf_len;
1957 doda 6801 char *buf;
1958 maya 3227
1959 maya 4546 strncpy_s(prefix, sizeof(prefix), "Received server identification string: ", _TRUNCATE);
1960     buf_len = strlen(prefix) + ID_len + 1;
1961 doda 6801 buf = (char *) malloc(buf_len);
1962 maya 3227 strncpy_s(buf, buf_len, prefix, _TRUNCATE);
1963     strncat_s(buf, buf_len, ID, _TRUNCATE);
1964     chop_newlines(buf);
1965 doda 6809 logputs(LOG_LEVEL_VERBOSE, buf);
1966 maya 3227 free(buf);
1967    
1968     if (ID[ID_len - 1] != '\n') {
1969     pvar->ssh_state.status_flags |= STATUS_IN_PARTIAL_ID_STRING;
1970     return FALSE;
1971     } else if ((pvar->ssh_state.status_flags & STATUS_IN_PARTIAL_ID_STRING) != 0) {
1972     pvar->ssh_state.status_flags &= ~STATUS_IN_PARTIAL_ID_STRING;
1973     return FALSE;
1974     } else if (strncmp(ID, "SSH-", 4) != 0) {
1975     return FALSE;
1976     } else {
1977     ID[ID_len - 1] = 0;
1978    
1979     if (ID_len > 1 && ID[ID_len - 2] == '\r') {
1980     ID[ID_len - 2] = 0;
1981     }
1982    
1983     pvar->ssh_state.server_ID = _strdup(ID);
1984    
1985 maya 4682 if (!parse_protocol_ID(pvar, ID)) {
1986 maya 3227 UTIL_get_lang_msg("MSG_SSH_VERSION_ERROR", pvar,
1987     "This program does not understand the server's version of the protocol.");
1988 maya 5678 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
1989 maya 4682 }
1990     else if ((negotiate = negotiate_protocol(pvar)) == 1) {
1991     UTIL_get_lang_msg("MSG_SSH_VERSION_ERROR", pvar,
1992     "This program does not understand the server's version of the protocol.");
1993 maya 5678 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
1994 maya 4682 }
1995     else if (negotiate == -1) {
1996     UTIL_get_lang_msg("MSG_SSH_VERSION_MISMATCH", pvar,
1997     "Protocol version mismatch. server:%d.%d client:%d");
1998     _snprintf_s(uimsg, sizeof(uimsg), _TRUNCATE, pvar->ts->UIMsg,
1999     pvar->protocol_major, pvar->protocol_minor, pvar->settings.ssh_protocol_version);
2000 maya 5678 notify_fatal_error(pvar, uimsg, TRUE);
2001 maya 4682 }
2002     else {
2003 maya 3227 char TTSSH_ID[1024];
2004     int TTSSH_ID_len;
2005    
2006 maya 4682 // SSH �o�[�W������ teraterm �����Z�b�g����
2007     // SCP �R�}���h������ (2008.2.3 maya)
2008     pvar->cv->isSSH = pvar->protocol_major;
2009    
2010 maya 3227 // �������g���o�[�W�������������� (2005.3.3 yutaka)
2011     _snprintf_s(TTSSH_ID, sizeof(TTSSH_ID), _TRUNCATE,
2012 maya 4656 "SSH-%d.%d-TTSSH/%d.%d Win32\r\n",
2013 doda 6835 pvar->protocol_major, pvar->protocol_minor,
2014     TTSSH_VERSION_MAJOR, TTSSH_VERSION_MINOR);
2015 maya 3227 TTSSH_ID_len = strlen(TTSSH_ID);
2016    
2017     // for SSH2(yutaka)
2018     // �N���C�A���g�o�[�W�����������i���s���������������j
2019     strncpy_s(pvar->client_version_string, sizeof(pvar->client_version_string),
2020     TTSSH_ID, _TRUNCATE);
2021    
2022     // �T�[�o�o�[�W�����������i���s���������������j(2005.3.9 yutaka)
2023     _snprintf_s(pvar->server_version_string,
2024     sizeof(pvar->server_version_string), _TRUNCATE,
2025     "%s", pvar->ssh_state.server_ID);
2026    
2027 doda 5928 // �T�[�o�o�[�W�������`�F�b�N
2028     server_version_check(pvar);
2029    
2030 doda 6809 if ((pvar->Psend) (pvar->socket, TTSSH_ID, TTSSH_ID_len, 0) != TTSSH_ID_len) {
2031 maya 3227 UTIL_get_lang_msg("MSG_SSH_SEND_ID_ERROR", pvar,
2032     "An error occurred while sending the SSH ID string.\n"
2033     "The connection will close.");
2034 maya 5678 notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
2035 maya 3227 } else {
2036 doda 6809 // ���s������
2037     chop_newlines(pvar->client_version_string);
2038     logprintf(LOG_LEVEL_VERBOSE, "Sent client identification string: %s", pvar->client_version_string);
2039 maya 3227
2040     push_memdump("server ID", NULL, pvar->server_version_string, strlen(pvar->server_version_string));
2041     push_memdump("client ID", NULL, pvar->client_version_string, strlen(pvar->client_version_string));
2042    
2043     // SSH�n���h�����o�^���s��
2044     init_protocol(pvar);
2045    
2046     SSH2_dispatch_init(1);
2047     SSH2_dispatch_add_message(SSH2_MSG_KEXINIT);
2048     }
2049     }
2050    
2051     return TRUE;
2052     }
2053     }
2054     }
2055    
2056     static BOOL handle_exit(PTInstVar pvar)
2057     {
2058     if (grab_payload(pvar, 4)) {
2059     begin_send_packet(pvar, SSH_CMSG_EXIT_CONFIRMATION, 0);
2060     finish_send_packet(pvar);
2061 maya 5678 notify_closed_connection(pvar, "disconnected by server request");
2062 maya 3227 }
2063     return TRUE;
2064     }
2065    
2066     static BOOL handle_data(PTInstVar pvar)
2067     {
2068     if (grab_payload_limited(pvar, 4)) {
2069     pvar->ssh_state.payload_datalen = get_payload_uint32(pvar, 0);
2070     pvar->ssh_state.payload_datastart = 4;
2071     }
2072     return TRUE;
2073     }
2074    
2075     static BOOL handle_channel_open(PTInstVar pvar)
2076     {
2077     int host_len;
2078     int originator_len;
2079    
2080     if ((pvar->ssh_state.
2081     server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
2082     if (grab_payload(pvar, 8)
2083     && grab_payload(pvar,
2084     8 + (host_len = get_payload_uint32(pvar, 4)))
2085     && grab_payload(pvar, originator_len =
2086     get_payload_uint32(pvar, host_len + 12))) {
2087     int local_port = get_payload_uint32(pvar, 8 + host_len);
2088    
2089     pvar->ssh_state.payload[8 + host_len] = 0;
2090     FWD_open(pvar, get_payload_uint32(pvar, 0),
2091     pvar->ssh_state.payload + 8, local_port,
2092     pvar->ssh_state.payload + 16 + host_len,
2093     originator_len,
2094     NULL);
2095     }
2096     } else {
2097     if (grab_payload(pvar, 8)
2098     && grab_payload(pvar,
2099     4 + (host_len = get_payload_uint32(pvar, 4)))) {
2100     int local_port = get_payload_uint32(pvar, 8 + host_len);
2101    
2102     pvar->ssh_state.payload[8 + host_len] = 0;
2103     FWD_open(pvar, get_payload_uint32(pvar, 0),
2104     pvar->ssh_state.payload + 8, local_port, NULL, 0,
2105     NULL);
2106     }
2107     }
2108    
2109     return TRUE;
2110     }
2111    
2112     static BOOL handle_X11_channel_open(PTInstVar pvar)
2113     {
2114     int originator_len;
2115    
2116     if ((pvar->ssh_state.server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
2117     if (grab_payload(pvar, 8)
2118     && grab_payload(pvar, originator_len = get_payload_uint32(pvar, 4))) {
2119     FWD_X11_open(pvar, get_payload_uint32(pvar, 0),
2120     pvar->ssh_state.payload + 8, originator_len, NULL);
2121     }
2122     } else {
2123     if (grab_payload(pvar, 4)) {
2124     FWD_X11_open(pvar, get_payload_uint32(pvar, 0), NULL, 0, NULL);
2125     }
2126     }
2127    
2128     return TRUE;
2129     }
2130    
2131     static BOOL handle_channel_open_confirmation(PTInstVar pvar)
2132     {
2133     if (grab_payload(pvar, 8)) {
2134     FWD_confirmed_open(pvar, get_payload_uint32(pvar, 0),
2135     get_payload_uint32(pvar, 4));
2136     }
2137     return FALSE;
2138     }
2139    
2140     static BOOL handle_channel_open_failure(PTInstVar pvar)
2141     {
2142     if (grab_payload(pvar, 4)) {
2143 doda 6844 FWD_failed_open(pvar, get_payload_uint32(pvar, 0), -1);
2144 maya 3227 }
2145     return FALSE;
2146     }
2147    
2148     static BOOL handle_channel_data(PTInstVar pvar)
2149     {
2150     int len;
2151    
2152     if (grab_payload(pvar, 8)
2153     && grab_payload(pvar, len = get_payload_uint32(pvar, 4))) {
2154     FWDChannel *channel;
2155     int local_channel_num = get_payload_uint32(pvar, 0);
2156     if (!FWD_check_local_channel_num(pvar, local_channel_num)) {
2157     return FALSE;
2158     }
2159     channel = pvar->fwd_state.channels + local_channel_num;
2160     if (channel->type == TYPE_AGENT) {
2161     SSH_agent_response(pvar, NULL, local_channel_num,
2162     pvar->ssh_state.payload + 8, len);
2163     }
2164     else {
2165     FWD_received_data(pvar, local_channel_num,
2166     pvar->ssh_state.payload + 8, len);
2167     }
2168     }
2169     return TRUE;
2170     }
2171    
2172     static BOOL handle_channel_input_eof(PTInstVar pvar)
2173     {
2174     if (grab_payload(pvar, 4)) {
2175     int local_channel_num = get_payload_uint32(pvar, 0);
2176     FWDChannel *channel;
2177     if (!FWD_check_local_channel_num(pvar, local_channel_num)) {
2178     return FALSE;
2179     }
2180     channel = pvar->fwd_state.channels + local_channel_num;
2181     if (channel->type == TYPE_AGENT) {
2182     channel->status |= FWD_CLOSED_REMOTE_IN;
2183     SSH_channel_input_eof(pvar, channel->remote_num, local_channel_num);
2184     }
2185     else {
2186     FWD_channel_input_eof(pvar, local_channel_num);
2187     }
2188     }
2189     return TRUE;
2190     }
2191    
2192     static BOOL handle_channel_output_eof(PTInstVar pvar)
2193     {
2194     if (grab_payload(pvar, 4)) {
2195     int local_channel_num = get_payload_uint32(pvar, 0);
2196     FWDChannel *channel;
2197     if (!FWD_check_local_channel_num(pvar, local_channel_num)) {
2198     return FALSE;
2199     }
2200     channel = pvar->fwd_state.channels + local_channel_num;
2201     if (channel->type == TYPE_AGENT) {
2202     channel->status |= FWD_CLOSED_REMOTE_OUT;
2203     SSH_channel_output_eof(pvar, channel->remote_num);
2204     FWD_free_channel(pvar, local_channel_num);
2205     }
2206     else {
2207     FWD_channel_output_eof(pvar, local_channel_num);
2208     }
2209     }
2210     return TRUE;
2211     }
2212    
2213     static BOOL handle_agent_open(PTInstVar pvar)
2214     {
2215     if (grab_payload(pvar, 4)) {
2216     int remote_id = get_payload_uint32(pvar, 0);
2217     int local_id;
2218    
2219 doda 4233 if (pvar->agentfwd_enable && FWD_agent_forward_confirm(pvar)) {
2220 maya 3227 local_id = FWD_agent_open(pvar, remote_id);
2221     if (local_id == -1) {
2222     SSH_fail_channel_open(pvar, remote_id);
2223     }
2224     else {
2225     SSH_confirm_channel_open(pvar, remote_id, local_id);
2226     }
2227     }
2228     else {
2229     SSH_fail_channel_open(pvar, remote_id);
2230     }
2231     }
2232     /*
2233     else {
2234     // ���m��������channel����������������������������
2235     }
2236     */
2237    
2238     return TRUE;
2239     }
2240    
2241    
2242    
2243     // �n���h�����O�������b�Z�[�W����������
2244    
2245     #define HANDLE_MESSAGE_MAX 30
2246     static unsigned char handle_messages[HANDLE_MESSAGE_MAX];
2247     static int handle_message_count = 0;
2248     static int handle_message_stage = 0;
2249    
2250     void SSH2_dispatch_init(int stage)
2251     {
2252     handle_message_count = 0;
2253     handle_message_stage = stage;
2254 doda 7011
2255     SSH2_dispatch_add_message(SSH2_MSG_IGNORE);
2256     SSH2_dispatch_add_message(SSH2_MSG_DEBUG);
2257     SSH2_dispatch_add_message(SSH2_MSG_DISCONNECT);
2258     SSH2_dispatch_add_message(SSH2_MSG_UNIMPLEMENTED);
2259 maya 3227 }
2260    
2261     int SSH2_dispatch_enabled_check(unsigned char message)
2262     {
2263     int i;
2264    
2265     for (i = 0 ; i < handle_message_count ; i++) {
2266     if (handle_messages[i] == message)
2267     return 1;
2268     }
2269     return 0;
2270     }
2271    
2272     void SSH2_dispatch_add_message(unsigned char message)
2273     {
2274     int i;
2275    
2276     if (handle_message_count >= HANDLE_MESSAGE_MAX) {
2277     // TODO: error check
2278 zmatsuo 7649 logprintf(LOG_LEVEL_ERROR, "%s: too many handlers. handlers:%d, max:%d", __FUNCTION__,
2279 doda 6824 handle_message_count, HANDLE_MESSAGE_MAX);
2280 maya 3227 return;
2281     }
2282    
2283     // �������o�^�������������b�Z�[�W������������
2284     for (i=0; i<handle_message_count; i++) {
2285     if (handle_messages[i] == message) {
2286     return;
2287     }
2288     }
2289    
2290     handle_messages[handle_message_count++] = message;
2291     }
2292    
2293     void SSH2_dispatch_add_range_message(unsigned char begin, unsigned char end)
2294     {
2295     unsigned char c;
2296    
2297     for (c = begin ; c <= end ; c++) {
2298     SSH2_dispatch_add_message(c);
2299     }
2300     }
2301    
2302 doda 6982 void SSH1_handle_packet(PTInstVar pvar, char *data, unsigned int len, unsigned int padding)
2303 maya 3227 {
2304 doda 6968 unsigned char message = prep_packet_ssh1(pvar, data, len, padding);
2305 maya 3227
2306     // SSH�����b�Z�[�W�^�C�v���`�F�b�N
2307     if (message != SSH_MSG_NONE) {
2308     // ���b�Z�[�W�^�C�v���������n���h�����N��
2309     SSHPacketHandler handler = get_handler(pvar, message);
2310    
2311 doda 6968 if (handler == NULL) {
2312     char buf[1024];
2313 maya 3227
2314 doda 6968 UTIL_get_lang_msg("MSG_SSH_UNEXP_MSG_ERROR", pvar, "Unexpected packet type received: %d");
2315     _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, message, handle_message_stage);
2316     notify_fatal_error(pvar, buf, TRUE);
2317     } else {
2318     if (!handler(pvar)) {
2319     deque_handlers(pvar, message);
2320 maya 3227 }
2321     }
2322 doda 6968 }
2323     }
2324 maya 3227
2325 doda 6985 void SSH2_handle_packet(PTInstVar pvar, char *data, unsigned int len, unsigned int aadlen, unsigned int authlen)
2326 doda 6968 {
2327 doda 6985 unsigned char message = prep_packet_ssh2(pvar, data, len, aadlen, authlen);
2328 doda 6968
2329     // SSH�����b�Z�[�W�^�C�v���`�F�b�N
2330     if (message != SSH_MSG_NONE) {
2331     // ���b�Z�[�W�^�C�v���������n���h�����N��
2332     SSHPacketHandler handler = get_handler(pvar, message);
2333    
2334     // �z���O�����b�Z�[�W�^�C�v�������������A�{�[�g�������B
2335     if (!SSH2_dispatch_enabled_check(message) || handler == NULL) {
2336     char buf[1024];
2337    
2338     UTIL_get_lang_msg("MSG_SSH_UNEXP_MSG2_ERROR", pvar, "Unexpected SSH2 message(%d) on current stage(%d)");
2339     _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, message, handle_message_stage);
2340     notify_fatal_error(pvar, buf, TRUE);
2341     return;
2342     }
2343    
2344 maya 3227 if (handler == NULL) {
2345 doda 6968 unsigned char *outmsg = begin_send_packet(pvar, SSH2_MSG_UNIMPLEMENTED, 4);
2346 maya 3227
2347 doda 6968 set_uint32(outmsg, pvar->ssh_state.receiver_sequence_number - 1);
2348     finish_send_packet(pvar);
2349 maya 3227
2350 zmatsuo 7649 logprintf(LOG_LEVEL_VERBOSE, "%s: SSH2_MSG_UNIMPLEMENTED was sent.", __FUNCTION__);
2351 doda 6968 /* XXX need to decompress incoming packet, but how? */
2352 maya 3227 } else {
2353     if (!handler(pvar)) {
2354     deque_handlers(pvar, message);
2355     }
2356     }
2357     }
2358     }
2359    
2360     static BOOL handle_pty_success(PTInstVar pvar)
2361     {
2362     FWD_enter_interactive_mode(pvar);
2363     enque_handler(pvar, SSH_SMSG_EXITSTATUS, handle_exit);
2364     enque_handler(pvar, SSH_SMSG_STDOUT_DATA, handle_data);
2365     enque_handler(pvar, SSH_SMSG_STDERR_DATA, handle_data);
2366     enque_handler(pvar, SSH_MSG_CHANNEL_DATA, handle_channel_data);
2367 doda 6967 enque_handler(pvar, SSH_MSG_CHANNEL_INPUT_EOF, handle_channel_input_eof);
2368     enque_handler(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED, handle_channel_output_eof);
2369 maya 3227 enque_handler(pvar, SSH_MSG_PORT_OPEN, handle_channel_open);
2370     enque_handler(pvar, SSH_SMSG_X11_OPEN, handle_X11_channel_open);
2371     enque_handler(pvar, SSH_SMSG_AGENT_OPEN, handle_agent_open);
2372     return FALSE;
2373     }
2374    
2375     static BOOL handle_pty_failure(PTInstVar pvar)
2376     {
2377     UTIL_get_lang_msg("MSG_SSH_ALLOC_TERMINAL_ERROR", pvar,
2378     "The server cannot allocate a pseudo-terminal. "
2379     "You may encounter some problems with the terminal.");
2380     notify_nonfatal_error(pvar, pvar->ts->UIMsg);
2381     return handle_pty_success(pvar);
2382     }
2383    
2384     static void prep_pty(PTInstVar pvar)
2385     {
2386     int len = strlen(pvar->ts->TermType);
2387 doda 6967 unsigned char *outmsg = begin_send_packet(pvar, SSH_CMSG_REQUEST_PTY, 4 + len + 16 + sizeof(ssh_ttymodes));
2388 maya 3227 static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
2389     static const SSHPacketHandler handlers[]
2390     = { handle_pty_success, handle_pty_failure };
2391 doda 6799 int x, y;
2392 maya 3227
2393 doda 6799 get_window_pixel_size(pvar, &x, &y);
2394    
2395 maya 3227 set_uint32(outmsg, len);
2396     memcpy(outmsg + 4, pvar->ts->TermType, len);
2397     set_uint32(outmsg + 4 + len, pvar->ssh_state.win_rows);
2398     set_uint32(outmsg + 4 + len + 4, pvar->ssh_state.win_cols);
2399 doda 6799 set_uint32(outmsg + 4 + len + 8, x);
2400     set_uint32