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 8086 - (hide annotations) (download) (as text)
Sat Sep 7 12:18:28 2019 UTC (4 years, 7 months ago) by yutakapon
Original Path: trunk/ttssh2/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 274931 byte(s)
チケット38959
ユーザ認証ダイアログの表示タイミングをknown_hostsダイアログの後に変更した。

branches/ttssh_improvedからリビジョン8027をマージ:
ProxyやNAT経由でサーバに接続できない場合、すでに切断状態にも関わらず、
認証ダイアログが表示されたままとなる問題を修正した。



........

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