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 2805 - (hide annotations) (download) (as text)
Sun Mar 27 04:39:55 2005 UTC (19 years ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 143581 byte(s)
SSH2のログ採取(verbose)のデータを追加した。

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