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 2856 - (hide annotations) (download) (as text)
Sun Mar 26 15:43:58 2006 UTC (18 years ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 175589 byte(s)
SSH2のknown_hosts対応を追加した。

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