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

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

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

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