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 2833 - (hide annotations) (download) (as text)
Sat Jul 9 17:08:47 2005 UTC (18 years, 9 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 166404 byte(s)
SSH2 packet compressionをサポートした。

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     static void enable_compression(PTInstVar pvar)
1769     {
1770     pvar->ssh_state.compress_stream.zalloc = NULL;
1771     pvar->ssh_state.compress_stream.zfree = NULL;
1772     pvar->ssh_state.compress_stream.opaque = NULL;
1773     if (deflateInit
1774     (&pvar->ssh_state.compress_stream,
1775     pvar->ssh_state.compression_level) != Z_OK) {
1776     notify_fatal_error(pvar,
1777     "An error occurred while setting up compression.\n"
1778     "The connection will close.");
1779     return;
1780     } else {
1781     pvar->ssh_state.compressing = TRUE;
1782     }
1783    
1784     pvar->ssh_state.decompress_stream.zalloc = NULL;
1785     pvar->ssh_state.decompress_stream.zfree = NULL;
1786     pvar->ssh_state.decompress_stream.opaque = NULL;
1787     if (inflateInit(&pvar->ssh_state.decompress_stream) != Z_OK) {
1788     deflateEnd(&pvar->ssh_state.compress_stream);
1789     notify_fatal_error(pvar,
1790     "An error occurred while setting up compression.\n"
1791     "The connection will close.");
1792     return;
1793     } else {
1794     pvar->ssh_state.decompressing = TRUE;
1795     buf_ensure_size(&pvar->ssh_state.postdecompress_inbuf,
1796     &pvar->ssh_state.postdecompress_inbuflen, 1000);
1797     }
1798 yutakakn 2833
1799     // SSH2�������k�E�W�J������SSH1���������s�������A���L�t���O���������������B(2005.7.9 yutaka)
1800     if (SSHv2(pvar)) {
1801     pvar->ssh_state.compressing = FALSE;
1802     pvar->ssh_state.decompressing = FALSE;
1803     }
1804    
1805 yutakakn 2728 }
1806    
1807     static BOOL handle_enable_compression(PTInstVar pvar)
1808     {
1809     enable_compression(pvar);
1810     prep_forwarding(pvar);
1811     return FALSE;
1812     }
1813    
1814     static BOOL handle_disable_compression(PTInstVar pvar)
1815     {
1816     prep_forwarding(pvar);
1817     return FALSE;
1818     }
1819    
1820     static void prep_compression(PTInstVar pvar)
1821     {
1822     if (pvar->session_settings.CompressionLevel > 0) {
1823 yutakakn 2833 // added if statement (2005.7.10 yutaka)
1824     if (SSHv1(pvar)) {
1825     static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1826     static const SSHPacketHandler handlers[]
1827     = { handle_enable_compression, handle_disable_compression };
1828 yutakakn 2728
1829 yutakakn 2833 unsigned char FAR *outmsg =
1830     begin_send_packet(pvar, SSH_CMSG_REQUEST_COMPRESSION, 4);
1831 yutakakn 2728
1832 yutakakn 2833 set_uint32(outmsg, pvar->session_settings.CompressionLevel);
1833     finish_send_packet(pvar);
1834 yutakakn 2728
1835 yutakakn 2833 enque_handlers(pvar, 2, msgs, handlers);
1836     }
1837    
1838 yutakakn 2728 pvar->ssh_state.compression_level =
1839     pvar->session_settings.CompressionLevel;
1840    
1841     } else {
1842 yutakakn 2833 // added if statement (2005.7.10 yutaka)
1843     if (SSHv1(pvar)) {
1844     prep_forwarding(pvar);
1845     }
1846 yutakakn 2728 }
1847     }
1848    
1849     static void enque_simple_auth_handlers(PTInstVar pvar)
1850     {
1851     static const int msgs[] = { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
1852     static const SSHPacketHandler handlers[]
1853     = { handle_auth_success, handle_auth_failure };
1854    
1855     enque_handlers(pvar, 2, msgs, handlers);
1856     }
1857    
1858     static BOOL handle_rsa_challenge(PTInstVar pvar)
1859     {
1860     int challenge_bytes;
1861    
1862     if (!grab_payload(pvar, 2)) {
1863     return FALSE;
1864     }
1865    
1866     challenge_bytes = get_mpint_len(pvar, 0);
1867    
1868     if (grab_payload(pvar, challenge_bytes)) {
1869     unsigned char FAR *outmsg =
1870     begin_send_packet(pvar, SSH_CMSG_AUTH_RSA_RESPONSE, 16);
1871    
1872     if (CRYPT_generate_RSA_challenge_response
1873     (pvar, pvar->ssh_state.payload + 2, challenge_bytes, outmsg)) {
1874 yutakakn 2811
1875     // �Z�b�V�������������p�X���[�h���g���������������A�����������\�[�X�������������B
1876     // socket close���������������������������������A���������������B(2005.4.8 yutaka)
1877     #if 0
1878     //AUTH_destroy_cur_cred(pvar);
1879     #endif
1880    
1881 yutakakn 2728 finish_send_packet(pvar);
1882    
1883     enque_simple_auth_handlers(pvar);
1884     } else {
1885     notify_fatal_error(pvar,
1886     "An error occurred while decrypting the RSA challenge.\n"
1887     "Perhaps the key file is corrupted.");
1888     }
1889     }
1890    
1891     return FALSE;
1892     }
1893    
1894     #define OBFUSCATING_ROUND_TO 32
1895    
1896     static int obfuscating_round_up(PTInstVar pvar, int size)
1897     {
1898     return (size + OBFUSCATING_ROUND_TO - 1) & ~(OBFUSCATING_ROUND_TO - 1);
1899     }
1900    
1901     static void try_send_credentials(PTInstVar pvar)
1902     {
1903     if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_CREDENTIALS) == 0) {
1904     AUTHCred FAR *cred = AUTH_get_cur_cred(pvar);
1905     static const int RSA_msgs[] =
1906     { SSH_SMSG_AUTH_RSA_CHALLENGE, SSH_SMSG_FAILURE };
1907     static const SSHPacketHandler RSA_handlers[]
1908     = { handle_rsa_challenge, handle_rsa_auth_refused };
1909     static const int TIS_msgs[] =
1910     { SSH_SMSG_AUTH_TIS_CHALLENGE, SSH_SMSG_FAILURE };
1911     static const SSHPacketHandler TIS_handlers[]
1912     = { handle_TIS_challenge, handle_auth_failure };
1913    
1914 yutakakn 2800 // SSH2���������������������X�L�b�v
1915     if (SSHv2(pvar))
1916     goto skip_ssh2;
1917    
1918 yutakakn 2728 switch (cred->method) {
1919     case SSH_AUTH_NONE:
1920     return;
1921     case SSH_AUTH_PASSWORD:{
1922     int len = strlen(cred->password);
1923     // Round up password length to discourage traffic analysis
1924     int obfuscated_len = obfuscating_round_up(pvar, len);
1925     unsigned char FAR *outmsg =
1926     begin_send_packet(pvar, SSH_CMSG_AUTH_PASSWORD,
1927     4 + obfuscated_len);
1928    
1929     notify_verbose_message(pvar,
1930     "Trying PASSWORD authentication...",
1931     LOG_LEVEL_VERBOSE);
1932    
1933     set_uint32(outmsg, obfuscated_len);
1934     memcpy(outmsg + 4, cred->password, len);
1935     memset(outmsg + 4 + len, 0, obfuscated_len - len);
1936 yutakakn 2811
1937     // �Z�b�V�������������p�X���[�h���g���������������A�����������\�[�X�������������B
1938     // socket close���������������������������������A���������������B(2005.4.8 yutaka)
1939     #if 0
1940     //AUTH_destroy_cur_cred(pvar);
1941     #endif
1942    
1943 yutakakn 2728 enque_simple_auth_handlers(pvar);
1944     break;
1945     }
1946     case SSH_AUTH_RHOSTS:{
1947     int len = strlen(cred->rhosts_client_user);
1948     unsigned char FAR *outmsg =
1949     begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS, 4 + len);
1950    
1951     notify_verbose_message(pvar,
1952     "Trying RHOSTS authentication...",
1953     LOG_LEVEL_VERBOSE);
1954    
1955     set_uint32(outmsg, len);
1956     memcpy(outmsg + 4, cred->rhosts_client_user, len);
1957     AUTH_destroy_cur_cred(pvar);
1958     enque_simple_auth_handlers(pvar);
1959     break;
1960     }
1961     case SSH_AUTH_RSA:{
1962     int len = BN_num_bytes(cred->key_pair->RSA_key->n);
1963     unsigned char FAR *outmsg =
1964     begin_send_packet(pvar, SSH_CMSG_AUTH_RSA, 2 + len);
1965    
1966     notify_verbose_message(pvar,
1967     "Trying RSA authentication...",
1968     LOG_LEVEL_VERBOSE);
1969    
1970     set_ushort16_MSBfirst(outmsg, len * 8);
1971     BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + 2);
1972     /* don't destroy the current credentials yet */
1973     enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
1974     break;
1975     }
1976     case SSH_AUTH_RHOSTS_RSA:{
1977     int mod_len = BN_num_bytes(cred->key_pair->RSA_key->n);
1978     int name_len = strlen(cred->rhosts_client_user);
1979     int exp_len = BN_num_bytes(cred->key_pair->RSA_key->e);
1980     int index;
1981     unsigned char FAR *outmsg =
1982     begin_send_packet(pvar, SSH_CMSG_AUTH_RHOSTS_RSA,
1983     12 + mod_len + name_len + exp_len);
1984    
1985     notify_verbose_message(pvar,
1986     "Trying RHOSTS+RSA authentication...",
1987     LOG_LEVEL_VERBOSE);
1988    
1989     set_uint32(outmsg, name_len);
1990     memcpy(outmsg + 4, cred->rhosts_client_user, name_len);
1991     index = 4 + name_len;
1992    
1993     set_uint32(outmsg + index, 8 * mod_len);
1994     set_ushort16_MSBfirst(outmsg + index + 4, 8 * exp_len);
1995     BN_bn2bin(cred->key_pair->RSA_key->e, outmsg + index + 6);
1996     index += 6 + exp_len;
1997    
1998     set_ushort16_MSBfirst(outmsg + index, 8 * mod_len);
1999     BN_bn2bin(cred->key_pair->RSA_key->n, outmsg + index + 2);
2000     /* don't destroy the current credentials yet */
2001     enque_handlers(pvar, 2, RSA_msgs, RSA_handlers);
2002     break;
2003     }
2004     case SSH_AUTH_TIS:{
2005     if (cred->password == NULL) {
2006     unsigned char FAR *outmsg =
2007     begin_send_packet(pvar, SSH_CMSG_AUTH_TIS, 0);
2008    
2009     notify_verbose_message(pvar,
2010 yutakakn 2800 "Trying TIS authentication...",
2011     LOG_LEVEL_VERBOSE);
2012 yutakakn 2728 enque_handlers(pvar, 2, TIS_msgs, TIS_handlers);
2013     } else {
2014     int len = strlen(cred->password);
2015     int obfuscated_len = obfuscating_round_up(pvar, len);
2016     unsigned char FAR *outmsg =
2017     begin_send_packet(pvar, SSH_CMSG_AUTH_TIS_RESPONSE,
2018 yutakakn 2800 4 + obfuscated_len);
2019 yutakakn 2728
2020     notify_verbose_message(pvar, "Sending TIS response",
2021 yutakakn 2800 LOG_LEVEL_VERBOSE);
2022 yutakakn 2728
2023     set_uint32(outmsg, obfuscated_len);
2024     memcpy(outmsg + 4, cred->password, len);
2025     memset(outmsg + 4 + len, 0, obfuscated_len - len);
2026     enque_simple_auth_handlers(pvar);
2027     }
2028 yutakakn 2800
2029 yutakakn 2728 AUTH_destroy_cur_cred(pvar);
2030     break;
2031     }
2032     default:
2033     notify_fatal_error(pvar,
2034     "Internal error: unsupported authentication method");
2035     return;
2036     }
2037    
2038     finish_send_packet(pvar);
2039 yutakakn 2800
2040     skip_ssh2:;
2041 yutakakn 2728 destroy_packet_buf(pvar);
2042    
2043     pvar->ssh_state.status_flags |= STATUS_DONT_SEND_CREDENTIALS;
2044     }
2045     }
2046    
2047     static void try_send_user_name(PTInstVar pvar)
2048     {
2049     if ((pvar->ssh_state.status_flags & STATUS_DONT_SEND_USER_NAME) == 0) {
2050     char FAR *username = AUTH_get_user_name(pvar);
2051    
2052     if (username != NULL) {
2053     int len = strlen(username);
2054     int obfuscated_len = obfuscating_round_up(pvar, len);
2055     unsigned char FAR *outmsg =
2056     begin_send_packet(pvar, SSH_CMSG_USER, 4 + obfuscated_len);
2057     char buf[1024] = "Sending user name: ";
2058     static const int msgs[] =
2059     { SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE };
2060     static const SSHPacketHandler handlers[]
2061     = { handle_noauth_success, handle_auth_required };
2062    
2063     set_uint32(outmsg, obfuscated_len);
2064     memcpy(outmsg + 4, username, len);
2065     memset(outmsg + 4 + len, 0, obfuscated_len - len);
2066     finish_send_packet(pvar);
2067    
2068     pvar->ssh_state.status_flags |= STATUS_DONT_SEND_USER_NAME;
2069    
2070     strncpy(buf + strlen(buf), username,
2071     sizeof(buf) - strlen(buf) - 2);
2072     buf[sizeof(buf) - 1] = 0;
2073     notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
2074    
2075     enque_handlers(pvar, 2, msgs, handlers);
2076     }
2077     }
2078     }
2079    
2080     static void send_session_key(PTInstVar pvar)
2081     {
2082     int encrypted_session_key_len;
2083     unsigned char FAR *outmsg;
2084    
2085     if (SSHv1(pvar)) {
2086     encrypted_session_key_len =
2087     CRYPT_get_encrypted_session_key_len(pvar);
2088     }
2089    
2090     if (!CRYPT_choose_ciphers(pvar))
2091     return;
2092    
2093     if (SSHv1(pvar)) {
2094     outmsg =
2095     begin_send_packet(pvar, SSH_CMSG_SESSION_KEY,
2096     15 + encrypted_session_key_len);
2097     outmsg[0] = (unsigned char) CRYPT_get_sender_cipher(pvar);
2098     memcpy(outmsg + 1, CRYPT_get_server_cookie(pvar), 8); /* antispoofing cookie */
2099     outmsg[9] = (unsigned char) (encrypted_session_key_len >> 5);
2100     outmsg[10] = (unsigned char) (encrypted_session_key_len << 3);
2101     if (!CRYPT_choose_session_key(pvar, outmsg + 11))
2102     return;
2103     set_uint32(outmsg + 11 + encrypted_session_key_len,
2104     SSH_PROTOFLAG_SCREEN_NUMBER |
2105     SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
2106     finish_send_packet(pvar);
2107     }
2108    
2109     if (!CRYPT_start_encryption(pvar, 1, 1))
2110     return;
2111     notify_established_secure_connection(pvar);
2112    
2113     if (SSHv1(pvar)) {
2114     enque_handler(pvar, SSH_SMSG_SUCCESS, handle_crypt_success);
2115     }
2116    
2117     pvar->ssh_state.status_flags &= ~STATUS_DONT_SEND_USER_NAME;
2118    
2119     if (SSHv1(pvar)) {
2120     try_send_user_name(pvar);
2121     }
2122     }
2123    
2124     /*************************
2125     END of message handlers
2126     ************************/
2127    
2128     void SSH_init(PTInstVar pvar)
2129     {
2130     int i;
2131    
2132     buf_create(&pvar->ssh_state.outbuf, &pvar->ssh_state.outbuflen);
2133     buf_create(&pvar->ssh_state.precompress_outbuf,
2134     &pvar->ssh_state.precompress_outbuflen);
2135     buf_create(&pvar->ssh_state.postdecompress_inbuf,
2136     &pvar->ssh_state.postdecompress_inbuflen);
2137     pvar->ssh_state.payload = NULL;
2138     pvar->ssh_state.compressing = FALSE;
2139     pvar->ssh_state.decompressing = FALSE;
2140     pvar->ssh_state.status_flags =
2141     STATUS_DONT_SEND_USER_NAME | STATUS_DONT_SEND_CREDENTIALS;
2142     pvar->ssh_state.payload_datalen = 0;
2143     pvar->ssh_state.hostname = NULL;
2144     pvar->ssh_state.server_ID = NULL;
2145     pvar->ssh_state.receiver_sequence_number = 0;
2146     pvar->ssh_state.sender_sequence_number = 0;
2147     for (i = 0; i < NUM_ELEM(pvar->ssh_state.packet_handlers); i++) {
2148     pvar->ssh_state.packet_handlers[i] = NULL;
2149     }
2150    
2151     // for SSH2(yutaka)
2152     memset(pvar->ssh2_keys, 0, sizeof(pvar->ssh2_keys));
2153     pvar->userauth_success = 0;
2154     pvar->session_nego_status = 0;
2155 yutakakn 2738 pvar->settings.ssh_protocol_version = 2; // SSH2(default)
2156 yutakakn 2728 pvar->rekeying = 0;
2157     pvar->key_done = 0;
2158 yutakakn 2739 pvar->ssh2_autologin = 0; // autologin disabled(default)
2159 yutakakn 2798 pvar->userauth_retry_count = 0;
2160 yutakakn 2833 pvar->decomp_buffer = NULL;
2161 yutakakn 2728
2162     }
2163    
2164     void SSH_open(PTInstVar pvar)
2165     {
2166     pvar->ssh_state.hostname = _strdup(pvar->ts->HostName);
2167     pvar->ssh_state.win_cols = pvar->ts->TerminalWidth;
2168     pvar->ssh_state.win_rows = pvar->ts->TerminalHeight;
2169     }
2170    
2171     void SSH_notify_disconnecting(PTInstVar pvar, char FAR * reason)
2172     {
2173     if (SSHv1(pvar)) {
2174     int len = reason == NULL ? 0 : strlen(reason);
2175     unsigned char FAR *outmsg =
2176     begin_send_packet(pvar, SSH_MSG_DISCONNECT, len + 4);
2177    
2178     set_uint32(outmsg, len);
2179     if (reason != NULL) {
2180     memcpy(outmsg + 4, reason, len);
2181     }
2182     finish_send_packet(pvar);
2183    
2184     } else { // for SSH2(yutaka)
2185     buffer_t *msg;
2186     unsigned char *outmsg;
2187     int len;
2188 yutakakn 2809 Channel_t *c;
2189 yutakakn 2728
2190 yutakakn 2809 c = ssh2_channel_lookup(pvar->shell_id);
2191     if (c == NULL)
2192     return;
2193    
2194 yutakakn 2728 // SSH2 server��channel close���`����
2195     msg = buffer_init();
2196     if (msg == NULL) {
2197     // TODO: error check
2198     return;
2199     }
2200 yutakakn 2809 buffer_put_int(msg, c->remote_id);
2201 yutakakn 2728
2202     len = buffer_len(msg);
2203     outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_CLOSE, len);
2204     memcpy(outmsg, buffer_ptr(msg), len);
2205     finish_send_packet(pvar);
2206     buffer_free(msg);
2207    
2208     }
2209    
2210     }
2211    
2212     void SSH_notify_host_OK(PTInstVar pvar)
2213     {
2214     if ((pvar->ssh_state.status_flags & STATUS_HOST_OK) == 0) {
2215     pvar->ssh_state.status_flags |= STATUS_HOST_OK;
2216     send_session_key(pvar);
2217     }
2218     }
2219    
2220     void SSH_notify_win_size(PTInstVar pvar, int cols, int rows)
2221     {
2222     pvar->ssh_state.win_cols = cols;
2223     pvar->ssh_state.win_rows = rows;
2224    
2225 yutakakn 2771 if (SSHv1(pvar)) {
2226     if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) == handle_data) {
2227     unsigned char FAR *outmsg =
2228     begin_send_packet(pvar, SSH_CMSG_WINDOW_SIZE, 16);
2229 yutakakn 2728
2230 yutakakn 2771 set_uint32(outmsg, rows);
2231     set_uint32(outmsg + 4, cols);
2232     set_uint32(outmsg + 8, 0);
2233     set_uint32(outmsg + 12, 0);
2234     finish_send_packet(pvar);
2235     }
2236    
2237 yutakakn 2777 } else if (SSHv2(pvar)) { // �^�[�~�i���T�C�Y���X���m������ (2005.1.4 yutaka)
2238     // SSH2�����������`�F�b�N���s���B(2005.1.5 yutaka)
2239 yutakakn 2771 buffer_t *msg;
2240     char *s;
2241     unsigned char *outmsg;
2242     int len;
2243 yutakakn 2809 Channel_t *c;
2244 yutakakn 2771
2245 yutakakn 2809 c = ssh2_channel_lookup(pvar->shell_id);
2246     if (c == NULL)
2247     return;
2248    
2249 yutakakn 2771 msg = buffer_init();
2250     if (msg == NULL) {
2251     // TODO: error check
2252     return;
2253     }
2254 yutakakn 2809 buffer_put_int(msg, c->remote_id);
2255 yutakakn 2771 s = "window-change";
2256     buffer_put_string(msg, s, strlen(s));
2257     buffer_put_char(msg, 0); // wantconfirm
2258     buffer_put_int(msg, pvar->ssh_state.win_cols); // columns
2259     buffer_put_int(msg, pvar->ssh_state.win_rows); // lines
2260     buffer_put_int(msg, 480); // XXX:
2261     buffer_put_int(msg, 640); // XXX:
2262     len = buffer_len(msg);
2263     outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_REQUEST, len);
2264     memcpy(outmsg, buffer_ptr(msg), len);
2265 yutakakn 2728 finish_send_packet(pvar);
2266 yutakakn 2771 buffer_free(msg);
2267    
2268 yutakakn 2805 notify_verbose_message(pvar, "SSH2_MSG_CHANNEL_REQUEST was sent at SSH_notify_win_size().", LOG_LEVEL_VERBOSE);
2269    
2270 yutakakn 2777 } else {
2271     // SSH�����������������������B
2272    
2273 yutakakn 2728 }
2274 yutakakn 2777
2275 yutakakn 2728 }
2276    
2277     int SSH_get_min_packet_size(PTInstVar pvar)
2278     {
2279     if (SSHv1(pvar)) {
2280     return 12;
2281     } else {
2282     int block_size = CRYPT_get_decryption_block_size(pvar);
2283    
2284     return max(16, block_size);
2285     }
2286     }
2287    
2288     /* data is guaranteed to be at least SSH_get_min_packet_size bytes long
2289     at least 5 bytes must be decrypted */
2290     void SSH_predecrpyt_packet(PTInstVar pvar, char FAR * data)
2291     {
2292     if (SSHv2(pvar)) {
2293     CRYPT_decrypt(pvar, data, get_predecryption_amount(pvar));
2294     }
2295     }
2296    
2297     int SSH_get_clear_MAC_size(PTInstVar pvar)
2298     {
2299     if (SSHv1(pvar)) {
2300     return 0;
2301     } else {
2302     return CRYPT_get_receiver_MAC_size(pvar);
2303     }
2304     }
2305    
2306     void SSH_notify_user_name(PTInstVar pvar)
2307     {
2308     try_send_user_name(pvar);
2309     }
2310    
2311     void SSH_notify_cred(PTInstVar pvar)
2312     {
2313     try_send_credentials(pvar);
2314     }
2315    
2316     void SSH_send(PTInstVar pvar, unsigned char const FAR * buf, int buflen)
2317     {
2318     if (SSHv1(pvar)) {
2319     if (get_handler(pvar, SSH_SMSG_STDOUT_DATA) != handle_data) {
2320     return;
2321     }
2322    
2323     while (buflen > 0) {
2324     int len =
2325     buflen >
2326     SSH_MAX_SEND_PACKET_SIZE ? SSH_MAX_SEND_PACKET_SIZE : buflen;
2327     unsigned char FAR *outmsg =
2328     begin_send_packet(pvar, SSH_CMSG_STDIN_DATA, 4 + len);
2329    
2330     set_uint32(outmsg, len);
2331    
2332     if (pvar->ssh_state.compressing) {
2333     buf_ensure_size(&pvar->ssh_state.outbuf,
2334     &pvar->ssh_state.outbuflen,
2335     len + (len >> 6) + 50);
2336     pvar->ssh_state.compress_stream.next_in =
2337     pvar->ssh_state.precompress_outbuf;
2338     pvar->ssh_state.compress_stream.avail_in = 5;
2339     pvar->ssh_state.compress_stream.next_out =
2340     pvar->ssh_state.outbuf + 12;
2341     pvar->ssh_state.compress_stream.avail_out =
2342     pvar->ssh_state.outbuflen - 12;
2343    
2344     if (deflate(&pvar->ssh_state.compress_stream, Z_NO_FLUSH) !=
2345     Z_OK) {
2346     notify_fatal_error(pvar, "Error compressing packet data");
2347     return;
2348     }
2349    
2350     pvar->ssh_state.compress_stream.next_in =
2351     (unsigned char FAR *) buf;
2352     pvar->ssh_state.compress_stream.avail_in = len;
2353    
2354     if (deflate(&pvar->ssh_state.compress_stream, Z_SYNC_FLUSH) !=
2355     Z_OK) {
2356     notify_fatal_error(pvar, "Error compressing packet data");
2357     return;
2358     }
2359     } else {
2360     memcpy(outmsg + 4, buf, len);
2361     }
2362    
2363     finish_send_packet_special(pvar, 1);
2364    
2365     buflen -= len;
2366     buf += len;
2367     }
2368    
2369     } else { // for SSH2(yutaka)
2370     buffer_t *msg;
2371     unsigned char *outmsg;
2372     int len;
2373 yutakakn 2809 Channel_t *c;
2374 yutakakn 2728
2375 yutakakn 2823 // SSH2���������������A�p�P�b�g���������B(2005.6.19 yutaka)
2376     if (pvar->rekeying) {
2377     // TODO: ���z���������p�P�b�g�j�����������A�p�P�b�g���������x���������������������A
2378     // �������������������B
2379     c = NULL;
2380    
2381     return;
2382     }
2383    
2384 yutakakn 2809 c = ssh2_channel_lookup(pvar->shell_id);
2385     if (c == NULL)
2386     return;
2387    
2388 yutakakn 2728 msg = buffer_init();
2389     if (msg == NULL) {
2390     // TODO: error check
2391     return;
2392     }
2393 yutakakn 2809 buffer_put_int(msg, c->remote_id);
2394 yutakakn 2728 buffer_put_string(msg, (char *)buf, buflen);
2395    
2396     len = buffer_len(msg);
2397     outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_DATA, len);
2398     memcpy(outmsg, buffer_ptr(msg), len);
2399     finish_send_packet(pvar);
2400     buffer_free(msg);
2401    
2402     // remote window size������
2403 yutakakn 2809 c->remote_window -= len;
2404 yutakakn 2728
2405     }
2406    
2407     }
2408    
2409     int SSH_extract_payload(PTInstVar pvar, unsigned char FAR * dest, int len)
2410     {
2411     int num_bytes = pvar->ssh_state.payload_datalen;
2412    
2413     if (num_bytes > len) {
2414     num_bytes = len;
2415     }
2416    
2417     if (!pvar->ssh_state.decompressing) {
2418     memcpy(dest,
2419     pvar->ssh_state.payload + pvar->ssh_state.payload_datastart,
2420     num_bytes);
2421     pvar->ssh_state.payload_datastart += num_bytes;
2422     } else if (num_bytes > 0) {
2423     pvar->ssh_state.decompress_stream.next_out = dest;
2424     pvar->ssh_state.decompress_stream.avail_out = num_bytes;
2425    
2426     if (inflate(&pvar->ssh_state.decompress_stream, Z_SYNC_FLUSH) !=
2427     Z_OK) {
2428     notify_fatal_error(pvar,
2429     "Invalid compressed data in received packet");
2430     return 0;
2431     }
2432     }
2433    
2434     pvar->ssh_state.payload_datalen -= num_bytes;
2435    
2436     return num_bytes;
2437     }
2438    
2439     void SSH_get_compression_info(PTInstVar pvar, char FAR * dest, int len)
2440     {
2441     char buf[1024];
2442     char buf2[1024];
2443    
2444 yutakakn 2833 // added support of SSH2 packet compression (2005.7.10 yutaka)
2445     if (pvar->ssh_state.compressing || pvar->ctos_compression) {
2446 yutakakn 2728 unsigned long total_in = pvar->ssh_state.compress_stream.total_in;
2447     unsigned long total_out =
2448     pvar->ssh_state.compress_stream.total_out;
2449    
2450     if (total_out > 0) {
2451     _snprintf(buf, sizeof(buf), "level %d; ratio %.1f (%ld:%ld)",
2452     pvar->ssh_state.compression_level,
2453     ((double) total_in) / total_out, total_in,
2454     total_out);
2455     } else {
2456     _snprintf(buf, sizeof(buf), "level %d",
2457     pvar->ssh_state.compression_level);
2458     }
2459     } else {
2460     strcpy(buf, "none");
2461     }
2462     buf[sizeof(buf) - 1] = 0;
2463    
2464 yutakakn 2833 if (pvar->ssh_state.decompressing || pvar->stoc_compression) {
2465 yutakakn 2728 unsigned long total_in =
2466     pvar->ssh_state.decompress_stream.total_in;
2467     unsigned long total_out =
2468     pvar->ssh_state.decompress_stream.total_out;
2469    
2470     if (total_in > 0) {
2471     _snprintf(buf2, sizeof(buf2), "level %d; ratio %.1f (%ld:%ld)",
2472     pvar->ssh_state.compression_level,
2473     ((double) total_out) / total_in, total_out,
2474     total_in);
2475     } else {
2476     _snprintf(buf2, sizeof(buf2), "level %d",
2477     pvar->ssh_state.compression_level);
2478     }
2479     } else {
2480     strcpy(buf2, "none");
2481     }
2482     buf2[sizeof(buf2) - 1] = 0;
2483    
2484     _snprintf(dest, len, "Upstream %s; Downstream %s", buf, buf2);
2485     dest[len - 1] = 0;
2486     }
2487    
2488     void SSH_get_server_ID_info(PTInstVar pvar, char FAR * dest, int len)
2489     {
2490     strncpy(dest, pvar->ssh_state.server_ID == NULL ? "Unknown"
2491     : pvar->ssh_state.server_ID, len);
2492     dest[len - 1] = 0;
2493     }
2494    
2495     void SSH_get_protocol_version_info(PTInstVar pvar, char FAR * dest,
2496     int len)
2497     {
2498     if (pvar->protocol_major == 0) {
2499     strncpy(dest, "Unknown", len);
2500     } else {
2501     _snprintf(dest, len, "%d.%d", pvar->protocol_major,
2502     pvar->protocol_minor);
2503     }
2504     dest[len - 1] = 0;
2505     }
2506    
2507     void SSH_end(PTInstVar pvar)
2508     {
2509     int i;
2510    
2511     for (i = 0; i < 256; i++) {
2512     SSHPacketHandlerItem FAR *first_item =
2513     pvar->ssh_state.packet_handlers[i];
2514    
2515     if (first_item != NULL) {
2516     SSHPacketHandlerItem FAR *item