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