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 6972 - (hide annotations) (download) (as text)
Tue Nov 7 22:26:20 2017 UTC (6 years, 5 months ago) by doda
Original Path: trunk/ttssh2/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 267775 byte(s)
EtM 絡みのコード整理。

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