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 2798 - (hide annotations) (download) (as text)
Thu Mar 10 13:40:39 2005 UTC (19 years, 1 month ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ssh.c
File MIME type: text/x-csrc
File size: 140602 byte(s)
すでにログイン処理を行っている場合は、SSH2_MSG_SERVICE_REQUESTの送信は
しないことにする。OpenSSHでは支障ないが、Tru64 UNIXではサーバエラーとなってしまうため。

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