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 2834 - (hide annotations) (download) (as text)
Sun Jul 10 06:44:48 2005 UTC (18 years, 9 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 167510 byte(s)
キー再作成時にパケット圧縮が正常に動作せず、サーバ側で正しく解凍できないバグを修正。

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     ptr->name = strdup(name);
405     ptr->desc = strdup(desc);
406     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     notify_fatal_error(pvar, "Received truncated packet");
523     return FALSE;
524     } else {
525     return TRUE;
526     }
527     }
528     }
529    
530     static BOOL grab_payload_limited(PTInstVar pvar, int num_bytes)
531     {
532     int in_buffer;
533    
534     pvar->ssh_state.payload_grabbed += num_bytes;
535     in_buffer = buffer_packet_data(pvar, pvar->ssh_state.payload_grabbed);
536    
537     if (in_buffer < 0) {
538     return FALSE;
539     } else {
540     if (pvar->ssh_state.payload_grabbed > in_buffer) {
541     notify_fatal_error(pvar, "Received truncated packet");
542     return FALSE;
543     } else {
544     return TRUE;
545     }
546     }
547     }
548    
549     #define get_payload_uint32(pvar, offset) get_uint32_MSBfirst((pvar)->ssh_state.payload + (offset))
550     #define get_uint32(buf) get_uint32_MSBfirst((buf))
551     #define set_uint32(buf, v) set_uint32_MSBfirst((buf), (v))
552     #define get_mpint_len(pvar, offset) ((get_ushort16_MSBfirst((pvar)->ssh_state.payload + (offset)) + 7) >> 3)
553     #define get_ushort16(buf) get_ushort16_MSBfirst((buf))
554    
555     #define do_crc(buf, len) (~(uint32)crc32(0xFFFFFFFF, (buf), (len)))
556    
557     /* Decrypt the payload, checksum it, eat the padding, get the packet type
558     and return it.
559     'data' points to the start of the packet --- its length field.
560     'len' is the length of the
561     payload + padding (+ length of CRC for SSHv1). 'padding' is the length
562     of the padding alone. */
563     static int prep_packet(PTInstVar pvar, char FAR * data, int len,
564     int padding)
565     {
566     pvar->ssh_state.payload = data + 4;
567     pvar->ssh_state.payloadlen = len;
568    
569     if (SSHv1(pvar)) {
570     if (CRYPT_detect_attack(pvar, pvar->ssh_state.payload, len)) {
571     notify_fatal_error(pvar,
572     "'CORE insertion attack' detected. Aborting connection.");
573     return SSH_MSG_NONE;
574     }
575    
576     CRYPT_decrypt(pvar, pvar->ssh_state.payload, len);
577     /* PKT guarantees that the data is always 4-byte aligned */
578     if (do_crc(pvar->ssh_state.payload, len - 4) !=
579     get_uint32_MSBfirst(pvar->ssh_state.payload + len - 4)) {
580     notify_fatal_error(pvar,
581     "Detected corrupted data; connection terminating.");
582     return SSH_MSG_NONE;
583     }
584    
585     pvar->ssh_state.payload += padding;
586     pvar->ssh_state.payloadlen -= padding + 4;
587     } else {
588     int already_decrypted = get_predecryption_amount(pvar);
589    
590     #if 0
591     CRYPT_decrypt(pvar, data + already_decrypted,
592     len - already_decrypted);
593     #else
594     CRYPT_decrypt(pvar, data + already_decrypted,
595     (4 + len) - already_decrypted);
596     #endif
597    
598     if (!CRYPT_verify_receiver_MAC
599     (pvar, pvar->ssh_state.receiver_sequence_number, data, len + 4,
600     data + len + 4)) {
601     notify_fatal_error(pvar,
602     "Detected corrupted data; connection terminating.");
603     return SSH_MSG_NONE;
604     }
605    
606     pvar->ssh_state.payload++;
607     pvar->ssh_state.payloadlen -= padding + 1;
608     }
609    
610     pvar->ssh_state.payload_grabbed = 0;
611    
612 yutakakn 2833 if (SSHv1(pvar)) {
613     if (pvar->ssh_state.decompressing) {
614     if (pvar->ssh_state.decompress_stream.avail_in != 0) {
615     notify_nonfatal_error(pvar,
616     "Internal error: a packet was not fully decompressed.\n"
617     "This is a bug, please report it.");
618     }
619    
620     pvar->ssh_state.decompress_stream.next_in =
621     pvar->ssh_state.payload;
622     pvar->ssh_state.decompress_stream.avail_in =
623     pvar->ssh_state.payloadlen;
624     pvar->ssh_state.decompress_stream.next_out =
625     pvar->ssh_state.postdecompress_inbuf;
626     pvar->ssh_state.payloadlen = -1;
627     } else {
628     pvar->ssh_state.payload++;
629 yutakakn 2728 }
630    
631 yutakakn 2833 if (!grab_payload_limited(pvar, 1)) {
632     return SSH_MSG_NONE;
633     }
634    
635 yutakakn 2728 } else {
636 yutakakn 2833 // support of SSH2 packet compression (2005.7.9 yutaka)
637     if (pvar->stoc_compression && pvar->ssh2_keys[MODE_IN].comp.enabled) { // compression enabled
638     int ret;
639 yutakakn 2728
640 yutakakn 2833 if (pvar->decomp_buffer == NULL) {
641     pvar->decomp_buffer = buffer_init();
642     if (pvar->decomp_buffer == NULL)
643     return SSH_MSG_NONE;
644     }
645     // ���x�m�������o�b�t�@���g�������������������Y�������B
646     buffer_clear(pvar->decomp_buffer);
647    
648     // packet size��padding�������������y�C���[�h�����������W�J�����B
649     ret = buffer_decompress(&pvar->ssh_state.decompress_stream,
650     pvar->ssh_state.payload, pvar->ssh_state.payloadlen, pvar->decomp_buffer);
651    
652     // �|�C���^���X�V�B
653     pvar->ssh_state.payload = buffer_ptr(pvar->decomp_buffer);
654     pvar->ssh_state.payload++;
655     pvar->ssh_state.payloadlen = buffer_len(pvar->decomp_buffer);
656    
657     } else {
658     pvar->ssh_state.payload++;
659     }
660    
661     if (!grab_payload_limited(pvar, 1)) {
662     return SSH_MSG_NONE;
663     }
664    
665 yutakakn 2728 }
666    
667     pvar->ssh_state.receiver_sequence_number++;
668    
669     return pvar->ssh_state.payload[-1];
670     }
671    
672     /* Create a packet to be sent. The SSH protocol packet type is in 'type';
673     'len' contains the length of the packet payload, in bytes (this
674     does not include the space for any of the packet headers or padding,
675     or for the packet type byte).
676     Returns a pointer to the payload data area, a region of length 'len',
677     to be filled by the caller. */
678     static unsigned char FAR *begin_send_packet(PTInstVar pvar, int type,
679     int len)
680     {
681     unsigned char FAR *buf;
682    
683     pvar->ssh_state.outgoing_packet_len = len + 1;
684    
685     if (pvar->ssh_state.compressing) {
686     buf_ensure_size(&pvar->ssh_state.precompress_outbuf,
687     &pvar->ssh_state.precompress_outbuflen, 1 + len);
688     buf = pvar->ssh_state.precompress_outbuf;
689     } else {
690     /* For SSHv2,
691     Encrypted_length is 4(packetlength) + 1(paddinglength) + 1(packettype)
692     + len(payload) + 4(minpadding), rounded up to nearest block_size
693     We only need a reasonable upper bound for the buffer size */
694     buf_ensure_size(&pvar->ssh_state.outbuf,
695     &pvar->ssh_state.outbuflen,
696     len + 30 + CRYPT_get_sender_MAC_size(pvar) +
697     CRYPT_get_encryption_block_size(pvar));
698     buf = pvar->ssh_state.outbuf + 12;
699     }
700    
701     buf[0] = (unsigned char) type;
702     return buf + 1;
703     }
704    
705     #define finish_send_packet(pvar) finish_send_packet_special((pvar), 0)
706    
707     static BOOL send_packet_blocking(PTInstVar pvar, char FAR * data, int len)
708     {
709     u_long do_block = 0;
710    
711     if ((pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow,
712     0, 0) == SOCKET_ERROR
713     || ioctlsocket(pvar->socket, FIONBIO, &do_block) == SOCKET_ERROR
714     || (pvar->Psend) (pvar->socket, data, len, 0) != len
715     || (pvar->PWSAAsyncSelect) (pvar->socket, pvar->NotificationWindow,
716     pvar->notification_msg,
717     pvar->notification_events) ==
718     SOCKET_ERROR) {
719     notify_fatal_error(pvar,
720     "A communications error occurred while sending an SSH packet.\n"
721     "The connection will close.");
722     return FALSE;
723     } else {
724     return TRUE;
725     }
726     }
727    
728     /* if skip_compress is true, then the data has already been compressed
729     into outbuf + 12 */
730     static void finish_send_packet_special(PTInstVar pvar, int skip_compress)
731     {
732     int len = pvar->ssh_state.outgoing_packet_len;
733     char FAR *data;
734     int data_length;
735 yutakakn 2833 buffer_t *msg = NULL; // for SSH2 packet compression
736 yutakakn 2728
737     if (pvar->ssh_state.compressing) {
738     if (!skip_compress) {
739     buf_ensure_size(&pvar->ssh_state.outbuf,
740     &pvar->ssh_state.outbuflen,
741     len + (len >> 6) + 50 +
742     CRYPT_get_sender_MAC_size(pvar));
743     pvar->ssh_state.compress_stream.next_in =
744     pvar->ssh_state.precompress_outbuf;
745     pvar->ssh_state.compress_stream.avail_in = len;
746     pvar->ssh_state.compress_stream.next_out =
747     pvar->ssh_state.outbuf + 12;
748     pvar->ssh_state.compress_stream.avail_out =
749     pvar->ssh_state.outbuflen - 12;
750    
751     if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
752     Z_OK) {
753     notify_fatal_error(pvar,
754     "An error occurred while compressing packet data.\n"
755     "The connection will close.");
756     return;
757     }
758     }
759    
760     len =
761     pvar->ssh_state.outbuflen - 12 -
762     pvar->ssh_state.compress_stream.avail_out;
763     }
764    
765     if (SSHv1(pvar)) {
766     int padding = 8 - ((len + 4) % 8);
767    
768     data = pvar->ssh_state.outbuf + 8 - padding;
769     data_length = padding + len + 8;
770    
771     set_uint32(data, len + 4);
772     if (CRYPT_get_receiver_cipher(pvar) != SSH_CIPHER_NONE) {
773     CRYPT_set_random_data(pvar, data + 4, padding);
774     } else {
775     memset(data + 4, 0, padding);
776     }
777     set_uint32(data + data_length - 4,
778     do_crc(data + 4, data_length - 8));
779     CRYPT_encrypt(pvar, data + 4, data_length - 4);
780     } else { //for SSH2(yutaka)
781     int block_size = CRYPT_get_encryption_block_size(pvar);
782     int encryption_size;
783     int padding;
784     BOOL ret;
785    
786 yutakakn 2833 /*
787     �f�[�^�\��
788     pvar->ssh_state.outbuf:
789     offset: 0 1 2 3 4 5 6 7 8 9 10 11 12 ... EOD
790     <--ignore---> ^^^^^^^^ <---- payload --->
791     packet length
792    
793     ^^padding
794    
795     <---------------------------->
796     SSH2 sending data on TCP
797    
798     NOTE:
799     payload = type(1) + raw-data
800     len = ssh_state.outgoing_packet_len = payload size
801     */
802     // �p�P�b�g���k���L���������A�p�P�b�g�����k�����������M�p�P�b�g���\�z�����B(2005.7.9 yutaka)
803     if (pvar->ctos_compression && pvar->ssh2_keys[MODE_OUT].comp.enabled) {
804     // �����o�b�t�@�� packet-length(4) + padding(1) + payload(any) �������B
805     msg = buffer_init();
806     if (msg == NULL) {
807     // TODO: error check
808     return;
809     }
810    
811     // ���k�������w�b�_�������y�C���[�h�����B
812     buffer_append(msg, "\0\0\0\0\0", 5); // 5 = packet-length(4) + padding(1)
813     if (buffer_compress(&pvar->ssh_state.compress_stream, pvar->ssh_state.outbuf + 12, len, msg) == -1) {
814     notify_fatal_error(pvar,
815     "An error occurred while compressing packet data.\n"
816     "The connection will close.");
817     return;
818     }
819     data = buffer_ptr(msg);
820     len = buffer_len(msg) - 5; // 'len' is overwritten.
821    
822     } else {
823     // �����k
824     data = pvar->ssh_state.outbuf + 7;
825    
826     }
827    
828     // ���M�p�P�b�g�\�z(input parameter: data, len)
829 yutakakn 2728 if (block_size < 8) {
830     block_size = 8;
831     }
832     encryption_size = ((len + 8) / block_size + 1) * block_size;
833     data_length = encryption_size + CRYPT_get_sender_MAC_size(pvar);
834    
835     set_uint32(data, encryption_size - 4);
836     padding = encryption_size - len - 5;
837     data[4] = (unsigned char) padding;
838     CRYPT_set_random_data(pvar, data + 5 + len, padding);
839     ret = CRYPT_build_sender_MAC(pvar,
840     pvar->ssh_state.sender_sequence_number,
841     data, encryption_size,
842     data + encryption_size);
843     if (ret == FALSE) { // HMAC��������������������������
844     data_length = encryption_size;
845     }
846    
847     // �p�P�b�g�������������BHMAC���~�������������O�B
848     CRYPT_encrypt(pvar, data, encryption_size);
849     }
850    
851     send_packet_blocking(pvar, data, data_length);
852    
853 yutakakn 2833 buffer_free(msg);
854    
855 yutakakn 2728 pvar->ssh_state.sender_sequence_number++;
856 yutakakn 2748
857     // ���M�������L�^
858     pvar->ssh_heartbeat_tick = time(NULL);
859 yutakakn 2728 }
860    
861     static void destroy_packet_buf(PTInstVar pvar)
862     {
863     memset(pvar->ssh_state.outbuf, 0, pvar->ssh_state.outbuflen);
864     if (pvar->ssh_state.compressing) {
865     memset(pvar->ssh_state.precompress_outbuf, 0,
866     pvar->ssh_state.precompress_outbuflen);
867     }
868     }
869    
870     /* The handlers are added to the queue for each message. When one of the
871     handlers fires, if it returns FALSE, then all handlers in the set are
872     removed from their queues. */
873     static void enque_handlers(PTInstVar pvar, int num_msgs,
874     const int FAR * messages,
875     const SSHPacketHandler FAR * handlers)
876     {
877     SSHPacketHandlerItem FAR *first_item;
878     SSHPacketHandlerItem FAR *last_item = NULL;
879     int i;
880    
881     for (i = 0; i < num_msgs; i++) {
882     SSHPacketHandlerItem FAR *item =
883     (SSHPacketHandlerItem FAR *)
884     malloc(sizeof(SSHPacketHandlerItem));
885     SSHPacketHandlerItem FAR *cur_item =
886     pvar->ssh_state.packet_handlers[messages[i]];
887    
888     item->handler = handlers[i];
889    
890     if (cur_item == NULL) {
891     pvar->ssh_state.packet_handlers[messages[i]] = item;
892     item->next_for_message = item;
893     item->last_for_message = item;
894     item->active_for_message = messages[i];
895     } else {
896     item->next_for_message = cur_item;
897     item->last_for_message = cur_item->last_for_message;
898     cur_item->last_for_message->next_for_message = item;
899     cur_item->last_for_message = item;
900     item->active_for_message = -1;
901     }
902    
903     if (last_item != NULL) {
904     last_item->next_in_set = item;
905     } else {
906     first_item = item;
907     }
908     last_item = item;
909     }
910    
911     if (last_item != NULL) {
912     last_item->next_in_set = first_item;
913     }
914     }
915    
916     static SSHPacketHandler get_handler(PTInstVar pvar, int message)
917     {
918     SSHPacketHandlerItem FAR *cur_item =
919     pvar->ssh_state.packet_handlers[message];
920    
921     if (cur_item == NULL) {
922     return NULL;
923     } else {
924     return cur_item->handler;
925     }
926     }
927    
928     /* Called only by SSH_handle_packet */
929     static void deque_handlers(PTInstVar pvar, int message)
930     {
931     SSHPacketHandlerItem FAR *cur_item =
932     pvar->ssh_state.packet_handlers[message];
933     SSHPacketHandlerItem FAR *first_item_in_set = cur_item;
934    
935     do {
936     SSHPacketHandlerItem FAR *next_in_set = cur_item->next_in_set;
937    
938     if (cur_item->active_for_message >= 0) {
939     SSHPacketHandlerItem FAR *replacement =
940     cur_item->next_for_message;
941    
942     if (replacement == cur_item) {
943     replacement = NULL;
944     } else {
945     replacement->active_for_message =
946     cur_item->active_for_message;
947     }
948     pvar->ssh_state.packet_handlers[cur_item->active_for_message] =
949     replacement;
950     }
951     cur_item->next_for_message->last_for_message =
952     cur_item->last_for_message;
953     cur_item->last_for_message->next_for_message =
954     cur_item->next_for_message;
955    
956     free(cur_item);
957     cur_item = next_in_set;
958     } while (cur_item != first_item_in_set);
959     }
960    
961     static void enque_handler(PTInstVar pvar, int message,
962     SSHPacketHandler handler)
963     {
964     enque_handlers(pvar, 1, &message, &handler);
965     }
966    
967     static void chop_newlines(char FAR * buf)
968     {
969     int len = strlen(buf);
970    
971     while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) {
972     buf[len - 1] = 0;
973     len--;
974     }
975     }
976    
977     /********************/
978     /* Message handlers */
979     /********************/
980    
981     static BOOL handle_forwarding_success(PTInstVar pvar)
982     {
983     return FALSE;
984     }
985    
986     static BOOL handle_forwarding_failure(PTInstVar pvar)
987     {
988     return FALSE;
989     }
990    
991     static void enque_forwarding_request_handlers(PTInstVar pvar)
992     {
993     static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
994     static const SSHPacketHandler handlers[]
995     = { handle_forwarding_success, handle_forwarding_failure };
996    
997     enque_handlers(pvar, 2, msgs, handlers);
998     }
999    
1000     static BOOL handle_auth_failure(PTInstVar pvar)
1001     {
1002     notify_verbose_message(pvar, "Authentication failed",
1003     LOG_LEVEL_VERBOSE);
1004    
1005     AUTH_set_generic_mode(pvar);
1006     AUTH_advance_to_next_cred(pvar);
1007     pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1008     try_send_credentials(pvar);
1009     return FALSE;
1010     }
1011    
1012     static BOOL handle_rsa_auth_refused(PTInstVar pvar)
1013     {
1014     AUTH_destroy_cur_cred(pvar);
1015     return handle_auth_failure(pvar);
1016     }
1017    
1018     static BOOL handle_TIS_challenge(PTInstVar pvar)
1019     {
1020     if (grab_payload(pvar, 4)) {
1021     int len = get_payload_uint32(pvar, 0);
1022    
1023     if (grab_payload(pvar, len)) {
1024     notify_verbose_message(pvar, "Received TIS challenge",
1025     LOG_LEVEL_VERBOSE);
1026    
1027     AUTH_set_TIS_mode(pvar, pvar->ssh_state.payload + 4, len);
1028     AUTH_advance_to_next_cred(pvar);
1029     pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1030     try_send_credentials(pvar);
1031     }
1032     }
1033     return FALSE;
1034     }
1035    
1036     static BOOL handle_auth_required(PTInstVar pvar)
1037     {
1038     notify_verbose_message(pvar, "Server requires authentication",
1039     LOG_LEVEL_VERBOSE);
1040    
1041     pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_CREDENTIALS;
1042     try_send_credentials(pvar);
1043     /* the first AUTH_advance_to_next_cred is issued early by ttxssh.c */
1044    
1045     return FALSE;
1046     }
1047    
1048     static BOOL handle_ignore(PTInstVar pvar)
1049     {
1050     if (grab_payload(pvar, 4)
1051     && grab_payload(pvar, get_payload_uint32(pvar, 0))) {
1052     /* ignore it! but it must be decompressed */
1053     }
1054     return TRUE;
1055     }
1056    
1057     static BOOL handle_debug(PTInstVar pvar)
1058     {
1059     BOOL always_display;
1060     char FAR *description;
1061     int description_len;
1062     char buf[2048];
1063    
1064     if (SSHv1(pvar)) {
1065     if (grab_payload(pvar, 4)
1066     && grab_payload(pvar, description_len =
1067     get_payload_uint32(pvar, 0))) {
1068     always_display = FALSE;
1069     description = pvar->ssh_state.payload + 4;
1070     description[description_len] = 0;
1071     } else {
1072     return TRUE;
1073     }
1074     } else {
1075     if (grab_payload(pvar, 5)
1076     && grab_payload(pvar,
1077     (description_len =
1078     get_payload_uint32(pvar, 1)) + 4)
1079     && grab_payload(pvar,
1080     get_payload_uint32(pvar,
1081     5 + description_len))) {
1082     always_display = pvar->ssh_state.payload[0] != 0;
1083     description = pvar->ssh_state.payload + 5;
1084     description[description_len] = 0;
1085     } else {
1086     return TRUE;
1087     }
1088     }
1089    
1090     chop_newlines(description);
1091     _snprintf(buf, sizeof(buf), "DEBUG message from server: %s",
1092     description);
1093     buf[sizeof(buf) - 1] = 0;
1094     if (always_display) {
1095     notify_nonfatal_error(pvar, buf);
1096     } else {
1097     notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
1098     }
1099     return TRUE;
1100     }
1101    
1102     static BOOL handle_disconnect(PTInstVar pvar)
1103     {
1104     int reason_code;
1105     char FAR *description;
1106     int description_len;
1107     char buf[2048];
1108     char FAR *explanation = "";
1109    
1110     if (SSHv1(pvar)) {
1111     if (grab_payload(pvar, 4)
1112     && grab_payload(pvar, description_len =
1113     get_payload_uint32(pvar, 0))) {
1114     reason_code = -1;
1115     description = pvar->ssh_state.payload + 4;
1116     description[description_len] = 0;
1117     } else {
1118     return TRUE;
1119     }
1120     } else {
1121     if (grab_payload(pvar, 8)
1122     && grab_payload(pvar,
1123     (description_len =
1124     get_payload_uint32(pvar, 4)) + 4)
1125     && grab_payload(pvar,
1126     get_payload_uint32(pvar,
1127     8 + description_len))) {
1128     reason_code = get_payload_uint32(pvar, 0);
1129     description = pvar->ssh_state.payload + 8;
1130     description[description_len] = 0;
1131     } else {
1132     return TRUE;
1133     }
1134     }
1135    
1136     chop_newlines(description);
1137     if (description[0] == 0) {
1138     description = NULL;
1139     }
1140    
1141     if (get_handler(pvar, SSH_SMSG_FAILURE) == handle_forwarding_failure) {
1142     explanation =
1143     "\nIt may have disconnected because it was unable to forward a port you requested to be forwarded from the server.\n"
1144     "This often happens when someone is already forwarding that port from the server.";
1145     }
1146    
1147     if (description != NULL) {
1148     _snprintf(buf, sizeof(buf),
1149     "Server disconnected with message '%s'.%s", description,
1150     explanation);
1151     } else {
1152     _snprintf(buf, sizeof(buf),
1153     "Server disconnected (no reason given).%s", explanation);
1154     }
1155     buf[sizeof(buf) - 1] = 0;
1156     notify_fatal_error(pvar, buf);
1157    
1158     return TRUE;
1159     }
1160    
1161     static BOOL handle_unimplemented(PTInstVar pvar)
1162     {
1163     /* Should never receive this since we only send base 2.0 protocol messages */
1164     grab_payload(pvar, 4);
1165     return TRUE;
1166     }
1167    
1168     static BOOL handle_crypt_success(PTInstVar pvar)
1169     {
1170     notify_verbose_message(pvar, "Secure mode successfully achieved",
1171     LOG_LEVEL_VERBOSE);
1172     return FALSE;
1173     }
1174    
1175     static BOOL handle_noauth_success(PTInstVar pvar)
1176     {
1177     notify_verbose_message(pvar, "Server does not require authentication",
1178     LOG_LEVEL_VERBOSE);
1179     prep_compression(pvar);
1180     return FALSE;
1181     }
1182    
1183     static BOOL handle_auth_success(PTInstVar pvar)
1184     {
1185     notify_verbose_message(pvar, "Authentication accepted",
1186     LOG_LEVEL_VERBOSE);
1187     prep_compression(pvar);
1188 yutakakn 2748
1189     // �n�[�g�r�[�g�E�X���b�h���J�n (2004.12.11 yutaka)
1190     start_ssh_heartbeat_thread(pvar);
1191    
1192 yutakakn 2728 return FALSE;
1193     }
1194    
1195     static BOOL handle_server_public_key(PTInstVar pvar)
1196     {
1197     int server_key_public_exponent_len;
1198     int server_key_public_modulus_pos;
1199     int server_key_public_modulus_len;
1200     int host_key_bits_pos;
1201     int host_key_public_exponent_len;
1202     int host_key_public_modulus_pos;
1203     int host_key_public_modulus_len;
1204     int protocol_flags_pos;
1205     int supported_ciphers;
1206     char FAR *inmsg;
1207    
1208     if (!grab_payload(pvar, 14))
1209     return FALSE;
1210     server_key_public_exponent_len = get_mpint_len(pvar, 12);
1211    
1212     if (!grab_payload(pvar, server_key_public_exponent_len + 2))
1213     return FALSE;
1214     server_key_public_modulus_pos = 14 + server_key_public_exponent_len;
1215     server_key_public_modulus_len =
1216     get_mpint_len(pvar, server_key_public_modulus_pos);
1217    
1218     if (!grab_payload(pvar, server_key_public_modulus_len + 6))
1219     return FALSE;
1220     host_key_bits_pos =
1221     server_key_public_modulus_pos + 2 + server_key_public_modulus_len;
1222     host_key_public_exponent_len =
1223     get_mpint_len(pvar, host_key_bits_pos + 4);
1224    
1225     if (!grab_payload(pvar, host_key_public_exponent_len + 2))
1226     return FALSE;
1227     host_key_public_modulus_pos =
1228     host_key_bits_pos + 6 + host_key_public_exponent_len;
1229     host_key_public_modulus_len =
1230     get_mpint_len(pvar, host_key_public_modulus_pos);
1231    
1232     if (!grab_payload(pvar, host_key_public_modulus_len + 12))
1233     return FALSE;
1234     protocol_flags_pos =
1235     host_key_public_modulus_pos + 2 + host_key_public_modulus_len;
1236    
1237     inmsg = pvar->ssh_state.payload;
1238    
1239     CRYPT_set_server_cookie(pvar, inmsg);
1240     if (!CRYPT_set_server_RSA_key
1241     (pvar, get_uint32(inmsg + 8), pvar->ssh_state.payload + 12,
1242     inmsg + server_key_public_modulus_pos))
1243     return FALSE;
1244     if (!CRYPT_set_host_RSA_key
1245     (pvar, get_uint32(inmsg + host_key_bits_pos),
1246     inmsg + host_key_bits_pos + 4,
1247     inmsg + host_key_public_modulus_pos))
1248     return FALSE;
1249     pvar->ssh_state.server_protocol_flags =
1250     get_uint32(inmsg + protocol_flags_pos);
1251    
1252     supported_ciphers = get_uint32(inmsg + protocol_flags_pos + 4);
1253     if (!CRYPT_set_supported_ciphers
1254     (pvar, supported_ciphers, supported_ciphers))
1255     return FALSE;
1256     if (!AUTH_set_supported_auth_types
1257     (pvar, get_uint32(inmsg + protocol_flags_pos + 8)))
1258     return FALSE;
1259    
1260     /* this must be the LAST THING in this function, since it can cause
1261     host_is_OK to be called. */
1262     HOSTS_check_host_key(pvar, pvar->ssh_state.hostname,
1263     get_uint32(inmsg + host_key_bits_pos),
1264     inmsg + host_key_bits_pos + 4,
1265     inmsg + host_key_public_modulus_pos);
1266    
1267     return FALSE;
1268     }
1269    
1270     /*
1271     The ID must have already been found to start with "SSH-". It must
1272     be null-terminated.
1273     */
1274     static BOOL parse_protocol_ID(PTInstVar pvar, char FAR * ID)
1275     {
1276     char FAR *str;
1277    
1278     for (str = ID + 4; *str >= '0' && *str <= '9'; str++) {
1279     }
1280    
1281     if (*str != '.') {
1282     return FALSE;
1283     }
1284    
1285     pvar->protocol_major = atoi(ID + 4);
1286     pvar->protocol_minor = atoi(str + 1);
1287    
1288     // for SSH2(yutaka)
1289     // 1.99����SSH2�����������s��
1290     if (pvar->protocol_major == 1 && pvar->protocol_minor == 99) {
1291     // ���[�U�� SSH2 ���I������������������
1292     if (pvar->settings.ssh_protocol_version == 2) {
1293     pvar->protocol_major = 2;
1294     pvar->protocol_minor = 0;
1295     }
1296    
1297     }
1298    
1299     for (str = str + 1; *str >= '0' && *str <= '9'; str++) {
1300     }
1301    
1302     return *str == '-';
1303     }
1304    
1305     /*
1306     On entry, the pvar->protocol_xxx fields hold the server's advertised
1307     protocol number. We replace the fields with the protocol number we will
1308     actually use, or return FALSE if there is no usable protocol version.
1309     */
1310     static BOOL negotiate_protocol(PTInstVar pvar)
1311     {
1312     switch (pvar->protocol_major) {
1313     case 1:
1314     if (pvar->protocol_minor > 5) {
1315     pvar->protocol_minor = 5;
1316     }
1317    
1318     return TRUE;
1319    
1320     // for SSH2(yutaka)
1321     case 2:
1322     return TRUE; // SSH2 support
1323    
1324     default:
1325     return FALSE;
1326     }
1327     }
1328    
1329     static void init_protocol(PTInstVar pvar)
1330     {
1331     CRYPT_initialize_random_numbers(pvar);
1332     HOSTS_prefetch_host_key(pvar, pvar->ssh_state.hostname);
1333     /* while we wait for a response from the server... */
1334    
1335     if (SSHv1(pvar)) {
1336     enque_handler(pvar, SSH_MSG_DISCONNECT, handle_disconnect);
1337     enque_handler(pvar, SSH_MSG_IGNORE, handle_ignore);
1338     enque_handler(pvar, SSH_MSG_DEBUG, handle_debug);
1339     enque_handler(pvar, SSH_SMSG_PUBLIC_KEY, handle_server_public_key);
1340    
1341     } else { // for SSH2(yutaka)
1342     enque_handler(pvar, SSH2_MSG_DISCONNECT, handle_disconnect);
1343     enque_handler(pvar, SSH2_MSG_IGNORE, handle_ignore);
1344     enque_handler(pvar, SSH2_MSG_DEBUG, handle_debug);
1345     enque_handler(pvar, SSH2_MSG_KEXINIT, handle_SSH2_kexinit);
1346     enque_handler(pvar, SSH2_MSG_KEXDH_INIT, handle_unimplemented);
1347     enque_handler(pvar, SSH2_MSG_KEXDH_REPLY, handle_SSH2_dh_common_reply);
1348     enque_handler(pvar, SSH2_MSG_KEX_DH_GEX_REPLY, handle_SSH2_dh_gex_reply);
1349     enque_handler(pvar, SSH2_MSG_NEWKEYS, handle_SSH2_newkeys);
1350     enque_handler(pvar, SSH2_MSG_SERVICE_ACCEPT, handle_SSH2_authrequest);
1351     enque_handler(pvar, SSH2_MSG_USERAUTH_SUCCESS, handle_SSH2_userauth_success);
1352     enque_handler(pvar, SSH2_MSG_USERAUTH_FAILURE, handle_SSH2_userauth_failure);
1353     enque_handler(pvar, SSH2_MSG_USERAUTH_BANNER, handle_SSH2_userauth_banner);
1354 yutakakn 2782 enque_handler(pvar, SSH2_MSG_USERAUTH_INFO_REQUEST, handle_SSH2_userauth_inforeq);
1355 yutakakn 2728
1356     enque_handler(pvar, SSH2_MSG_UNIMPLEMENTED, handle_unimplemented);
1357    
1358     // ���[�U�F�������f�B�X�p�b�`���[�`��
1359     enque_handler(pvar, SSH2_MSG_CHANNEL_CLOSE, handle_SSH2_channel_close);
1360     enque_handler(pvar, SSH2_MSG_CHANNEL_DATA, handle_SSH2_channel_data);
1361     enque_handler(pvar, SSH2_MSG_CHANNEL_EOF, handle_SSH2_channel_eof);
1362     // enque_handler(pvar, SSH2_MSG_CHANNEL_EXTENDED_DATA, handle_SSH2_channel_extended_data);
1363 yutakakn 2825 enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN, handle_SSH2_channel_open);
1364 yutakakn 2728 enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, handle_SSH2_open_confirm);
1365 yutakakn 2827 enque_handler(pvar, SSH2_MSG_CHANNEL_OPEN_FAILURE, handle_SSH2_open_failure);
1366 yutakakn 2728 enque_handler(pvar, SSH2_MSG_CHANNEL_REQUEST, handle_SSH2_channel_request);
1367     enque_handler(pvar, SSH2_MSG_CHANNEL_WINDOW_ADJUST, handle_SSH2_window_adjust);
1368     enque_handler(pvar, SSH2_MSG_CHANNEL_SUCCESS, handle_SSH2_channel_success);
1369     // enque_handler(pvar, SSH2_MSG_GLOBAL_REQUEST, handle_unimplemented);
1370 yutakakn 2825 enque_handler(pvar, SSH2_MSG_REQUEST_FAILURE, handle_SSH2_request_failure);
1371 yutakakn 2728 enque_handler(pvar, SSH2_MSG_REQUEST_SUCCESS, handle_SSH2_request_success);
1372    
1373     }
1374     }
1375    
1376     BOOL SSH_handle_server_ID(PTInstVar pvar, char FAR * ID, int ID_len)
1377     {
1378     static const char prefix[] = "Received server prologue string: ";
1379    
1380 yutakakn 2796 // initialize SSH2 memory dump (2005.3.7 yutaka)
1381     init_memdump();
1382     push_memdump("pure server ID", "�v���g�R�����������������J�n", ID, ID_len);
1383    
1384 yutakakn 2728 if (ID_len <= 0) {
1385     return FALSE;
1386     } else {
1387     char FAR *buf = (char FAR *) malloc(ID_len + NUM_ELEM(prefix));
1388    
1389     strcpy(buf, prefix);
1390     strncpy(buf + NUM_ELEM(prefix) - 1, ID, ID_len);
1391     buf[NUM_ELEM(prefix) + ID_len - 1] = 0;
1392     chop_newlines(buf);
1393    
1394     notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
1395    
1396     free(buf);
1397    
1398    
1399 yutakakn 2797 // ���������R�s�[������ (2005.3.9 yutaka)
1400     #if 0
1401 yutakakn 2728 // for calculate SSH2 hash
1402     // �T�[�o�o�[�W�����������i���s���������������j
1403     if (ID_len >= sizeof(pvar->server_version_string))
1404     return FALSE;
1405     strncpy(pvar->server_version_string, ID, ID_len);
1406 yutakakn 2797 #endif
1407 yutakakn 2728
1408    
1409     if (ID[ID_len - 1] != '\n') {
1410     pvar->ssh_state.status_flags |= STATUS_IN_PARTIAL_ID_STRING;
1411     return FALSE;
1412     } else
1413     if ((pvar->ssh_state.
1414     status_flags & STATUS_IN_PARTIAL_ID_STRING) != 0) {
1415     pvar->ssh_state.status_flags &= ~STATUS_IN_PARTIAL_ID_STRING;
1416     return FALSE;
1417     } else if (strncmp(ID, "SSH-", 4) != 0) {
1418     return FALSE;
1419     } else {
1420     ID[ID_len - 1] = 0;
1421    
1422     if (ID_len > 1 && ID[ID_len - 2] == '\r') {
1423     ID[ID_len - 2] = 0;
1424     }
1425    
1426     pvar->ssh_state.server_ID = _strdup(ID);
1427    
1428     if (!parse_protocol_ID(pvar, ID) || !negotiate_protocol(pvar)) {
1429     notify_fatal_error(pvar,
1430     "This program does not understand the server's version of the protocol.");
1431     } else {
1432     char TTSSH_ID[1024];
1433     int TTSSH_ID_len;
1434 yutakakn 2793 int a, b, c, d;
1435 yutakakn 2728
1436 yutakakn 2793 // �������g���o�[�W�������������� (2005.3.3 yutaka)
1437     get_file_version("ttxssh.dll", &a, &b, &c, &d);
1438    
1439 yutakakn 2728 _snprintf(TTSSH_ID, sizeof(TTSSH_ID),
1440 yutakakn 2793 "SSH-%d.%d-TTSSH/%d.%d Win32\n",
1441     pvar->protocol_major, pvar->protocol_minor, a, b);
1442 yutakakn 2728 TTSSH_ID_len = strlen(TTSSH_ID);
1443    
1444     // for SSH2(yutaka)
1445     // �N���C�A���g�o�[�W�����������i���s���������������j
1446     strncpy(pvar->client_version_string, TTSSH_ID, TTSSH_ID_len);
1447    
1448 yutakakn 2797 // �T�[�o�o�[�W�����������i���s���������������j(2005.3.9 yutaka)
1449     _snprintf(pvar->server_version_string, sizeof(pvar->server_version_string), "%s", pvar->ssh_state.server_ID);
1450    
1451 yutakakn 2728 if ((pvar->Psend) (pvar->socket, TTSSH_ID, TTSSH_ID_len,
1452     0) != TTSSH_ID_len) {
1453     notify_fatal_error(pvar,
1454     "An error occurred while sending the SSH ID string.\n"
1455     "The connection will close.");
1456     } else {
1457     // ���s�R�[�h������ (2004.8.4 yutaka)
1458     pvar->client_version_string[--TTSSH_ID_len] = 0;
1459    
1460 yutakakn 2796 push_memdump("server ID", NULL, pvar->server_version_string, strlen(pvar->server_version_string));
1461     push_memdump("client ID", NULL, pvar->client_version_string, strlen(pvar->client_version_string));
1462    
1463 yutakakn 2728 // SSH�n���h�����o�^���s��
1464     init_protocol(pvar);
1465    
1466     SSH2_dispatch_init(1);
1467     SSH2_dispatch_add_message(SSH2_MSG_KEXINIT);
1468 yutakakn 2796 SSH2_dispatch_add_message(SSH2_MSG_IGNORE); // XXX: Tru64 UNIX workaround (2005.3.3 yutaka)
1469 yutakakn 2728 }
1470     }
1471    
1472     return TRUE;
1473     }
1474     }
1475     }
1476    
1477     static BOOL handle_exit(PTInstVar pvar)
1478     {
1479     if (grab_payload(pvar, 4)) {
1480     begin_send_packet(pvar, SSH_CMSG_EXIT_CONFIRMATION, 0);
1481     finish_send_packet(pvar);
1482     notify_closed_connection(pvar);
1483     }
1484     return TRUE;
1485     }
1486    
1487     static BOOL handle_data(PTInstVar pvar)
1488     {
1489     if (grab_payload_limited(pvar, 4)) {
1490     pvar->ssh_state.payload_datalen = get_payload_uint32(pvar, 0);
1491     pvar->ssh_state.payload_datastart = 4;
1492     }
1493     return TRUE;
1494     }
1495    
1496     static BOOL handle_channel_open(PTInstVar pvar)
1497     {
1498     int host_len;
1499     int originator_len;
1500    
1501     if ((pvar->ssh_state.
1502     server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
1503     if (grab_payload(pvar, 8)
1504     && grab_payload(pvar,
1505     8 + (host_len = get_payload_uint32(pvar, 4)))
1506     && grab_payload(pvar, originator_len =
1507     get_payload_uint32(pvar, host_len + 12))) {
1508     int local_port = get_payload_uint32(pvar, 8 + host_len);
1509    
1510     pvar->ssh_state.payload[8 + host_len] = 0;
1511     FWD_open(pvar, get_payload_uint32(pvar, 0),
1512     pvar->ssh_state.payload + 8, local_port,
1513     pvar->ssh_state.payload + 16 + host_len,
1514 yutakakn 2826 originator_len,
1515     NULL);
1516 yutakakn 2728 }
1517     } else {
1518     if (grab_payload(pvar, 8)
1519     && grab_payload(pvar,
1520     4 + (host_len =
1521     get_payload_uint32(pvar, 4)))) {
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 yutakakn 2826 pvar->ssh_state.payload + 8, local_port, NULL, 0,
1527     NULL);
1528 yutakakn 2728 }
1529     }
1530    
1531     return TRUE;
1532     }
1533    
1534     static BOOL handle_X11_channel_open(PTInstVar pvar)
1535     {
1536     int originator_len;
1537    
1538     if ((pvar->ssh_state.
1539     server_protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0) {
1540     if (grab_payload(pvar, 8)
1541     && grab_payload(pvar, originator_len =
1542     get_payload_uint32(pvar, 4))) {
1543     FWD_X11_open(pvar, get_payload_uint32(pvar, 0),
1544 yutakakn 2829 pvar->ssh_state.payload + 8, originator_len, NULL);
1545 yutakakn 2728 }
1546     } else {
1547     if (grab_payload(pvar, 4)) {
1548 yutakakn 2829 FWD_X11_open(pvar, get_payload_uint32(pvar, 0), NULL, 0, NULL);
1549 yutakakn 2728 }
1550     }
1551    
1552     return TRUE;
1553     }
1554    
1555     static BOOL handle_channel_open_confirmation(PTInstVar pvar)
1556     {
1557     if (grab_payload(pvar, 8)) {
1558     FWD_confirmed_open(pvar, get_payload_uint32(pvar, 0),
1559     get_payload_uint32(pvar, 4));
1560     }
1561     return FALSE;
1562     }
1563    
1564     static BOOL handle_channel_open_failure(PTInstVar pvar)
1565     {
1566     if (grab_payload(pvar, 4)) {
1567     FWD_failed_open(pvar, get_payload_uint32(pvar, 0));
1568     }
1569     return FALSE;
1570     }
1571    
1572     static BOOL handle_channel_data(PTInstVar pvar)
1573     {
1574     int len;
1575    
1576     if (grab_payload(pvar, 8)
1577     && grab_payload(pvar, len = get_payload_uint32(pvar, 4))) {
1578     FWD_received_data(pvar, get_payload_uint32(pvar, 0),
1579     pvar->ssh_state.payload + 8, len);
1580     }
1581     return TRUE;
1582     }
1583    
1584     static BOOL handle_channel_input_eof(PTInstVar pvar)
1585     {
1586     if (grab_payload(pvar, 4)) {
1587     FWD_channel_input_eof(pvar, get_payload_uint32(pvar, 0));
1588     }
1589     return TRUE;
1590     }
1591    
1592     static BOOL handle_channel_output_eof(PTInstVar pvar)
1593     {
1594     if (grab_payload(pvar, 4)) {
1595     FWD_channel_output_eof(pvar, get_payload_uint32(pvar, 0));
1596     }
1597     return TRUE;
1598     }
1599    
1600    
1601    
1602     // �n���h�����O�������b�Z�[�W����������
1603    
1604     #define HANDLE_MESSAGE_MAX 30
1605     static unsigned char handle_messages[HANDLE_MESSAGE_MAX];
1606     static int handle_message_count = 0;
1607     static int handle_message_stage = 0;
1608    
1609     void SSH2_dispatch_init(int stage)
1610     {
1611     handle_message_count = 0;
1612     handle_message_stage = stage;
1613     }
1614    
1615     int SSH2_dispatch_enabled_check(unsigned char message)
1616     {
1617     int i;
1618    
1619     for (i = 0 ; i < handle_message_count ; i++) {
1620     if (handle_messages[i] == message)
1621     return 1;
1622     }
1623     return 0;
1624     }
1625    
1626     void SSH2_dispatch_add_message(unsigned char message)
1627     {
1628    
1629     if (handle_message_count >= HANDLE_MESSAGE_MAX) {
1630     // TODO: error check
1631     return;
1632     }
1633    
1634     handle_messages[handle_message_count++] = message;
1635     }
1636    
1637     void SSH2_dispatch_add_range_message(unsigned char begin, unsigned char end)
1638     {
1639     unsigned char c;
1640    
1641     for (c = begin ; c <= end ; c++) {
1642     SSH2_dispatch_add_message(c);
1643     }
1644     }
1645    
1646    
1647     void SSH_handle_packet(PTInstVar pvar, char FAR * data, int len,
1648     int padding)
1649     {
1650     unsigned char message = prep_packet(pvar, data, len, padding);
1651    
1652    
1653     #ifdef SSH2_DEBUG
1654     // for SSH2(yutaka)
1655     if (SSHv2(pvar)) {
1656     if (pvar->key_done) {
1657     message = message;
1658     }
1659    
1660     if (pvar->userauth_success) {
1661     message = message;
1662     }
1663    
1664     if (pvar->rekeying) {
1665     message = message;
1666     }
1667     }
1668     #endif
1669    
1670     // SSH�����b�Z�[�W�^�C�v���`�F�b�N
1671     if (message != SSH_MSG_NONE) {
1672     // ���b�Z�[�W�^�C�v���������n���h�����N��
1673     SSHPacketHandler handler = get_handler(pvar, message);
1674    
1675     // for SSH2(yutaka)
1676     if (SSHv2(pvar)) {
1677     // �z���O�����b�Z�[�W�^�C�v�������������A�{�[�g�������B
1678     if (!SSH2_dispatch_enabled_check(message) || handler == NULL) {
1679     char buf[1024];
1680    
1681     _snprintf(buf, sizeof(buf),
1682     "Unexpected SSH2 message(%d) on current stage(%d)", message, handle_message_stage);
1683     notify_fatal_error(pvar, buf);
1684     // abort
1685     }
1686     }
1687    
1688     if (handler == NULL) {
1689     if (SSHv1(pvar)) {
1690     char buf[1024];
1691    
1692     _snprintf(buf, sizeof(buf),
1693     "Unexpected packet type received: %d", message);
1694     buf[sizeof(buf) - 1] = 0;
1695     notify_fatal_error(pvar, buf);
1696     } else {
1697     unsigned char FAR *outmsg =
1698     begin_send_packet(pvar, SSH2_MSG_UNIMPLEMENTED, 4);
1699    
1700     set_uint32(outmsg,
1701     pvar->ssh_state.receiver_sequence_number - 1);
1702     finish_send_packet(pvar);
1703     /* XXX need to decompress incoming packet, but how? */
1704     }
1705     } else {
1706     if (!handler(pvar)) {
1707     deque_handlers(pvar, message);
1708     }
1709     }
1710     }
1711     }
1712    
1713     static BOOL handle_pty_success(PTInstVar pvar)
1714     {
1715     FWD_enter_interactive_mode(pvar);
1716     enque_handler(pvar, SSH_SMSG_EXITSTATUS, handle_exit);
1717     enque_handler(pvar, SSH_SMSG_STDOUT_DATA, handle_data);
1718     enque_handler(pvar, SSH_SMSG_STDERR_DATA, handle_data);
1719     enque_handler(pvar, SSH_MSG_CHANNEL_DATA, handle_channel_data);
1720     enque_handler(pvar, SSH_MSG_CHANNEL_INPUT_EOF,
1721     handle_channel_input_eof);
1722     enque_handler(pvar, SSH_MSG_CHANNEL_OUTPUT_CLOSED,
1723     handle_channel_output_eof);
1724     enque_handler(pvar, SSH_MSG_PORT_OPEN, handle_channel_open);
1725     enque_handler(pvar, SSH_SMSG_X11_OPEN, handle_X11_channel_open);
1726     return FALSE;
1727     }
1728    
1729     static BOOL handle_pty_failure(PTInstVar pvar)
1730     {
1731     notify_nonfatal_error(pvar,
1732     "The server cannot allocate a pseudo-terminal. "
1733     "You may encounter some problems with the terminal.");
1734     return handle_pty_success(pvar);
1735     }
1736    
1737     static void prep_pty(PTInstVar pvar)
1738     {
1739     int len = strlen(pvar->ts->TermType);
1740     unsigned char FAR *outmsg =
1741     begin_send_packet(pvar, SSH_CMSG_REQUEST_PTY,
1742     4 + len + 16 + sizeof(ssh_ttymodes));
1743     static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1744     static const SSHPacketHandler handlers[]
1745     = { handle_pty_success, handle_pty_failure };
1746    
1747     set_uint32(outmsg, len);
1748     memcpy(outmsg + 4, pvar->ts->TermType, len);
1749     set_uint32(outmsg + 4 + len, pvar->ssh_state.win_rows);
1750     set_uint32(outmsg + 4 + len + 4, pvar->ssh_state.win_cols);
1751     set_uint32(outmsg + 4 + len + 8, 0);
1752     set_uint32(outmsg + 4 + len + 12, 0);
1753     memcpy(outmsg + 4 + len + 16, ssh_ttymodes, sizeof(ssh_ttymodes));
1754     finish_send_packet(pvar);
1755    
1756     enque_handlers(pvar, 2, msgs, handlers);
1757    
1758     begin_send_packet(pvar, SSH_CMSG_EXEC_SHELL, 0);
1759     finish_send_packet(pvar);
1760     }
1761    
1762     static void prep_forwarding(PTInstVar pvar)
1763     {
1764     FWD_prep_forwarding(pvar);
1765     prep_pty(pvar);
1766     }
1767    
1768 yutakakn 2834
1769     //
1770     //
1771     // (2005.7.10 yutaka)
1772     static void enable_send_compression(PTInstVar pvar)
1773 yutakakn 2728 {
1774 yutakakn 2834 static int initialize = 0;
1775    
1776     if (initialize) {
1777     deflateEnd(&pvar->ssh_state.compress_stream);
1778     }
1779     initialize = 1;
1780    
1781 yutakakn 2728 pvar->ssh_state.compress_stream.zalloc = NULL;
1782     pvar->ssh_state.compress_stream.zfree = NULL;
1783     pvar->ssh_state.compress_stream.opaque = NULL;
1784     if (deflateInit
1785     (&pvar->ssh_state.compress_stream,
1786     pvar->ssh_state.compression_level) != Z_OK) {
1787     notify_fatal_error(pvar,
1788     "An error occurred while setting up compression.\n"
1789     "The connection will close.");
1790     return;
1791     } else {
1792 yutakakn 2834 // SSH2�������k�E�W�J������SSH1���������s�������A���L�t���O���������������B(2005.7.9 yutaka)
1793     if (SSHv2(pvar)) {
1794     pvar->ssh_state.compressing = FALSE;
1795     } else {
1796     pvar->ssh_state.compressing = TRUE;
1797     }
1798 yutakakn 2728 }
1799 yutakakn 2834 }
1800 yutakakn 2728
1801 yutakakn 2834 static void enable_recv_compression(PTInstVar pvar)
1802     {
1803     static int initialize = 0;
1804    
1805     if (initialize) {
1806     deflateEnd(&pvar->ssh_state.decompress_stream);
1807     }
1808     initialize = 1;
1809    
1810 yutakakn 2728 pvar->ssh_state.decompress_stream.zalloc = NULL;
1811     pvar->ssh_state.decompress_stream.zfree = NULL;
1812     pvar->ssh_state.decompress_stream.opaque = NULL;
1813     if (inflateInit(&pvar->ssh_state.decompress_stream) != Z_OK) {
1814     deflateEnd(&pvar->ssh_state.compress_stream);
1815     notify_fatal_error(pvar,
1816     "An error occurred while setting up compression.\n"
1817     "The connection will close.");
1818     return;
1819     } else {
1820 yutakakn 2834 // SSH2�������k�E�W�J������SSH1���������s�������A���L�t���O���������������B(2005.7.9 yutaka)
1821     if (SSHv2(pvar)) {
1822     pvar->ssh_state.decompressing = FALSE;
1823     } else {
1824     pvar->ssh_state.decompressing = TRUE;
1825     }
1826    
1827 yutakakn 2728 buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf,
1828     &pvar->ssh_state.postdecompress_inbuflen, 1000);
1829     }
1830 yutakakn 2834 }
1831 yutakakn 2833
1832 yutakakn 2834 static void enable_compression(PTInstVar pvar)
1833     {
1834     enable_send_compression(pvar);
1835     enable_recv_compression(pvar);
1836    
1837 yutakakn 2833 // SSH2�������k�E�W�J������SSH1���������s�������A���L�t���O���������������B(2005.7.9 yutaka)
1838     if (SSHv2(pvar)) {
1839     pvar->ssh_state.compressing = FALSE;
1840     pvar->ssh_state.decompressing = FALSE;
1841     }
1842    
1843 yutakakn 2728 }
1844    
1845     static BOOL handle_enable_compression(PTInstVar pvar)
1846     {
1847     enable_compression(pvar);
1848     prep_forwarding(pvar);
1849     return FALSE;
1850     }
1851    
1852     static BOOL handle_disable_compression(PTInstVar pvar)
1853     {
1854     prep_forwarding(pvar);
1855     return FALSE;
1856     }
1857    
1858     static void prep_compression(PTInstVar pvar)
1859     {
1860     if (pvar->session_settings.CompressionLevel > 0) {
1861 yutakakn 2833 // added if statement (2005.7.10 yutaka)
1862     if (SSHv1(pvar)) {
1863     static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1864     static const SSHPacketHandler handlers[]
1865     = { handle_enable_compression, handle_disable_compression };
1866 yutakakn 2728
1867 yutakakn 2833 unsigned char FAR *outmsg =
1868     begin_send_packet(pvar, SSH_CMSG_REQUEST_COMPRESSION, 4);
1869 yutakakn 2728
1870 yutakakn 2833 set_uint32(outmsg, pvar->session_settings.CompressionLevel);
1871     finish_send_packet(pvar);
1872 yutakakn 2728
1873 yutakakn 2833 enque_handlers(pvar, 2, msgs, handlers);
1874     }
1875    
1876 yutakakn 2728 pvar->ssh_state.compression_level =
1877     pvar->session_settings.CompressionLevel;
1878    
1879     } else {
1880 yutakakn 2833 // added if statement (2005.7.10 yutaka)
1881     if (SSHv1(pvar)) {
1882     prep_forwarding(pvar);
1883     }
1884 yutakakn 2728 }
1885     }
1886    
1887     static void enque_simple_auth_handlers(PTInstVar pvar)
1888     {
1889     static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1890     static const SSHPacketHandler handlers[]
1891     = { handle_auth_success, handle_auth_failure };
1892    
1893     enque_handlers(pvar, 2, msgs, handlers);
1894     }
1895    
1896     static BOOL handle_rsa_challenge(PTInstVar pvar)
1897     {
1898     int challenge_bytes;
1899    
1900     if (!grab_payload(pvar, 2)) {
1901     return FALSE;
1902     }
1903    
1904     challenge_bytes = get_mpint_len(pvar, 0);
1905    
1906     if (grab_payload(pvar, challenge_bytes)) {
1907     unsigned char FAR *outmsg =
1908     begin_send_packet(pvar, SSH_CMSG_AUTH_RSA_RESPONSE, 16);
1909    
1910     if (CRYPT_generate_RSA_challenge_response
1911     (pvar, pvar->ssh_state.payload + 2, challenge_bytes, outmsg)) {
1912 yutakakn 2811
1913     // �Z�b�V�������������p�X���[�h���g���������������A�����������\�[�X�������������B
1914     // socket close���������������������������������A���������������B(2005.4.8 yutaka)
1915     #if 0
1916     //AUTH_destroy_cur_cred(pvar);
1917     #endif
1918    
1919 yutakakn 2728 finish_send_packet(pvar);
1920    
1921     enque_simple_auth_handlers(pvar);
1922     } else {
1923     notify_fatal_error(pvar,
1924     "An error occurred while decrypting the RSA challenge.\n"
1925     "Perhaps the key file is corrupted.");
1926     }
1927     }
1928    
1929     return FALSE;
1930     }
1931    
1932     #define OBFUSCATING_ROUND_TO 32
1933    
1934     static int obfuscating_round_up(PTInstVar pvar, int size)
1935     {
1936     return (size + OBFUSCATING_ROUND_TO - 1) & ~(OBFUSCATING_ROUND_TO - 1);
1937     }
1938    
1939     static void try_send_credentials(PTInstVar pvar)
1940     {
1941     if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_CREDENTIALS) == 0) {
1942     AUTHCred FAR *cred = AUTH_get_cur_cred(pvar);
1943     static const int RSA_msgs[] =
1944     { SSH_SMSG_AUTH_RSA_CHALLENGE, SSH_SMSG_FAILURE };
1945     static const SSHPacketHandler RSA_handlers[]
1946     = { handle_rsa_challenge, handle_rsa_auth_refused };
1947     static const int TIS_msgs[] =
1948     { SSH_SMSG_AUTH_TIS_CHALLENGE, SSH_SMSG_FAILURE };
1949     static const SSHPacketHandler TIS_handlers[]
1950     = { handle_TIS_challenge, handle_auth_failure };
1951    
1952 yutakakn 2800 // SSH2���������������������X�L�b�v
1953     if (SSHv2(pvar))
1954     goto skip_ssh2;
1955    
1956 yutakakn 2728 switch (cred->method) {
1957     case SSH_AUTH_NONE:
1958     return;
1959     case SSH_AUTH_PASSWORD:{
1960     int len = strlen(cred->password);
1961     // Round up password length to discourage traffic analysis
1962     int obfuscated_len = obfuscating_round_up(pvar, len);
1963     unsigned char FAR *outmsg =
1964     begin_send_packet(pvar, SSH_CMSG_AUTH_PASSWORD,
1965     4 + obfuscated_len);
1966    
1967     notify_verbose_message(pvar,
1968     "Trying PASSWORD authentication...",
1969     LOG_LEVEL_VERBOSE);
1970    
1971     set_uint32(outmsg, obfuscated_len);
1972     memcpy(outmsg + 4, cred->password, len);
1973     memset(outmsg + 4 + len, 0, obfuscated_len - len);
1974 yutakakn 2811
1975     // �Z�b�V�������������p�X���[�h���g���������������A�����������\�[�X�������������B
1976     // socket close���������������������������������A���������������B(2005.4.8 yutaka)
1977     #if 0
1978     //AUTH_destroy_cur_cred(pvar);
1979     #endif
1980    
1981 yutakakn 2728 enque_simple_auth_handlers(pvar);
1982     break;
1983     }
1984     case SSH_AUTH_RHOSTS:{
1985     int len = strlen(cred->rhosts_client_user);
1986     unsigned char FAR *outmsg =
1987     begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS, 4 + len);
1988    
1989     notify_verbose_message(pvar,
1990     "Trying RHOSTS authentication...",
1991     LOG_LEVEL_VERBOSE);
1992    
1993     set_uint32(outmsg, len);
1994     memcpy(outmsg + 4, cred->rhosts_client_user, len);
1995     AUTH_destroy_cur_cred(pvar);
1996     enque_simple_auth_handlers(pvar);
1997     break;
1998     }
1999     case SSH_AUTH_RSA:{
2000     int len = BN_num_bytes(cred->key_pair->RSA_key->n);
2001     unsigned char FAR *outmsg =
2002     begin_send_packet(pvar, SSH_CMSG_AUTH_RSA, 2 + len);
2003    
2004     notify_verbose_message(pvar,
2005     "Trying RSA authentication...",
2006     LOG_LEVEL_VERBOSE);
2007    
2008     set_ushort16_MSBfirst(outmsg, len * 8);
2009     BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + 2);
2010     /* don't destroy the current credentials yet */
2011     enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
2012     break;
2013     }
2014     case SSH_AUTH_RHOSTS_RSA:{
2015     int mod_len = BN_num_bytes(cred->key_pair->RSA_key->n);
2016     int name_len = strlen(cred->rhosts_client_user);
2017     int exp_len = BN_num_bytes(cred->key_pair->RSA_key->e);
2018     int index;
2019     unsigned char FAR *outmsg =
2020     begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS_RSA,
2021     12 + mod_len + name_len + exp_len);
2022    
2023     notify_verbose_message(pvar,
2024     "Trying RHOSTS+RSA authentication...",
2025     LOG_LEVEL_VERBOSE);
2026    
2027     set_uint32(outmsg, name_len);
2028     memcpy(outmsg + 4, cred->rhosts_client_user, name_len);
2029     index = 4 + name_len;
2030    
2031     set_uint32(outmsg + index, 8 * mod_len);
2032     set_ushort16_MSBfirst(outmsg + index + 4, 8 * exp_len);
2033     BN_bn2bin(cred->key_pair->RSA_key->e, outmsg + index + 6);
2034     index += 6 + exp_len;
2035    
2036     set_ushort16_MSBfirst(outmsg + index, 8 * mod_len);
2037     BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + index + 2);
2038     /* don't destroy the current credentials yet */
2039     enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
2040     break;
2041     }
2042     case SSH_AUTH_TIS:{
2043     if (cred->password == NULL) {
2044     unsigned char FAR *outmsg =
2045     begin_send_packet(pvar, SSH_CMSG_AUTH_TIS, 0);
2046    
2047     notify_verbose_message(pvar,
2048 yutakakn 2800 "Trying TIS authentication...",
2049     LOG_LEVEL_VERBOSE);
2050 yutakakn 2728 enque_handlers(pvar, 2, TIS_msgs, TIS_handlers);
2051     } else {
2052     int len = strlen(cred->password);
2053     int obfuscated_len = obfuscating_round_up(pvar, len);
2054     unsigned char FAR *outmsg =
2055     begin_send_packet(pvar, SSH_CMSG_AUTH_TIS_RESPONSE,
2056 yutakakn 2800 4 + obfuscated_len);
2057 yutakakn 2728
2058     notify_verbose_message(pvar, "Sending TIS response",
2059 yutakakn 2800 LOG_LEVEL_VERBOSE);
2060 yutakakn 2728
2061     set_uint32(outmsg, obfuscated_len);
2062     memcpy(outmsg + 4, cred->password, len);
2063     memset(outmsg + 4 + len, 0, obfuscated_len - len);
2064     enque_simple_auth_handlers(pvar);
2065     }
2066 yutakakn 2800
2067 yutakakn 2728 AUTH_destroy_cur_cred(pvar);
2068     break;
2069     }
2070     default:
2071     notify_fatal_error(pvar,
2072     "Internal error: unsupported authentication method");
2073     return;
2074     }
2075    
2076     finish_send_packet(pvar);
2077 yutakakn 2800
2078     skip_ssh2:;
2079 yutakakn 2728 destroy_packet_buf(pvar);
2080    
2081     pvar->ssh_state.status_flags |= STATUS_DONT_SEND_CREDENTIALS;
2082     }
2083     }
2084    
2085     static void try_send_user_name(PTInstVar pvar)
2086     {
2087     if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_USER_NAME) == 0) {
2088     char FAR *username = AUTH_get_user_name(pvar);
2089    
2090     if (username != NULL) {
2091     int len = strlen(username);
2092     int obfuscated_len = obfuscating_round_up(pvar, len);
2093     unsigned char FAR *outmsg =
2094     begin_send_packet(pvar, SSH_CMSG_USER, 4 + obfuscated_len);
2095     char buf[1024] = "Sending user name: ";
2096     static const int msgs[] =
2097     { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
2098     static const SSHPacketHandler handlers[]
2099     = { handle_noauth_success, handle_auth_required };
2100    
2101     set_uint32(outmsg, obfuscated_len);
2102     memcpy(outmsg + 4, username, len);
2103     memset(outmsg + 4 + len, 0, obfuscated_len - len);
2104     finish_send_packet(pvar);
2105    
2106     pvar->ssh_state.status_flags |= STATUS_DONT_SEND_USER_NAME;
2107    
2108     strncpy(buf + strlen(buf), username,
2109     sizeof(buf) - strlen(buf) - 2);
2110     buf[sizeof(buf) - 1] = 0;
2111     notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
2112    
2113     enque_handlers(pvar, 2, msgs, handlers);
2114     }
2115     }
2116     }
2117    
2118     static void send_session_key(PTInstVar pvar)
2119     {
2120     int encrypted_session_key_len;
2121     unsigned char FAR *outmsg;
2122    
2123     if (SSHv1(pvar)) {
2124     encrypted_session_key_len =
2125     CRYPT_get_encrypted_session_key_len(pvar);
2126     }
2127    
2128     if (!CRYPT_choose_ciphers(pvar))
2129     return;
2130    
2131     if (SSHv1(pvar)) {
2132     outmsg =
2133     begin_send_packet(pvar, SSH_CMSG_SESSION_KEY,
2134     15 + encrypted_session_key_len);
2135     outmsg[0] = (unsigned char) CRYPT_get_sender_cipher(pvar);
2136     memcpy(outmsg + 1, CRYPT_get_server_cookie(pvar), 8); /* antispoofing cookie */
2137     outmsg[9] = (unsigned char) (encrypted_session_key_len >> 5);
2138     outmsg[10] = (unsigned char) (encrypted_session_key_len << 3);
2139     if (!CRYPT_choose_session_key(pvar, outmsg + 11))
2140     return;
2141     set_uint32(outmsg + 11 + encrypted_session_key_len,
2142     SSH_PROTOFLAG_SCREEN_NUMBER |
2143     SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
2144     finish_send_packet(pvar);
2145     }
2146    
2147     if (!CRYPT_start_encryption(pvar, 1, 1))
2148     return;
2149     notify_established_secure_connection(pvar);
2150    
2151     if (SSHv1(pvar)) {
2152     enque_handler(pvar, SSH_SMSG_SUCCESS, handle_crypt_success);
2153     }
2154    
2155     pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_USER_NAME;
2156    
2157     if (SSHv1(pvar)) {
2158     try_send_user_name(pvar);
2159     }
2160     }
2161    
2162     /*************************
2163     END of message handlers
2164     ************************/
2165    
2166     void SSH_init(PTInstVar pvar)
2167     {
2168     int i;
2169    
2170     buf_create(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
2171     buf_create(&pvar->ssh_state.precompress_outbuf,
2172     &pvar->ssh_state.precompress_outbuflen);
2173     buf_create(&pvar->ssh_state.postdecompress_inbuf,
2174     &pvar->ssh_state.postdecompress_inbuflen);
2175     pvar->ssh_state.payload = NULL;
2176     pvar->ssh_state.compressing = FALSE;
2177     pvar->ssh_state.decompressing = FALSE;
2178     pvar->ssh_state.status_flags =
2179     STATUS_DONT_SEND_USER_NAME | STATUS_DONT_SEND_CREDENTIALS;
2180     pvar->ssh_state.payload_datalen = 0;
2181     pvar->ssh_state.hostname = NULL;
2182     pvar->ssh_state.server_ID = NULL;
2183     pvar->ssh_state.receiver_sequence_number = 0;
2184     pvar->ssh_state.sender_sequence_number = 0;
2185     for (i = 0; i < NUM_ELEM(pvar->ssh_state.packet_handlers); i++) {
2186     pvar->ssh_state.packet_handlers[i] = NULL;
2187     }
2188    
2189     // for SSH2(yutaka)
2190     memset(pvar->ssh2_keys, 0, sizeof(pvar->ssh2_keys));
2191     pvar->userauth_success = 0;
2192     pvar->session_nego_status = 0;
2193 yutakakn 2738 pvar->settings.ssh_protocol_version = 2; // SSH2(default)
2194 yutakakn 2728 pvar->rekeying = 0;
2195     pvar->key_done = 0;
2196 yutakakn 2739 pvar->ssh2_autologin = 0; // autologin disabled(default)
2197 yutakakn 2798 pvar->userauth_retry_count = 0;
2198 yutakakn 2833 pvar->decomp_buffer = NULL;
2199 yutakakn 2728
2200     }
2201    
2202     void SSH_open(PTInstVar pvar)
2203     {
2204     pvar->ssh_state.hostname = _strdup(pvar->ts->HostName);
2205     pvar->ssh_state.win_cols = pvar->ts->TerminalWidth;
2206     pvar->ssh_state.win_rows = pvar->ts->TerminalHeight;
2207     }
2208    
2209     void SSH_notify_disconnecting(PTInstVar pvar, char FAR * reason)
2210     {
2211     if (SSHv1(pvar)) {
2212     int len = reason == NULL ? 0 : strlen(reason);
2213     unsigned char FAR *outmsg =
2214     begin_send_packet(pvar, SSH_MSG_DISCONNECT, len + 4);
2215    
2216     set_uint32(outmsg, len);
2217     if (reason != NULL) {
2218     memcpy(outmsg + 4, reason, len);
2219     }
2220     finish_send_packet(pvar);
2221    
2222     } else { // for SSH2(yutaka)
2223     buffer_t *msg;
2224     unsigned char *outmsg;
2225     int len;
2226 yutakakn 2809 Channel_t *c;
2227 yutakakn 2728
2228 yutakakn 2809 c = ssh2_channel_lookup(pvar->shell_id);
2229     if (c == NULL)
2230     return;
2231    
2232 yutakakn 2728 // SSH2 server��channel close���`����
2233     msg = buffer_init();
2234     if (msg == NULL) {
2235     // TODO: error check
2236     return;
2237     }
2238 yutakakn 2809 buffer_put_int(msg, c->remote_id);
2239 yutakakn 2728
2240     len = buffer_len(msg);
2241     outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_CLOSE, len);
2242     memcpy(outmsg, buffer_ptr(msg), len);
2243     finish_send_packet(pvar);
2244     buffer_free(msg);
2245    
2246     }
2247    
2248     }
2249    
2250     void SSH_notify_host_OK(PTInstVar pvar)
2251     {
2252     if ((pvar->ssh_state.status_flags & STATUS_HOST_OK) == 0) {
2253     pvar->ssh_state.status_flags |= STATUS_HOST_OK;
2254     send_session_key(pvar);
2255     }
2256     }
2257    
2258     void SSH_notify_win_size(PTInstVar pvar, int cols, int rows)
2259     {
2260     pvar->ssh_state.win_cols = cols;
2261     pvar->ssh_state.win_rows = rows;
2262    
2263 yutakakn 2771 if (SSHv1(pvar)) {
2264     if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) == handle_data) {
2265     unsigned char FAR *outmsg =
2266     begin_send_packet(pvar, SSH_CMSG_WINDOW_SIZE, 16);
2267 yutakakn 2728
2268 yutakakn 2771 set_uint32(outmsg, rows);
2269     set_uint32(outmsg + 4, cols);
2270     set_uint32(outmsg + 8, 0);
2271     set_uint32(outmsg + 12, 0);
2272     finish_send_packet(pvar);
2273     }
2274    
2275 yutakakn 2777 } else if (SSHv2(pvar)) { // �^�[�~�i���T�C�Y���X���m������ (2005.1.4 yutaka)
2276     // SSH2�����������`�F�b�N���s���B(2005.1.5 yutaka)
2277 yutakakn 2771 buffer_t *msg;
2278     char *s;
2279     unsigned char *outmsg;
2280     int len;
2281 yutakakn 2809 Channel_t *c;
2282 yutakakn 2771
2283 yutakakn 2809 c = ssh2_channel_lookup(pvar->shell_id);
2284     if (c == NULL)
2285     return;
2286    
2287 yutakakn 2771 msg = buffer_init();
2288     if (msg == NULL) {
2289     // TODO: error check
2290     return;
2291     }
2292 yutakakn 2809 buffer_put_int(msg, c->remote_id);
2293 yutakakn 2771 s = "window-change";
2294     buffer_put_string(msg, s, strlen(s));
2295     buffer_put_char(msg, 0); // wantconfirm
2296     buffer_put_int(msg, pvar->ssh_state.win_cols); // columns
2297     buffer_put_int(msg, pvar->ssh_state.win_rows); // lines
2298     buffer_put_int(msg, 480); // XXX:
2299     buffer_put_int(msg, 640); // XXX:
2300     len = buffer_len(msg);
2301     outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len);
2302     memcpy(outmsg, buffer_ptr(msg), len);
2303 yutakakn 2728 finish_send_packet(pvar);
2304 yutakakn 2771 buffer_free(msg);
2305    
2306 yutakakn 2805 notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_REQUEST was sent at SSH_notify_win_size().", LOG_LEVEL_VERBOSE);
2307    
2308 yutakakn 2777 } else {
2309     // SSH�����������������������B
2310    
2311 yutakakn 2728 }
2312 yutakakn 2777
2313 yutakakn 2728 }
2314    
2315     int SSH_get_min_packet_size(PTInstVar pvar)
2316     {
2317     if (SSHv1(pvar)) {
2318     return 12;
2319     } else {
2320     int block_size = CRYPT_get_decryption_block_size(pvar);
2321    
2322     return max(16, block_size);
2323     }
2324     }
2325    
2326     /* data is guaranteed to be at least SSH_get_min_packet_size bytes long
2327     at least 5 bytes must be decrypted */
2328     void SSH_predecrpyt_packet(PTInstVar pvar, char FAR * data)
2329     {
2330     if (SSHv2(pvar)) {
2331     CRYPT_decrypt(pvar, data, get_predecryption_amount(pvar));
2332     }
2333     }
2334    
2335     int SSH_get_clear_MAC_size(PTInstVar pvar)
2336     {
2337     if (SSHv1(pvar)) {
2338     return 0;
2339     } else {
2340     return CRYPT_get_receiver_MAC_size(pvar);
2341     }
2342     }
2343    
2344     void SSH_notify_user_name(PTInstVar pvar)
2345     {
2346     try_send_user_name(pvar);
2347     }
2348    
2349     void SSH_notify_cred(PTInstVar pvar)
2350     {
2351     try_send_credentials(pvar);
2352     }
2353    
2354     void SSH_send(PTInstVar pvar, unsigned char const FAR * buf, int buflen)
2355     {
2356     if (SSHv1(pvar)) {
2357     if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) != handle_data) {
2358     return;
2359     }
2360    
2361     while (buflen > 0) {
2362     int len =
2363     buflen >
2364     SSH_MAX_SEND_PACKET_SIZE ? SSH_MAX_SEND_PACKET_SIZE : buflen;
2365     unsigned char FAR *outmsg =
2366     begin_send_packet(pvar, SSH_CMSG_STDIN_DATA, 4 + len);
2367    
2368     set_uint32(outmsg, len);
2369    
2370     if (pvar->ssh_state.compressing) {
2371     buf_ensure_size(&pvar->ssh_state.outbuf,
2372     &pvar->ssh_state.outbuflen,
2373     len + (len >> 6) + 50);
2374     pvar->ssh_state.compress_stream.next_in =
2375     pvar->ssh_state.precompress_outbuf;
2376     pvar->ssh_state.compress_stream.avail_in = 5;
2377     pvar->ssh_state.compress_stream.next_out =
2378     pvar->ssh_state.outbuf + 12;
2379     pvar->ssh_state.compress_stream.avail_out =
2380     pvar->ssh_state.outbuflen - 12;
2381    
2382     if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) !=
2383     Z_OK) {
2384     notify_fatal_error(pvar, "Error compressing packet data");
2385     return;
2386     }
2387    
2388     pvar->ssh_state.compress_stream.next_in =
2389     (unsigned char FAR *) buf;
2390     pvar->ssh_state.compress_stream.avail_in = len;
2391    
2392     if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2393     Z_OK) {
2394     notify_fatal_error(pvar, "Error compressing packet data");
2395     return;
2396     }
2397     } else {
2398     memcpy(outmsg + 4, buf, len);
2399     }
2400    
2401     finish_send_packet_special(pvar, 1);
2402    
2403     buflen -= len;
2404     buf += len;
2405     }
2406    
2407     } else { // for SSH2(yutaka)
2408     buffer_t *msg;
2409     unsigned char *outmsg;
2410     int len;
2411 yutakakn 2809 Channel_t *c;
2412 yutakakn 2728
2413 yutakakn 2823 // SSH2���������������A�p�P�b�g���������B(2005.6.19 yutaka)
2414     if (pvar->rekeying) {
2415     // TODO: ���z���������p�P�b�g�j�����������A�p�P�b�g���������x���������������������A
2416     // �������������������B
2417     c = NULL;
2418    
2419     return;
2420     }
2421    
2422 yutakakn 2809 c = ssh2_channel_lookup(pvar->shell_id);
2423     if (c == NULL)
2424     return;
2425    
2426 yutakakn 2728 msg = buffer_init();
2427     if (msg == NULL) {
2428     // TODO: error check
2429     return;
2430     }
2431 yutakakn 2809 buffer_put_int(msg, c->remote_id);
2432 yutakakn 2728 buffer_put_string(msg, (char *)buf, buflen);
2433    
2434     len = buffer_len(msg);
2435     outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_DATA, len);
2436     memcpy(outmsg, buffer_ptr(msg), len);
2437     finish_send_packet(pvar);
2438     buffer_free(msg);
2439    
2440     // remote window size������
2441 yutakakn 2809 c->remote_window -= len;
2442 yutakakn 2728
2443     }
2444    
2445     }
2446    
2447     int SSH_extract_payload(PTInstVar pvar, unsigned char FAR * dest, int len)
2448     {
2449     int num_bytes = pvar->ssh_state.payload_datalen;
2450    
2451     if (num_bytes > len) {
2452     num_bytes = len;
2453     }
2454    
2455     if (!pvar->ssh_state.decompressing) {
2456     memcpy(dest,
2457     pvar->ssh_state.payload + pvar->ssh_state.payload_datastart,
2458     num_bytes);
2459     pvar->ssh_state.payload_datastart += num_bytes;
2460     } else if (num_bytes > 0) {
2461     pvar->ssh_state.decompress_stream.next_out = dest;
2462     pvar->ssh_state.decompress_stream.avail_out = num_bytes;
2463    
2464     if (inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH) !=
2465     Z_OK) {
2466     notify_fatal_error(pvar,
2467     "Invalid compressed data in received packet");
2468     return 0;
2469     }
2470     }
2471    
2472     pvar->ssh_state.payload_datalen -= num_bytes;
2473    
2474     return num_bytes;
2475     }
2476    
2477     void SSH_get_compression_info(PTInstVar pvar, char FAR * dest, int len)
2478     {
2479     char buf[1024];
2480     char buf2[1024];
2481    
2482 yutakakn 2833 // added support of SSH2 packet compression (2005.7.10 yutaka)
2483     if (pvar->ssh_state.compressing || pvar->ctos_compression) {
2484 yutakakn 2728 unsigned long total_in = pvar->ssh_state.compress_stream.total_in;
2485     unsigned long total_out =
2486     pvar->ssh_state.compress_stream.total_out;
2487    
2488     if (total_out > 0) {
2489     _snprintf(buf, sizeof(buf), "level %d; ratio %.1f (%ld:%ld)",
2490     pvar->ssh_state.compression_level,
2491     ((double) total_in) / total_out, total_in,
2492     total_out);
2493     } else {
2494     _snprintf(buf, sizeof(buf), "level %d",
2495     pvar->ssh_state.compression_level);
2496     }
2497     } else {
2498     strcpy(buf, "none");
2499     }
2500     buf[sizeof(buf) - 1] = 0;
2501    
2502 yutakakn 2833 if (pvar->ssh_state.decompressing || pvar->stoc_compression) {
2503 yutakakn 2728 unsigned long total_in =
2504     pvar->ssh_state.decompress_stream.total_in;
2505     unsigned long total_out =
2506     pvar->ssh_state.decompress_stream.total_out;
2507    
2508     if (total_in > 0) {
2509     _snprintf(buf2, sizeof(buf2), "level %d; ratio %.1f (%ld:%ld)",
2510     pvar->ssh_state.compression_level,
2511     ((double) total_out) / total_in, total_out,
2512     total_in);
2513     } else {
2514     _snprintf(buf2, sizeof(buf2), "level %d",
2515     pvar->ssh_state.compression_level);
2516     }
2517     } else {
2518     strcpy(buf2, "none");
2519     }
2520     buf2[sizeof(buf2) - 1] = 0;
2521    
2522     _snprintf(dest, len, "Upstream %s; Downstream %s", buf, buf2);
2523     dest[len - 1] = 0;
2524     }